UNPKG

svelte-language-server

Version:
149 lines 7.88 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.FindReferencesProviderImpl = void 0; const typescript_1 = __importDefault(require("typescript")); const utils_1 = require("../../../utils"); const utils_2 = require("../utils"); const utils_3 = require("./utils"); class FindReferencesProviderImpl { constructor(lsAndTsDocResolver, componentReferencesProvider) { this.lsAndTsDocResolver = lsAndTsDocResolver; this.componentReferencesProvider = componentReferencesProvider; } async findReferences(document, position, context, cancellationToken) { if (this.isPositionForComponentCodeLens(position) || this.isScriptStartOrEndTag(position, document)) { return this.componentReferencesProvider.findComponentReferences(document.uri); } const { lang, tsDoc, lsContainer } = await this.getLSAndTSDoc(document); if (cancellationToken?.isCancellationRequested) { return null; } const offset = tsDoc.offsetAt(tsDoc.getGeneratedPosition(position)); const rawReferences = lang.findReferences(tsDoc.filePath, tsDoc.offsetAt(tsDoc.getGeneratedPosition(position))); if (!rawReferences) { return null; } const snapshots = new utils_3.SnapshotMap(this.lsAndTsDocResolver, lsContainer); snapshots.set(tsDoc.filePath, tsDoc); if (rawReferences.some((ref) => ref.definition.kind === typescript_1.default.ScriptElementKind.alias)) { const componentReferences = await this.checkIfHasAliasedComponentReference(offset, tsDoc, lang); if (componentReferences?.length) { return componentReferences; } } const references = (0, utils_1.flatten)(rawReferences.map((ref) => ref.references)); references.push(...(await this.getStoreReferences(references, tsDoc, snapshots, lang, cancellationToken))); const locations = await Promise.all(references.map(async (ref) => this.mapReference(ref, context, snapshots, cancellationToken))); return (locations .filter(utils_1.isNotNullOrUndefined) // Possible $store references are added afterwards, sort for correct order .sort(sortLocationByFileAndRange)); } isScriptStartOrEndTag(position, document) { if (!document.scriptInfo) { return false; } const { start, end } = document.scriptInfo.container; const offset = document.offsetAt(position); return ((offset >= start && offset <= start + '<script'.length) || (offset >= end - '</script>'.length && offset <= end)); } isPositionForComponentCodeLens(position) { return position.line === 0 && position.character === 0; } /** * If references of a $store are searched, also find references for the corresponding store * and vice versa. */ async getStoreReferences(references, tsDoc, snapshots, lang, cancellationToken) { // If user started finding references at $store, find references for store, too let storeReferences = []; const storeReference = references.find((ref) => (0, utils_1.normalizePath)(ref.fileName) === tsDoc.filePath && (0, utils_3.isTextSpanInGeneratedCode)(tsDoc.getFullText(), ref.textSpan) && (0, utils_3.is$storeVariableIn$storeDeclaration)(tsDoc.getFullText(), ref.textSpan.start)); if (storeReference) { const additionalReferences = lang.findReferences(tsDoc.filePath, (0, utils_3.getStoreOffsetOf$storeDeclaration)(tsDoc.getFullText(), storeReference.textSpan.start)) || []; storeReferences = (0, utils_1.flatten)(additionalReferences.map((ref) => ref.references)); } // If user started finding references at store, find references for $store, too // If user started finding references at $store, find references for $store in other files const $storeReferences = []; for (const ref of [...references, ...storeReferences]) { const snapshot = await snapshots.retrieve(ref.fileName); if (cancellationToken?.isCancellationRequested) { return []; } if (!((0, utils_3.isTextSpanInGeneratedCode)(snapshot.getFullText(), ref.textSpan) && (0, utils_3.isStoreVariableIn$storeDeclaration)(snapshot.getFullText(), ref.textSpan.start))) { continue; } if (storeReference?.fileName === ref.fileName) { // $store in X -> usages of store -> store in X -> we would add duplicate $store references continue; } const additionalReferences = lang.findReferences(snapshot.filePath, (0, utils_3.get$storeOffsetOf$storeDeclaration)(snapshot.getFullText(), ref.textSpan.start)) || []; $storeReferences.push(...(0, utils_1.flatten)(additionalReferences.map((ref) => ref.references))); } return [...storeReferences, ...$storeReferences]; } async checkIfHasAliasedComponentReference(offset, tsDoc, lang) { const definitions = lang.getDefinitionAtPosition(tsDoc.filePath, offset); if (!definitions?.length) { return null; } const nonAliasDefinitions = definitions.filter((definition) => (0, utils_2.isGeneratedSvelteComponentName)(definition.name)); const references = await Promise.all(nonAliasDefinitions.map((definition) => this.componentReferencesProvider.findComponentReferences((0, utils_1.pathToUrl)(definition.fileName)))); const flattened = []; for (const ref of references) { if (ref) { const tmp = []; // perf optimization: we know each iteration has unique references for (const r of ref) { const exists = flattened.some((f) => f.uri === r.uri && f.range.start.line === r.range.start.line && f.range.start.character === r.range.start.character); if (!exists) { tmp.push(r); } } flattened.push(...tmp); } } return flattened; } async mapReference(ref, context, snapshots, cancellationToken) { if (!context.includeDeclaration && ref.isDefinition) { return null; } const snapshot = await snapshots.retrieve(ref.fileName); if (cancellationToken?.isCancellationRequested) { return null; } if ((0, utils_3.isTextSpanInGeneratedCode)(snapshot.getFullText(), ref.textSpan)) { return null; } // TODO we should deduplicate if we support finding references from multiple language service const location = (0, utils_2.convertToLocationForReferenceOrDefinition)(snapshot, ref.textSpan); // Some references are in generated code but not wrapped with explicit ignore comments. // These show up as zero-length ranges, so filter them out. if (!(0, utils_2.hasNonZeroRange)(location)) { return null; } return location; } async getLSAndTSDoc(document) { return this.lsAndTsDocResolver.getLSAndTSDoc(document); } } exports.FindReferencesProviderImpl = FindReferencesProviderImpl; function sortLocationByFileAndRange(l1, l2) { const localeCompare = l1.uri.localeCompare(l2.uri); return localeCompare === 0 ? (l1.range.start.line - l2.range.start.line) * 10000 + (l1.range.start.character - l2.range.start.character) : localeCompare; } //# sourceMappingURL=FindReferencesProvider.js.map