@tslite/services 0.0.0-stage → 1.12.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +55 -0
- package/NOTICE +13 -0
- package/dist/_namespaces/edit.d.ts +8 -0
- package/dist/_namespaces/edit.js +11 -0
- package/dist/_namespaces/ts.Completions.StringCompletions.d.ts +1 -0
- package/dist/_namespaces/ts.Completions.StringCompletions.js +2 -0
- package/dist/_namespaces/ts.Completions.d.ts +2 -0
- package/dist/_namespaces/ts.Completions.js +3 -0
- package/dist/_namespaces/ts.FindAllReferences.d.ts +2 -0
- package/dist/_namespaces/ts.FindAllReferences.js +3 -0
- package/dist/_namespaces/ts.GoToDefinition.d.ts +1 -0
- package/dist/_namespaces/ts.GoToDefinition.js +2 -0
- package/dist/_namespaces/ts.NavigationBar.d.ts +1 -0
- package/dist/_namespaces/ts.NavigationBar.js +2 -0
- package/dist/_namespaces/ts.OrganizeImports.d.ts +1 -0
- package/dist/_namespaces/ts.OrganizeImports.js +2 -0
- package/dist/_namespaces/ts.OutliningElementsCollector.d.ts +1 -0
- package/dist/_namespaces/ts.OutliningElementsCollector.js +2 -0
- package/dist/_namespaces/ts.Rename.d.ts +1 -0
- package/dist/_namespaces/ts.Rename.js +2 -0
- package/dist/_namespaces/ts.SignatureHelp.d.ts +1 -0
- package/dist/_namespaces/ts.SignatureHelp.js +2 -0
- package/dist/_namespaces/ts.SmartSelectionRange.d.ts +1 -0
- package/dist/_namespaces/ts.SmartSelectionRange.js +2 -0
- package/dist/_namespaces/ts.SymbolDisplay.d.ts +1 -0
- package/dist/_namespaces/ts.SymbolDisplay.js +2 -0
- package/dist/_namespaces/ts.codefix.d.ts +26 -0
- package/dist/_namespaces/ts.codefix.js +27 -0
- package/dist/_namespaces/ts.d.ts +17 -0
- package/dist/_namespaces/ts.formatting.d.ts +7 -0
- package/dist/_namespaces/ts.formatting.js +8 -0
- package/dist/_namespaces/ts.js +20 -0
- package/dist/_namespaces/ts.refactor.addOrRemoveBracesToArrowFunction.d.ts +1 -0
- package/dist/_namespaces/ts.refactor.addOrRemoveBracesToArrowFunction.js +2 -0
- package/dist/_namespaces/ts.refactor.convertParamsToDestructuredObject.d.ts +1 -0
- package/dist/_namespaces/ts.refactor.convertParamsToDestructuredObject.js +2 -0
- package/dist/_namespaces/ts.refactor.convertStringOrTemplateLiteral.d.ts +1 -0
- package/dist/_namespaces/ts.refactor.convertStringOrTemplateLiteral.js +2 -0
- package/dist/_namespaces/ts.refactor.d.ts +9 -0
- package/dist/_namespaces/ts.refactor.extractSymbol.d.ts +1 -0
- package/dist/_namespaces/ts.refactor.extractSymbol.js +2 -0
- package/dist/_namespaces/ts.refactor.js +10 -0
- package/dist/_namespaces/ts.textChanges.d.ts +1 -0
- package/dist/_namespaces/ts.textChanges.js +2 -0
- package/dist/classifier.d.ts +5 -0
- package/dist/classifier.js +439 -0
- package/dist/codeFixProvider.d.ts +13 -0
- package/dist/codeFixProvider.js +84 -0
- package/dist/codefixes/addConvertToUnknownForNonOverlappingTypes.d.ts +1 -0
- package/dist/codefixes/addConvertToUnknownForNonOverlappingTypes.js +21 -0
- package/dist/codefixes/addEmptyExportDeclaration.d.ts +1 -0
- package/dist/codefixes/addEmptyExportDeclaration.js +17 -0
- package/dist/codefixes/addMissingAsync.d.ts +1 -0
- package/dist/codefixes/addMissingAsync.js +75 -0
- package/dist/codefixes/addMissingAwait.d.ts +1 -0
- package/dist/codefixes/addMissingAwait.js +236 -0
- package/dist/codefixes/addMissingConst.d.ts +1 -0
- package/dist/codefixes/addMissingConst.js +91 -0
- package/dist/codefixes/addNameToNamelessParameter.d.ts +1 -0
- package/dist/codefixes/addNameToNamelessParameter.js +29 -0
- package/dist/codefixes/convertConstToLet.d.ts +1 -0
- package/dist/codefixes/convertConstToLet.js +30 -0
- package/dist/codefixes/convertToAsyncFunction.d.ts +1 -0
- package/dist/codefixes/convertToAsyncFunction.js +495 -0
- package/dist/codefixes/convertToMappedObjectType.d.ts +1 -0
- package/dist/codefixes/convertToMappedObjectType.js +48 -0
- package/dist/codefixes/correctQualifiedNameToIndexedAccessType.d.ts +1 -0
- package/dist/codefixes/correctQualifiedNameToIndexedAccessType.js +33 -0
- package/dist/codefixes/fixAddModuleReferTypeMissingTypeof.d.ts +1 -0
- package/dist/codefixes/fixAddModuleReferTypeMissingTypeof.js +27 -0
- package/dist/codefixes/fixAwaitInSyncFunction.d.ts +1 -0
- package/dist/codefixes/fixAwaitInSyncFunction.js +69 -0
- package/dist/codefixes/fixExpectedComma.d.ts +1 -0
- package/dist/codefixes/fixExpectedComma.js +35 -0
- package/dist/codefixes/fixInvalidJsxCharacters.d.ts +1 -0
- package/dist/codefixes/fixInvalidJsxCharacters.js +41 -0
- package/dist/codefixes/fixMissingCallParentheses.d.ts +1 -0
- package/dist/codefixes/fixMissingCallParentheses.js +42 -0
- package/dist/codefixes/fixSpelling.d.ts +1 -0
- package/dist/codefixes/fixSpelling.js +94 -0
- package/dist/codefixes/fixUnreachableCode.d.ts +1 -0
- package/dist/codefixes/fixUnreachableCode.js +65 -0
- package/dist/codefixes/fixUnusedIdentifier.d.ts +1 -0
- package/dist/codefixes/fixUnusedIdentifier.js +224 -0
- package/dist/codefixes/helpers.d.ts +8 -0
- package/dist/codefixes/helpers.js +53 -0
- package/dist/codefixes/importFixes.d.ts +14 -0
- package/dist/codefixes/importFixes.js +441 -0
- package/dist/codefixes/inferFromUsage.d.ts +1 -0
- package/dist/codefixes/inferFromUsage.js +742 -0
- package/dist/codefixes/removeUnnecessaryAwait.d.ts +1 -0
- package/dist/codefixes/removeUnnecessaryAwait.js +41 -0
- package/dist/codefixes/returnValueCorrect.d.ts +1 -0
- package/dist/codefixes/returnValueCorrect.js +132 -0
- package/dist/codefixes/splitTypeOnlyImport.d.ts +1 -0
- package/dist/codefixes/splitTypeOnlyImport.js +32 -0
- package/dist/codefixes/useBigintLiteral.d.ts +1 -0
- package/dist/codefixes/useBigintLiteral.js +29 -0
- package/dist/completions.d.ts +83 -0
- package/dist/completions.js +1720 -0
- package/dist/documentHighlights.d.ts +8 -0
- package/dist/documentHighlights.js +367 -0
- package/dist/documentRegistry.d.ts +36 -0
- package/dist/documentRegistry.js +63 -0
- package/dist/editingServices.d.ts +1 -0
- package/dist/editingServices.js +4 -0
- package/dist/findAllReferences.d.ts +113 -0
- package/dist/findAllReferences.js +1366 -0
- package/dist/formatting/formatting.d.ts +26 -0
- package/dist/formatting/formatting.js +1021 -0
- package/dist/formatting/formattingContext.d.ts +34 -0
- package/dist/formatting/formattingContext.js +78 -0
- package/dist/formatting/formattingScanner.d.ts +14 -0
- package/dist/formatting/formattingScanner.js +228 -0
- package/dist/formatting/rule.d.ts +31 -0
- package/dist/formatting/rule.js +22 -0
- package/dist/formatting/rules.d.ts +7 -0
- package/dist/formatting/rules.js +610 -0
- package/dist/formatting/rulesMap.d.ts +5 -0
- package/dist/formatting/rulesMap.js +127 -0
- package/dist/formatting/smartIndenter.d.ts +44 -0
- package/dist/formatting/smartIndenter.js +518 -0
- package/dist/getEditsForFileRename.d.ts +6 -0
- package/dist/getEditsForFileRename.js +86 -0
- package/dist/goToDefinition.d.ts +8 -0
- package/dist/goToDefinition.js +246 -0
- package/dist/importTracker.d.ts +50 -0
- package/dist/importTracker.js +422 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +3 -0
- package/dist/navigationBar.d.ts +3 -0
- package/dist/navigationBar.js +549 -0
- package/dist/organizeImports.d.ts +18 -0
- package/dist/organizeImports.js +290 -0
- package/dist/outliningElementsCollector.d.ts +2 -0
- package/dist/outliningElementsCollector.js +261 -0
- package/dist/refactorProvider.d.ts +5 -0
- package/dist/refactorProvider.js +16 -0
- package/dist/refactors/addOrRemoveBracesToArrowFunction.d.ts +1 -0
- package/dist/refactors/addOrRemoveBracesToArrowFunction.js +86 -0
- package/dist/refactors/convertExport.d.ts +1 -0
- package/dist/refactors/convertExport.js +126 -0
- package/dist/refactors/convertImport.d.ts +1 -0
- package/dist/refactors/convertImport.js +116 -0
- package/dist/refactors/convertParamsToDestructuredObject.d.ts +1 -0
- package/dist/refactors/convertParamsToDestructuredObject.js +282 -0
- package/dist/refactors/convertStringOrTemplateLiteral.d.ts +1 -0
- package/dist/refactors/convertStringOrTemplateLiteral.js +148 -0
- package/dist/refactors/extractSymbol.d.ts +60 -0
- package/dist/refactors/extractSymbol.js +1281 -0
- package/dist/refactors/extractType.d.ts +1 -0
- package/dist/refactors/extractType.js +102 -0
- package/dist/refactors/moveToNewFile.d.ts +1 -0
- package/dist/refactors/moveToNewFile.js +477 -0
- package/dist/rename.d.ts +2 -0
- package/dist/rename.js +100 -0
- package/dist/services.d.ts +48 -0
- package/dist/services.js +1480 -0
- package/dist/signatureHelp.d.ts +8 -0
- package/dist/signatureHelp.js +414 -0
- package/dist/smartSelection.d.ts +2 -0
- package/dist/smartSelection.js +243 -0
- package/dist/stringCompletions.d.ts +4 -0
- package/dist/stringCompletions.js +220 -0
- package/dist/suggestionDiagnostics.d.ts +6 -0
- package/dist/suggestionDiagnostics.js +92 -0
- package/dist/symbolDisplay.d.ts +16 -0
- package/dist/symbolDisplay.js +400 -0
- package/dist/textChanges.d.ts +161 -0
- package/dist/textChanges.js +1163 -0
- package/dist/types.d.ts +908 -0
- package/dist/types.js +263 -0
- package/dist/utilities.d.ts +283 -0
- package/dist/utilities.js +1981 -0
- package/package.json +45 -3
- package/README.md +0 -3
|
@@ -0,0 +1,1366 @@
|
|
|
1
|
+
// Modificado de microsoft/TypeScript v3.9.10, src/services/findAllReferences.ts: o namespace virou módulo ES, com os imports explícitos.
|
|
2
|
+
// O arquivo entra com o que os serviços que já vieram usam (o núcleo das referências, para os highlights); o resto dele vem
|
|
3
|
+
// com o grupo que o usa (o docs/ARCHITECTURE.md do pacote).
|
|
4
|
+
import { CheckFlags, Debug, InternalSymbolName, NodeFlags, ScriptTarget, SymbolDisplay, SymbolDisplayPartKind, SymbolFlags, SyntaxKind, addToSeen, append, arrayToSet, climbPastPropertyAccess, compareValues, contains, createMap, createTextSpan, createTextSpanFromBounds, displayPart, emptyArray, emptyOptions, escapeLeadingUnderscores, find, findAncestor, findIndex, first, firstDefined, firstOrUndefined, flatMap, forEachReturnStatement, getAdjustedReferenceLocation, getAdjustedRenameLocation, getCheckFlags, getContainerNode, getContainingObjectLiteralElement, getDeclarationFromName, getDeclarationOfKind, getMeaningFromDeclaration, getMeaningFromLocation, getNameOfDeclaration, getNameTable, getNodeId, getNodeKind, getPropertySymbolFromBindingElement, getPropertySymbolsFromContextualType, getSymbolId, getTextOfNode, getTouchingPropertyName, hasInitializer, hasType, isArrayLiteralOrObjectLiteralDestructuringPattern, isAssertionExpression, isBinaryExpression, isBindingElement, isBreakOrContinueStatement, isCallExpression, isCatchClause, isComputedPropertyName, isDeclaration, isDeclarationName, isExportAssignment, isExportSpecifier, isExpressionStatement, isExternalModuleSymbol, isExternalOrCommonJsModule, isForInOrOfStatement, isFunctionLike, isFunctionLikeDeclaration, isIdentifier, isIdentifierPart, isImportOrExportSpecifier, isImportSpecifier, isInNonReferenceComment, isInString, isJsxClosingElement, isJsxOpeningElement, isJsxSelfClosingElement, isLiteralComputedPropertyDeclarationName, isLiteralNameOfPropertyDeclarationOrIndexAccess, isModuleDeclaration, isObjectBindingElementWithoutPropertyName, isQualifiedName, isShorthandPropertyAssignment, isSourceFile, isStatement, isStringLiteral, isStringLiteralLike, isTypeAliasDeclaration, isTypeElement, isTypeKeyword, isTypeLiteralNode, isTypeNode, isTypeOperatorNode, isUnionTypeNode, isVariableDeclarationList, isVariableLike, isVariableStatement, isWriteAccess, map, mapDefined, nodeSeenTracker, punctuationPart, stripQuotes, symbolName, textPart, tokenToString, tryGetImportFromModuleSpecifier, } from "./_namespaces/ts.js";
|
|
5
|
+
import { createImportTracker, findModuleReferences, getExportInfo, getImportOrExportSymbol, } from "./_namespaces/ts.FindAllReferences.js";
|
|
6
|
+
/** Na tag, também o label e o `this` (CK-02). */
|
|
7
|
+
export var DefinitionKind;
|
|
8
|
+
(function (DefinitionKind) {
|
|
9
|
+
DefinitionKind[DefinitionKind["Symbol"] = 0] = "Symbol";
|
|
10
|
+
DefinitionKind[DefinitionKind["Keyword"] = 1] = "Keyword";
|
|
11
|
+
DefinitionKind[DefinitionKind["String"] = 2] = "String";
|
|
12
|
+
})(DefinitionKind || (DefinitionKind = {}));
|
|
13
|
+
export var EntryKind;
|
|
14
|
+
(function (EntryKind) {
|
|
15
|
+
EntryKind[EntryKind["Span"] = 0] = "Span";
|
|
16
|
+
EntryKind[EntryKind["Node"] = 1] = "Node";
|
|
17
|
+
EntryKind[EntryKind["StringLiteral"] = 2] = "StringLiteral";
|
|
18
|
+
EntryKind[EntryKind["SearchedLocalFoundProperty"] = 3] = "SearchedLocalFoundProperty";
|
|
19
|
+
EntryKind[EntryKind["SearchedPropertyFoundLocal"] = 4] = "SearchedPropertyFoundLocal";
|
|
20
|
+
})(EntryKind || (EntryKind = {}));
|
|
21
|
+
export function nodeEntry(node, kind = 1 /* EntryKind.Node */) {
|
|
22
|
+
return {
|
|
23
|
+
kind,
|
|
24
|
+
node: node.name || node,
|
|
25
|
+
context: getContextNodeForNodeEntry(node)
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
export function isContextWithStartAndEndNode(node) {
|
|
29
|
+
return node && node.kind === undefined;
|
|
30
|
+
}
|
|
31
|
+
function getContextNodeForNodeEntry(node) {
|
|
32
|
+
if (isDeclaration(node)) {
|
|
33
|
+
return getContextNode(node);
|
|
34
|
+
}
|
|
35
|
+
if (!node.parent)
|
|
36
|
+
return undefined;
|
|
37
|
+
if (!isDeclaration(node.parent) && !isExportAssignment(node.parent)) {
|
|
38
|
+
// Na tag, também a atribuição especial de um arquivo JavaScript (CK-03).
|
|
39
|
+
// Jsx Tags
|
|
40
|
+
if (isJsxOpeningElement(node.parent) || isJsxClosingElement(node.parent)) {
|
|
41
|
+
return node.parent.parent;
|
|
42
|
+
}
|
|
43
|
+
// Na tag, também o statement com label (CK-02).
|
|
44
|
+
else if (isJsxSelfClosingElement(node.parent) ||
|
|
45
|
+
isBreakOrContinueStatement(node.parent)) {
|
|
46
|
+
return node.parent;
|
|
47
|
+
}
|
|
48
|
+
else if (isStringLiteralLike(node)) {
|
|
49
|
+
const validImport = tryGetImportFromModuleSpecifier(node);
|
|
50
|
+
if (validImport) {
|
|
51
|
+
// Na tag, também a tag do JSDoc em que o import de tipo estava (CK-03).
|
|
52
|
+
const declOrStatement = findAncestor(validImport, node => isDeclaration(node) ||
|
|
53
|
+
isStatement(node));
|
|
54
|
+
return isDeclaration(declOrStatement) ?
|
|
55
|
+
getContextNode(declOrStatement) :
|
|
56
|
+
declOrStatement;
|
|
57
|
+
}
|
|
58
|
+
}
|
|
59
|
+
// Handle computed property name
|
|
60
|
+
const propertyName = findAncestor(node, isComputedPropertyName);
|
|
61
|
+
return propertyName ?
|
|
62
|
+
getContextNode(propertyName.parent) :
|
|
63
|
+
undefined;
|
|
64
|
+
}
|
|
65
|
+
// Na tag, também o construtor e o `default` de uma declaração exportada (CK-02).
|
|
66
|
+
if (node.parent.name === node || // node is name of declaration, use parent
|
|
67
|
+
isExportAssignment(node.parent) ||
|
|
68
|
+
// Property name of the import export specifier or binding pattern, use parent
|
|
69
|
+
((isImportOrExportSpecifier(node.parent) || isBindingElement(node.parent))
|
|
70
|
+
&& node.parent.propertyName === node)) {
|
|
71
|
+
return getContextNode(node.parent);
|
|
72
|
+
}
|
|
73
|
+
return undefined;
|
|
74
|
+
}
|
|
75
|
+
export function getContextNode(node) {
|
|
76
|
+
if (!node)
|
|
77
|
+
return undefined;
|
|
78
|
+
switch (node.kind) {
|
|
79
|
+
case SyntaxKind.VariableDeclaration:
|
|
80
|
+
return !isVariableDeclarationList(node.parent) || node.parent.declarations.length !== 1 ?
|
|
81
|
+
node :
|
|
82
|
+
isVariableStatement(node.parent.parent) ?
|
|
83
|
+
node.parent.parent :
|
|
84
|
+
isForInOrOfStatement(node.parent.parent) ?
|
|
85
|
+
getContextNode(node.parent.parent) :
|
|
86
|
+
node.parent;
|
|
87
|
+
case SyntaxKind.BindingElement:
|
|
88
|
+
return getContextNode(node.parent.parent);
|
|
89
|
+
case SyntaxKind.ImportSpecifier:
|
|
90
|
+
return node.parent.parent.parent;
|
|
91
|
+
case SyntaxKind.ExportSpecifier:
|
|
92
|
+
case SyntaxKind.NamespaceImport:
|
|
93
|
+
return node.parent.parent;
|
|
94
|
+
case SyntaxKind.ImportClause:
|
|
95
|
+
return node.parent;
|
|
96
|
+
case SyntaxKind.BinaryExpression:
|
|
97
|
+
return isExpressionStatement(node.parent) ?
|
|
98
|
+
node.parent :
|
|
99
|
+
node;
|
|
100
|
+
case SyntaxKind.ForOfStatement:
|
|
101
|
+
case SyntaxKind.ForInStatement:
|
|
102
|
+
return {
|
|
103
|
+
start: node.initializer,
|
|
104
|
+
end: node.expression
|
|
105
|
+
};
|
|
106
|
+
case SyntaxKind.PropertyAssignment:
|
|
107
|
+
case SyntaxKind.ShorthandPropertyAssignment:
|
|
108
|
+
return isArrayLiteralOrObjectLiteralDestructuringPattern(node.parent) ?
|
|
109
|
+
getContextNode(findAncestor(node.parent, node => isBinaryExpression(node) || isForInOrOfStatement(node))) :
|
|
110
|
+
node;
|
|
111
|
+
default:
|
|
112
|
+
return node;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
export function toContextSpan(textSpan, sourceFile, context) {
|
|
116
|
+
if (!context)
|
|
117
|
+
return undefined;
|
|
118
|
+
const contextSpan = isContextWithStartAndEndNode(context) ?
|
|
119
|
+
getTextSpan(context.start, sourceFile, context.end) :
|
|
120
|
+
getTextSpan(context, sourceFile);
|
|
121
|
+
return contextSpan.start !== textSpan.start || contextSpan.length !== textSpan.length ?
|
|
122
|
+
{ contextSpan } :
|
|
123
|
+
undefined;
|
|
124
|
+
}
|
|
125
|
+
export var FindReferencesUse;
|
|
126
|
+
(function (FindReferencesUse) {
|
|
127
|
+
/**
|
|
128
|
+
* When searching for references to a symbol, the location will not be adjusted (this is the default behavior when not specified).
|
|
129
|
+
*/
|
|
130
|
+
FindReferencesUse[FindReferencesUse["Other"] = 0] = "Other";
|
|
131
|
+
/**
|
|
132
|
+
* When searching for references to a symbol, the location will be adjusted if the cursor was on a keyword.
|
|
133
|
+
*/
|
|
134
|
+
FindReferencesUse[FindReferencesUse["References"] = 1] = "References";
|
|
135
|
+
/**
|
|
136
|
+
* When searching for references to a symbol, the location will be adjusted if the cursor was on a keyword.
|
|
137
|
+
* Unlike `References`, the location will only be adjusted keyword belonged to a declaration with a valid name.
|
|
138
|
+
* If set, we will find fewer references -- if it is referenced by several different names, we still only find references for the original name.
|
|
139
|
+
*/
|
|
140
|
+
FindReferencesUse[FindReferencesUse["Rename"] = 2] = "Rename";
|
|
141
|
+
})(FindReferencesUse || (FindReferencesUse = {}));
|
|
142
|
+
export function findReferencedSymbols(program, cancellationToken, sourceFiles, sourceFile, position) {
|
|
143
|
+
const node = getTouchingPropertyName(sourceFile, position);
|
|
144
|
+
const referencedSymbols = Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, { use: 1 /* FindReferencesUse.References */ });
|
|
145
|
+
const checker = program.getTypeChecker();
|
|
146
|
+
return !referencedSymbols || !referencedSymbols.length ? undefined : mapDefined(referencedSymbols, ({ definition, references }) =>
|
|
147
|
+
// Only include referenced symbols that have a valid definition.
|
|
148
|
+
definition && {
|
|
149
|
+
definition: checker.runWithCancellationToken(cancellationToken, checker => definitionToReferencedSymbolDefinitionInfo(definition, checker, node)),
|
|
150
|
+
references: references.map(toReferenceEntry)
|
|
151
|
+
});
|
|
152
|
+
}
|
|
153
|
+
export function getImplementationsAtPosition(program, cancellationToken, sourceFiles, sourceFile, position) {
|
|
154
|
+
const node = getTouchingPropertyName(sourceFile, position);
|
|
155
|
+
let referenceEntries;
|
|
156
|
+
const entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position);
|
|
157
|
+
// Na tag, também o `super` (CK-02).
|
|
158
|
+
if (node.parent.kind === SyntaxKind.PropertyAccessExpression
|
|
159
|
+
|| node.parent.kind === SyntaxKind.BindingElement
|
|
160
|
+
|| node.parent.kind === SyntaxKind.ElementAccessExpression) {
|
|
161
|
+
referenceEntries = entries && [...entries];
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
const queue = entries && [...entries];
|
|
165
|
+
const seenNodes = createMap();
|
|
166
|
+
while (queue && queue.length) {
|
|
167
|
+
const entry = queue.shift();
|
|
168
|
+
if (!addToSeen(seenNodes, getNodeId(entry.node))) {
|
|
169
|
+
continue;
|
|
170
|
+
}
|
|
171
|
+
referenceEntries = append(referenceEntries, entry);
|
|
172
|
+
const entries = getImplementationReferenceEntries(program, cancellationToken, sourceFiles, entry.node, entry.node.pos);
|
|
173
|
+
if (entries) {
|
|
174
|
+
queue.push(...entries);
|
|
175
|
+
}
|
|
176
|
+
}
|
|
177
|
+
}
|
|
178
|
+
const checker = program.getTypeChecker();
|
|
179
|
+
return map(referenceEntries, entry => toImplementationLocation(entry, checker));
|
|
180
|
+
}
|
|
181
|
+
function getImplementationReferenceEntries(program, cancellationToken, sourceFiles, node, position) {
|
|
182
|
+
if (node.kind === SyntaxKind.SourceFile) {
|
|
183
|
+
return undefined;
|
|
184
|
+
}
|
|
185
|
+
const checker = program.getTypeChecker();
|
|
186
|
+
// If invoked directly on a shorthand property assignment, then return
|
|
187
|
+
// the declaration of the symbol being assigned (not the symbol being assigned to).
|
|
188
|
+
if (node.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
|
189
|
+
const result = [];
|
|
190
|
+
Core.getReferenceEntriesForShorthandPropertyAssignment(node, checker, node => result.push(nodeEntry(node)));
|
|
191
|
+
return result;
|
|
192
|
+
}
|
|
193
|
+
// Na tag, o `super` e o acesso a partir dele davam a única implementação, a declaração do símbolo (CK-02).
|
|
194
|
+
else {
|
|
195
|
+
// Perform "Find all References" and retrieve only those that are implementations
|
|
196
|
+
return getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, { implementations: true, use: 1 /* FindReferencesUse.References */ });
|
|
197
|
+
}
|
|
198
|
+
}
|
|
199
|
+
export function findReferenceOrRenameEntries(program, cancellationToken, sourceFiles, node, position, options, convertEntry) {
|
|
200
|
+
return map(flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options)), entry => convertEntry(entry, node, program.getTypeChecker()));
|
|
201
|
+
}
|
|
202
|
+
export function getReferenceEntriesForNode(position, node, program, sourceFiles, cancellationToken, options = {}, sourceFilesSet = arrayToSet(sourceFiles, f => f.fileName)) {
|
|
203
|
+
return flattenEntries(Core.getReferencedSymbolsForNode(position, node, program, sourceFiles, cancellationToken, options, sourceFilesSet));
|
|
204
|
+
}
|
|
205
|
+
function flattenEntries(referenceSymbols) {
|
|
206
|
+
return referenceSymbols && flatMap(referenceSymbols, r => r.references);
|
|
207
|
+
}
|
|
208
|
+
function definitionToReferencedSymbolDefinitionInfo(def, checker, originalNode) {
|
|
209
|
+
const info = (() => {
|
|
210
|
+
switch (def.type) {
|
|
211
|
+
case 0 /* DefinitionKind.Symbol */: {
|
|
212
|
+
const { symbol } = def;
|
|
213
|
+
const { displayParts, kind } = getDefinitionKindAndDisplayParts(symbol, checker, originalNode);
|
|
214
|
+
const name = displayParts.map(p => p.text).join("");
|
|
215
|
+
const declaration = symbol.declarations ? first(symbol.declarations) : undefined;
|
|
216
|
+
return {
|
|
217
|
+
node: declaration ?
|
|
218
|
+
getNameOfDeclaration(declaration) || declaration :
|
|
219
|
+
originalNode,
|
|
220
|
+
name,
|
|
221
|
+
kind,
|
|
222
|
+
displayParts,
|
|
223
|
+
context: getContextNode(declaration)
|
|
224
|
+
};
|
|
225
|
+
}
|
|
226
|
+
// Na tag, também o label e o `this` (CK-02).
|
|
227
|
+
case 1 /* DefinitionKind.Keyword */: {
|
|
228
|
+
const { node } = def;
|
|
229
|
+
const name = tokenToString(node.kind);
|
|
230
|
+
return { node, name, kind: "keyword" /* ScriptElementKind.keyword */, displayParts: [{ text: name, kind: "keyword" /* ScriptElementKind.keyword */ }] };
|
|
231
|
+
}
|
|
232
|
+
case 2 /* DefinitionKind.String */: {
|
|
233
|
+
const { node } = def;
|
|
234
|
+
return { node, name: node.text, kind: "var" /* ScriptElementKind.variableElement */, displayParts: [displayPart(getTextOfNode(node), SymbolDisplayPartKind.stringLiteral)] };
|
|
235
|
+
}
|
|
236
|
+
default:
|
|
237
|
+
return Debug.assertNever(def);
|
|
238
|
+
}
|
|
239
|
+
})();
|
|
240
|
+
const { node, name, kind, displayParts, context } = info;
|
|
241
|
+
const sourceFile = node.getSourceFile();
|
|
242
|
+
const textSpan = getTextSpan(isComputedPropertyName(node) ? node.expression : node, sourceFile);
|
|
243
|
+
return {
|
|
244
|
+
containerKind: "" /* ScriptElementKind.unknown */,
|
|
245
|
+
containerName: "",
|
|
246
|
+
fileName: sourceFile.fileName,
|
|
247
|
+
kind,
|
|
248
|
+
name,
|
|
249
|
+
textSpan,
|
|
250
|
+
displayParts,
|
|
251
|
+
...toContextSpan(textSpan, sourceFile, context)
|
|
252
|
+
};
|
|
253
|
+
}
|
|
254
|
+
function getDefinitionKindAndDisplayParts(symbol, checker, node) {
|
|
255
|
+
const meaning = Core.getIntersectingMeaningFromDeclarations(node, symbol);
|
|
256
|
+
const enclosingDeclaration = symbol.declarations && firstOrUndefined(symbol.declarations) || node;
|
|
257
|
+
const { displayParts, symbolKind } = SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, enclosingDeclaration.getSourceFile(), enclosingDeclaration, enclosingDeclaration, meaning);
|
|
258
|
+
return { displayParts, kind: symbolKind };
|
|
259
|
+
}
|
|
260
|
+
export function toRenameLocation(entry, originalNode, checker, providePrefixAndSuffixText) {
|
|
261
|
+
return { ...entryToDocumentSpan(entry), ...(providePrefixAndSuffixText && getPrefixAndSuffixText(entry, originalNode, checker)) };
|
|
262
|
+
}
|
|
263
|
+
export function toReferenceEntry(entry) {
|
|
264
|
+
const documentSpan = entryToDocumentSpan(entry);
|
|
265
|
+
if (entry.kind === 0 /* EntryKind.Span */) {
|
|
266
|
+
return { ...documentSpan, isWriteAccess: false, isDefinition: false };
|
|
267
|
+
}
|
|
268
|
+
const { kind, node } = entry;
|
|
269
|
+
return {
|
|
270
|
+
...documentSpan,
|
|
271
|
+
isWriteAccess: isWriteAccessForReference(node),
|
|
272
|
+
isDefinition: isDefinitionForReference(node),
|
|
273
|
+
isInString: kind === 2 /* EntryKind.StringLiteral */ ? true : undefined,
|
|
274
|
+
};
|
|
275
|
+
}
|
|
276
|
+
function entryToDocumentSpan(entry) {
|
|
277
|
+
if (entry.kind === 0 /* EntryKind.Span */) {
|
|
278
|
+
return { textSpan: entry.textSpan, fileName: entry.fileName };
|
|
279
|
+
}
|
|
280
|
+
else {
|
|
281
|
+
const sourceFile = entry.node.getSourceFile();
|
|
282
|
+
const textSpan = getTextSpan(entry.node, sourceFile);
|
|
283
|
+
return {
|
|
284
|
+
textSpan,
|
|
285
|
+
fileName: sourceFile.fileName,
|
|
286
|
+
...toContextSpan(textSpan, sourceFile, entry.context)
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
}
|
|
290
|
+
function getPrefixAndSuffixText(entry, originalNode, checker) {
|
|
291
|
+
if (entry.kind !== 0 /* EntryKind.Span */ && isIdentifier(originalNode)) {
|
|
292
|
+
const { node, kind } = entry;
|
|
293
|
+
const name = originalNode.text;
|
|
294
|
+
const isShorthandAssignment = isShorthandPropertyAssignment(node.parent);
|
|
295
|
+
if (isShorthandAssignment || isObjectBindingElementWithoutPropertyName(node.parent) && node.parent.name === node) {
|
|
296
|
+
const prefixColon = { prefixText: name + ": " };
|
|
297
|
+
const suffixColon = { suffixText: ": " + name };
|
|
298
|
+
return kind === 3 /* EntryKind.SearchedLocalFoundProperty */ ? prefixColon
|
|
299
|
+
: kind === 4 /* EntryKind.SearchedPropertyFoundLocal */ ? suffixColon
|
|
300
|
+
// In `const o = { x }; o.x`, symbolAtLocation at `x` in `{ x }` is the property symbol.
|
|
301
|
+
// For a binding element `const { x } = o;`, symbolAtLocation at `x` is the property symbol.
|
|
302
|
+
: isShorthandAssignment ? suffixColon : prefixColon;
|
|
303
|
+
}
|
|
304
|
+
else if (isImportSpecifier(entry.node.parent) && !entry.node.parent.propertyName) {
|
|
305
|
+
// If the original symbol was using this alias, just rename the alias.
|
|
306
|
+
const originalSymbol = isExportSpecifier(originalNode.parent) ? checker.getExportSpecifierLocalTargetSymbol(originalNode.parent) : checker.getSymbolAtLocation(originalNode);
|
|
307
|
+
return contains(originalSymbol.declarations, entry.node.parent) ? { prefixText: name + " as " } : emptyOptions;
|
|
308
|
+
}
|
|
309
|
+
else if (isExportSpecifier(entry.node.parent) && !entry.node.parent.propertyName) {
|
|
310
|
+
// If the symbol for the node is same as declared node symbol use prefix text
|
|
311
|
+
return originalNode === entry.node || checker.getSymbolAtLocation(originalNode) === checker.getSymbolAtLocation(entry.node) ?
|
|
312
|
+
{ prefixText: name + " as " } :
|
|
313
|
+
{ suffixText: " as " + name };
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
return emptyOptions;
|
|
317
|
+
}
|
|
318
|
+
function toImplementationLocation(entry, checker) {
|
|
319
|
+
const documentSpan = entryToDocumentSpan(entry);
|
|
320
|
+
if (entry.kind !== 0 /* EntryKind.Span */) {
|
|
321
|
+
const { node } = entry;
|
|
322
|
+
return {
|
|
323
|
+
...documentSpan,
|
|
324
|
+
...implementationKindDisplayParts(node, checker)
|
|
325
|
+
};
|
|
326
|
+
}
|
|
327
|
+
else {
|
|
328
|
+
return { ...documentSpan, kind: "" /* ScriptElementKind.unknown */, displayParts: [] };
|
|
329
|
+
}
|
|
330
|
+
}
|
|
331
|
+
function implementationKindDisplayParts(node, checker) {
|
|
332
|
+
const symbol = checker.getSymbolAtLocation(isDeclaration(node) && node.name ? node.name : node);
|
|
333
|
+
if (symbol) {
|
|
334
|
+
return getDefinitionKindAndDisplayParts(symbol, checker, node);
|
|
335
|
+
}
|
|
336
|
+
else if (node.kind === SyntaxKind.ObjectLiteralExpression) {
|
|
337
|
+
return {
|
|
338
|
+
kind: "interface" /* ScriptElementKind.interfaceElement */,
|
|
339
|
+
displayParts: [punctuationPart(SyntaxKind.OpenParenToken), textPart("object literal"), punctuationPart(SyntaxKind.CloseParenToken)]
|
|
340
|
+
};
|
|
341
|
+
}
|
|
342
|
+
// Na tag, também a class expression anônima (CK-02).
|
|
343
|
+
else {
|
|
344
|
+
return { kind: getNodeKind(node), displayParts: [] };
|
|
345
|
+
}
|
|
346
|
+
}
|
|
347
|
+
export function toHighlightSpan(entry) {
|
|
348
|
+
const documentSpan = entryToDocumentSpan(entry);
|
|
349
|
+
if (entry.kind === 0 /* EntryKind.Span */) {
|
|
350
|
+
return {
|
|
351
|
+
fileName: documentSpan.fileName,
|
|
352
|
+
span: {
|
|
353
|
+
textSpan: documentSpan.textSpan,
|
|
354
|
+
kind: "reference" /* HighlightSpanKind.reference */
|
|
355
|
+
}
|
|
356
|
+
};
|
|
357
|
+
}
|
|
358
|
+
const writeAccess = isWriteAccessForReference(entry.node);
|
|
359
|
+
const span = {
|
|
360
|
+
textSpan: documentSpan.textSpan,
|
|
361
|
+
kind: writeAccess ? "writtenReference" /* HighlightSpanKind.writtenReference */ : "reference" /* HighlightSpanKind.reference */,
|
|
362
|
+
isInString: entry.kind === 2 /* EntryKind.StringLiteral */ ? true : undefined,
|
|
363
|
+
...documentSpan.contextSpan && { contextSpan: documentSpan.contextSpan }
|
|
364
|
+
};
|
|
365
|
+
return { fileName: documentSpan.fileName, span };
|
|
366
|
+
}
|
|
367
|
+
function getTextSpan(node, sourceFile, endNode) {
|
|
368
|
+
let start = node.getStart(sourceFile);
|
|
369
|
+
let end = (endNode || node).getEnd();
|
|
370
|
+
if (isStringLiteralLike(node)) {
|
|
371
|
+
Debug.assert(endNode === undefined);
|
|
372
|
+
start += 1;
|
|
373
|
+
end -= 1;
|
|
374
|
+
}
|
|
375
|
+
return createTextSpanFromBounds(start, end);
|
|
376
|
+
}
|
|
377
|
+
export function getTextSpanOfEntry(entry) {
|
|
378
|
+
return entry.kind === 0 /* EntryKind.Span */ ? entry.textSpan :
|
|
379
|
+
getTextSpan(entry.node, entry.node.getSourceFile());
|
|
380
|
+
}
|
|
381
|
+
/** A node is considered a writeAccess iff it is a name of a declaration or a target of an assignment */
|
|
382
|
+
function isWriteAccessForReference(node) {
|
|
383
|
+
const decl = getDeclarationFromName(node);
|
|
384
|
+
return !!decl && declarationIsWriteAccess(decl) || node.kind === SyntaxKind.DefaultKeyword || isWriteAccess(node);
|
|
385
|
+
}
|
|
386
|
+
/** Na tag, também o `constructor` da declaração do construtor (CK-02). */
|
|
387
|
+
function isDefinitionForReference(node) {
|
|
388
|
+
return node.kind === SyntaxKind.DefaultKeyword
|
|
389
|
+
|| !!getDeclarationFromName(node)
|
|
390
|
+
|| isLiteralComputedPropertyDeclarationName(node);
|
|
391
|
+
}
|
|
392
|
+
/**
|
|
393
|
+
* True if 'decl' provides a value, as in `const f = () => {}`;
|
|
394
|
+
* false if 'decl' is just a location for a future write, as in 'let x;'
|
|
395
|
+
* Na tag, também a classe, o enum e o membro dele, a interface e a `function`, o construtor, o método, o acessor, a
|
|
396
|
+
* propriedade de classe e a method signature (CK-02, CK-36), o `import =` e o `export as namespace`, e as tags do JSDoc
|
|
397
|
+
* (CK-03).
|
|
398
|
+
*/
|
|
399
|
+
function declarationIsWriteAccess(decl) {
|
|
400
|
+
// Consider anything in an ambient declaration to be a write access since it may be coming from JS.
|
|
401
|
+
if (!!(decl.flags & NodeFlags.Ambient))
|
|
402
|
+
return true;
|
|
403
|
+
switch (decl.kind) {
|
|
404
|
+
case SyntaxKind.BinaryExpression:
|
|
405
|
+
case SyntaxKind.BindingElement:
|
|
406
|
+
case SyntaxKind.DefaultKeyword:
|
|
407
|
+
case SyntaxKind.ExportSpecifier:
|
|
408
|
+
case SyntaxKind.ImportClause: // default import
|
|
409
|
+
case SyntaxKind.ImportSpecifier:
|
|
410
|
+
case SyntaxKind.JsxAttribute:
|
|
411
|
+
case SyntaxKind.ModuleDeclaration:
|
|
412
|
+
case SyntaxKind.NamespaceImport:
|
|
413
|
+
case SyntaxKind.NamespaceExport:
|
|
414
|
+
case SyntaxKind.Parameter:
|
|
415
|
+
case SyntaxKind.ShorthandPropertyAssignment:
|
|
416
|
+
case SyntaxKind.TypeAliasDeclaration:
|
|
417
|
+
case SyntaxKind.TypeParameter:
|
|
418
|
+
return true;
|
|
419
|
+
case SyntaxKind.PropertyAssignment:
|
|
420
|
+
// In `({ x: y } = 0);`, `x` is not a write access. (Won't call this function for `y`.)
|
|
421
|
+
return !isArrayLiteralOrObjectLiteralDestructuringPattern(decl.parent);
|
|
422
|
+
case SyntaxKind.VariableDeclaration:
|
|
423
|
+
return !!decl.initializer || isCatchClause(decl.parent);
|
|
424
|
+
case SyntaxKind.PropertySignature:
|
|
425
|
+
return false;
|
|
426
|
+
default:
|
|
427
|
+
return Debug.failBadSyntaxKind(decl);
|
|
428
|
+
}
|
|
429
|
+
}
|
|
430
|
+
/** Encapsulates the core find-all-references algorithm. */
|
|
431
|
+
export var Core;
|
|
432
|
+
(function (Core) {
|
|
433
|
+
/** Core find-all-references algorithm. Handles special cases before delegating to `getReferencedSymbolsForSymbol`. */
|
|
434
|
+
function getReferencedSymbolsForNode(_position, node, program, sourceFiles, cancellationToken, options = {}, sourceFilesSet = arrayToSet(sourceFiles, f => f.fileName)) {
|
|
435
|
+
if (options.use === 1 /* FindReferencesUse.References */) {
|
|
436
|
+
node = getAdjustedReferenceLocation(node);
|
|
437
|
+
}
|
|
438
|
+
else if (options.use === 2 /* FindReferencesUse.Rename */) {
|
|
439
|
+
node = getAdjustedRenameLocation(node);
|
|
440
|
+
}
|
|
441
|
+
// Na tag, no arquivo, a referência `/// <reference …>` na posição dava as referências ao arquivo referido (o
|
|
442
|
+
// `GoToDefinition.getReferenceAtPosition`); a referência por texto saiu (CK-03).
|
|
443
|
+
if (isSourceFile(node)) {
|
|
444
|
+
return undefined;
|
|
445
|
+
}
|
|
446
|
+
if (!options.implementations) {
|
|
447
|
+
const special = getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken);
|
|
448
|
+
if (special) {
|
|
449
|
+
return special;
|
|
450
|
+
}
|
|
451
|
+
}
|
|
452
|
+
const checker = program.getTypeChecker();
|
|
453
|
+
const symbol = checker.getSymbolAtLocation(node);
|
|
454
|
+
// Could not find a symbol e.g. unknown identifier
|
|
455
|
+
if (!symbol) {
|
|
456
|
+
// String literal might be a property (and thus have a symbol), so do this here rather than in getReferencedSymbolsSpecial.
|
|
457
|
+
return !options.implementations && isStringLiteral(node) ? getReferencesForStringLiteral(node, sourceFiles, cancellationToken) : undefined;
|
|
458
|
+
}
|
|
459
|
+
// Na tag, o símbolo `export=` dava as referências ao módulo (CK-03).
|
|
460
|
+
const moduleReferences = getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, sourceFilesSet);
|
|
461
|
+
if (moduleReferences && !(symbol.flags & SymbolFlags.Transient)) {
|
|
462
|
+
return moduleReferences;
|
|
463
|
+
}
|
|
464
|
+
// Na tag, também as referências ao módulo do `export as namespace` de um UMD (CK-03).
|
|
465
|
+
const references = getReferencedSymbolsForSymbol(symbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options);
|
|
466
|
+
return mergeReferences(program, moduleReferences, references);
|
|
467
|
+
}
|
|
468
|
+
Core.getReferencedSymbolsForNode = getReferencedSymbolsForNode;
|
|
469
|
+
/** Na tag, também as referências ao valor do `export =` do módulo (CK-03). */
|
|
470
|
+
function getReferencedSymbolsForModuleIfDeclaredBySourceFile(symbol, program, sourceFiles, sourceFilesSet) {
|
|
471
|
+
const moduleSourceFile = (symbol.flags & SymbolFlags.Module) && symbol.declarations && find(symbol.declarations, isSourceFile);
|
|
472
|
+
if (!moduleSourceFile)
|
|
473
|
+
return undefined;
|
|
474
|
+
return getReferencedSymbolsForModule(program, symbol, sourceFiles, sourceFilesSet);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* Merges the references by sorting them (by file index in sourceFiles and their location in it) that point to same definition symbol
|
|
478
|
+
*/
|
|
479
|
+
function mergeReferences(program, ...referencesToMerge) {
|
|
480
|
+
let result;
|
|
481
|
+
for (const references of referencesToMerge) {
|
|
482
|
+
if (!references || !references.length)
|
|
483
|
+
continue;
|
|
484
|
+
if (!result) {
|
|
485
|
+
result = references;
|
|
486
|
+
continue;
|
|
487
|
+
}
|
|
488
|
+
for (const entry of references) {
|
|
489
|
+
if (!entry.definition || entry.definition.type !== 0 /* DefinitionKind.Symbol */) {
|
|
490
|
+
result.push(entry);
|
|
491
|
+
continue;
|
|
492
|
+
}
|
|
493
|
+
const symbol = entry.definition.symbol;
|
|
494
|
+
const refIndex = findIndex(result, ref => !!ref.definition &&
|
|
495
|
+
ref.definition.type === 0 /* DefinitionKind.Symbol */ &&
|
|
496
|
+
ref.definition.symbol === symbol);
|
|
497
|
+
if (refIndex === -1) {
|
|
498
|
+
result.push(entry);
|
|
499
|
+
continue;
|
|
500
|
+
}
|
|
501
|
+
const reference = result[refIndex];
|
|
502
|
+
result[refIndex] = {
|
|
503
|
+
definition: reference.definition,
|
|
504
|
+
references: reference.references.concat(entry.references).sort((entry1, entry2) => {
|
|
505
|
+
const entry1File = getSourceFileIndexOfEntry(program, entry1);
|
|
506
|
+
const entry2File = getSourceFileIndexOfEntry(program, entry2);
|
|
507
|
+
if (entry1File !== entry2File) {
|
|
508
|
+
return compareValues(entry1File, entry2File);
|
|
509
|
+
}
|
|
510
|
+
const entry1Span = getTextSpanOfEntry(entry1);
|
|
511
|
+
const entry2Span = getTextSpanOfEntry(entry2);
|
|
512
|
+
return entry1Span.start !== entry2Span.start ?
|
|
513
|
+
compareValues(entry1Span.start, entry2Span.start) :
|
|
514
|
+
compareValues(entry1Span.length, entry2Span.length);
|
|
515
|
+
})
|
|
516
|
+
};
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
return result;
|
|
520
|
+
}
|
|
521
|
+
function getSourceFileIndexOfEntry(program, entry) {
|
|
522
|
+
const sourceFile = entry.kind === 0 /* EntryKind.Span */ ?
|
|
523
|
+
program.getSourceFile(entry.fileName) :
|
|
524
|
+
entry.node.getSourceFile();
|
|
525
|
+
return program.getSourceFiles().indexOf(sourceFile);
|
|
526
|
+
}
|
|
527
|
+
/**
|
|
528
|
+
* As referências a um módulo: os imports dele e as declarações. Na tag, também a referência `/// <reference …>` ao
|
|
529
|
+
* arquivo, o valor do `export =` e o `module.exports` (CK-03).
|
|
530
|
+
*/
|
|
531
|
+
function getReferencedSymbolsForModule(program, symbol, sourceFiles, _sourceFilesSet) {
|
|
532
|
+
Debug.assert(!!symbol.valueDeclaration);
|
|
533
|
+
const references = mapDefined(findModuleReferences(program, sourceFiles, symbol), reference => nodeEntry(reference.literal));
|
|
534
|
+
if (symbol.declarations) {
|
|
535
|
+
for (const decl of symbol.declarations) {
|
|
536
|
+
switch (decl.kind) {
|
|
537
|
+
case SyntaxKind.SourceFile:
|
|
538
|
+
// Don't include the source file itself. (This may not be ideal behavior, but awkward to include an entire file as a reference.)
|
|
539
|
+
break;
|
|
540
|
+
// Na tag, também o `declare module "x"` que aumentava o módulo (CK-02).
|
|
541
|
+
default:
|
|
542
|
+
// This may be merged with something.
|
|
543
|
+
Debug.assert(!!(symbol.flags & SymbolFlags.Transient), "Expected a module symbol to be declared by a SourceFile or ModuleDeclaration.");
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
}
|
|
547
|
+
return references.length ? [{ definition: { type: 0 /* DefinitionKind.Symbol */, symbol }, references }] : emptyArray;
|
|
548
|
+
}
|
|
549
|
+
/** As in a `readonly prop: any` or `constructor(readonly prop: any)`, not a `readonly any[]`. */
|
|
550
|
+
function isReadonlyTypeOperator(node) {
|
|
551
|
+
return node.kind === SyntaxKind.ReadonlyKeyword
|
|
552
|
+
&& isTypeOperatorNode(node.parent)
|
|
553
|
+
&& node.parent.operator === SyntaxKind.ReadonlyKeyword;
|
|
554
|
+
}
|
|
555
|
+
/**
|
|
556
|
+
* getReferencedSymbols for special node kinds. Na tag, também o label (CK-02), o `this` e o `super` (CK-02), e o
|
|
557
|
+
* `void` de uma expressão não era o tipo `void` (CK-63).
|
|
558
|
+
*/
|
|
559
|
+
function getReferencedSymbolsSpecial(node, sourceFiles, cancellationToken) {
|
|
560
|
+
if (isTypeKeyword(node.kind)) {
|
|
561
|
+
// A modifier readonly (like on a property declaration) is not special;
|
|
562
|
+
// a readonly type keyword (like `readonly string[]`) is.
|
|
563
|
+
if (node.kind === SyntaxKind.ReadonlyKeyword && !isReadonlyTypeOperator(node)) {
|
|
564
|
+
return undefined;
|
|
565
|
+
}
|
|
566
|
+
// Likewise, when we *are* looking for a special keyword, make sure we
|
|
567
|
+
// *don’t* include readonly member modifiers.
|
|
568
|
+
return getAllReferencesForKeyword(sourceFiles, node.kind, cancellationToken, node.kind === SyntaxKind.ReadonlyKeyword ? isReadonlyTypeOperator : undefined);
|
|
569
|
+
}
|
|
570
|
+
return undefined;
|
|
571
|
+
}
|
|
572
|
+
/** Core find-all-references algorithm for a normal symbol. */
|
|
573
|
+
function getReferencedSymbolsForSymbol(originalSymbol, node, sourceFiles, sourceFilesSet, checker, cancellationToken, options) {
|
|
574
|
+
const symbol = node && skipPastExportOrImportSpecifierOrUnion(originalSymbol, node, checker, /*useLocalSymbolForExportSpecifier*/ !isForRenameWithPrefixAndSuffixText(options)) || originalSymbol;
|
|
575
|
+
// Compute the meaning from the location and the symbol it references
|
|
576
|
+
const searchMeaning = node ? getIntersectingMeaningFromDeclarations(node, symbol) : 7 /* SemanticMeaning.All */;
|
|
577
|
+
const result = [];
|
|
578
|
+
// Na tag, o nome de uma classe e o `constructor` davam uma busca especial (o `SpecialSearchKind`, CK-02).
|
|
579
|
+
const state = new State(sourceFiles, sourceFilesSet, checker, cancellationToken, searchMeaning, options, result);
|
|
580
|
+
const exportSpecifier = !isForRenameWithPrefixAndSuffixText(options) ? undefined : find(symbol.declarations, isExportSpecifier);
|
|
581
|
+
if (exportSpecifier) {
|
|
582
|
+
// When renaming at an export specifier, rename the export and not the thing being exported.
|
|
583
|
+
getReferencesAtExportSpecifier(exportSpecifier.name, symbol, exportSpecifier, state.createSearch(node, originalSymbol, /*comingFrom*/ undefined), state, /*addReferencesHere*/ true, /*alwaysGetReferences*/ true);
|
|
584
|
+
}
|
|
585
|
+
else if (node && node.kind === SyntaxKind.DefaultKeyword) {
|
|
586
|
+
addReference(node, symbol, state);
|
|
587
|
+
searchForImportsOfExport(node, symbol, { exportingModuleSymbol: Debug.checkDefined(symbol.parent, "Expected export symbol to have a parent"), exportKind: 1 /* ExportKind.Default */ }, state);
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
const search = state.createSearch(node, symbol, /*comingFrom*/ undefined, { allSearchSymbols: node ? populateSearchSymbolSet(symbol, node, checker, options.use === 2 /* FindReferencesUse.Rename */, !!options.providePrefixAndSuffixTextForRename) : [symbol] });
|
|
591
|
+
getReferencesInContainerOrFiles(symbol, state, search);
|
|
592
|
+
}
|
|
593
|
+
return result;
|
|
594
|
+
}
|
|
595
|
+
function getReferencesInContainerOrFiles(symbol, state, search) {
|
|
596
|
+
// Try to get the smallest valid scope that we can limit our search to;
|
|
597
|
+
// otherwise we'll need to search globally (i.e. include each file).
|
|
598
|
+
const scope = getSymbolScope(symbol);
|
|
599
|
+
if (scope) {
|
|
600
|
+
getReferencesInContainer(scope, scope.getSourceFile(), search, state, /*addReferencesHere*/ !(isSourceFile(scope) && !contains(state.sourceFiles, scope)));
|
|
601
|
+
}
|
|
602
|
+
else {
|
|
603
|
+
// Global search
|
|
604
|
+
for (const sourceFile of state.sourceFiles) {
|
|
605
|
+
state.cancellationToken.throwIfCancellationRequested();
|
|
606
|
+
searchForName(sourceFile, search, state);
|
|
607
|
+
}
|
|
608
|
+
}
|
|
609
|
+
}
|
|
610
|
+
/** Handle a few special cases relating to export/import specifiers. */
|
|
611
|
+
function skipPastExportOrImportSpecifierOrUnion(symbol, node, checker, useLocalSymbolForExportSpecifier) {
|
|
612
|
+
const { parent } = node;
|
|
613
|
+
if (isExportSpecifier(parent) && useLocalSymbolForExportSpecifier) {
|
|
614
|
+
return getLocalSymbolForExportSpecifier(node, symbol, parent, checker);
|
|
615
|
+
}
|
|
616
|
+
// If the symbol is declared as part of a declaration like `{ type: "a" } | { type: "b" }`, use the property on the union type to get more references.
|
|
617
|
+
return firstDefined(symbol.declarations, decl => {
|
|
618
|
+
if (!decl.parent) {
|
|
619
|
+
// Ignore UMD module and global merge
|
|
620
|
+
if (symbol.flags & SymbolFlags.Transient)
|
|
621
|
+
return undefined;
|
|
622
|
+
// Assertions for GH#21814. We should be handling SourceFile symbols in `getReferencedSymbolsForModule` instead of getting here.
|
|
623
|
+
Debug.fail(`Unexpected symbol at ${Debug.formatSyntaxKind(node.kind)}: ${Debug.formatSymbol(symbol)}`);
|
|
624
|
+
}
|
|
625
|
+
return isTypeLiteralNode(decl.parent) && isUnionTypeNode(decl.parent.parent)
|
|
626
|
+
? checker.getPropertyOfType(checker.getTypeFromTypeNode(decl.parent.parent), symbol.name)
|
|
627
|
+
: undefined;
|
|
628
|
+
});
|
|
629
|
+
}
|
|
630
|
+
function getNonModuleSymbolOfMergedModuleSymbol(symbol) {
|
|
631
|
+
if (!(symbol.flags & (SymbolFlags.Module | SymbolFlags.Transient)))
|
|
632
|
+
return undefined;
|
|
633
|
+
const decl = symbol.declarations && find(symbol.declarations, d => !isSourceFile(d) && !isModuleDeclaration(d));
|
|
634
|
+
return decl && decl.symbol;
|
|
635
|
+
}
|
|
636
|
+
/**
|
|
637
|
+
* Holds all state needed for the finding references.
|
|
638
|
+
* Unlike `Search`, there is only one `State`.
|
|
639
|
+
*/
|
|
640
|
+
class State {
|
|
641
|
+
constructor(sourceFiles, sourceFilesSet, checker, cancellationToken, searchMeaning, options, result) {
|
|
642
|
+
this.sourceFiles = sourceFiles;
|
|
643
|
+
this.sourceFilesSet = sourceFilesSet;
|
|
644
|
+
this.checker = checker;
|
|
645
|
+
this.cancellationToken = cancellationToken;
|
|
646
|
+
this.searchMeaning = searchMeaning;
|
|
647
|
+
this.options = options;
|
|
648
|
+
this.result = result;
|
|
649
|
+
/**
|
|
650
|
+
* Type nodes can contain multiple references to the same type. For example:
|
|
651
|
+
* let x: Foo & (Foo & Bar) = ...
|
|
652
|
+
* Because we are returning the implementation locations and not the identifier locations,
|
|
653
|
+
* duplicate entries would be returned here as each of the type references is part of
|
|
654
|
+
* the same implementation. For that reason, check before we add a new entry.
|
|
655
|
+
*/
|
|
656
|
+
this.markSeenContainingTypeReference = nodeSeenTracker();
|
|
657
|
+
/**
|
|
658
|
+
* It's possible that we will encounter the right side of `export { foo as bar } from "x";` more than once.
|
|
659
|
+
* For example:
|
|
660
|
+
* // b.ts
|
|
661
|
+
* export { foo as bar } from "./a";
|
|
662
|
+
* import { bar } from "./b";
|
|
663
|
+
*
|
|
664
|
+
* Normally at `foo as bar` we directly add `foo` and do not locally search for it (since it doesn't declare a local).
|
|
665
|
+
* But another reference to it may appear in the same source file.
|
|
666
|
+
* See `tests/cases/fourslash/transitiveExportImports3.ts`.
|
|
667
|
+
*/
|
|
668
|
+
this.markSeenReExportRHS = nodeSeenTracker();
|
|
669
|
+
this.symbolIdToReferences = [];
|
|
670
|
+
// Source file ID → symbol ID → Whether the symbol has been searched for in the source file.
|
|
671
|
+
this.sourceFileToSeenSymbols = [];
|
|
672
|
+
}
|
|
673
|
+
includesSourceFile(sourceFile) {
|
|
674
|
+
return this.sourceFilesSet.has(sourceFile.fileName);
|
|
675
|
+
}
|
|
676
|
+
/** Gets every place to look for references of an exported symbols. See `ImportsResult` in `importTracker.ts` for more documentation. */
|
|
677
|
+
getImportSearches(exportSymbol, exportInfo) {
|
|
678
|
+
if (!this.importTracker)
|
|
679
|
+
this.importTracker = createImportTracker(this.sourceFiles, this.sourceFilesSet, this.checker, this.cancellationToken);
|
|
680
|
+
return this.importTracker(exportSymbol, exportInfo, this.options.use === 2 /* FindReferencesUse.Rename */);
|
|
681
|
+
}
|
|
682
|
+
/** @param allSearchSymbols set of additional symbols for use by `includes`. */
|
|
683
|
+
createSearch(_location, symbol, comingFrom, searchOptions = {}) {
|
|
684
|
+
// Note: if this is an external module symbol, the name doesn't include quotes.
|
|
685
|
+
// Na tag, o `export default class C {}` dava o nome local `C` (o `getLocalSymbolForExportDefault`); o modificador
|
|
686
|
+
// `default` de uma declaração saiu com a classe e a `function` (CK-02).
|
|
687
|
+
const { text = stripQuotes(symbolName(getNonModuleSymbolOfMergedModuleSymbol(symbol) || symbol)), allSearchSymbols = [symbol], } = searchOptions;
|
|
688
|
+
const escapedText = escapeLeadingUnderscores(text);
|
|
689
|
+
return { symbol, comingFrom, text, escapedText, allSearchSymbols, includes: sym => contains(allSearchSymbols, sym) };
|
|
690
|
+
}
|
|
691
|
+
/**
|
|
692
|
+
* Callback to add references for a particular searched symbol.
|
|
693
|
+
* This initializes a reference group, so only call this if you will add at least one reference.
|
|
694
|
+
*/
|
|
695
|
+
referenceAdder(searchSymbol) {
|
|
696
|
+
const symbolId = getSymbolId(searchSymbol);
|
|
697
|
+
let references = this.symbolIdToReferences[symbolId];
|
|
698
|
+
if (!references) {
|
|
699
|
+
references = this.symbolIdToReferences[symbolId] = [];
|
|
700
|
+
this.result.push({ definition: { type: 0 /* DefinitionKind.Symbol */, symbol: searchSymbol }, references });
|
|
701
|
+
}
|
|
702
|
+
return (node, kind) => references.push(nodeEntry(node, kind));
|
|
703
|
+
}
|
|
704
|
+
/** Add a reference with no associated definition. */
|
|
705
|
+
addStringOrCommentReference(fileName, textSpan) {
|
|
706
|
+
this.result.push({
|
|
707
|
+
definition: undefined,
|
|
708
|
+
references: [{ kind: 0 /* EntryKind.Span */, fileName, textSpan }]
|
|
709
|
+
});
|
|
710
|
+
}
|
|
711
|
+
/** Returns `true` the first time we search for a symbol in a file and `false` afterwards. */
|
|
712
|
+
markSearchedSymbols(sourceFile, symbols) {
|
|
713
|
+
const sourceId = getNodeId(sourceFile);
|
|
714
|
+
const seenSymbols = this.sourceFileToSeenSymbols[sourceId] || (this.sourceFileToSeenSymbols[sourceId] = createMap());
|
|
715
|
+
let anyNewSymbols = false;
|
|
716
|
+
for (const sym of symbols) {
|
|
717
|
+
anyNewSymbols = addToSeen(seenSymbols, getSymbolId(sym)) || anyNewSymbols;
|
|
718
|
+
}
|
|
719
|
+
return anyNewSymbols;
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
/** Search for all imports of a given exported symbol using `State.getImportSearches`. */
|
|
723
|
+
function searchForImportsOfExport(exportLocation, exportSymbol, exportInfo, state) {
|
|
724
|
+
const { importSearches, singleReferences, indirectUsers } = state.getImportSearches(exportSymbol, exportInfo);
|
|
725
|
+
// For `import { foo as bar }` just add the reference to `foo`, and don't otherwise search in the file.
|
|
726
|
+
if (singleReferences.length) {
|
|
727
|
+
const addRef = state.referenceAdder(exportSymbol);
|
|
728
|
+
for (const singleRef of singleReferences) {
|
|
729
|
+
if (shouldAddSingleReference(singleRef, state))
|
|
730
|
+
addRef(singleRef);
|
|
731
|
+
}
|
|
732
|
+
}
|
|
733
|
+
// For each import, find all references to that import in its source file.
|
|
734
|
+
for (const [importLocation, importSymbol] of importSearches) {
|
|
735
|
+
getReferencesInSourceFile(importLocation.getSourceFile(), state.createSearch(importLocation, importSymbol, 1 /* ImportExport.Export */), state);
|
|
736
|
+
}
|
|
737
|
+
if (indirectUsers.length) {
|
|
738
|
+
let indirectSearch;
|
|
739
|
+
switch (exportInfo.exportKind) {
|
|
740
|
+
case 0 /* ExportKind.Named */:
|
|
741
|
+
indirectSearch = state.createSearch(exportLocation, exportSymbol, 1 /* ImportExport.Export */);
|
|
742
|
+
break;
|
|
743
|
+
case 1 /* ExportKind.Default */:
|
|
744
|
+
// Search for a property access to '.default'. This can't be renamed.
|
|
745
|
+
indirectSearch = state.options.use === 2 /* FindReferencesUse.Rename */ ? undefined : state.createSearch(exportLocation, exportSymbol, 1 /* ImportExport.Export */, { text: "default" });
|
|
746
|
+
break;
|
|
747
|
+
// Na tag, também o `export =`, sem busca indireta (CK-03).
|
|
748
|
+
}
|
|
749
|
+
if (indirectSearch) {
|
|
750
|
+
for (const indirectUser of indirectUsers) {
|
|
751
|
+
searchForName(indirectUser, indirectSearch, state);
|
|
752
|
+
}
|
|
753
|
+
}
|
|
754
|
+
}
|
|
755
|
+
}
|
|
756
|
+
function eachExportReference(sourceFiles, checker, cancellationToken, exportSymbol, exportingModuleSymbol, exportName, isDefaultExport, cb) {
|
|
757
|
+
const importTracker = createImportTracker(sourceFiles, arrayToSet(sourceFiles, f => f.fileName), checker, cancellationToken);
|
|
758
|
+
const { importSearches, indirectUsers } = importTracker(exportSymbol, { exportKind: isDefaultExport ? 1 /* ExportKind.Default */ : 0 /* ExportKind.Named */, exportingModuleSymbol }, /*isForRename*/ false);
|
|
759
|
+
for (const [importLocation] of importSearches) {
|
|
760
|
+
cb(importLocation);
|
|
761
|
+
}
|
|
762
|
+
for (const indirectUser of indirectUsers) {
|
|
763
|
+
for (const node of getPossibleSymbolReferenceNodes(indirectUser, isDefaultExport ? "default" : exportName)) {
|
|
764
|
+
// Import specifiers should be handled by importSearches
|
|
765
|
+
if (isIdentifier(node) && !isImportOrExportSpecifier(node.parent) && checker.getSymbolAtLocation(node) === exportSymbol) {
|
|
766
|
+
cb(node);
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
}
|
|
770
|
+
}
|
|
771
|
+
Core.eachExportReference = eachExportReference;
|
|
772
|
+
function shouldAddSingleReference(singleRef, state) {
|
|
773
|
+
if (!hasMatchingMeaning(singleRef, state))
|
|
774
|
+
return false;
|
|
775
|
+
if (state.options.use !== 2 /* FindReferencesUse.Rename */)
|
|
776
|
+
return true;
|
|
777
|
+
// Don't rename an import type `import("./module-name")` when renaming `name` in `export = name;`
|
|
778
|
+
if (!isIdentifier(singleRef))
|
|
779
|
+
return false;
|
|
780
|
+
// At `default` in `import { default as x }` or `export { default as x }`, do add a reference, but do not rename.
|
|
781
|
+
return !(isImportOrExportSpecifier(singleRef.parent) && singleRef.escapedText === InternalSymbolName.Default);
|
|
782
|
+
}
|
|
783
|
+
// Go to the symbol we imported from and find references for it.
|
|
784
|
+
function searchForImportedSymbol(symbol, state) {
|
|
785
|
+
if (!symbol.declarations)
|
|
786
|
+
return;
|
|
787
|
+
for (const declaration of symbol.declarations) {
|
|
788
|
+
const exportingFile = declaration.getSourceFile();
|
|
789
|
+
// Need to search in the file even if it's not in the search-file set, because it might export the symbol.
|
|
790
|
+
getReferencesInSourceFile(exportingFile, state.createSearch(declaration, symbol, 0 /* ImportExport.Import */), state, state.includesSourceFile(exportingFile));
|
|
791
|
+
}
|
|
792
|
+
}
|
|
793
|
+
/** Search for all occurences of an identifier in a source file (and filter out the ones that match). */
|
|
794
|
+
function searchForName(sourceFile, search, state) {
|
|
795
|
+
if (getNameTable(sourceFile).get(search.escapedText) !== undefined) {
|
|
796
|
+
getReferencesInSourceFile(sourceFile, search, state);
|
|
797
|
+
}
|
|
798
|
+
}
|
|
799
|
+
function getPropertySymbolOfDestructuringAssignment(location, checker) {
|
|
800
|
+
return isArrayLiteralOrObjectLiteralDestructuringPattern(location.parent.parent)
|
|
801
|
+
? checker.getPropertySymbolOfDestructuringAssignment(location)
|
|
802
|
+
: undefined;
|
|
803
|
+
}
|
|
804
|
+
/**
|
|
805
|
+
* Determines the smallest scope in which a symbol may have named references.
|
|
806
|
+
* Note that not every construct has been accounted for. This function can
|
|
807
|
+
* probably be improved.
|
|
808
|
+
*
|
|
809
|
+
* @returns undefined if the scope cannot be determined, implying that
|
|
810
|
+
* a reference to a symbol can occur anywhere.
|
|
811
|
+
*/
|
|
812
|
+
function getSymbolScope(symbol) {
|
|
813
|
+
// Na tag, o nome de uma function expression ou de uma class expression tinha como escopo a própria expressão
|
|
814
|
+
// (CK-02).
|
|
815
|
+
const { declarations, flags, parent } = symbol;
|
|
816
|
+
if (!declarations) {
|
|
817
|
+
return undefined;
|
|
818
|
+
}
|
|
819
|
+
// A propriedade e o método são públicos, e podem ser acessados de qualquer lugar. Na tag, o escopo da propriedade
|
|
820
|
+
// ou do método privado era a classe dele (CK-02).
|
|
821
|
+
if (flags & (SymbolFlags.Property | SymbolFlags.Method)) {
|
|
822
|
+
return undefined;
|
|
823
|
+
}
|
|
824
|
+
// If symbol is of object binding pattern element without property name we would want to
|
|
825
|
+
// look for property too and that could be anywhere
|
|
826
|
+
if (declarations.some(isObjectBindingElementWithoutPropertyName)) {
|
|
827
|
+
return undefined;
|
|
828
|
+
}
|
|
829
|
+
/*
|
|
830
|
+
If the symbol has a parent, it's globally visible unless:
|
|
831
|
+
- It's a type parameter.
|
|
832
|
+
- The parent is an external module: then we should only search in the module (and recurse on the export later).
|
|
833
|
+
Na tag, também a propriedade privada, e o módulo com `export as namespace` expunha o símbolo de todo lugar (CK-02,
|
|
834
|
+
CK-03).
|
|
835
|
+
*/
|
|
836
|
+
const exposedByParent = parent && !(symbol.flags & SymbolFlags.TypeParameter);
|
|
837
|
+
if (exposedByParent && !isExternalModuleSymbol(parent)) {
|
|
838
|
+
return undefined;
|
|
839
|
+
}
|
|
840
|
+
let scope;
|
|
841
|
+
for (const declaration of declarations) {
|
|
842
|
+
const container = getContainerNode(declaration);
|
|
843
|
+
if (scope && scope !== container) {
|
|
844
|
+
// Different declarations have different containers, bail out
|
|
845
|
+
return undefined;
|
|
846
|
+
}
|
|
847
|
+
if (!container || container.kind === SyntaxKind.SourceFile && !isExternalOrCommonJsModule(container)) {
|
|
848
|
+
// This is a global variable and not an external module, any declaration defined
|
|
849
|
+
// within this scope is visible outside the file
|
|
850
|
+
return undefined;
|
|
851
|
+
}
|
|
852
|
+
// The search scope is the container node
|
|
853
|
+
scope = container;
|
|
854
|
+
}
|
|
855
|
+
// If symbol.parent, this means we are in an export of an external module. (Otherwise we would have returned `undefined` above.)
|
|
856
|
+
// For an export of a module, we may be in a declaration file, and it may be accessed elsewhere. E.g.:
|
|
857
|
+
// declare module "a" { export type T = number; }
|
|
858
|
+
// declare module "b" { import { T } from "a"; export const x: T; }
|
|
859
|
+
// So we must search the whole source file. (Because we will mark the source file as seen, we we won't return to it when searching for imports.)
|
|
860
|
+
return exposedByParent ? scope.getSourceFile() : scope;
|
|
861
|
+
}
|
|
862
|
+
/** Used as a quick check for whether a symbol is used at all in a file (besides its definition). */
|
|
863
|
+
function isSymbolReferencedInFile(definition, checker, sourceFile, searchContainer = sourceFile) {
|
|
864
|
+
return eachSymbolReferenceInFile(definition, checker, sourceFile, () => true, searchContainer) || false;
|
|
865
|
+
}
|
|
866
|
+
Core.isSymbolReferencedInFile = isSymbolReferencedInFile;
|
|
867
|
+
function eachSymbolReferenceInFile(definition, checker, sourceFile, cb, searchContainer = sourceFile) {
|
|
868
|
+
// Na tag, o nome de uma parameter property dava o símbolo da propriedade (CK-02).
|
|
869
|
+
const symbol = checker.getSymbolAtLocation(definition);
|
|
870
|
+
if (!symbol)
|
|
871
|
+
return undefined;
|
|
872
|
+
for (const token of getPossibleSymbolReferenceNodes(sourceFile, symbol.name, searchContainer)) {
|
|
873
|
+
if (!isIdentifier(token) || token === definition || token.escapedText !== definition.escapedText)
|
|
874
|
+
continue;
|
|
875
|
+
const referenceSymbol = checker.getSymbolAtLocation(token); // See GH#19955 for why the type annotation is necessary
|
|
876
|
+
if (referenceSymbol === symbol
|
|
877
|
+
|| checker.getShorthandAssignmentValueSymbol(token.parent) === symbol
|
|
878
|
+
|| isExportSpecifier(token.parent) && getLocalSymbolForExportSpecifier(token, referenceSymbol, token.parent, checker) === symbol) {
|
|
879
|
+
const res = cb(token);
|
|
880
|
+
if (res)
|
|
881
|
+
return res;
|
|
882
|
+
}
|
|
883
|
+
}
|
|
884
|
+
}
|
|
885
|
+
Core.eachSymbolReferenceInFile = eachSymbolReferenceInFile;
|
|
886
|
+
function eachSignatureCall(signature, sourceFiles, checker, cb) {
|
|
887
|
+
if (!signature.name || !isIdentifier(signature.name))
|
|
888
|
+
return;
|
|
889
|
+
const symbol = Debug.checkDefined(checker.getSymbolAtLocation(signature.name));
|
|
890
|
+
for (const sourceFile of sourceFiles) {
|
|
891
|
+
for (const name of getPossibleSymbolReferenceNodes(sourceFile, symbol.name)) {
|
|
892
|
+
if (!isIdentifier(name) || name === signature.name || name.escapedText !== signature.name.escapedText)
|
|
893
|
+
continue;
|
|
894
|
+
const called = climbPastPropertyAccess(name);
|
|
895
|
+
const call = called.parent;
|
|
896
|
+
if (!isCallExpression(call) || call.expression !== called)
|
|
897
|
+
continue;
|
|
898
|
+
const referenceSymbol = checker.getSymbolAtLocation(name);
|
|
899
|
+
if (referenceSymbol && checker.getRootSymbols(referenceSymbol).some(s => s === symbol)) {
|
|
900
|
+
cb(call);
|
|
901
|
+
}
|
|
902
|
+
}
|
|
903
|
+
}
|
|
904
|
+
}
|
|
905
|
+
Core.eachSignatureCall = eachSignatureCall;
|
|
906
|
+
function getPossibleSymbolReferenceNodes(sourceFile, symbolName, container = sourceFile) {
|
|
907
|
+
return getPossibleSymbolReferencePositions(sourceFile, symbolName, container).map(pos => getTouchingPropertyName(sourceFile, pos));
|
|
908
|
+
}
|
|
909
|
+
function getPossibleSymbolReferencePositions(sourceFile, symbolName, container = sourceFile) {
|
|
910
|
+
const positions = [];
|
|
911
|
+
/// TODO: Cache symbol existence for files to save text search
|
|
912
|
+
// Also, need to make this work for unicode escapes.
|
|
913
|
+
// Be resilient in the face of a symbol with no name or zero length name
|
|
914
|
+
if (!symbolName || !symbolName.length) {
|
|
915
|
+
return positions;
|
|
916
|
+
}
|
|
917
|
+
const text = sourceFile.text;
|
|
918
|
+
const sourceLength = text.length;
|
|
919
|
+
const symbolNameLength = symbolName.length;
|
|
920
|
+
let position = text.indexOf(symbolName, container.pos);
|
|
921
|
+
while (position >= 0) {
|
|
922
|
+
// If we are past the end, stop looking
|
|
923
|
+
if (position > container.end)
|
|
924
|
+
break;
|
|
925
|
+
// We found a match. Make sure it's not part of a larger word (i.e. the char
|
|
926
|
+
// before and after it have to be a non-identifier char).
|
|
927
|
+
const endPosition = position + symbolNameLength;
|
|
928
|
+
if ((position === 0 || !isIdentifierPart(text.charCodeAt(position - 1), ScriptTarget.Latest)) &&
|
|
929
|
+
(endPosition === sourceLength || !isIdentifierPart(text.charCodeAt(endPosition), ScriptTarget.Latest))) {
|
|
930
|
+
// Found a real match. Keep searching.
|
|
931
|
+
positions.push(position);
|
|
932
|
+
}
|
|
933
|
+
position = text.indexOf(symbolName, position + symbolNameLength + 1);
|
|
934
|
+
}
|
|
935
|
+
return positions;
|
|
936
|
+
}
|
|
937
|
+
function isValidReferencePosition(node, searchSymbolName) {
|
|
938
|
+
// Compare the length so we filter out strict superstrings of the symbol we are looking for
|
|
939
|
+
// Na tag, também o nome `#private` (CK-02); e, no literal, o nome de um `declare module "x"` (CK-02), o `require` de
|
|
940
|
+
// um `import =` e o nome de propriedade do `Object.defineProperty` de um arquivo JavaScript (CK-03).
|
|
941
|
+
switch (node.kind) {
|
|
942
|
+
case SyntaxKind.Identifier:
|
|
943
|
+
return node.text.length === searchSymbolName.length;
|
|
944
|
+
case SyntaxKind.NoSubstitutionTemplateLiteral:
|
|
945
|
+
case SyntaxKind.StringLiteral: {
|
|
946
|
+
const str = node;
|
|
947
|
+
return isLiteralNameOfPropertyDeclarationOrIndexAccess(str) &&
|
|
948
|
+
str.text.length === searchSymbolName.length;
|
|
949
|
+
}
|
|
950
|
+
case SyntaxKind.NumericLiteral:
|
|
951
|
+
return isLiteralNameOfPropertyDeclarationOrIndexAccess(node) && node.text.length === searchSymbolName.length;
|
|
952
|
+
case SyntaxKind.DefaultKeyword:
|
|
953
|
+
return "default".length === searchSymbolName.length;
|
|
954
|
+
default:
|
|
955
|
+
return false;
|
|
956
|
+
}
|
|
957
|
+
}
|
|
958
|
+
function getAllReferencesForKeyword(sourceFiles, keywordKind, cancellationToken, filter) {
|
|
959
|
+
const references = flatMap(sourceFiles, sourceFile => {
|
|
960
|
+
cancellationToken.throwIfCancellationRequested();
|
|
961
|
+
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, tokenToString(keywordKind), sourceFile), referenceLocation => {
|
|
962
|
+
if (referenceLocation.kind === keywordKind && (!filter || filter(referenceLocation))) {
|
|
963
|
+
return nodeEntry(referenceLocation);
|
|
964
|
+
}
|
|
965
|
+
});
|
|
966
|
+
});
|
|
967
|
+
return references.length ? [{ definition: { type: 1 /* DefinitionKind.Keyword */, node: references[0].node }, references }] : undefined;
|
|
968
|
+
}
|
|
969
|
+
function getReferencesInSourceFile(sourceFile, search, state, addReferencesHere = true) {
|
|
970
|
+
state.cancellationToken.throwIfCancellationRequested();
|
|
971
|
+
return getReferencesInContainer(sourceFile, sourceFile, search, state, addReferencesHere);
|
|
972
|
+
}
|
|
973
|
+
/**
|
|
974
|
+
* Search within node "container" for references for a search value, where the search value is defined as a
|
|
975
|
+
* tuple of(searchSymbol, searchText, searchLocation, and searchMeaning).
|
|
976
|
+
* searchLocation: a node where the search value
|
|
977
|
+
*/
|
|
978
|
+
function getReferencesInContainer(container, sourceFile, search, state, addReferencesHere) {
|
|
979
|
+
if (!state.markSearchedSymbols(sourceFile, search.allSearchSymbols)) {
|
|
980
|
+
return;
|
|
981
|
+
}
|
|
982
|
+
for (const position of getPossibleSymbolReferencePositions(sourceFile, search.text, container)) {
|
|
983
|
+
getReferencesAtLocation(sourceFile, position, search, state, addReferencesHere);
|
|
984
|
+
}
|
|
985
|
+
}
|
|
986
|
+
function hasMatchingMeaning(referenceLocation, state) {
|
|
987
|
+
return !!(getMeaningFromLocation(referenceLocation) & state.searchMeaning);
|
|
988
|
+
}
|
|
989
|
+
function getReferencesAtLocation(sourceFile, position, search, state, addReferencesHere) {
|
|
990
|
+
const referenceLocation = getTouchingPropertyName(sourceFile, position);
|
|
991
|
+
if (!isValidReferencePosition(referenceLocation, search.text)) {
|
|
992
|
+
// This wasn't the start of a token. Check to see if it might be a
|
|
993
|
+
// match in a comment or string if that's what the caller is asking
|
|
994
|
+
// for.
|
|
995
|
+
if (!state.options.implementations && (state.options.findInStrings && isInString(sourceFile, position) || state.options.findInComments && isInNonReferenceComment(sourceFile, position))) {
|
|
996
|
+
// In the case where we're looking inside comments/strings, we don't have
|
|
997
|
+
// an actual definition. So just use 'undefined' here. Features like
|
|
998
|
+
// 'Rename' won't care (as they ignore the definitions), and features like
|
|
999
|
+
// 'FindReferences' will just filter out these results.
|
|
1000
|
+
state.addStringOrCommentReference(sourceFile.fileName, createTextSpan(position, search.text.length));
|
|
1001
|
+
}
|
|
1002
|
+
return;
|
|
1003
|
+
}
|
|
1004
|
+
if (!hasMatchingMeaning(referenceLocation, state))
|
|
1005
|
+
return;
|
|
1006
|
+
const referenceSymbol = state.checker.getSymbolAtLocation(referenceLocation);
|
|
1007
|
+
if (!referenceSymbol) {
|
|
1008
|
+
return;
|
|
1009
|
+
}
|
|
1010
|
+
const parent = referenceLocation.parent;
|
|
1011
|
+
if (isImportSpecifier(parent) && parent.propertyName === referenceLocation) {
|
|
1012
|
+
// This is added through `singleReferences` in ImportsResult. If we happen to see it again, don't add it again.
|
|
1013
|
+
return;
|
|
1014
|
+
}
|
|
1015
|
+
if (isExportSpecifier(parent)) {
|
|
1016
|
+
Debug.assert(referenceLocation.kind === SyntaxKind.Identifier);
|
|
1017
|
+
getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, parent, search, state, addReferencesHere);
|
|
1018
|
+
return;
|
|
1019
|
+
}
|
|
1020
|
+
const relatedSymbol = getRelatedSymbol(search, referenceSymbol, referenceLocation, state);
|
|
1021
|
+
if (!relatedSymbol) {
|
|
1022
|
+
getReferenceForShorthandProperty(referenceSymbol, search, state);
|
|
1023
|
+
return;
|
|
1024
|
+
}
|
|
1025
|
+
// Na tag, a busca do nome de uma classe e do `constructor` acrescentava as referências do construtor e o `this`
|
|
1026
|
+
// estático da classe (CK-02).
|
|
1027
|
+
if (addReferencesHere)
|
|
1028
|
+
addReference(referenceLocation, relatedSymbol, state);
|
|
1029
|
+
getImportOrExportReferences(referenceLocation, referenceSymbol, search, state);
|
|
1030
|
+
}
|
|
1031
|
+
function getReferencesAtExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, search, state, addReferencesHere, alwaysGetReferences) {
|
|
1032
|
+
Debug.assert(!alwaysGetReferences || !!state.options.providePrefixAndSuffixTextForRename, "If alwaysGetReferences is true, then prefix/suffix text must be enabled");
|
|
1033
|
+
const { parent, propertyName, name } = exportSpecifier;
|
|
1034
|
+
const exportDeclaration = parent.parent;
|
|
1035
|
+
const localSymbol = getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, state.checker);
|
|
1036
|
+
if (!alwaysGetReferences && !search.includes(localSymbol)) {
|
|
1037
|
+
return;
|
|
1038
|
+
}
|
|
1039
|
+
if (!propertyName) {
|
|
1040
|
+
// Don't rename at `export { default } from "m";`. (but do continue to search for imports of the re-export)
|
|
1041
|
+
if (!(state.options.use === 2 /* FindReferencesUse.Rename */ && (name.escapedText === InternalSymbolName.Default))) {
|
|
1042
|
+
addRef();
|
|
1043
|
+
}
|
|
1044
|
+
}
|
|
1045
|
+
else if (referenceLocation === propertyName) {
|
|
1046
|
+
// For `export { foo as bar } from "baz"`, "`foo`" will be added from the singleReferences for import searches of the original export.
|
|
1047
|
+
// For `export { foo as bar };`, where `foo` is a local, so add it now.
|
|
1048
|
+
if (!exportDeclaration.moduleSpecifier) {
|
|
1049
|
+
addRef();
|
|
1050
|
+
}
|
|
1051
|
+
if (addReferencesHere && state.options.use !== 2 /* FindReferencesUse.Rename */ && state.markSeenReExportRHS(name)) {
|
|
1052
|
+
addReference(name, Debug.checkDefined(exportSpecifier.symbol), state);
|
|
1053
|
+
}
|
|
1054
|
+
}
|
|
1055
|
+
else {
|
|
1056
|
+
if (state.markSeenReExportRHS(referenceLocation)) {
|
|
1057
|
+
addRef();
|
|
1058
|
+
}
|
|
1059
|
+
}
|
|
1060
|
+
// For `export { foo as bar }`, rename `foo`, but not `bar`.
|
|
1061
|
+
if (!isForRenameWithPrefixAndSuffixText(state.options) || alwaysGetReferences) {
|
|
1062
|
+
const isDefaultExport = referenceLocation.originalKeywordKind === SyntaxKind.DefaultKeyword
|
|
1063
|
+
|| exportSpecifier.name.originalKeywordKind === SyntaxKind.DefaultKeyword;
|
|
1064
|
+
const exportKind = isDefaultExport ? 1 /* ExportKind.Default */ : 0 /* ExportKind.Named */;
|
|
1065
|
+
const exportSymbol = Debug.checkDefined(exportSpecifier.symbol);
|
|
1066
|
+
const exportInfo = getExportInfo(exportSymbol, exportKind, state.checker);
|
|
1067
|
+
if (exportInfo) {
|
|
1068
|
+
searchForImportsOfExport(referenceLocation, exportSymbol, exportInfo, state);
|
|
1069
|
+
}
|
|
1070
|
+
}
|
|
1071
|
+
// At `export { x } from "foo"`, also search for the imported symbol `"foo".x`.
|
|
1072
|
+
if (search.comingFrom !== 1 /* ImportExport.Export */ && exportDeclaration.moduleSpecifier && !propertyName && !isForRenameWithPrefixAndSuffixText(state.options)) {
|
|
1073
|
+
const imported = state.checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
|
|
1074
|
+
if (imported)
|
|
1075
|
+
searchForImportedSymbol(imported, state);
|
|
1076
|
+
}
|
|
1077
|
+
function addRef() {
|
|
1078
|
+
if (addReferencesHere)
|
|
1079
|
+
addReference(referenceLocation, localSymbol, state);
|
|
1080
|
+
}
|
|
1081
|
+
}
|
|
1082
|
+
function getLocalSymbolForExportSpecifier(referenceLocation, referenceSymbol, exportSpecifier, checker) {
|
|
1083
|
+
return isExportSpecifierAlias(referenceLocation, exportSpecifier) && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier) || referenceSymbol;
|
|
1084
|
+
}
|
|
1085
|
+
function isExportSpecifierAlias(referenceLocation, exportSpecifier) {
|
|
1086
|
+
const { parent, propertyName, name } = exportSpecifier;
|
|
1087
|
+
Debug.assert(propertyName === referenceLocation || name === referenceLocation);
|
|
1088
|
+
if (propertyName) {
|
|
1089
|
+
// Given `export { foo as bar } [from "someModule"]`: It's an alias at `foo`, but at `bar` it's a new symbol.
|
|
1090
|
+
return propertyName === referenceLocation;
|
|
1091
|
+
}
|
|
1092
|
+
else {
|
|
1093
|
+
// `export { foo } from "foo"` is a re-export.
|
|
1094
|
+
// `export { foo };` is not a re-export, it creates an alias for the local variable `foo`.
|
|
1095
|
+
return !parent.parent.moduleSpecifier;
|
|
1096
|
+
}
|
|
1097
|
+
}
|
|
1098
|
+
function getImportOrExportReferences(referenceLocation, referenceSymbol, search, state) {
|
|
1099
|
+
const importOrExport = getImportOrExportSymbol(referenceLocation, referenceSymbol, state.checker, search.comingFrom === 1 /* ImportExport.Export */);
|
|
1100
|
+
if (!importOrExport)
|
|
1101
|
+
return;
|
|
1102
|
+
const { symbol } = importOrExport;
|
|
1103
|
+
if (importOrExport.kind === 0 /* ImportExport.Import */) {
|
|
1104
|
+
if (!(isForRenameWithPrefixAndSuffixText(state.options))) {
|
|
1105
|
+
searchForImportedSymbol(symbol, state);
|
|
1106
|
+
}
|
|
1107
|
+
}
|
|
1108
|
+
else {
|
|
1109
|
+
searchForImportsOfExport(referenceLocation, symbol, importOrExport.exportInfo, state);
|
|
1110
|
+
}
|
|
1111
|
+
}
|
|
1112
|
+
function getReferenceForShorthandProperty({ flags, valueDeclaration }, search, state) {
|
|
1113
|
+
const shorthandValueSymbol = state.checker.getShorthandAssignmentValueSymbol(valueDeclaration);
|
|
1114
|
+
const name = valueDeclaration && getNameOfDeclaration(valueDeclaration);
|
|
1115
|
+
/*
|
|
1116
|
+
* Because in short-hand property assignment, an identifier which stored as name of the short-hand property assignment
|
|
1117
|
+
* has two meanings: property name and property value. Therefore when we do findAllReference at the position where
|
|
1118
|
+
* an identifier is declared, the language service should return the position of the variable declaration as well as
|
|
1119
|
+
* the position in short-hand property assignment excluding property accessing. However, if we do findAllReference at the
|
|
1120
|
+
* position of property accessing, the referenceEntry of such position will be handled in the first case.
|
|
1121
|
+
*/
|
|
1122
|
+
if (!(flags & SymbolFlags.Transient) && name && search.includes(shorthandValueSymbol)) {
|
|
1123
|
+
addReference(name, shorthandValueSymbol, state);
|
|
1124
|
+
}
|
|
1125
|
+
}
|
|
1126
|
+
function addReference(referenceLocation, relatedSymbol, state) {
|
|
1127
|
+
const { kind, symbol } = "kind" in relatedSymbol ? relatedSymbol : { kind: undefined, symbol: relatedSymbol }; // eslint-disable-line no-in-operator
|
|
1128
|
+
const addRef = state.referenceAdder(symbol);
|
|
1129
|
+
if (state.options.implementations) {
|
|
1130
|
+
addImplementationReferences(referenceLocation, addRef, state);
|
|
1131
|
+
}
|
|
1132
|
+
else {
|
|
1133
|
+
addRef(referenceLocation, kind);
|
|
1134
|
+
}
|
|
1135
|
+
}
|
|
1136
|
+
function addImplementationReferences(refNode, addReference, state) {
|
|
1137
|
+
// Check if we found a function/propertyAssignment/method with an implementation or initializer
|
|
1138
|
+
if (isDeclarationName(refNode) && isImplementation(refNode.parent)) {
|
|
1139
|
+
addReference(refNode);
|
|
1140
|
+
return;
|
|
1141
|
+
}
|
|
1142
|
+
if (refNode.kind !== SyntaxKind.Identifier) {
|
|
1143
|
+
return;
|
|
1144
|
+
}
|
|
1145
|
+
if (refNode.parent.kind === SyntaxKind.ShorthandPropertyAssignment) {
|
|
1146
|
+
// Go ahead and dereference the shorthand assignment by going to its definition
|
|
1147
|
+
getReferenceEntriesForShorthandPropertyAssignment(refNode, state.checker, addReference);
|
|
1148
|
+
}
|
|
1149
|
+
// Na tag, o nome no `extends` ou no `implements` de uma classe dava a classe como implementação (o
|
|
1150
|
+
// `getContainingClassIfInHeritageClause`, CK-02).
|
|
1151
|
+
// If we got a type reference, try and see if the reference applies to any expressions that can implement an interface
|
|
1152
|
+
// Find the first node whose parent isn't a type node -- i.e., the highest type node.
|
|
1153
|
+
const typeNode = findAncestor(refNode, a => !isQualifiedName(a.parent) && !isTypeNode(a.parent) && !isTypeElement(a.parent));
|
|
1154
|
+
const typeHavingNode = typeNode.parent;
|
|
1155
|
+
if (hasType(typeHavingNode) && typeHavingNode.type === typeNode && state.markSeenContainingTypeReference(typeHavingNode)) {
|
|
1156
|
+
if (hasInitializer(typeHavingNode)) {
|
|
1157
|
+
addIfImplementation(typeHavingNode.initializer);
|
|
1158
|
+
}
|
|
1159
|
+
else if (isFunctionLike(typeHavingNode) && typeHavingNode.body) {
|
|
1160
|
+
const body = typeHavingNode.body;
|
|
1161
|
+
if (body.kind === SyntaxKind.Block) {
|
|
1162
|
+
forEachReturnStatement(body, returnStatement => {
|
|
1163
|
+
if (returnStatement.expression)
|
|
1164
|
+
addIfImplementation(returnStatement.expression);
|
|
1165
|
+
});
|
|
1166
|
+
}
|
|
1167
|
+
else {
|
|
1168
|
+
addIfImplementation(body);
|
|
1169
|
+
}
|
|
1170
|
+
}
|
|
1171
|
+
else if (isAssertionExpression(typeHavingNode)) {
|
|
1172
|
+
addIfImplementation(typeHavingNode.expression);
|
|
1173
|
+
}
|
|
1174
|
+
}
|
|
1175
|
+
function addIfImplementation(e) {
|
|
1176
|
+
if (isImplementationExpression(e))
|
|
1177
|
+
addReference(e);
|
|
1178
|
+
}
|
|
1179
|
+
}
|
|
1180
|
+
/**
|
|
1181
|
+
* Returns true if this is an expression that can be considered an implementation
|
|
1182
|
+
*/
|
|
1183
|
+
function isImplementationExpression(node) {
|
|
1184
|
+
// Na tag, também a function expression e a class expression (CK-02).
|
|
1185
|
+
switch (node.kind) {
|
|
1186
|
+
case SyntaxKind.ParenthesizedExpression:
|
|
1187
|
+
return isImplementationExpression(node.expression);
|
|
1188
|
+
case SyntaxKind.ArrowFunction:
|
|
1189
|
+
case SyntaxKind.ObjectLiteralExpression:
|
|
1190
|
+
case SyntaxKind.ArrayLiteralExpression:
|
|
1191
|
+
return true;
|
|
1192
|
+
default:
|
|
1193
|
+
return false;
|
|
1194
|
+
}
|
|
1195
|
+
}
|
|
1196
|
+
function getReferencesForStringLiteral(node, sourceFiles, cancellationToken) {
|
|
1197
|
+
const references = flatMap(sourceFiles, sourceFile => {
|
|
1198
|
+
cancellationToken.throwIfCancellationRequested();
|
|
1199
|
+
return mapDefined(getPossibleSymbolReferenceNodes(sourceFile, node.text), ref => isStringLiteral(ref) && ref.text === node.text ? nodeEntry(ref, 2 /* EntryKind.StringLiteral */) : undefined);
|
|
1200
|
+
});
|
|
1201
|
+
return [{
|
|
1202
|
+
definition: { type: 2 /* DefinitionKind.String */, node },
|
|
1203
|
+
references
|
|
1204
|
+
}];
|
|
1205
|
+
}
|
|
1206
|
+
// For certain symbol kinds, we need to include other symbols in the search set.
|
|
1207
|
+
// This is not needed when searching for re-exports.
|
|
1208
|
+
// Na tag, também o `implementations` e o `allowBaseTypes` do `forEachRelatedSymbol`, que só decidiam a busca nas
|
|
1209
|
+
// bases, e o `baseSymbol` do callback, que trazia a propriedade da base (CK-02, CK-48).
|
|
1210
|
+
function populateSearchSymbolSet(symbol, location, checker, isForRename, providePrefixAndSuffixText) {
|
|
1211
|
+
const result = [];
|
|
1212
|
+
forEachRelatedSymbol(symbol, location, checker, isForRename, !(isForRename && providePrefixAndSuffixText), (sym, root) => { result.push(root || sym); });
|
|
1213
|
+
return result;
|
|
1214
|
+
}
|
|
1215
|
+
function forEachRelatedSymbol(symbol, location, checker, isForRenamePopulateSearchSymbolSet, onlyIncludeBindingElementAtReferenceLocation, cbSymbol) {
|
|
1216
|
+
const containingObjectLiteralElement = getContainingObjectLiteralElement(location);
|
|
1217
|
+
if (containingObjectLiteralElement) {
|
|
1218
|
+
/* Because in short-hand property assignment, location has two meaning : property name and as value of the property
|
|
1219
|
+
* When we do findAllReference at the position of the short-hand property assignment, we would want to have references to position of
|
|
1220
|
+
* property name and variable declaration of the identifier.
|
|
1221
|
+
* Like in below example, when querying for all references for an identifier 'name', of the property assignment, the language service
|
|
1222
|
+
* should show both 'name' in 'obj' and 'name' in variable declaration
|
|
1223
|
+
* const name = "Foo";
|
|
1224
|
+
* const obj = { name };
|
|
1225
|
+
* In order to do that, we will populate the search set with the value symbol of the identifier as a value of the property assignment
|
|
1226
|
+
* so that when matching with potential reference symbol, both symbols from property declaration and variable declaration
|
|
1227
|
+
* will be included correctly.
|
|
1228
|
+
*/
|
|
1229
|
+
const shorthandValueSymbol = checker.getShorthandAssignmentValueSymbol(location.parent); // gets the local symbol
|
|
1230
|
+
if (shorthandValueSymbol && isForRenamePopulateSearchSymbolSet) {
|
|
1231
|
+
// When renaming 'x' in `const o = { x }`, just rename the local variable, not the property.
|
|
1232
|
+
return cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, 3 /* EntryKind.SearchedLocalFoundProperty */);
|
|
1233
|
+
}
|
|
1234
|
+
// If the location is in a context sensitive location (i.e. in an object literal) try
|
|
1235
|
+
// to get a contextual type for it, and add the property symbol from the contextual
|
|
1236
|
+
// type to the search set
|
|
1237
|
+
const contextualType = checker.getContextualType(containingObjectLiteralElement.parent);
|
|
1238
|
+
const res = contextualType && firstDefined(getPropertySymbolsFromContextualType(containingObjectLiteralElement, checker, contextualType, /*unionSymbolOk*/ true), sym => fromRoot(sym, 4 /* EntryKind.SearchedPropertyFoundLocal */));
|
|
1239
|
+
if (res)
|
|
1240
|
+
return res;
|
|
1241
|
+
// If the location is name of property symbol from object literal destructuring pattern
|
|
1242
|
+
// Search the property symbol
|
|
1243
|
+
// for ( { property: p2 } of elems) { }
|
|
1244
|
+
const propertySymbol = getPropertySymbolOfDestructuringAssignment(location, checker);
|
|
1245
|
+
const res1 = propertySymbol && cbSymbol(propertySymbol, /*rootSymbol*/ undefined, 4 /* EntryKind.SearchedPropertyFoundLocal */);
|
|
1246
|
+
if (res1)
|
|
1247
|
+
return res1;
|
|
1248
|
+
const res2 = shorthandValueSymbol && cbSymbol(shorthandValueSymbol, /*rootSymbol*/ undefined, 3 /* EntryKind.SearchedLocalFoundProperty */);
|
|
1249
|
+
if (res2)
|
|
1250
|
+
return res2;
|
|
1251
|
+
}
|
|
1252
|
+
// Na tag, também o global de um módulo UMD, pelo `export as namespace` (CK-03).
|
|
1253
|
+
const res = fromRoot(symbol);
|
|
1254
|
+
if (res)
|
|
1255
|
+
return res;
|
|
1256
|
+
// Na tag, a parameter property buscava também o outro símbolo dela: a propriedade, se era o parâmetro, e o
|
|
1257
|
+
// parâmetro, se era a propriedade (CK-02).
|
|
1258
|
+
const exportSpecifier = getDeclarationOfKind(symbol, SyntaxKind.ExportSpecifier);
|
|
1259
|
+
if (!isForRenamePopulateSearchSymbolSet || exportSpecifier && !exportSpecifier.propertyName) {
|
|
1260
|
+
const localSymbol = exportSpecifier && checker.getExportSpecifierLocalTargetSymbol(exportSpecifier);
|
|
1261
|
+
if (localSymbol) {
|
|
1262
|
+
const res = cbSymbol(localSymbol, /*rootSymbol*/ undefined, 1 /* EntryKind.Node */);
|
|
1263
|
+
if (res)
|
|
1264
|
+
return res;
|
|
1265
|
+
}
|
|
1266
|
+
}
|
|
1267
|
+
// symbolAtLocation for a binding element is the local symbol. See if the search symbol is the property.
|
|
1268
|
+
// Don't do this when populating search set for a rename when prefix and suffix text will be provided -- just rename the local.
|
|
1269
|
+
if (!isForRenamePopulateSearchSymbolSet) {
|
|
1270
|
+
let bindingElementPropertySymbol;
|
|
1271
|
+
if (onlyIncludeBindingElementAtReferenceLocation) {
|
|
1272
|
+
bindingElementPropertySymbol = isObjectBindingElementWithoutPropertyName(location.parent) ? getPropertySymbolFromBindingElement(checker, location.parent) : undefined;
|
|
1273
|
+
}
|
|
1274
|
+
else {
|
|
1275
|
+
bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
|
|
1276
|
+
}
|
|
1277
|
+
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, 4 /* EntryKind.SearchedPropertyFoundLocal */);
|
|
1278
|
+
}
|
|
1279
|
+
Debug.assert(isForRenamePopulateSearchSymbolSet);
|
|
1280
|
+
// due to the above assert and the arguments at the uses of this function,
|
|
1281
|
+
// (onlyIncludeBindingElementAtReferenceLocation <=> !providePrefixAndSuffixTextForRename) holds
|
|
1282
|
+
const includeOriginalSymbolOfBindingElement = onlyIncludeBindingElementAtReferenceLocation;
|
|
1283
|
+
if (includeOriginalSymbolOfBindingElement) {
|
|
1284
|
+
const bindingElementPropertySymbol = getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker);
|
|
1285
|
+
return bindingElementPropertySymbol && fromRoot(bindingElementPropertySymbol, 4 /* EntryKind.SearchedPropertyFoundLocal */);
|
|
1286
|
+
}
|
|
1287
|
+
function fromRoot(sym, kind) {
|
|
1288
|
+
// If this is a union property:
|
|
1289
|
+
// - In populateSearchSymbolsSet we will add all the symbols from all its source symbols in all unioned types.
|
|
1290
|
+
// - In findRelatedSymbol, we will just use the union symbol if any source symbol is included in the search.
|
|
1291
|
+
// If the symbol is an instantiation from a another symbol (e.g. widened symbol):
|
|
1292
|
+
// - In populateSearchSymbolsSet, add the root the list
|
|
1293
|
+
// - In findRelatedSymbol, return the source symbol if that is in the search. (Do not return the instantiation symbol.)
|
|
1294
|
+
// Na tag, também a propriedade de mesmo nome nas classes e interfaces-base: a classe saiu (CK-02), e a interface
|
|
1295
|
+
// que fica, a dos embutidos, não tem base (CK-48).
|
|
1296
|
+
return firstDefined(checker.getRootSymbols(sym), rootSymbol => cbSymbol(sym, rootSymbol, kind));
|
|
1297
|
+
}
|
|
1298
|
+
function getPropertySymbolOfObjectBindingPatternWithoutPropertyName(symbol, checker) {
|
|
1299
|
+
const bindingElement = getDeclarationOfKind(symbol, SyntaxKind.BindingElement);
|
|
1300
|
+
if (bindingElement && isObjectBindingElementWithoutPropertyName(bindingElement)) {
|
|
1301
|
+
return getPropertySymbolFromBindingElement(checker, bindingElement);
|
|
1302
|
+
}
|
|
1303
|
+
}
|
|
1304
|
+
}
|
|
1305
|
+
function getRelatedSymbol(search, referenceSymbol, referenceLocation, state) {
|
|
1306
|
+
const { checker } = state;
|
|
1307
|
+
return forEachRelatedSymbol(referenceSymbol, referenceLocation, checker, /*isForRenamePopulateSearchSymbolSet*/ false,
|
|
1308
|
+
/*onlyIncludeBindingElementAtReferenceLocation*/ state.options.use !== 2 /* FindReferencesUse.Rename */ || !!state.options.providePrefixAndSuffixTextForRename, (sym, rootSymbol, kind) => search.includes(rootSymbol || sym)
|
|
1309
|
+
// For a synthetic (e.g. union) property, use the union symbol.
|
|
1310
|
+
? { symbol: rootSymbol && !(getCheckFlags(sym) & CheckFlags.Synthetic) ? rootSymbol : sym, kind }
|
|
1311
|
+
: undefined);
|
|
1312
|
+
}
|
|
1313
|
+
/**
|
|
1314
|
+
* Given an initial searchMeaning, extracted from a location, widen the search scope based on the declarations
|
|
1315
|
+
* of the corresponding symbol. e.g. if we are searching for "Foo" in value position, but "Foo" references a class
|
|
1316
|
+
* then we need to widen the search to include type positions as well.
|
|
1317
|
+
* On the contrary, if we are searching for "Bar" in type position and we trace bar to an interface, and an uninstantiated
|
|
1318
|
+
* module, we want to keep the search limited to only types, as the two declarations (interface and uninstantiated module)
|
|
1319
|
+
* do not intersect in any of the three spaces.
|
|
1320
|
+
*/
|
|
1321
|
+
function getIntersectingMeaningFromDeclarations(node, symbol) {
|
|
1322
|
+
let meaning = getMeaningFromLocation(node);
|
|
1323
|
+
const { declarations } = symbol;
|
|
1324
|
+
if (declarations) {
|
|
1325
|
+
let lastIterationMeaning;
|
|
1326
|
+
do {
|
|
1327
|
+
// The result is order-sensitive, for instance if initialMeaning === Namespace, and declarations = [class, instantiated module]
|
|
1328
|
+
// we need to consider both as they initialMeaning intersects with the module in the namespace space, and the module
|
|
1329
|
+
// intersects with the class in the value space.
|
|
1330
|
+
// To achieve that we will keep iterating until the result stabilizes.
|
|
1331
|
+
// Remember the last meaning
|
|
1332
|
+
lastIterationMeaning = meaning;
|
|
1333
|
+
for (const declaration of declarations) {
|
|
1334
|
+
const declarationMeaning = getMeaningFromDeclaration(declaration);
|
|
1335
|
+
if (declarationMeaning & meaning) {
|
|
1336
|
+
meaning |= declarationMeaning;
|
|
1337
|
+
}
|
|
1338
|
+
}
|
|
1339
|
+
} while (meaning !== lastIterationMeaning);
|
|
1340
|
+
}
|
|
1341
|
+
return meaning;
|
|
1342
|
+
}
|
|
1343
|
+
Core.getIntersectingMeaningFromDeclarations = getIntersectingMeaningFromDeclarations;
|
|
1344
|
+
/** Na tag, também a classe e o enum, e, no contexto ambiente, a interface não era implementação (CK-02). */
|
|
1345
|
+
function isImplementation(node) {
|
|
1346
|
+
return !!(node.flags & NodeFlags.Ambient) ? !isTypeAliasDeclaration(node) :
|
|
1347
|
+
(isVariableLike(node) ? hasInitializer(node) :
|
|
1348
|
+
isFunctionLikeDeclaration(node) ? !!node.body :
|
|
1349
|
+
isModuleDeclaration(node));
|
|
1350
|
+
}
|
|
1351
|
+
function getReferenceEntriesForShorthandPropertyAssignment(node, checker, addReference) {
|
|
1352
|
+
const refSymbol = checker.getSymbolAtLocation(node);
|
|
1353
|
+
const shorthandSymbol = checker.getShorthandAssignmentValueSymbol(refSymbol.valueDeclaration);
|
|
1354
|
+
if (shorthandSymbol) {
|
|
1355
|
+
for (const declaration of shorthandSymbol.getDeclarations()) {
|
|
1356
|
+
if (getMeaningFromDeclaration(declaration) & 1 /* SemanticMeaning.Value */) {
|
|
1357
|
+
addReference(declaration);
|
|
1358
|
+
}
|
|
1359
|
+
}
|
|
1360
|
+
}
|
|
1361
|
+
}
|
|
1362
|
+
Core.getReferenceEntriesForShorthandPropertyAssignment = getReferenceEntriesForShorthandPropertyAssignment;
|
|
1363
|
+
function isForRenameWithPrefixAndSuffixText(options) {
|
|
1364
|
+
return options.use === 2 /* FindReferencesUse.Rename */ && options.providePrefixAndSuffixTextForRename;
|
|
1365
|
+
}
|
|
1366
|
+
})(Core || (Core = {}));
|