Revamping to matrix style
This commit is contained in:
243
node_modules/@volar/language-service/lib/features/provideDiagnostics.js
generated
vendored
Normal file
243
node_modules/@volar/language-service/lib/features/provideDiagnostics.js
generated
vendored
Normal file
@@ -0,0 +1,243 @@
|
||||
"use strict";
|
||||
Object.defineProperty(exports, "__esModule", { value: true });
|
||||
exports.errorMarkups = void 0;
|
||||
exports.register = register;
|
||||
exports.transformDiagnostic = transformDiagnostic;
|
||||
exports.updateRange = updateRange;
|
||||
const language_core_1 = require("@volar/language-core");
|
||||
const vscode_uri_1 = require("vscode-uri");
|
||||
const cancellation_1 = require("../utils/cancellation");
|
||||
const common_1 = require("../utils/common");
|
||||
const dedupe = require("../utils/dedupe");
|
||||
const featureWorkers_1 = require("../utils/featureWorkers");
|
||||
const uriMap_1 = require("../utils/uriMap");
|
||||
exports.errorMarkups = (0, uriMap_1.createUriMap)();
|
||||
function register(context) {
|
||||
const lastResponses = (0, uriMap_1.createUriMap)();
|
||||
const cacheMaps = {
|
||||
semantic: new Map(),
|
||||
syntactic: new Map(),
|
||||
};
|
||||
context.env.onDidChangeConfiguration?.(() => {
|
||||
lastResponses.clear();
|
||||
cacheMaps.semantic.clear();
|
||||
cacheMaps.syntactic.clear();
|
||||
});
|
||||
return async (uri, response, token = cancellation_1.NoneCancellationToken) => {
|
||||
let langaugeIdAndSnapshot;
|
||||
const decoded = context.decodeEmbeddedDocumentUri(uri);
|
||||
if (decoded) {
|
||||
langaugeIdAndSnapshot = context.language.scripts.get(decoded[0])?.generated?.embeddedCodes.get(decoded[1]);
|
||||
}
|
||||
else {
|
||||
langaugeIdAndSnapshot = context.language.scripts.get(uri);
|
||||
}
|
||||
if (!langaugeIdAndSnapshot) {
|
||||
return [];
|
||||
}
|
||||
const document = context.documents.get(uri, langaugeIdAndSnapshot.languageId, langaugeIdAndSnapshot.snapshot);
|
||||
const lastResponse = lastResponses.get(uri) ?? lastResponses.set(uri, {
|
||||
semantic: { errors: [] },
|
||||
syntactic: { errors: [] },
|
||||
}).get(uri);
|
||||
let updateCacheRangeFailed = false;
|
||||
let errorsUpdated = false;
|
||||
let lastCheckCancelAt = 0;
|
||||
for (const cache of Object.values(lastResponse)) {
|
||||
const oldSnapshot = cache.snapshot;
|
||||
const oldDocument = cache.document;
|
||||
const change = oldSnapshot ? langaugeIdAndSnapshot.snapshot.getChangeRange(oldSnapshot) : undefined;
|
||||
cache.snapshot = langaugeIdAndSnapshot.snapshot;
|
||||
cache.document = document;
|
||||
if (!updateCacheRangeFailed && oldDocument && change) {
|
||||
const changeRange = {
|
||||
range: {
|
||||
start: oldDocument.positionAt(change.span.start),
|
||||
end: oldDocument.positionAt(change.span.start + change.span.length),
|
||||
},
|
||||
newEnd: document.positionAt(change.span.start + change.newLength),
|
||||
};
|
||||
for (const error of cache.errors) {
|
||||
if (!updateRange(error.range, changeRange)) {
|
||||
updateCacheRangeFailed = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
await worker('syntactic', cacheMaps.syntactic, lastResponse.syntactic);
|
||||
processResponse();
|
||||
await worker('semantic', cacheMaps.semantic, lastResponse.semantic);
|
||||
return collectErrors();
|
||||
function processResponse() {
|
||||
if (errorsUpdated && !updateCacheRangeFailed) {
|
||||
response?.(collectErrors());
|
||||
errorsUpdated = false;
|
||||
}
|
||||
}
|
||||
function collectErrors() {
|
||||
return Object.values(lastResponse).flatMap(({ errors }) => errors);
|
||||
}
|
||||
async function worker(kind, cacheMap, cache) {
|
||||
const result = await (0, featureWorkers_1.documentFeatureWorker)(context, uri, docs => docs[2].mappings.some(mapping => (0, language_core_1.isDiagnosticsEnabled)(mapping.data)), async (plugin, document) => {
|
||||
const interFileDependencies = plugin[0].capabilities.diagnosticProvider?.interFileDependencies;
|
||||
if (kind === 'semantic' !== interFileDependencies) {
|
||||
return;
|
||||
}
|
||||
if (Date.now() - lastCheckCancelAt >= 10) {
|
||||
await (0, common_1.sleep)(10); // waiting LSP event polling
|
||||
lastCheckCancelAt = Date.now();
|
||||
}
|
||||
if (token.isCancellationRequested) {
|
||||
return;
|
||||
}
|
||||
const pluginIndex = context.plugins.indexOf(plugin);
|
||||
const pluginCache = cacheMap.get(pluginIndex) ?? cacheMap.set(pluginIndex, new Map()).get(pluginIndex);
|
||||
const cache = pluginCache.get(document.uri);
|
||||
if (!interFileDependencies && cache && cache.documentVersion === document.version) {
|
||||
return cache.errors;
|
||||
}
|
||||
const errors = await plugin[1].provideDiagnostics?.(document, token) || [];
|
||||
errors.forEach(error => {
|
||||
error.data = {
|
||||
uri: uri.toString(),
|
||||
version: document.version,
|
||||
pluginIndex: pluginIndex,
|
||||
isFormat: false,
|
||||
original: {
|
||||
data: error.data,
|
||||
},
|
||||
documentUri: document.uri,
|
||||
};
|
||||
});
|
||||
errorsUpdated = true;
|
||||
pluginCache.set(document.uri, {
|
||||
documentVersion: document.version,
|
||||
errors,
|
||||
});
|
||||
return errors;
|
||||
}, (errors, map) => {
|
||||
return errors
|
||||
.map(error => transformDiagnostic(context, error, map))
|
||||
.filter(error => !!error);
|
||||
}, arr => dedupe.withDiagnostics(arr.flat()));
|
||||
if (result) {
|
||||
cache.errors = result;
|
||||
cache.snapshot = langaugeIdAndSnapshot?.snapshot;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
function transformDiagnostic(context, error, docs) {
|
||||
// clone it to avoid modify cache
|
||||
let _error = { ...error };
|
||||
if (docs) {
|
||||
const range = (0, featureWorkers_1.getSourceRange)(docs, error.range, data => (0, language_core_1.shouldReportDiagnostics)(data, error.source, error.code));
|
||||
if (!range) {
|
||||
return;
|
||||
}
|
||||
_error.range = range;
|
||||
}
|
||||
if (_error.relatedInformation) {
|
||||
const relatedInfos = [];
|
||||
for (const info of _error.relatedInformation) {
|
||||
const decoded = context.decodeEmbeddedDocumentUri(vscode_uri_1.URI.parse(info.location.uri));
|
||||
const sourceScript = decoded && context.language.scripts.get(decoded[0]);
|
||||
const virtualCode = decoded && sourceScript?.generated?.embeddedCodes.get(decoded[1]);
|
||||
if (sourceScript && virtualCode) {
|
||||
const embeddedDocument = context.documents.get(context.encodeEmbeddedDocumentUri(sourceScript.id, virtualCode.id), virtualCode.languageId, virtualCode.snapshot);
|
||||
for (const [sourceScript, map] of context.language.maps.forEach(virtualCode)) {
|
||||
const sourceDocument = context.documents.get(sourceScript.id, sourceScript.languageId, sourceScript.snapshot);
|
||||
const docs = [sourceDocument, embeddedDocument, map];
|
||||
const range = (0, featureWorkers_1.getSourceRange)(docs, info.location.range, data => (0, language_core_1.shouldReportDiagnostics)(data, undefined, undefined));
|
||||
if (range) {
|
||||
relatedInfos.push({
|
||||
location: {
|
||||
uri: sourceDocument.uri,
|
||||
range,
|
||||
},
|
||||
message: info.message,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
relatedInfos.push(info);
|
||||
}
|
||||
}
|
||||
_error.relatedInformation = relatedInfos;
|
||||
}
|
||||
return _error;
|
||||
}
|
||||
function updateRange(range, change) {
|
||||
if (!updatePosition(range.start, change, false)) {
|
||||
return;
|
||||
}
|
||||
if (!updatePosition(range.end, change, true)) {
|
||||
return;
|
||||
}
|
||||
if (range.end.line === range.start.line && range.end.character <= range.start.character) {
|
||||
range.end.character++;
|
||||
}
|
||||
return range;
|
||||
}
|
||||
function updatePosition(position, change, isEnd) {
|
||||
if (change.range.end.line > position.line) {
|
||||
if (change.newEnd.line > position.line) {
|
||||
// No change
|
||||
return true;
|
||||
}
|
||||
else if (change.newEnd.line === position.line) {
|
||||
position.character = Math.min(position.character, change.newEnd.character);
|
||||
return true;
|
||||
}
|
||||
else if (change.newEnd.line < position.line) {
|
||||
position.line = change.newEnd.line;
|
||||
position.character = change.newEnd.character;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (change.range.end.line === position.line) {
|
||||
const characterDiff = change.newEnd.character - change.range.end.character;
|
||||
if (position.character >= change.range.end.character) {
|
||||
if (change.newEnd.line !== change.range.end.line) {
|
||||
position.line = change.newEnd.line;
|
||||
position.character = change.newEnd.character + position.character - change.range.end.character;
|
||||
}
|
||||
else {
|
||||
if (isEnd ? change.range.end.character < position.character : change.range.end.character <= position.character) {
|
||||
position.character += characterDiff;
|
||||
}
|
||||
else {
|
||||
const offset = change.range.end.character - position.character;
|
||||
if (-characterDiff > offset) {
|
||||
position.character += characterDiff + offset;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
if (change.newEnd.line === change.range.end.line) {
|
||||
const offset = change.range.end.character - position.character;
|
||||
if (-characterDiff > offset) {
|
||||
position.character += characterDiff + offset;
|
||||
}
|
||||
}
|
||||
else if (change.newEnd.line < change.range.end.line) {
|
||||
position.line = change.newEnd.line;
|
||||
position.character = change.newEnd.character;
|
||||
}
|
||||
else {
|
||||
// No change
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (change.range.end.line < position.line) {
|
||||
position.line += change.newEnd.line - change.range.end.line;
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//# sourceMappingURL=provideDiagnostics.js.map
|
||||
Reference in New Issue
Block a user