573 lines
29 KiB
Plaintext
573 lines
29 KiB
Plaintext
"use strict";
|
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
exports.decorateLanguageService = void 0;
|
|
const language_core_1 = require("@volar/language-core");
|
|
const dedupe_1 = require("./dedupe");
|
|
const utils_1 = require("./utils");
|
|
const transform_1 = require("./transform");
|
|
function decorateLanguageService(files, languageService) {
|
|
// ignored methods
|
|
const { getNavigationTree, getOutliningSpans, } = languageService;
|
|
languageService.getNavigationTree = fileName => {
|
|
const [virtualCode] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
const tree = getNavigationTree(fileName);
|
|
tree.childItems = undefined;
|
|
return tree;
|
|
}
|
|
else {
|
|
return getNavigationTree(fileName);
|
|
}
|
|
};
|
|
languageService.getOutliningSpans = fileName => {
|
|
const [virtualCode] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
return [];
|
|
}
|
|
else {
|
|
return getOutliningSpans(fileName);
|
|
}
|
|
};
|
|
// methods
|
|
const { findReferences, findRenameLocations, getCompletionEntryDetails, getCompletionsAtPosition, getDefinitionAndBoundSpan, getDefinitionAtPosition, getFileReferences, getImplementationAtPosition, getQuickInfoAtPosition, getReferencesAtPosition, getSemanticDiagnostics, getSyntacticDiagnostics, getSuggestionDiagnostics, getTypeDefinitionAtPosition, getEncodedSemanticClassifications, getDocumentHighlights, getApplicableRefactors, getEditsForRefactor, getRenameInfo, getCodeFixesAtPosition, prepareCallHierarchy, provideCallHierarchyIncomingCalls, provideCallHierarchyOutgoingCalls, provideInlayHints, organizeImports, } = languageService;
|
|
languageService.prepareCallHierarchy = (fileName, position) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
const item = prepareCallHierarchy(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
if (Array.isArray(item)) {
|
|
return item.map(item => (0, transform_1.transformCallHierarchyItem)(files, item, language_core_1.isCallHierarchyEnabled));
|
|
}
|
|
else if (item) {
|
|
return (0, transform_1.transformCallHierarchyItem)(files, item, language_core_1.isCallHierarchyEnabled);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return prepareCallHierarchy(fileName, position);
|
|
}
|
|
};
|
|
languageService.provideCallHierarchyIncomingCalls = (fileName, position) => {
|
|
let calls = [];
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
calls = provideCallHierarchyIncomingCalls(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
calls = provideCallHierarchyIncomingCalls(fileName, position);
|
|
}
|
|
return calls
|
|
.map(call => {
|
|
const from = (0, transform_1.transformCallHierarchyItem)(files, call.from, language_core_1.isCallHierarchyEnabled);
|
|
const fromSpans = call.fromSpans
|
|
.map(span => (0, transform_1.transformSpan)(files, call.from.file, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
.filter(utils_1.notEmpty);
|
|
return {
|
|
from,
|
|
fromSpans,
|
|
};
|
|
});
|
|
};
|
|
languageService.provideCallHierarchyOutgoingCalls = (fileName, position) => {
|
|
let calls = [];
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isCallHierarchyEnabled)(mapping.data)) {
|
|
calls = provideCallHierarchyOutgoingCalls(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
calls = provideCallHierarchyOutgoingCalls(fileName, position);
|
|
}
|
|
return calls
|
|
.map(call => {
|
|
const to = (0, transform_1.transformCallHierarchyItem)(files, call.to, language_core_1.isCallHierarchyEnabled);
|
|
const fromSpans = call.fromSpans
|
|
.map(span => (0, transform_1.transformSpan)(files, fileName, span, language_core_1.isCallHierarchyEnabled)?.textSpan)
|
|
.filter(utils_1.notEmpty);
|
|
return {
|
|
to,
|
|
fromSpans,
|
|
};
|
|
});
|
|
};
|
|
languageService.organizeImports = (args, formatOptions, preferences) => {
|
|
const unresolved = organizeImports(args, formatOptions, preferences);
|
|
const resolved = unresolved
|
|
.map(changes => (0, transform_1.transformFileTextChanges)(files, changes, language_core_1.isCodeActionsEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return resolved;
|
|
};
|
|
languageService.getQuickInfoAtPosition = (fileName, position) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isHoverEnabled)(mapping.data)) {
|
|
const result = getQuickInfoAtPosition(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
if (result) {
|
|
const textSpan = (0, transform_1.transformSpan)(files, fileName, result.textSpan, language_core_1.isHoverEnabled)?.textSpan;
|
|
if (textSpan) {
|
|
return {
|
|
...result,
|
|
textSpan,
|
|
};
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return getQuickInfoAtPosition(fileName, position);
|
|
}
|
|
};
|
|
languageService.getDocumentHighlights = (fileName, position, filesToSearch) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isHighlightEnabled, position => getDocumentHighlights(fileName, position, filesToSearch), function* (result) {
|
|
for (const ref of result) {
|
|
for (const reference of ref.highlightSpans) {
|
|
yield [reference.fileName ?? ref.fileName, reference.textSpan.start];
|
|
}
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(highlights => {
|
|
return {
|
|
...highlights,
|
|
highlightSpans: highlights.highlightSpans
|
|
.map(span => {
|
|
const textSpan = (0, transform_1.transformSpan)(files, span.fileName ?? highlights.fileName, span.textSpan, language_core_1.isHighlightEnabled)?.textSpan;
|
|
if (textSpan) {
|
|
return {
|
|
...span,
|
|
contextSpan: (0, transform_1.transformSpan)(files, span.fileName ?? highlights.fileName, span.contextSpan, language_core_1.isHighlightEnabled)?.textSpan,
|
|
textSpan,
|
|
};
|
|
}
|
|
})
|
|
.filter(utils_1.notEmpty),
|
|
};
|
|
});
|
|
return resolved;
|
|
};
|
|
languageService.getApplicableRefactors = (fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
|
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
const por = typeof positionOrRange === 'number'
|
|
? generateOffset + sourceFile.snapshot.getLength()
|
|
: {
|
|
pos: generateOffset + sourceFile.snapshot.getLength(),
|
|
end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceFile.snapshot.getLength(),
|
|
};
|
|
return getApplicableRefactors(fileName, por, preferences, triggerReason, kind, includeInteractiveActions);
|
|
}
|
|
}
|
|
return [];
|
|
}
|
|
else {
|
|
return getApplicableRefactors(fileName, positionOrRange, preferences, triggerReason, kind, includeInteractiveActions);
|
|
}
|
|
};
|
|
languageService.getEditsForRefactor = (fileName, formatOptions, positionOrRange, refactorName, actionName, preferences) => {
|
|
let edits;
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(typeof positionOrRange === 'number' ? positionOrRange : positionOrRange.pos)) {
|
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
const por = typeof positionOrRange === 'number'
|
|
? generateOffset + sourceFile.snapshot.getLength()
|
|
: {
|
|
pos: generateOffset + sourceFile.snapshot.getLength(),
|
|
end: generateOffset + positionOrRange.end - positionOrRange.pos + sourceFile.snapshot.getLength(),
|
|
};
|
|
edits = getEditsForRefactor(fileName, formatOptions, por, refactorName, actionName, preferences);
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
edits = getEditsForRefactor(fileName, formatOptions, positionOrRange, refactorName, actionName, preferences);
|
|
}
|
|
if (edits) {
|
|
edits.edits = edits.edits
|
|
.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCodeActionsEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return edits;
|
|
}
|
|
};
|
|
languageService.getRenameInfo = (fileName, position, options) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isRenameEnabled)(mapping.data)) {
|
|
const info = getRenameInfo(fileName, generateOffset + sourceFile.snapshot.getLength(), options);
|
|
if (info.canRename) {
|
|
const span = (0, transform_1.transformSpan)(files, fileName, info.triggerSpan, language_core_1.isRenameEnabled);
|
|
if (span) {
|
|
info.triggerSpan = span.textSpan;
|
|
return info;
|
|
}
|
|
}
|
|
else {
|
|
return info;
|
|
}
|
|
}
|
|
}
|
|
return {
|
|
canRename: false,
|
|
localizedErrorMessage: 'Failed to get rename locations',
|
|
};
|
|
}
|
|
else {
|
|
return getRenameInfo(fileName, position, options);
|
|
}
|
|
};
|
|
languageService.getCodeFixesAtPosition = (fileName, start, end, errorCodes, formatOptions, preferences) => {
|
|
let fixes = [];
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateStart, mapping] of map.getGeneratedOffsets(start)) {
|
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
for (const [generateEnd, mapping] of map.getGeneratedOffsets(end)) {
|
|
if ((0, language_core_1.isCodeActionsEnabled)(mapping.data)) {
|
|
fixes = getCodeFixesAtPosition(fileName, generateStart + sourceFile.snapshot.getLength(), generateEnd + sourceFile.snapshot.getLength(), errorCodes, formatOptions, preferences);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
fixes = getCodeFixesAtPosition(fileName, start, end, errorCodes, formatOptions, preferences);
|
|
}
|
|
fixes = fixes.map(fix => {
|
|
fix.changes = fix.changes.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCodeActionsEnabled)).filter(utils_1.notEmpty);
|
|
return fix;
|
|
});
|
|
return fixes;
|
|
};
|
|
languageService.getEncodedSemanticClassifications = (fileName, span, format) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
let start;
|
|
let end;
|
|
for (const mapping of map.mappings) {
|
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data) && mapping.sourceOffsets[0] >= span.start && mapping.sourceOffsets[0] <= span.start + span.length) {
|
|
start ??= mapping.generatedOffsets[0];
|
|
end ??= mapping.generatedOffsets[mapping.generatedOffsets.length - 1];
|
|
start = Math.min(start, mapping.generatedOffsets[0]);
|
|
end = Math.max(end, mapping.generatedOffsets[mapping.generatedOffsets.length - 1]);
|
|
}
|
|
}
|
|
if (start === undefined || end === undefined) {
|
|
start = 0;
|
|
end = 0;
|
|
}
|
|
start += sourceFile.snapshot.getLength();
|
|
end += sourceFile.snapshot.getLength();
|
|
const result = getEncodedSemanticClassifications(fileName, { start, length: end - start }, format);
|
|
const spans = [];
|
|
for (let i = 0; i < result.spans.length; i += 3) {
|
|
for (const [sourceStart, mapping] of map.getSourceOffsets(result.spans[i] - sourceFile.snapshot.getLength())) {
|
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
|
|
for (const [sourceEnd, mapping] of map.getSourceOffsets(result.spans[i] + result.spans[i + 1] - sourceFile.snapshot.getLength())) {
|
|
if ((0, language_core_1.isSemanticTokensEnabled)(mapping.data)) {
|
|
spans.push(sourceStart, sourceEnd - sourceStart, result.spans[i + 2]);
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
result.spans = spans;
|
|
return result;
|
|
}
|
|
else {
|
|
return getEncodedSemanticClassifications(fileName, span, format);
|
|
}
|
|
};
|
|
languageService.getSyntacticDiagnostics = fileName => {
|
|
return getSyntacticDiagnostics(fileName)
|
|
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
.filter(utils_1.notEmpty);
|
|
};
|
|
languageService.getSemanticDiagnostics = fileName => {
|
|
return getSemanticDiagnostics(fileName)
|
|
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
.filter(utils_1.notEmpty);
|
|
};
|
|
languageService.getSuggestionDiagnostics = fileName => {
|
|
return getSuggestionDiagnostics(fileName)
|
|
.map(d => (0, transform_1.transformDiagnostic)(files, d))
|
|
.filter(utils_1.notEmpty);
|
|
};
|
|
languageService.getDefinitionAndBoundSpan = (fileName, position) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isDefinitionEnabled, position => getDefinitionAndBoundSpan(fileName, position), function* (result) {
|
|
for (const ref of result.definitions ?? []) {
|
|
yield [ref.fileName, ref.textSpan.start];
|
|
}
|
|
});
|
|
const textSpan = unresolved
|
|
.map(s => (0, transform_1.transformSpan)(files, fileName, s.textSpan, language_core_1.isDefinitionEnabled)?.textSpan)
|
|
.filter(utils_1.notEmpty)[0];
|
|
if (!textSpan) {
|
|
return;
|
|
}
|
|
const definitions = unresolved
|
|
.map(s => s.definitions
|
|
?.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
.filter(utils_1.notEmpty))
|
|
.filter(utils_1.notEmpty)
|
|
.flat();
|
|
return {
|
|
textSpan,
|
|
definitions: (0, dedupe_1.dedupeDocumentSpans)(definitions),
|
|
};
|
|
};
|
|
languageService.findReferences = (fileName, position) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isReferencesEnabled, position => findReferences(fileName, position), function* (result) {
|
|
for (const ref of result) {
|
|
for (const reference of ref.references) {
|
|
yield [reference.fileName, reference.textSpan.start];
|
|
}
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(symbol => {
|
|
const definition = (0, transform_1.transformDocumentSpan)(files, symbol.definition, language_core_1.isDefinitionEnabled);
|
|
if (definition) {
|
|
return {
|
|
definition,
|
|
references: symbol.references
|
|
.map(r => (0, transform_1.transformDocumentSpan)(files, r, language_core_1.isReferencesEnabled))
|
|
.filter(utils_1.notEmpty),
|
|
};
|
|
}
|
|
})
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeReferencedSymbols)(resolved);
|
|
};
|
|
languageService.getDefinitionAtPosition = (fileName, position) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isDefinitionEnabled, position => getDefinitionAtPosition(fileName, position), function* (result) {
|
|
for (const ref of result) {
|
|
yield [ref.fileName, ref.textSpan.start];
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isDefinitionEnabled, s.fileName !== fileName))
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
};
|
|
languageService.getTypeDefinitionAtPosition = (fileName, position) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isTypeDefinitionEnabled, position => getTypeDefinitionAtPosition(fileName, position), function* (result) {
|
|
for (const ref of result) {
|
|
yield [ref.fileName, ref.textSpan.start];
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isTypeDefinitionEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
};
|
|
languageService.getImplementationAtPosition = (fileName, position) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isImplementationEnabled, position => getImplementationAtPosition(fileName, position), function* (result) {
|
|
for (const ref of result) {
|
|
yield [ref.fileName, ref.textSpan.start];
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isImplementationEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
};
|
|
languageService.findRenameLocations = (fileName, position, findInStrings, findInComments, preferences) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isRenameEnabled, position => findRenameLocations(fileName, position, findInStrings, findInComments, preferences), function* (result) {
|
|
for (const ref of result) {
|
|
yield [ref.fileName, ref.textSpan.start];
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isRenameEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
};
|
|
languageService.getReferencesAtPosition = (fileName, position) => {
|
|
const unresolved = linkedCodeFeatureWorker(fileName, position, language_core_1.isReferencesEnabled, position => getReferencesAtPosition(fileName, position), function* (result) {
|
|
for (const ref of result) {
|
|
yield [ref.fileName, ref.textSpan.start];
|
|
}
|
|
});
|
|
const resolved = unresolved
|
|
.flat()
|
|
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isReferencesEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
};
|
|
languageService.getCompletionsAtPosition = (fileName, position, options, formattingSettings) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
let mainResult;
|
|
let additionalResults = [];
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isCompletionEnabled)(mapping.data)) {
|
|
const isAdditional = typeof mapping.data.completion === 'object' && mapping.data.completion.isAdditional;
|
|
if (!isAdditional && mainResult) {
|
|
continue;
|
|
}
|
|
const result = getCompletionsAtPosition(fileName, generateOffset + sourceFile.snapshot.getLength(), options, formattingSettings);
|
|
if (result) {
|
|
for (const entry of result.entries) {
|
|
entry.replacementSpan = (0, transform_1.transformSpan)(files, fileName, entry.replacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
|
|
}
|
|
result.optionalReplacementSpan = (0, transform_1.transformSpan)(files, fileName, result.optionalReplacementSpan, language_core_1.isCompletionEnabled)?.textSpan;
|
|
if (isAdditional) {
|
|
additionalResults.push(result);
|
|
}
|
|
else {
|
|
mainResult = result;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
if (!mainResult && additionalResults.length) {
|
|
mainResult = additionalResults.shift();
|
|
}
|
|
if (mainResult) {
|
|
return {
|
|
...mainResult,
|
|
entries: [
|
|
...mainResult.entries,
|
|
...additionalResults.map(additionalResult => additionalResult.entries).flat(),
|
|
],
|
|
};
|
|
}
|
|
}
|
|
else {
|
|
return getCompletionsAtPosition(fileName, position, options, formattingSettings);
|
|
}
|
|
};
|
|
languageService.getCompletionEntryDetails = (fileName, position, entryName, formatOptions, source, preferences, data) => {
|
|
let details;
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if ((0, language_core_1.isCompletionEnabled)(mapping.data)) {
|
|
details = getCompletionEntryDetails(fileName, generateOffset + sourceFile.snapshot.getLength(), entryName, formatOptions, source, preferences, data);
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
return getCompletionEntryDetails(fileName, position, entryName, formatOptions, source, preferences, data);
|
|
}
|
|
if (details?.codeActions) {
|
|
for (const codeAction of details.codeActions) {
|
|
codeAction.changes = codeAction.changes.map(edit => (0, transform_1.transformFileTextChanges)(files, edit, language_core_1.isCompletionEnabled)).filter(utils_1.notEmpty);
|
|
}
|
|
}
|
|
return details;
|
|
};
|
|
languageService.provideInlayHints = (fileName, span, preferences) => {
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
let start;
|
|
let end;
|
|
for (const mapping of map.mappings) {
|
|
if ((0, language_core_1.isInlayHintsEnabled)(mapping.data) && mapping.sourceOffsets[0] >= span.start && mapping.sourceOffsets[0] <= span.start + span.length) {
|
|
start ??= mapping.generatedOffsets[0];
|
|
end ??= mapping.generatedOffsets[mapping.generatedOffsets.length - 1];
|
|
start = Math.min(start, mapping.generatedOffsets[0]);
|
|
end = Math.max(end, mapping.generatedOffsets[mapping.generatedOffsets.length - 1]);
|
|
}
|
|
}
|
|
if (start === undefined || end === undefined) {
|
|
start = 0;
|
|
end = 0;
|
|
}
|
|
start += sourceFile.snapshot.getLength();
|
|
end += sourceFile.snapshot.getLength();
|
|
const result = provideInlayHints(fileName, { start, length: end - start }, preferences);
|
|
const hints = [];
|
|
for (const hint of result) {
|
|
for (const [sourcePosition, mapping] of map.getSourceOffsets(hint.position - sourceFile.snapshot.getLength())) {
|
|
if ((0, language_core_1.isInlayHintsEnabled)(mapping.data)) {
|
|
hints.push({
|
|
...hint,
|
|
position: sourcePosition,
|
|
});
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
return hints;
|
|
}
|
|
else {
|
|
return provideInlayHints(fileName, span, preferences);
|
|
}
|
|
};
|
|
languageService.getFileReferences = fileName => {
|
|
const unresolved = getFileReferences(fileName);
|
|
const resolved = unresolved
|
|
.map(s => (0, transform_1.transformDocumentSpan)(files, s, language_core_1.isReferencesEnabled))
|
|
.filter(utils_1.notEmpty);
|
|
return (0, dedupe_1.dedupeDocumentSpans)(resolved);
|
|
};
|
|
function linkedCodeFeatureWorker(fileName, position, filter, worker, getLinkedCodes) {
|
|
let results = [];
|
|
const processedFilePositions = new Set();
|
|
const [virtualCode, sourceFile, map] = (0, utils_1.getVirtualFileAndMap)(files, fileName);
|
|
if (virtualCode) {
|
|
for (const [generateOffset, mapping] of map.getGeneratedOffsets(position)) {
|
|
if (filter(mapping.data)) {
|
|
process(fileName, generateOffset + sourceFile.snapshot.getLength());
|
|
}
|
|
}
|
|
}
|
|
else {
|
|
process(fileName, position);
|
|
}
|
|
return results;
|
|
function process(fileName, position) {
|
|
if (processedFilePositions.has(fileName + ':' + position)) {
|
|
return;
|
|
}
|
|
processedFilePositions.add(fileName + ':' + position);
|
|
const result = worker(position);
|
|
if (!result) {
|
|
return;
|
|
}
|
|
results = results.concat(result);
|
|
for (const ref of getLinkedCodes(result)) {
|
|
processedFilePositions.add(ref[0] + ':' + ref[1]);
|
|
const [virtualFile, sourceFile] = (0, utils_1.getVirtualFileAndMap)(files, ref[0]);
|
|
if (!virtualFile) {
|
|
continue;
|
|
}
|
|
const linkedCodeMap = files.getLinkedCodeMap(virtualFile.code);
|
|
if (!linkedCodeMap) {
|
|
continue;
|
|
}
|
|
for (const linkedCodeOffset of linkedCodeMap.getLinkedOffsets(ref[1] - sourceFile.snapshot.getLength())) {
|
|
process(ref[0], linkedCodeOffset + sourceFile.snapshot.getLength());
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
exports.decorateLanguageService = decorateLanguageService;
|
|
//# sourceMappingURL=decorateLanguageService.js.map |