@tslite/services 0.0.0-stage → 1.13.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.
Files changed (176) hide show
  1. package/LICENSE +55 -0
  2. package/NOTICE +13 -0
  3. package/dist/_namespaces/edit.d.ts +8 -0
  4. package/dist/_namespaces/edit.js +11 -0
  5. package/dist/_namespaces/ts.Completions.StringCompletions.d.ts +1 -0
  6. package/dist/_namespaces/ts.Completions.StringCompletions.js +2 -0
  7. package/dist/_namespaces/ts.Completions.d.ts +2 -0
  8. package/dist/_namespaces/ts.Completions.js +3 -0
  9. package/dist/_namespaces/ts.FindAllReferences.d.ts +2 -0
  10. package/dist/_namespaces/ts.FindAllReferences.js +3 -0
  11. package/dist/_namespaces/ts.GoToDefinition.d.ts +1 -0
  12. package/dist/_namespaces/ts.GoToDefinition.js +2 -0
  13. package/dist/_namespaces/ts.NavigationBar.d.ts +1 -0
  14. package/dist/_namespaces/ts.NavigationBar.js +2 -0
  15. package/dist/_namespaces/ts.OrganizeImports.d.ts +1 -0
  16. package/dist/_namespaces/ts.OrganizeImports.js +2 -0
  17. package/dist/_namespaces/ts.OutliningElementsCollector.d.ts +1 -0
  18. package/dist/_namespaces/ts.OutliningElementsCollector.js +2 -0
  19. package/dist/_namespaces/ts.Rename.d.ts +1 -0
  20. package/dist/_namespaces/ts.Rename.js +2 -0
  21. package/dist/_namespaces/ts.SignatureHelp.d.ts +1 -0
  22. package/dist/_namespaces/ts.SignatureHelp.js +2 -0
  23. package/dist/_namespaces/ts.SmartSelectionRange.d.ts +1 -0
  24. package/dist/_namespaces/ts.SmartSelectionRange.js +2 -0
  25. package/dist/_namespaces/ts.SymbolDisplay.d.ts +1 -0
  26. package/dist/_namespaces/ts.SymbolDisplay.js +2 -0
  27. package/dist/_namespaces/ts.codefix.d.ts +26 -0
  28. package/dist/_namespaces/ts.codefix.js +27 -0
  29. package/dist/_namespaces/ts.d.ts +17 -0
  30. package/dist/_namespaces/ts.formatting.d.ts +7 -0
  31. package/dist/_namespaces/ts.formatting.js +8 -0
  32. package/dist/_namespaces/ts.js +20 -0
  33. package/dist/_namespaces/ts.refactor.addOrRemoveBracesToArrowFunction.d.ts +1 -0
  34. package/dist/_namespaces/ts.refactor.addOrRemoveBracesToArrowFunction.js +2 -0
  35. package/dist/_namespaces/ts.refactor.convertParamsToDestructuredObject.d.ts +1 -0
  36. package/dist/_namespaces/ts.refactor.convertParamsToDestructuredObject.js +2 -0
  37. package/dist/_namespaces/ts.refactor.convertStringOrTemplateLiteral.d.ts +1 -0
  38. package/dist/_namespaces/ts.refactor.convertStringOrTemplateLiteral.js +2 -0
  39. package/dist/_namespaces/ts.refactor.d.ts +9 -0
  40. package/dist/_namespaces/ts.refactor.extractSymbol.d.ts +1 -0
  41. package/dist/_namespaces/ts.refactor.extractSymbol.js +2 -0
  42. package/dist/_namespaces/ts.refactor.js +10 -0
  43. package/dist/_namespaces/ts.textChanges.d.ts +1 -0
  44. package/dist/_namespaces/ts.textChanges.js +2 -0
  45. package/dist/classifier.d.ts +5 -0
  46. package/dist/classifier.js +439 -0
  47. package/dist/codeFixProvider.d.ts +13 -0
  48. package/dist/codeFixProvider.js +84 -0
  49. package/dist/codefixes/addConvertToUnknownForNonOverlappingTypes.d.ts +1 -0
  50. package/dist/codefixes/addConvertToUnknownForNonOverlappingTypes.js +21 -0
  51. package/dist/codefixes/addEmptyExportDeclaration.d.ts +1 -0
  52. package/dist/codefixes/addEmptyExportDeclaration.js +17 -0
  53. package/dist/codefixes/addMissingAsync.d.ts +1 -0
  54. package/dist/codefixes/addMissingAsync.js +75 -0
  55. package/dist/codefixes/addMissingAwait.d.ts +1 -0
  56. package/dist/codefixes/addMissingAwait.js +236 -0
  57. package/dist/codefixes/addMissingConst.d.ts +1 -0
  58. package/dist/codefixes/addMissingConst.js +91 -0
  59. package/dist/codefixes/addNameToNamelessParameter.d.ts +1 -0
  60. package/dist/codefixes/addNameToNamelessParameter.js +29 -0
  61. package/dist/codefixes/convertConstToLet.d.ts +1 -0
  62. package/dist/codefixes/convertConstToLet.js +30 -0
  63. package/dist/codefixes/convertToAsyncFunction.d.ts +1 -0
  64. package/dist/codefixes/convertToAsyncFunction.js +495 -0
  65. package/dist/codefixes/convertToMappedObjectType.d.ts +1 -0
  66. package/dist/codefixes/convertToMappedObjectType.js +48 -0
  67. package/dist/codefixes/correctQualifiedNameToIndexedAccessType.d.ts +1 -0
  68. package/dist/codefixes/correctQualifiedNameToIndexedAccessType.js +33 -0
  69. package/dist/codefixes/fixAddModuleReferTypeMissingTypeof.d.ts +1 -0
  70. package/dist/codefixes/fixAddModuleReferTypeMissingTypeof.js +27 -0
  71. package/dist/codefixes/fixAwaitInSyncFunction.d.ts +1 -0
  72. package/dist/codefixes/fixAwaitInSyncFunction.js +69 -0
  73. package/dist/codefixes/fixExpectedComma.d.ts +1 -0
  74. package/dist/codefixes/fixExpectedComma.js +35 -0
  75. package/dist/codefixes/fixInvalidJsxCharacters.d.ts +1 -0
  76. package/dist/codefixes/fixInvalidJsxCharacters.js +41 -0
  77. package/dist/codefixes/fixMissingCallParentheses.d.ts +1 -0
  78. package/dist/codefixes/fixMissingCallParentheses.js +42 -0
  79. package/dist/codefixes/fixSpelling.d.ts +1 -0
  80. package/dist/codefixes/fixSpelling.js +94 -0
  81. package/dist/codefixes/fixUnreachableCode.d.ts +1 -0
  82. package/dist/codefixes/fixUnreachableCode.js +65 -0
  83. package/dist/codefixes/fixUnusedIdentifier.d.ts +1 -0
  84. package/dist/codefixes/fixUnusedIdentifier.js +224 -0
  85. package/dist/codefixes/helpers.d.ts +8 -0
  86. package/dist/codefixes/helpers.js +53 -0
  87. package/dist/codefixes/importFixes.d.ts +14 -0
  88. package/dist/codefixes/importFixes.js +441 -0
  89. package/dist/codefixes/inferFromUsage.d.ts +1 -0
  90. package/dist/codefixes/inferFromUsage.js +742 -0
  91. package/dist/codefixes/removeUnnecessaryAwait.d.ts +1 -0
  92. package/dist/codefixes/removeUnnecessaryAwait.js +41 -0
  93. package/dist/codefixes/returnValueCorrect.d.ts +1 -0
  94. package/dist/codefixes/returnValueCorrect.js +132 -0
  95. package/dist/codefixes/splitTypeOnlyImport.d.ts +1 -0
  96. package/dist/codefixes/splitTypeOnlyImport.js +32 -0
  97. package/dist/codefixes/useBigintLiteral.d.ts +1 -0
  98. package/dist/codefixes/useBigintLiteral.js +29 -0
  99. package/dist/completions.d.ts +83 -0
  100. package/dist/completions.js +1720 -0
  101. package/dist/documentHighlights.d.ts +8 -0
  102. package/dist/documentHighlights.js +367 -0
  103. package/dist/documentRegistry.d.ts +36 -0
  104. package/dist/documentRegistry.js +63 -0
  105. package/dist/editingServices.d.ts +1 -0
  106. package/dist/editingServices.js +4 -0
  107. package/dist/findAllReferences.d.ts +113 -0
  108. package/dist/findAllReferences.js +1366 -0
  109. package/dist/formatting/formatting.d.ts +26 -0
  110. package/dist/formatting/formatting.js +1021 -0
  111. package/dist/formatting/formattingContext.d.ts +34 -0
  112. package/dist/formatting/formattingContext.js +78 -0
  113. package/dist/formatting/formattingScanner.d.ts +14 -0
  114. package/dist/formatting/formattingScanner.js +228 -0
  115. package/dist/formatting/rule.d.ts +31 -0
  116. package/dist/formatting/rule.js +22 -0
  117. package/dist/formatting/rules.d.ts +7 -0
  118. package/dist/formatting/rules.js +610 -0
  119. package/dist/formatting/rulesMap.d.ts +5 -0
  120. package/dist/formatting/rulesMap.js +127 -0
  121. package/dist/formatting/smartIndenter.d.ts +44 -0
  122. package/dist/formatting/smartIndenter.js +518 -0
  123. package/dist/getEditsForFileRename.d.ts +6 -0
  124. package/dist/getEditsForFileRename.js +86 -0
  125. package/dist/goToDefinition.d.ts +8 -0
  126. package/dist/goToDefinition.js +246 -0
  127. package/dist/importTracker.d.ts +50 -0
  128. package/dist/importTracker.js +422 -0
  129. package/dist/index.d.ts +1 -0
  130. package/dist/index.js +3 -0
  131. package/dist/navigationBar.d.ts +3 -0
  132. package/dist/navigationBar.js +549 -0
  133. package/dist/organizeImports.d.ts +18 -0
  134. package/dist/organizeImports.js +290 -0
  135. package/dist/outliningElementsCollector.d.ts +2 -0
  136. package/dist/outliningElementsCollector.js +261 -0
  137. package/dist/refactorProvider.d.ts +5 -0
  138. package/dist/refactorProvider.js +16 -0
  139. package/dist/refactors/addOrRemoveBracesToArrowFunction.d.ts +1 -0
  140. package/dist/refactors/addOrRemoveBracesToArrowFunction.js +86 -0
  141. package/dist/refactors/convertExport.d.ts +1 -0
  142. package/dist/refactors/convertExport.js +126 -0
  143. package/dist/refactors/convertImport.d.ts +1 -0
  144. package/dist/refactors/convertImport.js +116 -0
  145. package/dist/refactors/convertParamsToDestructuredObject.d.ts +1 -0
  146. package/dist/refactors/convertParamsToDestructuredObject.js +282 -0
  147. package/dist/refactors/convertStringOrTemplateLiteral.d.ts +1 -0
  148. package/dist/refactors/convertStringOrTemplateLiteral.js +148 -0
  149. package/dist/refactors/extractSymbol.d.ts +60 -0
  150. package/dist/refactors/extractSymbol.js +1281 -0
  151. package/dist/refactors/extractType.d.ts +1 -0
  152. package/dist/refactors/extractType.js +102 -0
  153. package/dist/refactors/moveToNewFile.d.ts +1 -0
  154. package/dist/refactors/moveToNewFile.js +477 -0
  155. package/dist/rename.d.ts +2 -0
  156. package/dist/rename.js +100 -0
  157. package/dist/services.d.ts +48 -0
  158. package/dist/services.js +1480 -0
  159. package/dist/signatureHelp.d.ts +8 -0
  160. package/dist/signatureHelp.js +414 -0
  161. package/dist/smartSelection.d.ts +2 -0
  162. package/dist/smartSelection.js +243 -0
  163. package/dist/stringCompletions.d.ts +4 -0
  164. package/dist/stringCompletions.js +220 -0
  165. package/dist/suggestionDiagnostics.d.ts +6 -0
  166. package/dist/suggestionDiagnostics.js +92 -0
  167. package/dist/symbolDisplay.d.ts +16 -0
  168. package/dist/symbolDisplay.js +400 -0
  169. package/dist/textChanges.d.ts +161 -0
  170. package/dist/textChanges.js +1163 -0
  171. package/dist/types.d.ts +908 -0
  172. package/dist/types.js +263 -0
  173. package/dist/utilities.d.ts +283 -0
  174. package/dist/utilities.js +1981 -0
  175. package/package.json +45 -3
  176. package/README.md +0 -3
@@ -0,0 +1,1720 @@
1
+ // Modificado de microsoft/TypeScript v3.9.10, src/services/completions.ts: o namespace virou módulo ES, com os imports explícitos.
2
+ import { CharacterCodes, ContextFlags, Debug, InternalSymbolName, LanguageVariant, NodeFlags, ScriptTarget, SignatureHelp, SymbolDisplay, SymbolDisplayPartKind, SymbolFlags, SyntaxKind, TypeFlags, addToSeen, arrayToSet, cast, createMap, createTextRangeFromSpan, createTextSpanFromBounds, createTextSpanFromNode, createUnderscoreEscapedMap, displayPart, filterMutate, find, findAncestor, findChildOfKind, findPrecedingToken, first, firstDefined, getCombinedLocalAndExportSymbolFlags, getContextualTypeFromParent, getEscapedTextOfIdentifierOrLiteral, getLineAndCharacterOfPosition, getNameForExportedSymbol, getNameOfDeclaration, getReplacementSpanForContextToken, getRootDeclaration, getSwitchedType, getSymbolId, getTokenAtPosition, getTouchingPropertyName, hasIndexSignature, hasInitializer, hasType, isAssertionExpression, isBinaryExpression, isBindingElement, isCallExpression, isCaseClause, isComputedPropertyName, isContextualKeyword, isDeclarationName, isEntityName, isEqualityOperatorKind, isExportAssignment, isExportSpecifier, isExpression, isExternalModuleSymbol, isFunctionLikeDeclaration, isFunctionLikeKind, isIdentifier, isIdentifierANonContextualKeyword, isIdentifierText, isInComment, isInString, isJsxAttribute, isJsxClosingElement, isJsxExpression, isJsxSpreadAttribute, isKeyword, isKnownSymbol, isLiteralImportTypeNode, isModuleDeclaration, isNamedExports, isNamedImportsOrExports, isObjectBindingPattern, isObjectLiteralExpression, isObjectTypeDeclaration, isPartOfTypeNode, isPossiblyTypeArgumentPosition, isPropertyAccessExpression, isPropertyNameLiteral, isSingleOrDoubleQuote, isSourceFile, isSpreadAssignment, isStatement, isString, isStringLiteralLike, isStringLiteralOrTemplate, isStringTextContainingNode, isTypeElement, isTypeKeyword, isTypeOfExpression, isVariableLike, last, lastOrUndefined, mapDefined, memoize, nodeIsMissing, or, positionBelongsToNode, positionIsASICandidate, pseudoBigIntToString, quote, rangeContainsPositionExclusive, skipAlias, some, startsWith, stringToToken, stripQuotes, textPart, timestamp, tokenToString, tryCast, tryGetImportFromModuleSpecifier, typeHasCallOrConstructSignatures, } from "./_namespaces/ts.js";
3
+ import { StringCompletions, } from "./_namespaces/ts.Completions.js";
4
+ // O alvo da configuração fixa (CK-24): o do nome que se oferece e o da conversão do nome de um módulo.
5
+ const languageVersion = ScriptTarget.ES2020;
6
+ let autoImportProvider;
7
+ /** Registra o auto-import do completion: quem o chama é a edição, ao carregar (CK-67). */
8
+ export function registerAutoImportProvider(provider) {
9
+ autoImportProvider = provider;
10
+ }
11
+ export var SortText;
12
+ (function (SortText) {
13
+ SortText["LocationPriority"] = "0";
14
+ SortText["OptionalMember"] = "1";
15
+ SortText["MemberDeclaredBySpreadAssignment"] = "2";
16
+ SortText["SuggestedClassMembers"] = "3";
17
+ SortText["GlobalsOrKeywords"] = "4";
18
+ SortText["AutoImportSuggestions"] = "5";
19
+ SortText["JavascriptIdentifiers"] = "6";
20
+ })(SortText || (SortText = {}));
21
+ var SymbolOriginInfoKind;
22
+ (function (SymbolOriginInfoKind) {
23
+ SymbolOriginInfoKind[SymbolOriginInfoKind["SymbolMember"] = 2] = "SymbolMember";
24
+ SymbolOriginInfoKind[SymbolOriginInfoKind["Export"] = 4] = "Export";
25
+ SymbolOriginInfoKind[SymbolOriginInfoKind["Promise"] = 8] = "Promise";
26
+ SymbolOriginInfoKind[SymbolOriginInfoKind["Nullable"] = 16] = "Nullable";
27
+ SymbolOriginInfoKind[SymbolOriginInfoKind["SymbolMemberNoExport"] = 2] = "SymbolMemberNoExport";
28
+ SymbolOriginInfoKind[SymbolOriginInfoKind["SymbolMemberExport"] = 6] = "SymbolMemberExport";
29
+ })(SymbolOriginInfoKind || (SymbolOriginInfoKind = {}));
30
+ function originIsSymbolMember(origin) {
31
+ return !!(origin.kind & 2 /* SymbolOriginInfoKind.SymbolMember */);
32
+ }
33
+ function originIsExport(origin) {
34
+ return !!(origin && origin.kind & 4 /* SymbolOriginInfoKind.Export */);
35
+ }
36
+ function originIsPromise(origin) {
37
+ return !!(origin.kind & 8 /* SymbolOriginInfoKind.Promise */);
38
+ }
39
+ function originIsNullableMember(origin) {
40
+ return !!(origin.kind & 16 /* SymbolOriginInfoKind.Nullable */);
41
+ }
42
+ var KeywordCompletionFilters;
43
+ (function (KeywordCompletionFilters) {
44
+ KeywordCompletionFilters[KeywordCompletionFilters["None"] = 0] = "None";
45
+ KeywordCompletionFilters[KeywordCompletionFilters["All"] = 1] = "All";
46
+ KeywordCompletionFilters[KeywordCompletionFilters["InterfaceElementKeywords"] = 2] = "InterfaceElementKeywords";
47
+ KeywordCompletionFilters[KeywordCompletionFilters["FunctionLikeBodyKeywords"] = 3] = "FunctionLikeBodyKeywords";
48
+ KeywordCompletionFilters[KeywordCompletionFilters["TypeAssertionKeywords"] = 4] = "TypeAssertionKeywords";
49
+ KeywordCompletionFilters[KeywordCompletionFilters["TypeKeywords"] = 5] = "TypeKeywords";
50
+ KeywordCompletionFilters[KeywordCompletionFilters["Last"] = 5] = "Last";
51
+ })(KeywordCompletionFilters || (KeywordCompletionFilters = {}));
52
+ var GlobalsSearch;
53
+ (function (GlobalsSearch) {
54
+ GlobalsSearch[GlobalsSearch["Continue"] = 0] = "Continue";
55
+ GlobalsSearch[GlobalsSearch["Success"] = 1] = "Success";
56
+ GlobalsSearch[GlobalsSearch["Fail"] = 2] = "Fail";
57
+ })(GlobalsSearch || (GlobalsSearch = {}));
58
+ export function getCompletionsAtPosition(host, program, log, sourceFile, position, preferences, triggerCharacter) {
59
+ const typeChecker = program.getTypeChecker();
60
+ const contextToken = findPrecedingToken(position, sourceFile);
61
+ if (triggerCharacter && !isInString(sourceFile, position, contextToken) && !isValidTrigger(sourceFile, triggerCharacter, contextToken, position)) {
62
+ return undefined;
63
+ }
64
+ const stringCompletions = StringCompletions.getStringLiteralCompletions(sourceFile, position, contextToken, typeChecker, host, log, preferences);
65
+ if (stringCompletions) {
66
+ return stringCompletions;
67
+ }
68
+ const completionData = getCompletionData(program, log, sourceFile, position, preferences, /*detailsEntryId*/ undefined, host);
69
+ if (!completionData) {
70
+ return undefined;
71
+ }
72
+ return completionInfoFromData(sourceFile, typeChecker, log, completionData, preferences);
73
+ }
74
+ function completionInfoFromData(sourceFile, typeChecker, log, completionData, preferences) {
75
+ const { symbols, completionKind, isInSnippetScope, isNewIdentifierLocation, location, propertyAccessToConvert, keywordFilters, literals, symbolToOriginInfoMap, isJsxInitializer, symbolToSortTextMap, } = completionData;
76
+ if (location && location.parent && isJsxClosingElement(location.parent)) {
77
+ // In the TypeScript JSX element, if such element is not defined. When users query for completion at closing tag,
78
+ // instead of simply giving unknown value, the completion will return the tag-name of an associated opening-element.
79
+ // For example:
80
+ // var x = <div> </ /*1*/
81
+ // The completion list at "1" will contain "div>" with type any
82
+ // And at `<div> </ /*1*/ >` (with a closing `>`), the completion list will contain "div".
83
+ const tagName = location.parent.parent.openingElement.tagName;
84
+ const hasClosingAngleBracket = !!findChildOfKind(location.parent, SyntaxKind.GreaterThanToken, sourceFile);
85
+ const entry = {
86
+ name: tagName.getFullText(sourceFile) + (hasClosingAngleBracket ? "" : ">"),
87
+ kind: "class" /* ScriptElementKind.classElement */,
88
+ kindModifiers: undefined,
89
+ sortText: SortText.LocationPriority,
90
+ };
91
+ return { isGlobalCompletion: false, isMemberCompletion: true, isNewIdentifierLocation: false, entries: [entry] };
92
+ }
93
+ const entries = [];
94
+ if (!isNewIdentifierLocation && (!symbols || symbols.length === 0) && keywordFilters === 0 /* KeywordCompletionFilters.None */) {
95
+ return undefined;
96
+ }
97
+ getCompletionEntriesFromSymbols(symbols, entries,
98
+ /* contextToken */ undefined, location, sourceFile, typeChecker, languageVersion, log, completionKind, preferences, propertyAccessToConvert, completionData.isJsxIdentifierExpected, isJsxInitializer, symbolToOriginInfoMap, symbolToSortTextMap);
99
+ if (keywordFilters !== 0 /* KeywordCompletionFilters.None */) {
100
+ const entryNames = arrayToSet(entries, e => e.name);
101
+ for (const keywordEntry of getTypescriptKeywordCompletions(keywordFilters)) {
102
+ if (!entryNames.has(keywordEntry.name)) {
103
+ entries.push(keywordEntry);
104
+ }
105
+ }
106
+ }
107
+ for (const literal of literals) {
108
+ entries.push(createCompletionEntryForLiteral(literal, preferences));
109
+ }
110
+ return { isGlobalCompletion: isInSnippetScope, isMemberCompletion: isMemberCompletionKind(completionKind), isNewIdentifierLocation, entries };
111
+ }
112
+ function isMemberCompletionKind(kind) {
113
+ switch (kind) {
114
+ case 0 /* CompletionKind.ObjectPropertyDeclaration */:
115
+ case 3 /* CompletionKind.MemberLike */:
116
+ case 2 /* CompletionKind.PropertyAccess */:
117
+ return true;
118
+ default:
119
+ return false;
120
+ }
121
+ }
122
+ function completionNameForLiteral(literal, preferences) {
123
+ return typeof literal === "object" ? pseudoBigIntToString(literal) + "n" :
124
+ isString(literal) ? quote(literal, preferences) : JSON.stringify(literal);
125
+ }
126
+ function createCompletionEntryForLiteral(literal, preferences) {
127
+ return { name: completionNameForLiteral(literal, preferences), kind: "string" /* ScriptElementKind.string */, kindModifiers: "" /* ScriptElementKindModifier.none */, sortText: SortText.LocationPriority };
128
+ }
129
+ function createCompletionEntry(symbol, sortText, contextToken, location, sourceFile, typeChecker, name, needsConvertPropertyAccess, origin, propertyAccessToConvert, isJsxInitializer, preferences) {
130
+ let insertText;
131
+ let replacementSpan = getReplacementSpanForContextToken(contextToken);
132
+ const insertQuestionDot = origin && originIsNullableMember(origin);
133
+ const useBraces = origin && originIsSymbolMember(origin) || needsConvertPropertyAccess;
134
+ // O `needsConvertPropertyAccess` só vem com um acesso a converter; um global de nome que não é identificador não o
135
+ // tem.
136
+ if ((useBraces || insertQuestionDot) && propertyAccessToConvert) {
137
+ insertText = useBraces ? needsConvertPropertyAccess ? `[${quotePropertyName(name, preferences)}]` : `[${name}]` : name;
138
+ if (insertQuestionDot || propertyAccessToConvert.questionDotToken) {
139
+ insertText = `?.${insertText}`;
140
+ }
141
+ const dot = findChildOfKind(propertyAccessToConvert, SyntaxKind.DotToken, sourceFile) ||
142
+ findChildOfKind(propertyAccessToConvert, SyntaxKind.QuestionDotToken, sourceFile);
143
+ if (!dot) {
144
+ return undefined;
145
+ }
146
+ // If the text after the '.' starts with this name, write over it. Else, add new text.
147
+ const end = startsWith(name, propertyAccessToConvert.name.text) ? propertyAccessToConvert.name.end : dot.end;
148
+ replacementSpan = createTextSpanFromBounds(dot.getStart(sourceFile), end);
149
+ }
150
+ if (isJsxInitializer) {
151
+ if (insertText === undefined)
152
+ insertText = name;
153
+ insertText = `{${insertText}}`;
154
+ if (typeof isJsxInitializer !== "boolean") {
155
+ replacementSpan = createTextSpanFromNode(isJsxInitializer, sourceFile);
156
+ }
157
+ }
158
+ if (origin && originIsPromise(origin) && propertyAccessToConvert) {
159
+ if (insertText === undefined)
160
+ insertText = name;
161
+ const precedingToken = findPrecedingToken(propertyAccessToConvert.pos, sourceFile);
162
+ let awaitText = "";
163
+ if (precedingToken && positionIsASICandidate(precedingToken.end, precedingToken.parent, sourceFile)) {
164
+ awaitText = ";";
165
+ }
166
+ awaitText += `(await ${propertyAccessToConvert.expression.getText()})`;
167
+ insertText = needsConvertPropertyAccess ? `${awaitText}${insertText}` : `${awaitText}${insertQuestionDot ? "?." : "."}${insertText}`;
168
+ replacementSpan = createTextSpanFromBounds(propertyAccessToConvert.getStart(sourceFile), propertyAccessToConvert.end);
169
+ }
170
+ if (insertText !== undefined && !preferences.includeCompletionsWithInsertText) {
171
+ return undefined;
172
+ }
173
+ // TODO(drosen): Right now we just permit *all* semantic meanings when calling
174
+ // 'getSymbolKind' which is permissible given that it is backwards compatible; but
175
+ // really we should consider passing the meaning for the node so that we don't report
176
+ // that a suggestion for a value is an interface. We COULD also just do what
177
+ // 'getSymbolModifiers' does, which is to use the first declaration.
178
+ // Use a 'sortText' of 0' so that all symbol completion entries come before any other
179
+ // entries (like JavaScript identifier entries).
180
+ return {
181
+ name,
182
+ kind: SymbolDisplay.getSymbolKind(typeChecker, symbol, location), // TODO: GH#18217
183
+ kindModifiers: SymbolDisplay.getSymbolModifiers(symbol),
184
+ sortText,
185
+ source: getSourceFromOrigin(origin),
186
+ hasAction: origin && originIsExport(origin) || undefined,
187
+ // Na tag, também a marca do item recomendado, que só o enum e a classe davam (CK-02).
188
+ insertText,
189
+ replacementSpan,
190
+ };
191
+ }
192
+ function quotePropertyName(name, preferences) {
193
+ if (/^\d+$/.test(name)) {
194
+ return name;
195
+ }
196
+ return quote(name, preferences);
197
+ }
198
+ function getSourceFromOrigin(origin) {
199
+ if (originIsExport(origin)) {
200
+ return stripQuotes(origin.moduleSymbol.name);
201
+ }
202
+ }
203
+ export function getCompletionEntriesFromSymbols(symbols, entries, contextToken, location, sourceFile, typeChecker, target, log, kind, preferences, propertyAccessToConvert, jsxIdentifierExpected, isJsxInitializer, symbolToOriginInfoMap, symbolToSortTextMap) {
204
+ const start = timestamp();
205
+ // Tracks unique names.
206
+ // Value is set to false for global variables or completions from external module exports, because we can have multiple of those;
207
+ // true otherwise. Based on the order we add things we will always see locals first, then globals, then module exports.
208
+ // So adding a completion for a local will prevent us from adding completions for external module exports sharing the same name.
209
+ const uniques = createMap();
210
+ for (const symbol of symbols) {
211
+ const origin = symbolToOriginInfoMap ? symbolToOriginInfoMap[getSymbolId(symbol)] : undefined;
212
+ const info = getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, !!jsxIdentifierExpected);
213
+ if (!info) {
214
+ continue;
215
+ }
216
+ const { name, needsConvertPropertyAccess } = info;
217
+ if (uniques.get(name)) {
218
+ continue;
219
+ }
220
+ const entry = createCompletionEntry(symbol, symbolToSortTextMap && symbolToSortTextMap[getSymbolId(symbol)] || SortText.LocationPriority, contextToken, location, sourceFile, typeChecker, name, needsConvertPropertyAccess, origin, propertyAccessToConvert, isJsxInitializer, preferences);
221
+ if (!entry) {
222
+ continue;
223
+ }
224
+ /** True for locals; false for globals, module exports from other files, `this.` completions. */
225
+ const shouldShadowLaterSymbols = !origin && !(symbol.parent === undefined && !some(symbol.declarations, d => d.getSourceFile() === location.getSourceFile()));
226
+ uniques.set(name, shouldShadowLaterSymbols);
227
+ entries.push(entry);
228
+ }
229
+ log("getCompletionsAtPosition: getCompletionEntriesFromSymbols: " + (timestamp() - start));
230
+ // Prevent consumers of this map from having to worry about
231
+ // the boolean value. Externally, it should be seen as the
232
+ // set of all names.
233
+ return {
234
+ has: name => uniques.has(name),
235
+ add: name => uniques.set(name, true),
236
+ };
237
+ }
238
+ function getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences) {
239
+ const completionData = getCompletionData(program, log, sourceFile, position, { includeCompletionsForModuleExports: true, includeCompletionsWithInsertText: true }, entryId, host);
240
+ if (!completionData) {
241
+ return { type: "none" };
242
+ }
243
+ const { symbols, literals, location, completionKind, symbolToOriginInfoMap, previousToken, isJsxInitializer, isTypeOnlyLocation } = completionData;
244
+ const literal = find(literals, l => completionNameForLiteral(l, preferences) === entryId.name);
245
+ if (literal !== undefined)
246
+ return { type: "literal", literal };
247
+ // Find the symbol with the matching entry name.
248
+ // We don't need to perform character checks here because we're only comparing the
249
+ // name against 'entryName' (which is known to be good), not building a new
250
+ // completion entry.
251
+ return firstDefined(symbols, (symbol) => {
252
+ const origin = symbolToOriginInfoMap[getSymbolId(symbol)];
253
+ const info = getCompletionEntryDisplayNameForSymbol(symbol, languageVersion, origin, completionKind, completionData.isJsxIdentifierExpected);
254
+ return info && info.name === entryId.name && getSourceFromOrigin(origin) === entryId.source
255
+ ? { type: "symbol", symbol, location, symbolToOriginInfoMap, previousToken, isJsxInitializer, isTypeOnlyLocation }
256
+ : undefined;
257
+ }) || { type: "none" };
258
+ }
259
+ /**
260
+ * O detalhe de um item do completion. Na tag, quem chama monta o contexto de formatação, que só a ação do auto-import
261
+ * usa; aqui, as opções de formatação seguem cruas até o auto-import da edição, que monta o contexto (CK-67).
262
+ */
263
+ export function getCompletionEntryDetails(program, log, sourceFile, position, entryId, host, formatOptions, preferences, cancellationToken) {
264
+ const typeChecker = program.getTypeChecker();
265
+ const { name } = entryId;
266
+ const contextToken = findPrecedingToken(position, sourceFile);
267
+ if (isInString(sourceFile, position, contextToken)) {
268
+ return StringCompletions.getStringLiteralCompletionDetails(name, sourceFile, position, contextToken, typeChecker, host, cancellationToken);
269
+ }
270
+ // Todos os símbolos do completion, calculados de novo.
271
+ const symbolCompletion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences);
272
+ switch (symbolCompletion.type) {
273
+ case "symbol": {
274
+ const { symbol, location, symbolToOriginInfoMap, previousToken } = symbolCompletion;
275
+ const { codeActions, sourceDisplay } = getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, typeChecker, host, sourceFile, position, previousToken, formatOptions, preferences);
276
+ return createCompletionDetailsForSymbol(symbol, typeChecker, sourceFile, location, cancellationToken, codeActions, sourceDisplay); // TODO: GH#18217
277
+ }
278
+ case "literal": {
279
+ const { literal } = symbolCompletion;
280
+ return createSimpleDetails(completionNameForLiteral(literal, preferences), "string" /* ScriptElementKind.string */, typeof literal === "string" ? SymbolDisplayPartKind.stringLiteral : SymbolDisplayPartKind.numericLiteral);
281
+ }
282
+ case "none":
283
+ // Didn't find a symbol with this name. See if we can find a keyword instead.
284
+ return allKeywordsCompletions().some(c => c.name === name) ? createSimpleDetails(name, "keyword" /* ScriptElementKind.keyword */, SymbolDisplayPartKind.keyword) : undefined;
285
+ default:
286
+ Debug.assertNever(symbolCompletion);
287
+ }
288
+ }
289
+ function createSimpleDetails(name, kind, kind2) {
290
+ return createCompletionDetails(name, "" /* ScriptElementKindModifier.none */, kind, [displayPart(name, kind2)]);
291
+ }
292
+ export function createCompletionDetailsForSymbol(symbol, checker, sourceFile, location, cancellationToken, codeActions, sourceDisplay) {
293
+ const { displayParts, documentation, symbolKind, tags } = checker.runWithCancellationToken(cancellationToken, checker => SymbolDisplay.getSymbolDisplayPartsDocumentationAndSymbolKind(checker, symbol, sourceFile, location, location, 7 /* SemanticMeaning.All */));
294
+ return createCompletionDetails(symbol.name, SymbolDisplay.getSymbolModifiers(symbol), symbolKind, displayParts, documentation, tags, codeActions, sourceDisplay);
295
+ }
296
+ export function createCompletionDetails(name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source) {
297
+ return { name, kindModifiers, kind, displayParts, documentation, tags, codeActions, source };
298
+ }
299
+ function getCompletionEntryCodeActionsAndSourceDisplay(symbolToOriginInfoMap, symbol, program, checker, host, sourceFile, position, previousToken, formatOptions, preferences) {
300
+ const symbolOriginInfo = symbolToOriginInfoMap[getSymbolId(symbol)];
301
+ // A origem de um módulo só existe com o auto-import, e o auto-import, com a edição registrada (CK-67).
302
+ if (!symbolOriginInfo || !originIsExport(symbolOriginInfo) || !autoImportProvider) {
303
+ return { codeActions: undefined, sourceDisplay: undefined };
304
+ }
305
+ const { moduleSymbol } = symbolOriginInfo;
306
+ const exportedSymbol = checker.getMergedSymbol(skipAlias(symbol.exportSymbol || symbol, checker));
307
+ const { moduleSpecifier, codeAction } = autoImportProvider.getImportCompletionAction(exportedSymbol, moduleSymbol, sourceFile, getNameForExportedSymbol(symbol, languageVersion), host, program, formatOptions, previousToken && isIdentifier(previousToken) ? previousToken.getStart(sourceFile) : position, preferences);
308
+ return { sourceDisplay: [textPart(moduleSpecifier)], codeActions: [codeAction] };
309
+ }
310
+ export function getCompletionEntrySymbol(program, log, sourceFile, position, entryId, host, preferences) {
311
+ const completion = getSymbolCompletionFromEntryId(program, log, sourceFile, position, entryId, host, preferences);
312
+ return completion.type === "symbol" ? completion.symbol : undefined;
313
+ }
314
+ export var CompletionKind;
315
+ (function (CompletionKind) {
316
+ CompletionKind[CompletionKind["ObjectPropertyDeclaration"] = 0] = "ObjectPropertyDeclaration";
317
+ CompletionKind[CompletionKind["Global"] = 1] = "Global";
318
+ CompletionKind[CompletionKind["PropertyAccess"] = 2] = "PropertyAccess";
319
+ CompletionKind[CompletionKind["MemberLike"] = 3] = "MemberLike";
320
+ CompletionKind[CompletionKind["String"] = 4] = "String";
321
+ CompletionKind[CompletionKind["None"] = 5] = "None";
322
+ })(CompletionKind || (CompletionKind = {}));
323
+ function getContextualType(previousToken, position, sourceFile, checker) {
324
+ const { parent } = previousToken;
325
+ switch (previousToken.kind) {
326
+ case SyntaxKind.Identifier:
327
+ return getContextualTypeFromParent(previousToken, checker);
328
+ case SyntaxKind.EqualsToken:
329
+ switch (parent.kind) {
330
+ case SyntaxKind.VariableDeclaration:
331
+ return checker.getContextualType(parent.initializer); // TODO: GH#18217
332
+ case SyntaxKind.BinaryExpression:
333
+ return checker.getTypeAtLocation(parent.left);
334
+ case SyntaxKind.JsxAttribute:
335
+ return checker.getContextualTypeForJsxAttribute(parent);
336
+ default:
337
+ return undefined;
338
+ }
339
+ case SyntaxKind.CaseKeyword:
340
+ return getSwitchedType(cast(parent, isCaseClause), checker);
341
+ case SyntaxKind.OpenBraceToken:
342
+ return isJsxExpression(parent) && parent.parent.kind !== SyntaxKind.JsxElement ? checker.getContextualTypeForJsxAttribute(parent.parent) : undefined;
343
+ default:
344
+ const argInfo = SignatureHelp.getArgumentInfoForCompletions(previousToken, position, sourceFile);
345
+ return argInfo ?
346
+ // At `,`, treat this as the next argument after the comma.
347
+ checker.getContextualTypeForArgumentAtIndex(argInfo.invocation, argInfo.argumentIndex + (previousToken.kind === SyntaxKind.CommaToken ? 1 : 0)) :
348
+ isEqualityOperatorKind(previousToken.kind) && isBinaryExpression(parent) && isEqualityOperatorKind(parent.operatorToken.kind) ?
349
+ // o completion em `x ==/**/` é o do lado direito
350
+ checker.getTypeAtLocation(parent.left) :
351
+ checker.getContextualType(previousToken);
352
+ }
353
+ }
354
+ function getFirstSymbolInChain(symbol, enclosingDeclaration, checker) {
355
+ const chain = checker.getAccessibleSymbolChain(symbol, enclosingDeclaration, /*meaning*/ SymbolFlags.All, /*useOnlyExternalAliasing*/ false);
356
+ if (chain)
357
+ return first(chain);
358
+ return symbol.parent && (isModuleSymbol(symbol.parent) ? symbol : getFirstSymbolInChain(symbol.parent, enclosingDeclaration, checker));
359
+ }
360
+ function isModuleSymbol(symbol) {
361
+ return symbol.declarations.some(d => d.kind === SyntaxKind.SourceFile);
362
+ }
363
+ function getCompletionData(program, log, sourceFile, position, preferences, detailsEntryId, host) {
364
+ const typeChecker = program.getTypeChecker();
365
+ let start = timestamp();
366
+ const currentToken = getTokenAtPosition(sourceFile, position);
367
+ log("getCompletionData: Get current token: " + (timestamp() - start));
368
+ start = timestamp();
369
+ const insideComment = isInComment(sourceFile, position, currentToken);
370
+ log("getCompletionData: Is inside comment: " + (timestamp() - start));
371
+ let isInSnippetScope = false;
372
+ // Dentro de um comentário não há completion. Na tag, o comentário do JSDoc tinha o das tags e o do tipo de uma tag,
373
+ // e a cópia não tem o JSDoc (CK-03).
374
+ if (insideComment) {
375
+ log("Returning an empty list because completion was inside a regular comment or plain text part of a JsDoc comment.");
376
+ return undefined;
377
+ }
378
+ start = timestamp();
379
+ const previousToken = findPrecedingToken(position, sourceFile, /*startNode*/ undefined); // TODO: GH#18217
380
+ log("getCompletionData: Get previous token 1: " + (timestamp() - start));
381
+ // The decision to provide completion depends on the contextToken, which is determined through the previousToken.
382
+ // Note: 'previousToken' (and thus 'contextToken') can be undefined if we are the beginning of the file
383
+ let contextToken = previousToken;
384
+ // Check if the caret is at the end of an identifier; this is a partial identifier that we want to complete: e.g. a.toS|
385
+ // Skip this partial identifier and adjust the contextToken to the token that precedes it.
386
+ if (contextToken && position <= contextToken.end && (isIdentifier(contextToken) || isKeyword(contextToken.kind))) {
387
+ const start = timestamp();
388
+ contextToken = findPrecedingToken(contextToken.getFullStart(), sourceFile, /*startNode*/ undefined); // TODO: GH#18217
389
+ log("getCompletionData: Get previous token 2: " + (timestamp() - start));
390
+ }
391
+ // Find the node where completion is requested on.
392
+ // Also determine whether we are trying to complete with members of that node
393
+ // or attributes of a JSX tag.
394
+ let node = currentToken;
395
+ let propertyAccessToConvert;
396
+ let isRightOfDot = false;
397
+ let isRightOfQuestionDot = false;
398
+ let isRightOfOpenTag = false;
399
+ let isStartingCloseTag = false;
400
+ let isJsxInitializer = false;
401
+ let isJsxIdentifierExpected = false;
402
+ let location = getTouchingPropertyName(sourceFile, position);
403
+ if (contextToken) {
404
+ // Bail out if this is a known invalid completion location
405
+ if (isCompletionListBlocker(contextToken)) {
406
+ log("Returning an empty list because completion was requested in an invalid position.");
407
+ return undefined;
408
+ }
409
+ let parent = contextToken.parent;
410
+ if (contextToken.kind === SyntaxKind.DotToken || contextToken.kind === SyntaxKind.QuestionDotToken) {
411
+ isRightOfDot = contextToken.kind === SyntaxKind.DotToken;
412
+ isRightOfQuestionDot = contextToken.kind === SyntaxKind.QuestionDotToken;
413
+ switch (parent.kind) {
414
+ case SyntaxKind.PropertyAccessExpression:
415
+ propertyAccessToConvert = parent;
416
+ node = propertyAccessToConvert.expression;
417
+ if (node.end === contextToken.pos &&
418
+ isCallExpression(node) &&
419
+ node.getChildCount(sourceFile) &&
420
+ last(node.getChildren(sourceFile)).kind !== SyntaxKind.CloseParenToken) {
421
+ // This is likely dot from incorrectly parsed call expression and user is starting to write spread
422
+ // eg: Math.min(./**/)
423
+ return undefined;
424
+ }
425
+ break;
426
+ case SyntaxKind.QualifiedName:
427
+ node = parent.left;
428
+ break;
429
+ case SyntaxKind.ModuleDeclaration:
430
+ node = parent.name;
431
+ break;
432
+ case SyntaxKind.ImportType:
433
+ node = parent;
434
+ break;
435
+ default:
436
+ // There is nothing that precedes the dot, so this likely just a stray character
437
+ // or leading into a '...' token. Just bail out instead.
438
+ return undefined;
439
+ }
440
+ }
441
+ else if (sourceFile.languageVariant === LanguageVariant.JSX) {
442
+ // <UI.Test /* completion position */ />
443
+ // If the tagname is a property access expression, we will then walk up to the top most of property access expression.
444
+ // Then, try to get a JSX container and its associated attributes type.
445
+ if (parent && parent.kind === SyntaxKind.PropertyAccessExpression) {
446
+ contextToken = parent;
447
+ parent = parent.parent;
448
+ }
449
+ // Fix location
450
+ if (currentToken.parent === location) {
451
+ switch (currentToken.kind) {
452
+ case SyntaxKind.GreaterThanToken:
453
+ if (currentToken.parent.kind === SyntaxKind.JsxElement || currentToken.parent.kind === SyntaxKind.JsxOpeningElement) {
454
+ location = currentToken;
455
+ }
456
+ break;
457
+ case SyntaxKind.SlashToken:
458
+ if (currentToken.parent.kind === SyntaxKind.JsxSelfClosingElement) {
459
+ location = currentToken;
460
+ }
461
+ break;
462
+ }
463
+ }
464
+ switch (parent.kind) {
465
+ case SyntaxKind.JsxClosingElement:
466
+ if (contextToken.kind === SyntaxKind.SlashToken) {
467
+ isStartingCloseTag = true;
468
+ location = contextToken;
469
+ }
470
+ break;
471
+ case SyntaxKind.BinaryExpression:
472
+ if (!binaryExpressionMayBeOpenTag(parent)) {
473
+ break;
474
+ }
475
+ // falls through
476
+ case SyntaxKind.JsxSelfClosingElement:
477
+ case SyntaxKind.JsxElement:
478
+ case SyntaxKind.JsxOpeningElement:
479
+ isJsxIdentifierExpected = true;
480
+ if (contextToken.kind === SyntaxKind.LessThanToken) {
481
+ isRightOfOpenTag = true;
482
+ location = contextToken;
483
+ }
484
+ break;
485
+ case SyntaxKind.JsxAttribute:
486
+ switch (previousToken.kind) {
487
+ case SyntaxKind.EqualsToken:
488
+ isJsxInitializer = true;
489
+ break;
490
+ case SyntaxKind.Identifier:
491
+ isJsxIdentifierExpected = true;
492
+ // For `<div x=[|f/**/|]`, `parent` will be `x` and `previousToken.parent` will be `f` (which is its own JsxAttribute)
493
+ // Note for `<div someBool f>` we don't want to treat this as a jsx inializer, instead it's the attribute name.
494
+ if (parent !== previousToken.parent &&
495
+ !parent.initializer &&
496
+ findChildOfKind(parent, SyntaxKind.EqualsToken, sourceFile)) {
497
+ isJsxInitializer = previousToken;
498
+ }
499
+ }
500
+ break;
501
+ }
502
+ }
503
+ }
504
+ const semanticStart = timestamp();
505
+ let completionKind = 5 /* CompletionKind.None */;
506
+ let isNewIdentifierLocation = false;
507
+ let keywordFilters = 0 /* KeywordCompletionFilters.None */;
508
+ // This also gets mutated in nested-functions after the return
509
+ let symbols = [];
510
+ const symbolToOriginInfoMap = [];
511
+ const symbolToSortTextMap = [];
512
+ const isTypeOnly = isTypeOnlyCompletion();
513
+ if (isRightOfDot || isRightOfQuestionDot) {
514
+ getTypeScriptMemberSymbols();
515
+ }
516
+ else if (isRightOfOpenTag) {
517
+ const tagSymbols = typeChecker.getJsxIntrinsicTagNamesAt(location);
518
+ Debug.assertEachIsDefined(tagSymbols, "getJsxIntrinsicTagNames() should all be defined");
519
+ tryGetGlobalSymbols();
520
+ symbols = tagSymbols.concat(symbols);
521
+ completionKind = 3 /* CompletionKind.MemberLike */;
522
+ keywordFilters = 0 /* KeywordCompletionFilters.None */;
523
+ }
524
+ else if (isStartingCloseTag) {
525
+ const tagName = contextToken.parent.parent.openingElement.tagName;
526
+ const tagSymbol = typeChecker.getSymbolAtLocation(tagName);
527
+ if (tagSymbol) {
528
+ symbols = [tagSymbol];
529
+ }
530
+ completionKind = 3 /* CompletionKind.MemberLike */;
531
+ keywordFilters = 0 /* KeywordCompletionFilters.None */;
532
+ }
533
+ else {
534
+ // For JavaScript or TypeScript, if we're not after a dot, then just try to get the
535
+ // global symbols in scope. These results should be valid for either language as
536
+ // the set of symbols that can be referenced from this location.
537
+ if (!tryGetGlobalSymbols()) {
538
+ return undefined;
539
+ }
540
+ }
541
+ log("getCompletionData: Semantic work: " + (timestamp() - semanticStart));
542
+ const contextualType = previousToken && getContextualType(previousToken, position, sourceFile, typeChecker);
543
+ const literals = mapDefined(contextualType && (contextualType.isUnion() ? contextualType.types : [contextualType]), t => t.isLiteral() ? t.value : undefined);
544
+ // Na tag, o tipo esperado dava também o item recomendado, que só o enum e a classe davam (CK-02).
545
+ return {
546
+ symbols,
547
+ completionKind,
548
+ isInSnippetScope,
549
+ propertyAccessToConvert,
550
+ isNewIdentifierLocation,
551
+ location,
552
+ keywordFilters,
553
+ literals,
554
+ symbolToOriginInfoMap,
555
+ previousToken,
556
+ isJsxInitializer,
557
+ symbolToSortTextMap,
558
+ isTypeOnlyLocation: isTypeOnly,
559
+ isJsxIdentifierExpected,
560
+ };
561
+ function getTypeScriptMemberSymbols() {
562
+ // Right of dot member completion list
563
+ completionKind = 2 /* CompletionKind.PropertyAccess */;
564
+ // Since this is qualified name check it's a type node location
565
+ const isImportType = isLiteralImportTypeNode(node);
566
+ const isTypeLocation = (isImportType && !node.isTypeOf)
567
+ || isPartOfTypeNode(node.parent)
568
+ || isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker);
569
+ if (isEntityName(node) || isImportType) {
570
+ const isNamespaceName = isModuleDeclaration(node.parent);
571
+ if (isNamespaceName)
572
+ isNewIdentifierLocation = true;
573
+ let symbol = typeChecker.getSymbolAtLocation(node);
574
+ if (symbol) {
575
+ symbol = skipAlias(symbol, typeChecker);
576
+ if (symbol.flags & SymbolFlags.Module) {
577
+ // os membros do módulo
578
+ const exportedSymbols = typeChecker.getExportsOfModule(symbol);
579
+ Debug.assertEachIsDefined(exportedSymbols, "getExportsOfModule() should all be defined");
580
+ const isValidValueAccess = (symbol) => typeChecker.isValidPropertyAccess(isImportType ? node : (node.parent), symbol.name);
581
+ const isValidTypeAccess = (symbol) => symbolCanBeReferencedAtTypeLocation(symbol);
582
+ const isValidAccess = isNamespaceName
583
+ // At `namespace N.M/**/`, if this is the only declaration of `M`, don't include `M` as a completion.
584
+ ? symbol => !!(symbol.flags & SymbolFlags.Namespace) && !symbol.declarations.every(d => d.parent === node.parent)
585
+ : isTypeLocation ? isValidTypeAccess : isValidValueAccess;
586
+ for (const exportedSymbol of exportedSymbols) {
587
+ if (isValidAccess(exportedSymbol)) {
588
+ symbols.push(exportedSymbol);
589
+ }
590
+ }
591
+ // If the module is merged with a value, we must get the type of the class and add its propertes (for inherited static methods).
592
+ if (!isTypeLocation &&
593
+ symbol.declarations &&
594
+ symbol.declarations.some(d => d.kind !== SyntaxKind.SourceFile && d.kind !== SyntaxKind.ModuleDeclaration)) {
595
+ let type = typeChecker.getTypeOfSymbolAtLocation(symbol, node).getNonOptionalType();
596
+ let insertQuestionDot = false;
597
+ if (type.isNullableType()) {
598
+ const canCorrectToQuestionDot = isRightOfDot &&
599
+ !isRightOfQuestionDot &&
600
+ preferences.includeAutomaticOptionalChainCompletions !== false;
601
+ if (canCorrectToQuestionDot || isRightOfQuestionDot) {
602
+ type = type.getNonNullableType();
603
+ if (canCorrectToQuestionDot) {
604
+ insertQuestionDot = true;
605
+ }
606
+ }
607
+ }
608
+ addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot);
609
+ }
610
+ return;
611
+ }
612
+ }
613
+ }
614
+ if (!isTypeLocation) {
615
+ let type = typeChecker.getTypeAtLocation(node).getNonOptionalType();
616
+ let insertQuestionDot = false;
617
+ if (type.isNullableType()) {
618
+ const canCorrectToQuestionDot = isRightOfDot &&
619
+ !isRightOfQuestionDot &&
620
+ preferences.includeAutomaticOptionalChainCompletions !== false;
621
+ if (canCorrectToQuestionDot || isRightOfQuestionDot) {
622
+ type = type.getNonNullableType();
623
+ if (canCorrectToQuestionDot) {
624
+ insertQuestionDot = true;
625
+ }
626
+ }
627
+ }
628
+ addTypeProperties(type, !!(node.flags & NodeFlags.AwaitContext), insertQuestionDot);
629
+ }
630
+ }
631
+ function addTypeProperties(type, insertAwait, insertQuestionDot) {
632
+ isNewIdentifierLocation = !!type.getStringIndexType();
633
+ if (isRightOfQuestionDot && some(type.getCallSignatures())) {
634
+ isNewIdentifierLocation = true;
635
+ }
636
+ const propertyAccess = node.kind === SyntaxKind.ImportType ? node : node.parent;
637
+ for (const symbol of type.getApparentProperties()) {
638
+ if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, type, symbol)) {
639
+ addPropertySymbol(symbol, /*insertAwait*/ false, insertQuestionDot);
640
+ }
641
+ }
642
+ if (insertAwait && preferences.includeCompletionsWithInsertText) {
643
+ const promiseType = typeChecker.getPromisedTypeOfPromise(type);
644
+ if (promiseType) {
645
+ for (const symbol of promiseType.getApparentProperties()) {
646
+ if (typeChecker.isValidPropertyAccessForCompletions(propertyAccess, promiseType, symbol)) {
647
+ addPropertySymbol(symbol, /* insertAwait */ true, insertQuestionDot);
648
+ }
649
+ }
650
+ }
651
+ }
652
+ }
653
+ function addPropertySymbol(symbol, insertAwait, insertQuestionDot) {
654
+ // For a computed property with an accessible name like `Symbol.iterator`,
655
+ // we'll add a completion for the *name* `Symbol` instead of for the property.
656
+ // If this is e.g. [Symbol.iterator], add a completion for `Symbol`.
657
+ const computedPropertyName = firstDefined(symbol.declarations, decl => tryCast(getNameOfDeclaration(decl), isComputedPropertyName));
658
+ if (computedPropertyName) {
659
+ const leftMostName = getLeftMostName(computedPropertyName.expression); // The completion is for `Symbol`, not `iterator`.
660
+ const nameSymbol = leftMostName && typeChecker.getSymbolAtLocation(leftMostName);
661
+ // If this is nested like for `namespace N { export const sym = Symbol(); }`, we'll add the completion for `N`.
662
+ const firstAccessibleSymbol = nameSymbol && getFirstSymbolInChain(nameSymbol, contextToken, typeChecker);
663
+ if (firstAccessibleSymbol && !symbolToOriginInfoMap[getSymbolId(firstAccessibleSymbol)]) {
664
+ symbols.push(firstAccessibleSymbol);
665
+ const moduleSymbol = firstAccessibleSymbol.parent;
666
+ symbolToOriginInfoMap[getSymbolId(firstAccessibleSymbol)] =
667
+ !moduleSymbol || !isExternalModuleSymbol(moduleSymbol)
668
+ ? { kind: getNullableSymbolOriginInfoKind(2 /* SymbolOriginInfoKind.SymbolMemberNoExport */) }
669
+ : { kind: getNullableSymbolOriginInfoKind(6 /* SymbolOriginInfoKind.SymbolMemberExport */), moduleSymbol, isDefaultExport: false };
670
+ }
671
+ else if (preferences.includeCompletionsWithInsertText) {
672
+ addSymbolOriginInfo(symbol);
673
+ symbols.push(symbol);
674
+ }
675
+ }
676
+ else {
677
+ addSymbolOriginInfo(symbol);
678
+ symbols.push(symbol);
679
+ }
680
+ function addSymbolOriginInfo(symbol) {
681
+ if (preferences.includeCompletionsWithInsertText) {
682
+ if (insertAwait && !symbolToOriginInfoMap[getSymbolId(symbol)]) {
683
+ symbolToOriginInfoMap[getSymbolId(symbol)] = { kind: getNullableSymbolOriginInfoKind(8 /* SymbolOriginInfoKind.Promise */) };
684
+ }
685
+ else if (insertQuestionDot) {
686
+ symbolToOriginInfoMap[getSymbolId(symbol)] = { kind: 16 /* SymbolOriginInfoKind.Nullable */ };
687
+ }
688
+ }
689
+ }
690
+ function getNullableSymbolOriginInfoKind(kind) {
691
+ return insertQuestionDot ? kind | 16 /* SymbolOriginInfoKind.Nullable */ : kind;
692
+ }
693
+ }
694
+ /** Given 'a.b.c', returns 'a'. */
695
+ function getLeftMostName(e) {
696
+ return isIdentifier(e) ? e : isPropertyAccessExpression(e) ? getLeftMostName(e.expression) : undefined;
697
+ }
698
+ function tryGetGlobalSymbols() {
699
+ const result = tryGetObjectLikeCompletionSymbols()
700
+ || tryGetImportOrExportClauseCompletionSymbols()
701
+ || tryGetLocalNamedExportCompletionSymbols()
702
+ || tryGetClassLikeCompletionSymbols()
703
+ || tryGetJsxCompletionSymbols()
704
+ || (getGlobalCompletions(), 1 /* GlobalsSearch.Success */);
705
+ return result === 1 /* GlobalsSearch.Success */;
706
+ }
707
+ function tryGetJsxCompletionSymbols() {
708
+ const jsxContainer = tryGetContainingJsxElement(contextToken);
709
+ // Cursor is inside a JSX self-closing element or opening element
710
+ const attrsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes);
711
+ if (!attrsType)
712
+ return 0 /* GlobalsSearch.Continue */;
713
+ const completionsType = jsxContainer && typeChecker.getContextualType(jsxContainer.attributes, ContextFlags.Completions);
714
+ symbols = filterJsxAttributes(getPropertiesForObjectExpression(attrsType, completionsType, jsxContainer.attributes, typeChecker), jsxContainer.attributes.properties);
715
+ setSortTextToOptionalMember();
716
+ completionKind = 3 /* CompletionKind.MemberLike */;
717
+ isNewIdentifierLocation = false;
718
+ return 1 /* GlobalsSearch.Success */;
719
+ }
720
+ function getGlobalCompletions() {
721
+ keywordFilters = tryGetFunctionLikeBodyCompletionContainer(contextToken) ? 3 /* KeywordCompletionFilters.FunctionLikeBodyKeywords */ : 1 /* KeywordCompletionFilters.All */;
722
+ // Get all entities in the current scope.
723
+ completionKind = 1 /* CompletionKind.Global */;
724
+ isNewIdentifierLocation = isNewIdentifierDefinitionLocation(contextToken);
725
+ if (previousToken !== contextToken) {
726
+ Debug.assert(!!previousToken, "Expected 'contextToken' to be defined when different from 'previousToken'.");
727
+ }
728
+ // We need to find the node that will give us an appropriate scope to begin
729
+ // aggregating completion candidates. This is achieved in 'getScopeNode'
730
+ // by finding the first node that encompasses a position, accounting for whether a node
731
+ // is "complete" to decide whether a position belongs to the node.
732
+ //
733
+ // However, at the end of an identifier, we are interested in the scope of the identifier
734
+ // itself, but fall outside of the identifier. For instance:
735
+ //
736
+ // xyz => x$
737
+ //
738
+ // the cursor is outside of both the 'x' and the arrow function 'xyz => x',
739
+ // so 'xyz' is not returned in our results.
740
+ //
741
+ // We define 'adjustedPosition' so that we may appropriately account for
742
+ // being at the end of an identifier. The intention is that if requesting completion
743
+ // at the end of an identifier, it should be effectively equivalent to requesting completion
744
+ // anywhere inside/at the beginning of the identifier. So in the previous case, the
745
+ // 'adjustedPosition' will work as if requesting completion in the following:
746
+ //
747
+ // xyz => $x
748
+ //
749
+ // If previousToken !== contextToken, then
750
+ // - 'contextToken' was adjusted to the token prior to 'previousToken'
751
+ // because we were at the end of an identifier.
752
+ // - 'previousToken' is defined.
753
+ const adjustedPosition = previousToken !== contextToken ?
754
+ previousToken.getStart() :
755
+ position;
756
+ const scopeNode = getScopeNode(contextToken, adjustedPosition, sourceFile) || sourceFile;
757
+ isInSnippetScope = isSnippetScope(scopeNode);
758
+ const symbolMeanings = (isTypeOnly ? SymbolFlags.None : SymbolFlags.Value) | SymbolFlags.Type | SymbolFlags.Namespace | SymbolFlags.Alias;
759
+ symbols = typeChecker.getSymbolsInScope(scopeNode, symbolMeanings);
760
+ Debug.assertEachIsDefined(symbols, "getSymbolsInScope() should all be defined");
761
+ for (const symbol of symbols) {
762
+ if (!some(symbol.declarations, d => d.getSourceFile() === sourceFile)) {
763
+ symbolToSortTextMap[getSymbolId(symbol)] = SortText.GlobalsOrKeywords;
764
+ }
765
+ }
766
+ if (shouldOfferImportCompletions()) {
767
+ const lowerCaseTokenText = previousToken && isIdentifier(previousToken) ? previousToken.text.toLowerCase() : "";
768
+ const autoImportSuggestions = getSymbolsFromOtherSourceFileExports(languageVersion, host);
769
+ autoImportSuggestions.forEach(({ symbol, symbolName, skipFilter, origin }) => {
770
+ if (detailsEntryId) {
771
+ if (detailsEntryId.source && stripQuotes(origin.moduleSymbol.name) !== detailsEntryId.source) {
772
+ return;
773
+ }
774
+ }
775
+ else if (!skipFilter && !stringContainsCharactersInOrder(symbolName.toLowerCase(), lowerCaseTokenText)) {
776
+ return;
777
+ }
778
+ const symbolId = getSymbolId(symbol);
779
+ symbols.push(symbol);
780
+ symbolToOriginInfoMap[symbolId] = origin;
781
+ symbolToSortTextMap[symbolId] = SortText.AutoImportSuggestions;
782
+ });
783
+ }
784
+ filterGlobalCompletion(symbols);
785
+ }
786
+ function shouldOfferImportCompletions() {
787
+ if (!preferences.includeCompletionsForModuleExports)
788
+ return false;
789
+ // O auto-import monta a edição do import, e só existe com a edição registrada (CK-67).
790
+ if (!autoImportProvider)
791
+ return false;
792
+ // Na tag, a conferência seguia pelo módulo do arquivo e pelas opções. O alvo da configuração fixa já indica os
793
+ // módulos ES (o `compilerOptionsIndicateEs6Modules` dele é verdadeiro), e a conferência sempre aceita (CK-24).
794
+ return true;
795
+ }
796
+ function isSnippetScope(scopeNode) {
797
+ switch (scopeNode.kind) {
798
+ case SyntaxKind.SourceFile:
799
+ case SyntaxKind.TemplateExpression:
800
+ case SyntaxKind.JsxExpression:
801
+ case SyntaxKind.Block:
802
+ return true;
803
+ default:
804
+ return isStatement(scopeNode);
805
+ }
806
+ }
807
+ function filterGlobalCompletion(symbols) {
808
+ const isTypeOnly = isTypeOnlyCompletion();
809
+ if (isTypeOnly) {
810
+ keywordFilters = isTypeAssertion()
811
+ ? 4 /* KeywordCompletionFilters.TypeAssertionKeywords */
812
+ : 5 /* KeywordCompletionFilters.TypeKeywords */;
813
+ }
814
+ filterMutate(symbols, symbol => {
815
+ if (!isSourceFile(location)) {
816
+ // export default /**/ aceita todo significado
817
+ if (isExportAssignment(location.parent)) {
818
+ return true;
819
+ }
820
+ symbol = skipAlias(symbol, typeChecker);
821
+ if (isTypeOnly) {
822
+ // It's a type, but you can reach it by namespace.type as well
823
+ return symbolCanBeReferencedAtTypeLocation(symbol);
824
+ }
825
+ }
826
+ // expressions are value space (which includes the value namespaces)
827
+ return !!(getCombinedLocalAndExportSymbolFlags(symbol) & SymbolFlags.Value);
828
+ });
829
+ }
830
+ function isTypeAssertion() {
831
+ return isAssertionExpression(contextToken.parent);
832
+ }
833
+ function isTypeOnlyCompletion() {
834
+ return !isContextTokenValueLocation(contextToken) &&
835
+ (isPossiblyTypeArgumentPosition(contextToken, sourceFile, typeChecker)
836
+ || isPartOfTypeNode(location)
837
+ || isContextTokenTypeLocation(contextToken));
838
+ }
839
+ function isContextTokenValueLocation(contextToken) {
840
+ return contextToken &&
841
+ contextToken.kind === SyntaxKind.TypeOfKeyword &&
842
+ (contextToken.parent.kind === SyntaxKind.TypeQuery || isTypeOfExpression(contextToken.parent));
843
+ }
844
+ function isContextTokenTypeLocation(contextToken) {
845
+ if (contextToken) {
846
+ const parentKind = contextToken.parent.kind;
847
+ switch (contextToken.kind) {
848
+ case SyntaxKind.ColonToken:
849
+ return parentKind === SyntaxKind.PropertySignature ||
850
+ parentKind === SyntaxKind.Parameter ||
851
+ parentKind === SyntaxKind.VariableDeclaration ||
852
+ isFunctionLikeKind(parentKind);
853
+ case SyntaxKind.EqualsToken:
854
+ return parentKind === SyntaxKind.TypeAliasDeclaration;
855
+ case SyntaxKind.AsKeyword:
856
+ return parentKind === SyntaxKind.AsExpression;
857
+ case SyntaxKind.LessThanToken:
858
+ return parentKind === SyntaxKind.TypeReference;
859
+ case SyntaxKind.ExtendsKeyword:
860
+ return parentKind === SyntaxKind.TypeParameter;
861
+ }
862
+ }
863
+ return false;
864
+ }
865
+ /** True if symbol is a type or a module containing at least one type. */
866
+ function symbolCanBeReferencedAtTypeLocation(symbol, seenModules = createMap()) {
867
+ const sym = skipAlias(symbol.exportSymbol || symbol, typeChecker);
868
+ return !!(sym.flags & SymbolFlags.Type) ||
869
+ !!(sym.flags & SymbolFlags.Module) &&
870
+ addToSeen(seenModules, getSymbolId(sym)) &&
871
+ typeChecker.getExportsOfModule(sym).some(e => symbolCanBeReferencedAtTypeLocation(e, seenModules));
872
+ }
873
+ /**
874
+ * Gathers symbols that can be imported from other files, de-duplicating along the way. Symbols can be "duplicates"
875
+ * if re-exported from another module, e.g. `export { foo } from "./a"`. That syntax creates a fresh symbol, but
876
+ * it’s just an alias to the first, and both have the same name, so we generally want to filter those aliases out,
877
+ * if and only if the the first can be imported (it may be excluded due to package.json filtering in
878
+ * `codefix.forEachExternalModuleToImportFrom`).
879
+ *
880
+ * Example. Imagine a chain of node_modules re-exporting one original symbol:
881
+ *
882
+ * ```js
883
+ * node_modules/x/index.js node_modules/y/index.js node_modules/z/index.js
884
+ * +-----------------------+ +--------------------------+ +--------------------------+
885
+ * | | | | | |
886
+ * | export const foo = 0; | <--- | export { foo } from 'x'; | <--- | export { foo } from 'y'; |
887
+ * | | | | | |
888
+ * +-----------------------+ +--------------------------+ +--------------------------+
889
+ * ```
890
+ *
891
+ * Also imagine three buckets, which we’ll reference soon:
892
+ *
893
+ * ```md
894
+ * | | | | | |
895
+ * | **Bucket A** | | **Bucket B** | | **Bucket C** |
896
+ * | Symbols to | | Aliases to symbols | | Symbols to return |
897
+ * | definitely | | in Buckets A or C | | if nothing better |
898
+ * | return | | (don’t return these) | | comes along |
899
+ * |__________________| |______________________| |___________________|
900
+ * ```
901
+ *
902
+ * We _probably_ want to show `foo` from 'x', but not from 'y' or 'z'. However, if 'x' is not in a package.json, it
903
+ * will not appear in a `forEachExternalModuleToImportFrom` iteration. Furthermore, the order of iterations is not
904
+ * guaranteed, as it is host-dependent. Therefore, when presented with the symbol `foo` from module 'y' alone, we
905
+ * may not be sure whether or not it should go in the list. So, we’ll take the following steps:
906
+ *
907
+ * 1. Resolve alias `foo` from 'y' to the export declaration in 'x', get the symbol there, and see if that symbol is
908
+ * already in Bucket A (symbols we already know will be returned). If it is, put `foo` from 'y' in Bucket B
909
+ * (symbols that are aliases to symbols in Bucket A). If it’s not, put it in Bucket C.
910
+ * 2. Next, imagine we see `foo` from module 'z'. Again, we resolve the alias to the nearest export, which is in 'y'.
911
+ * At this point, if that nearest export from 'y' is in _any_ of the three buckets, we know the symbol in 'z'
912
+ * should never be returned in the final list, so put it in Bucket B.
913
+ * 3. Next, imagine we see `foo` from module 'x', the original. Syntactically, it doesn’t look like a re-export, so
914
+ * we can just check Bucket C to see if we put any aliases to the original in there. If they exist, throw them out.
915
+ * Put this symbol in Bucket A.
916
+ * 4. After we’ve iterated through every symbol of every module, any symbol left in Bucket C means that step 3 didn’t
917
+ * occur for that symbol---that is, the original symbol is not in Bucket A, so we should include the alias. Move
918
+ * everything from Bucket C to Bucket A.
919
+ */
920
+ function getSymbolsFromOtherSourceFileExports(target, host) {
921
+ const startTime = timestamp();
922
+ log(`getSymbolsFromOtherSourceFileExports: Recomputing list${detailsEntryId ? " for details entry" : ""}`);
923
+ const seenResolvedModules = createMap();
924
+ const seenExports = createMap();
925
+ /** Bucket B */
926
+ const aliasesToAlreadyIncludedSymbols = createMap();
927
+ /** Bucket C */
928
+ const aliasesToReturnIfOriginalsAreMissing = createMap();
929
+ /** Bucket A */
930
+ const results = [];
931
+ /** Ids present in `results` for faster lookup */
932
+ const resultSymbolIds = createMap();
933
+ autoImportProvider.forEachExternalModuleToImportFrom(program, host, sourceFile, moduleSymbol => {
934
+ // Perf -- ignore other modules if this is a request for details
935
+ if (detailsEntryId && detailsEntryId.source && stripQuotes(moduleSymbol.name) !== detailsEntryId.source) {
936
+ return;
937
+ }
938
+ // Na tag, o alvo do módulo podia ser o valor do `export =`, que vários módulos podiam exportar, e entrava como item
939
+ // próprio; sem o `export =`, o alvo é o próprio módulo (CK-03).
940
+ if (!addToSeen(seenResolvedModules, getSymbolId(moduleSymbol))) {
941
+ return;
942
+ }
943
+ for (const symbol of typeChecker.getExportsAndPropertiesOfModule(moduleSymbol)) {
944
+ const symbolId = getSymbolId(symbol).toString();
945
+ // `getExportsAndPropertiesOfModule` can include duplicates
946
+ if (!addToSeen(seenExports, symbolId)) {
947
+ continue;
948
+ }
949
+ // If this is `export { _break as break };` (a keyword) -- skip this and prefer the keyword completion.
950
+ if (some(symbol.declarations, d => isExportSpecifier(d) && !!d.propertyName && isIdentifierANonContextualKeyword(d.name))) {
951
+ continue;
952
+ }
953
+ // If `symbol.parent !== moduleSymbol`, this is an `export * from "foo"` re-export. Those don't create new symbols.
954
+ const isExportStarFromReExport = typeChecker.getMergedSymbol(symbol.parent) !== moduleSymbol;
955
+ // If `!!d.parent.parent.moduleSpecifier`, this is `export { foo } from "foo"` re-export, which creates a new symbol (thus isn't caught by the first check).
956
+ if (isExportStarFromReExport || some(symbol.declarations, d => isExportSpecifier(d) && !d.propertyName && !!d.parent.parent.moduleSpecifier)) {
957
+ // Walk the export chain back one module (step 1 or 2 in diagrammed example).
958
+ // Or, in the case of `export * from "foo"`, `symbol` already points to the original export, so just use that.
959
+ const nearestExportSymbol = isExportStarFromReExport ? symbol : getNearestExportSymbol(symbol);
960
+ if (!nearestExportSymbol)
961
+ continue;
962
+ const nearestExportSymbolId = getSymbolId(nearestExportSymbol).toString();
963
+ const symbolHasBeenSeen = resultSymbolIds.has(nearestExportSymbolId) || aliasesToAlreadyIncludedSymbols.has(nearestExportSymbolId);
964
+ if (!symbolHasBeenSeen) {
965
+ aliasesToReturnIfOriginalsAreMissing.set(nearestExportSymbolId, { alias: symbol, moduleSymbol });
966
+ aliasesToAlreadyIncludedSymbols.set(symbolId, true);
967
+ }
968
+ else {
969
+ // Perf - we know this symbol is an alias to one that’s already covered in `symbols`, so store it here
970
+ // in case another symbol re-exports this one; that way we can short-circuit as soon as we see this symbol id.
971
+ addToSeen(aliasesToAlreadyIncludedSymbols, symbolId);
972
+ }
973
+ }
974
+ else {
975
+ // This is not a re-export, so see if we have any aliases pending and remove them (step 3 in diagrammed example)
976
+ aliasesToReturnIfOriginalsAreMissing.delete(symbolId);
977
+ pushSymbol(symbol, moduleSymbol);
978
+ }
979
+ }
980
+ });
981
+ // By this point, any potential duplicates that were actually duplicates have been
982
+ // removed, so the rest need to be added. (Step 4 in diagrammed example)
983
+ aliasesToReturnIfOriginalsAreMissing.forEach(({ alias, moduleSymbol }) => pushSymbol(alias, moduleSymbol));
984
+ log(`getSymbolsFromOtherSourceFileExports: ${timestamp() - startTime}`);
985
+ return results;
986
+ function pushSymbol(symbol, moduleSymbol, skipFilter = false) {
987
+ // Na tag, o `default` de uma declaração exportada dava o símbolo local dela; o modificador saiu com a `function` e a
988
+ // classe (CK-02), e o `export default` que fica é de expressão, sem símbolo local.
989
+ const isDefaultExport = symbol.escapedName === InternalSymbolName.Default;
990
+ if (typeChecker.isUndefinedSymbol(symbol)) {
991
+ return;
992
+ }
993
+ addToSeen(resultSymbolIds, getSymbolId(symbol));
994
+ const origin = { kind: 4 /* SymbolOriginInfoKind.Export */, moduleSymbol, isDefaultExport };
995
+ results.push({
996
+ symbol,
997
+ symbolName: getNameForExportedSymbol(symbol, target),
998
+ origin,
999
+ skipFilter,
1000
+ });
1001
+ }
1002
+ }
1003
+ function getNearestExportSymbol(fromSymbol) {
1004
+ return findAlias(typeChecker, fromSymbol, alias => {
1005
+ return some(alias.declarations, d => isExportSpecifier(d) || !!d.localSymbol);
1006
+ });
1007
+ }
1008
+ /**
1009
+ * True if you could remove some characters in `a` to get `b`.
1010
+ * E.g., true for "abcdef" and "bdf".
1011
+ * But not true for "abcdef" and "dbf".
1012
+ */
1013
+ function stringContainsCharactersInOrder(str, characters) {
1014
+ if (characters.length === 0) {
1015
+ return true;
1016
+ }
1017
+ let characterIndex = 0;
1018
+ for (let strIndex = 0; strIndex < str.length; strIndex++) {
1019
+ if (str.charCodeAt(strIndex) === characters.charCodeAt(characterIndex)) {
1020
+ characterIndex++;
1021
+ if (characterIndex === characters.length) {
1022
+ return true;
1023
+ }
1024
+ }
1025
+ }
1026
+ // Did not find all characters
1027
+ return false;
1028
+ }
1029
+ /**
1030
+ * Finds the first node that "embraces" the position, so that one may
1031
+ * accurately aggregate locals from the closest containing scope.
1032
+ */
1033
+ function getScopeNode(initialToken, position, sourceFile) {
1034
+ let scope = initialToken;
1035
+ while (scope && !positionBelongsToNode(scope, position, sourceFile)) {
1036
+ scope = scope.parent;
1037
+ }
1038
+ return scope;
1039
+ }
1040
+ function isCompletionListBlocker(contextToken) {
1041
+ const start = timestamp();
1042
+ const result = isInStringOrRegularExpressionOrTemplateLiteral(contextToken) ||
1043
+ isSolelyIdentifierDefinitionLocation(contextToken) ||
1044
+ isDotOfNumericLiteral(contextToken) ||
1045
+ isInJsxText(contextToken);
1046
+ log("getCompletionsAtPosition: isCompletionListBlocker: " + (timestamp() - start));
1047
+ return result;
1048
+ }
1049
+ function isInJsxText(contextToken) {
1050
+ if (contextToken.kind === SyntaxKind.JsxText) {
1051
+ return true;
1052
+ }
1053
+ if (contextToken.kind === SyntaxKind.GreaterThanToken && contextToken.parent) {
1054
+ if (contextToken.parent.kind === SyntaxKind.JsxOpeningElement) {
1055
+ // Two possibilities:
1056
+ // 1. <div>/**/
1057
+ // - contextToken: GreaterThanToken (before cursor)
1058
+ // - location: JSXElement
1059
+ // - different parents (JSXOpeningElement, JSXElement)
1060
+ // 2. <Component<string> /**/>
1061
+ // - contextToken: GreaterThanToken (before cursor)
1062
+ // - location: GreaterThanToken (after cursor)
1063
+ // - same parent (JSXOpeningElement)
1064
+ return location.parent.kind !== SyntaxKind.JsxOpeningElement;
1065
+ }
1066
+ if (contextToken.parent.kind === SyntaxKind.JsxClosingElement || contextToken.parent.kind === SyntaxKind.JsxSelfClosingElement) {
1067
+ return !!contextToken.parent.parent && contextToken.parent.parent.kind === SyntaxKind.JsxElement;
1068
+ }
1069
+ }
1070
+ return false;
1071
+ }
1072
+ function isNewIdentifierDefinitionLocation(previousToken) {
1073
+ if (previousToken) {
1074
+ const containingNodeKind = previousToken.parent.kind;
1075
+ // Previous token may have been a keyword that was converted to an identifier.
1076
+ switch (keywordForNode(previousToken)) {
1077
+ case SyntaxKind.CommaToken:
1078
+ return containingNodeKind === SyntaxKind.CallExpression // func( a, |
1079
+ || containingNodeKind === SyntaxKind.ArrayLiteralExpression // [a, |
1080
+ || containingNodeKind === SyntaxKind.BinaryExpression // const x = (a, |
1081
+ || containingNodeKind === SyntaxKind.FunctionType; // var x: (s: string, list|
1082
+ case SyntaxKind.OpenParenToken:
1083
+ return containingNodeKind === SyntaxKind.CallExpression // func( |
1084
+ || containingNodeKind === SyntaxKind.ParenthesizedExpression // const x = (a|
1085
+ || containingNodeKind === SyntaxKind.ParenthesizedType; // function F(pred: (a| /* this can become an arrow function, where 'a' is the argument */
1086
+ case SyntaxKind.OpenBracketToken:
1087
+ return containingNodeKind === SyntaxKind.ArrayLiteralExpression // [ |
1088
+ || containingNodeKind === SyntaxKind.IndexSignature // [ | : string ]
1089
+ || containingNodeKind === SyntaxKind.ComputedPropertyName; // [ | /* this can become an index signature */
1090
+ // Na tag, também o `module`, que saiu do scanner com o `module X` e o `declare module "x"` (CK-02, CK-56).
1091
+ case SyntaxKind.NamespaceKeyword: // namespace |
1092
+ return true;
1093
+ case SyntaxKind.DotToken:
1094
+ return containingNodeKind === SyntaxKind.ModuleDeclaration; // module A.|
1095
+ case SyntaxKind.EqualsToken:
1096
+ return containingNodeKind === SyntaxKind.VariableDeclaration // const x = a|
1097
+ || containingNodeKind === SyntaxKind.BinaryExpression; // x = a|
1098
+ case SyntaxKind.TemplateHead:
1099
+ return containingNodeKind === SyntaxKind.TemplateExpression; // `aa ${|
1100
+ case SyntaxKind.TemplateMiddle:
1101
+ return containingNodeKind === SyntaxKind.TemplateSpan; // `aa ${10} dd ${|
1102
+ }
1103
+ }
1104
+ return false;
1105
+ }
1106
+ function isInStringOrRegularExpressionOrTemplateLiteral(contextToken) {
1107
+ // A posição está num literal se está dentro do texto dele, ou no fim de um que não fechou. Na tag, também no fim
1108
+ // de uma regex, pelas flags; a Linguagem não tem o literal de regex (CK-02).
1109
+ return isStringTextContainingNode(contextToken) && (rangeContainsPositionExclusive(createTextRangeFromSpan(createTextSpanFromNode(contextToken)), position) ||
1110
+ position === contextToken.end && !!contextToken.isUnterminated);
1111
+ }
1112
+ /**
1113
+ * Aggregates relevant symbols for completion in object literals and object binding patterns.
1114
+ * Relevant symbols are stored in the captured 'symbols' variable.
1115
+ *
1116
+ * @returns true if 'symbols' was successfully populated; false otherwise.
1117
+ */
1118
+ function tryGetObjectLikeCompletionSymbols() {
1119
+ const objectLikeContainer = tryGetObjectLikeCompletionContainer(contextToken);
1120
+ if (!objectLikeContainer)
1121
+ return 0 /* GlobalsSearch.Continue */;
1122
+ // We're looking up possible property names from contextual/inferred/declared type.
1123
+ completionKind = 0 /* CompletionKind.ObjectPropertyDeclaration */;
1124
+ let typeMembers;
1125
+ let existingMembers;
1126
+ if (objectLikeContainer.kind === SyntaxKind.ObjectLiteralExpression) {
1127
+ const instantiatedType = typeChecker.getContextualType(objectLikeContainer);
1128
+ const completionsType = instantiatedType && typeChecker.getContextualType(objectLikeContainer, ContextFlags.Completions);
1129
+ if (!instantiatedType || !completionsType)
1130
+ return 2 /* GlobalsSearch.Fail */;
1131
+ isNewIdentifierLocation = hasIndexSignature(instantiatedType || completionsType);
1132
+ typeMembers = getPropertiesForObjectExpression(instantiatedType, completionsType, objectLikeContainer, typeChecker);
1133
+ existingMembers = objectLikeContainer.properties;
1134
+ }
1135
+ else {
1136
+ Debug.assert(objectLikeContainer.kind === SyntaxKind.ObjectBindingPattern);
1137
+ // We are *only* completing on properties from the type being destructured.
1138
+ isNewIdentifierLocation = false;
1139
+ const rootDeclaration = getRootDeclaration(objectLikeContainer.parent);
1140
+ if (!isVariableLike(rootDeclaration))
1141
+ return Debug.fail("Root declaration is not variable-like.");
1142
+ // We don't want to complete using the type acquired by the shape
1143
+ // of the binding pattern; we are only interested in types acquired
1144
+ // through type declaration or inference.
1145
+ // Also proceed if rootDeclaration is a parameter and if its containing function expression/arrow function is contextually typed -
1146
+ // type of parameter will flow in from the contextual type of the function
1147
+ let canGetType = hasInitializer(rootDeclaration) || hasType(rootDeclaration) || rootDeclaration.parent.parent.kind === SyntaxKind.ForOfStatement;
1148
+ if (!canGetType && rootDeclaration.kind === SyntaxKind.Parameter) {
1149
+ if (isExpression(rootDeclaration.parent)) {
1150
+ canGetType = !!typeChecker.getContextualType(rootDeclaration.parent);
1151
+ }
1152
+ }
1153
+ if (canGetType) {
1154
+ const typeForObject = typeChecker.getTypeAtLocation(objectLikeContainer);
1155
+ if (!typeForObject)
1156
+ return 2 /* GlobalsSearch.Fail */;
1157
+ // Na tag, a propriedade não pública ficava de fora, salvo dentro da classe dela; a Linguagem não tem
1158
+ // classe nem o modificador de acesso (CK-02).
1159
+ typeMembers = typeChecker.getPropertiesOfType(typeForObject);
1160
+ existingMembers = objectLikeContainer.elements;
1161
+ }
1162
+ }
1163
+ if (typeMembers && typeMembers.length > 0) {
1164
+ // Add filtered items to the completion list
1165
+ symbols = filterObjectMembersList(typeMembers, Debug.checkDefined(existingMembers));
1166
+ }
1167
+ setSortTextToOptionalMember();
1168
+ return 1 /* GlobalsSearch.Success */;
1169
+ }
1170
+ /**
1171
+ * Aggregates relevant symbols for completion in import clauses and export clauses
1172
+ * whose declarations have a module specifier; for instance, symbols will be aggregated for
1173
+ *
1174
+ * import { | } from "moduleName";
1175
+ * export { a as foo, | } from "moduleName";
1176
+ *
1177
+ * but not for
1178
+ *
1179
+ * export { | };
1180
+ *
1181
+ * Relevant symbols are stored in the captured 'symbols' variable.
1182
+ */
1183
+ function tryGetImportOrExportClauseCompletionSymbols() {
1184
+ // `import { |` or `import { a as 0, | }`
1185
+ const namedImportsOrExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
1186
+ ? tryCast(contextToken.parent, isNamedImportsOrExports) : undefined;
1187
+ if (!namedImportsOrExports)
1188
+ return 0 /* GlobalsSearch.Continue */;
1189
+ // try to show exported member for imported/re-exported module
1190
+ const { moduleSpecifier } = namedImportsOrExports.kind === SyntaxKind.NamedImports ? namedImportsOrExports.parent.parent : namedImportsOrExports.parent;
1191
+ if (!moduleSpecifier)
1192
+ return namedImportsOrExports.kind === SyntaxKind.NamedImports ? 2 /* GlobalsSearch.Fail */ : 0 /* GlobalsSearch.Continue */;
1193
+ const moduleSpecifierSymbol = typeChecker.getSymbolAtLocation(moduleSpecifier); // TODO: GH#18217
1194
+ if (!moduleSpecifierSymbol)
1195
+ return 2 /* GlobalsSearch.Fail */;
1196
+ completionKind = 3 /* CompletionKind.MemberLike */;
1197
+ isNewIdentifierLocation = false;
1198
+ const exports = typeChecker.getExportsAndPropertiesOfModule(moduleSpecifierSymbol);
1199
+ const existing = arrayToSet(namedImportsOrExports.elements, n => isCurrentlyEditingNode(n) ? undefined : (n.propertyName || n.name).escapedText);
1200
+ symbols = exports.filter(e => e.escapedName !== InternalSymbolName.Default && !existing.get(e.escapedName));
1201
+ return 1 /* GlobalsSearch.Success */;
1202
+ }
1203
+ /**
1204
+ * Adds local declarations for completions in named exports:
1205
+ *
1206
+ * export { | };
1207
+ *
1208
+ * Does not check for the absence of a module specifier (`export {} from "./other"`)
1209
+ * because `tryGetImportOrExportClauseCompletionSymbols` runs first and handles that,
1210
+ * preventing this function from running.
1211
+ */
1212
+ function tryGetLocalNamedExportCompletionSymbols() {
1213
+ const namedExports = contextToken && (contextToken.kind === SyntaxKind.OpenBraceToken || contextToken.kind === SyntaxKind.CommaToken)
1214
+ ? tryCast(contextToken.parent, isNamedExports)
1215
+ : undefined;
1216
+ if (!namedExports) {
1217
+ return 0 /* GlobalsSearch.Continue */;
1218
+ }
1219
+ const localsContainer = findAncestor(namedExports, or(isSourceFile, isModuleDeclaration));
1220
+ completionKind = 5 /* CompletionKind.None */;
1221
+ isNewIdentifierLocation = false;
1222
+ localsContainer.locals?.forEach((symbol, name) => {
1223
+ symbols.push(symbol);
1224
+ if (localsContainer.symbol?.exports?.has(name)) {
1225
+ symbolToSortTextMap[getSymbolId(symbol)] = SortText.OptionalMember;
1226
+ }
1227
+ });
1228
+ return 1 /* GlobalsSearch.Success */;
1229
+ }
1230
+ /**
1231
+ * O completion no corpo de um tipo de objeto: só as palavras-chave de um membro. Na tag, o de uma classe oferecia
1232
+ * também os membros do tipo base; a Linguagem não tem classe (CK-02), e o tipo de objeto é o literal.
1233
+ */
1234
+ function tryGetClassLikeCompletionSymbols() {
1235
+ const decl = tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location, position);
1236
+ if (!decl)
1237
+ return 0 /* GlobalsSearch.Continue */;
1238
+ completionKind = 3 /* CompletionKind.MemberLike */;
1239
+ // um membro novo
1240
+ isNewIdentifierLocation = true;
1241
+ keywordFilters = 2 /* KeywordCompletionFilters.InterfaceElementKeywords */;
1242
+ return 1 /* GlobalsSearch.Success */;
1243
+ }
1244
+ /**
1245
+ * Returns the immediate owning object literal or binding pattern of a context token,
1246
+ * on the condition that one exists and that the context implies completion should be given.
1247
+ */
1248
+ function tryGetObjectLikeCompletionContainer(contextToken) {
1249
+ if (contextToken) {
1250
+ const { parent } = contextToken;
1251
+ switch (contextToken.kind) {
1252
+ case SyntaxKind.OpenBraceToken: // const x = { |
1253
+ case SyntaxKind.CommaToken: // const x = { a: 0, |
1254
+ if (isObjectLiteralExpression(parent) || isObjectBindingPattern(parent)) {
1255
+ return parent;
1256
+ }
1257
+ break;
1258
+ }
1259
+ }
1260
+ return undefined;
1261
+ }
1262
+ function tryGetFunctionLikeBodyCompletionContainer(contextToken) {
1263
+ if (contextToken) {
1264
+ let prev;
1265
+ const container = findAncestor(contextToken.parent, (node) => {
1266
+ if (isFunctionLikeDeclaration(node) && prev === node.body) {
1267
+ return true;
1268
+ }
1269
+ prev = node;
1270
+ return false;
1271
+ });
1272
+ return container && container;
1273
+ }
1274
+ }
1275
+ function tryGetContainingJsxElement(contextToken) {
1276
+ if (contextToken) {
1277
+ const parent = contextToken.parent;
1278
+ switch (contextToken.kind) {
1279
+ case SyntaxKind.GreaterThanToken: // End of a type argument list
1280
+ case SyntaxKind.LessThanSlashToken:
1281
+ case SyntaxKind.SlashToken:
1282
+ case SyntaxKind.Identifier:
1283
+ case SyntaxKind.PropertyAccessExpression:
1284
+ case SyntaxKind.JsxAttributes:
1285
+ case SyntaxKind.JsxAttribute:
1286
+ case SyntaxKind.JsxSpreadAttribute:
1287
+ if (parent && (parent.kind === SyntaxKind.JsxSelfClosingElement || parent.kind === SyntaxKind.JsxOpeningElement)) {
1288
+ if (contextToken.kind === SyntaxKind.GreaterThanToken) {
1289
+ const precedingToken = findPrecedingToken(contextToken.pos, sourceFile, /*startNode*/ undefined);
1290
+ if (!parent.typeArguments || (precedingToken && precedingToken.kind === SyntaxKind.SlashToken))
1291
+ break;
1292
+ }
1293
+ return parent;
1294
+ }
1295
+ else if (parent.kind === SyntaxKind.JsxAttribute) {
1296
+ // Currently we parse JsxOpeningLikeElement as:
1297
+ // JsxOpeningLikeElement
1298
+ // attributes: JsxAttributes
1299
+ // properties: NodeArray<JsxAttributeLike>
1300
+ return parent.parent.parent;
1301
+ }
1302
+ break;
1303
+ // The context token is the closing } or " of an attribute, which means
1304
+ // its parent is a JsxExpression, whose parent is a JsxAttribute,
1305
+ // whose parent is a JsxOpeningLikeElement
1306
+ case SyntaxKind.StringLiteral:
1307
+ if (parent && ((parent.kind === SyntaxKind.JsxAttribute) || (parent.kind === SyntaxKind.JsxSpreadAttribute))) {
1308
+ // Currently we parse JsxOpeningLikeElement as:
1309
+ // JsxOpeningLikeElement
1310
+ // attributes: JsxAttributes
1311
+ // properties: NodeArray<JsxAttributeLike>
1312
+ return parent.parent.parent;
1313
+ }
1314
+ break;
1315
+ case SyntaxKind.CloseBraceToken:
1316
+ if (parent &&
1317
+ parent.kind === SyntaxKind.JsxExpression &&
1318
+ parent.parent && parent.parent.kind === SyntaxKind.JsxAttribute) {
1319
+ // Currently we parse JsxOpeningLikeElement as:
1320
+ // JsxOpeningLikeElement
1321
+ // attributes: JsxAttributes
1322
+ // properties: NodeArray<JsxAttributeLike>
1323
+ // each JsxAttribute can have initializer as JsxExpression
1324
+ return parent.parent.parent.parent;
1325
+ }
1326
+ if (parent && parent.kind === SyntaxKind.JsxSpreadAttribute) {
1327
+ // Currently we parse JsxOpeningLikeElement as:
1328
+ // JsxOpeningLikeElement
1329
+ // attributes: JsxAttributes
1330
+ // properties: NodeArray<JsxAttributeLike>
1331
+ return parent.parent.parent;
1332
+ }
1333
+ break;
1334
+ }
1335
+ }
1336
+ return undefined;
1337
+ }
1338
+ /**
1339
+ * @returns true if we are certain that the currently edited location must define a new location; false otherwise.
1340
+ */
1341
+ function isSolelyIdentifierDefinitionLocation(contextToken) {
1342
+ const parent = contextToken.parent;
1343
+ const containingNodeKind = parent.kind;
1344
+ switch (contextToken.kind) {
1345
+ case SyntaxKind.CommaToken:
1346
+ return containingNodeKind === SyntaxKind.VariableDeclaration ||
1347
+ isVariableDeclarationListButNotTypeArgument(contextToken) ||
1348
+ containingNodeKind === SyntaxKind.VariableStatement ||
1349
+ isFunctionLikeKind(containingNodeKind) ||
1350
+ containingNodeKind === SyntaxKind.ArrayBindingPattern || // var [x, y|
1351
+ containingNodeKind === SyntaxKind.TypeAliasDeclaration; // type Map, K, |
1352
+ case SyntaxKind.DotToken:
1353
+ return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [.|
1354
+ case SyntaxKind.ColonToken:
1355
+ return containingNodeKind === SyntaxKind.BindingElement; // var {x :html|
1356
+ case SyntaxKind.OpenBracketToken:
1357
+ return containingNodeKind === SyntaxKind.ArrayBindingPattern; // var [x|
1358
+ case SyntaxKind.OpenParenToken:
1359
+ return containingNodeKind === SyntaxKind.CatchClause ||
1360
+ isFunctionLikeKind(containingNodeKind);
1361
+ case SyntaxKind.LessThanToken:
1362
+ return containingNodeKind === SyntaxKind.TypeAliasDeclaration || // type List< |
1363
+ isFunctionLikeKind(containingNodeKind);
1364
+ case SyntaxKind.DotDotDotToken:
1365
+ return containingNodeKind === SyntaxKind.Parameter ||
1366
+ (!!parent.parent && parent.parent.kind === SyntaxKind.ArrayBindingPattern); // var [...z|
1367
+ case SyntaxKind.AsKeyword:
1368
+ return containingNodeKind === SyntaxKind.ImportSpecifier ||
1369
+ containingNodeKind === SyntaxKind.ExportSpecifier ||
1370
+ containingNodeKind === SyntaxKind.NamespaceImport;
1371
+ case SyntaxKind.ImportKeyword:
1372
+ case SyntaxKind.LetKeyword:
1373
+ case SyntaxKind.ConstKeyword:
1374
+ case SyntaxKind.TypeKeyword: // type htm|
1375
+ return true;
1376
+ }
1377
+ // Depois de uma palavra-chave de membro, num tipo de objeto, há completion.
1378
+ if (isClassMemberCompletionKeyword(keywordForNode(contextToken)) && isFromObjectTypeDeclaration(contextToken)) {
1379
+ return false;
1380
+ }
1381
+ // A palavra-chave que o parser leu como identificador.
1382
+ switch (keywordForNode(contextToken)) {
1383
+ case SyntaxKind.ConstKeyword:
1384
+ case SyntaxKind.DeclareKeyword:
1385
+ case SyntaxKind.LetKeyword:
1386
+ return true;
1387
+ }
1388
+ return isDeclarationName(contextToken)
1389
+ && !isJsxAttribute(contextToken.parent);
1390
+ }
1391
+ function isDotOfNumericLiteral(contextToken) {
1392
+ if (contextToken.kind === SyntaxKind.NumericLiteral) {
1393
+ const text = contextToken.getFullText();
1394
+ return text.charAt(text.length - 1) === ".";
1395
+ }
1396
+ return false;
1397
+ }
1398
+ function isVariableDeclarationListButNotTypeArgument(node) {
1399
+ return node.parent.kind === SyntaxKind.VariableDeclarationList
1400
+ && !isPossiblyTypeArgumentPosition(node, sourceFile, typeChecker);
1401
+ }
1402
+ /**
1403
+ * Filters out completion suggestions for named imports or exports.
1404
+ *
1405
+ * @returns Symbols to be suggested in an object binding pattern or object literal expression, barring those whose declarations
1406
+ * do not occur at the current position and have not otherwise been typed.
1407
+ */
1408
+ function filterObjectMembersList(contextualMemberSymbols, existingMembers) {
1409
+ if (existingMembers.length === 0) {
1410
+ return contextualMemberSymbols;
1411
+ }
1412
+ const membersDeclaredBySpreadAssignment = createMap();
1413
+ const existingMemberNames = createUnderscoreEscapedMap();
1414
+ for (const m of existingMembers) {
1415
+ // Ignore omitted expressions for missing members
1416
+ if (m.kind !== SyntaxKind.PropertyAssignment &&
1417
+ m.kind !== SyntaxKind.ShorthandPropertyAssignment &&
1418
+ m.kind !== SyntaxKind.BindingElement &&
1419
+ m.kind !== SyntaxKind.SpreadAssignment) {
1420
+ continue;
1421
+ }
1422
+ // If this is the current item we are editing right now, do not filter it out
1423
+ if (isCurrentlyEditingNode(m)) {
1424
+ continue;
1425
+ }
1426
+ let existingName;
1427
+ if (isSpreadAssignment(m)) {
1428
+ setMembersDeclaredBySpreadAssignment(m, membersDeclaredBySpreadAssignment);
1429
+ }
1430
+ else if (isBindingElement(m) && m.propertyName) {
1431
+ // include only identifiers in completion list
1432
+ if (m.propertyName.kind === SyntaxKind.Identifier) {
1433
+ existingName = m.propertyName.escapedText;
1434
+ }
1435
+ }
1436
+ else {
1437
+ // TODO: Account for computed property name
1438
+ // NOTE: if one only performs this step when m.name is an identifier,
1439
+ // things like '__proto__' are not filtered out.
1440
+ const name = getNameOfDeclaration(m);
1441
+ existingName = name && isPropertyNameLiteral(name) ? getEscapedTextOfIdentifierOrLiteral(name) : undefined;
1442
+ }
1443
+ existingMemberNames.set(existingName, true); // TODO: GH#18217
1444
+ }
1445
+ const filteredSymbols = contextualMemberSymbols.filter(m => !existingMemberNames.get(m.escapedName));
1446
+ setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols);
1447
+ return filteredSymbols;
1448
+ }
1449
+ function setMembersDeclaredBySpreadAssignment(declaration, membersDeclaredBySpreadAssignment) {
1450
+ const expression = declaration.expression;
1451
+ const symbol = typeChecker.getSymbolAtLocation(expression);
1452
+ const type = symbol && typeChecker.getTypeOfSymbolAtLocation(symbol, expression);
1453
+ const properties = type && type.properties;
1454
+ if (properties) {
1455
+ properties.forEach(property => {
1456
+ membersDeclaredBySpreadAssignment.set(property.name, true);
1457
+ });
1458
+ }
1459
+ }
1460
+ // Set SortText to OptionalMember if it is an optional member
1461
+ function setSortTextToOptionalMember() {
1462
+ symbols.forEach(m => {
1463
+ if (m.flags & SymbolFlags.Optional) {
1464
+ symbolToSortTextMap[getSymbolId(m)] = symbolToSortTextMap[getSymbolId(m)] || SortText.OptionalMember;
1465
+ }
1466
+ });
1467
+ }
1468
+ // Set SortText to MemberDeclaredBySpreadAssignment if it is fulfilled by spread assignment
1469
+ function setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, contextualMemberSymbols) {
1470
+ if (membersDeclaredBySpreadAssignment.size === 0) {
1471
+ return;
1472
+ }
1473
+ for (const contextualMemberSymbol of contextualMemberSymbols) {
1474
+ if (membersDeclaredBySpreadAssignment.has(contextualMemberSymbol.name)) {
1475
+ symbolToSortTextMap[getSymbolId(contextualMemberSymbol)] = SortText.MemberDeclaredBySpreadAssignment;
1476
+ }
1477
+ }
1478
+ }
1479
+ /**
1480
+ * Filters out completion suggestions from 'symbols' according to existing JSX attributes.
1481
+ *
1482
+ * @returns Symbols to be suggested in a JSX element, barring those whose attributes
1483
+ * do not occur at the current position and have not otherwise been typed.
1484
+ */
1485
+ function filterJsxAttributes(symbols, attributes) {
1486
+ const seenNames = createUnderscoreEscapedMap();
1487
+ const membersDeclaredBySpreadAssignment = createMap();
1488
+ for (const attr of attributes) {
1489
+ // If this is the current item we are editing right now, do not filter it out
1490
+ if (isCurrentlyEditingNode(attr)) {
1491
+ continue;
1492
+ }
1493
+ if (attr.kind === SyntaxKind.JsxAttribute) {
1494
+ seenNames.set(attr.name.escapedText, true);
1495
+ }
1496
+ else if (isJsxSpreadAttribute(attr)) {
1497
+ setMembersDeclaredBySpreadAssignment(attr, membersDeclaredBySpreadAssignment);
1498
+ }
1499
+ }
1500
+ const filteredSymbols = symbols.filter(a => !seenNames.get(a.escapedName));
1501
+ setSortTextToMemberDeclaredBySpreadAssignment(membersDeclaredBySpreadAssignment, filteredSymbols);
1502
+ return filteredSymbols;
1503
+ }
1504
+ function isCurrentlyEditingNode(node) {
1505
+ return node.getStart(sourceFile) <= position && position <= node.getEnd();
1506
+ }
1507
+ }
1508
+ function getCompletionEntryDisplayNameForSymbol(symbol, target, origin, kind, jsxIdentifierExpected) {
1509
+ const name = originIsExport(origin) ? getNameForExportedSymbol(symbol, target) : symbol.name;
1510
+ if (name === undefined
1511
+ // If the symbol is external module, don't show it in the completion list
1512
+ // (i.e declare module "http" { const x; } | // <= request completion here, "http" should not be there)
1513
+ || symbol.flags & SymbolFlags.Module && isSingleOrDoubleQuote(name.charCodeAt(0))
1514
+ // If the symbol is the internal name of an ES symbol, it is not a valid entry. Internal names for ES symbols start with "__@"
1515
+ || isKnownSymbol(symbol)) {
1516
+ return undefined;
1517
+ }
1518
+ const validNameResult = { name, needsConvertPropertyAccess: false };
1519
+ if (isIdentifierText(name, target, jsxIdentifierExpected ? LanguageVariant.JSX : LanguageVariant.Standard)) {
1520
+ return validNameResult;
1521
+ }
1522
+ switch (kind) {
1523
+ case 3 /* CompletionKind.MemberLike */:
1524
+ return undefined;
1525
+ case 0 /* CompletionKind.ObjectPropertyDeclaration */:
1526
+ // TODO: GH#18169
1527
+ return { name: JSON.stringify(name), needsConvertPropertyAccess: false };
1528
+ case 2 /* CompletionKind.PropertyAccess */:
1529
+ case 1 /* CompletionKind.Global */: // For a 'this.' completion it will be in a global context, but may have a non-identifier name.
1530
+ // Don't add a completion for a name starting with a space. See https://github.com/Microsoft/TypeScript/pull/20547
1531
+ return name.charCodeAt(0) === CharacterCodes.space ? undefined : { name, needsConvertPropertyAccess: true };
1532
+ case 5 /* CompletionKind.None */:
1533
+ case 4 /* CompletionKind.String */:
1534
+ return validNameResult;
1535
+ default:
1536
+ Debug.assertNever(kind);
1537
+ }
1538
+ }
1539
+ // A cache of completion entries for keywords, these do not change between sessions
1540
+ const _keywordCompletions = [];
1541
+ const allKeywordsCompletions = memoize(() => {
1542
+ const res = [];
1543
+ for (let i = SyntaxKind.FirstKeyword; i <= SyntaxKind.LastKeyword; i++) {
1544
+ // A palavra que a Linguagem não usa não é palavra-chave no scanner, e não se oferece (CK-56).
1545
+ const name = tokenToString(i);
1546
+ if (name === undefined)
1547
+ continue;
1548
+ res.push({
1549
+ name,
1550
+ kind: "keyword" /* ScriptElementKind.keyword */,
1551
+ kindModifiers: "" /* ScriptElementKindModifier.none */,
1552
+ sortText: SortText.GlobalsOrKeywords
1553
+ });
1554
+ }
1555
+ return res;
1556
+ });
1557
+ function getTypescriptKeywordCompletions(keywordFilter) {
1558
+ return _keywordCompletions[keywordFilter] || (_keywordCompletions[keywordFilter] = allKeywordsCompletions().filter(entry => {
1559
+ const kind = stringToToken(entry.name);
1560
+ switch (keywordFilter) {
1561
+ case 0 /* KeywordCompletionFilters.None */:
1562
+ return false;
1563
+ case 1 /* KeywordCompletionFilters.All */:
1564
+ // Na tag, também o `module` (CK-02, CK-56).
1565
+ return isFunctionLikeBodyKeyword(kind)
1566
+ || kind === SyntaxKind.DeclareKeyword
1567
+ || kind === SyntaxKind.TypeKeyword
1568
+ || kind === SyntaxKind.NamespaceKeyword
1569
+ || kind === SyntaxKind.AsKeyword
1570
+ || isTypeKeyword(kind) && kind !== SyntaxKind.UndefinedKeyword;
1571
+ case 3 /* KeywordCompletionFilters.FunctionLikeBodyKeywords */:
1572
+ return isFunctionLikeBodyKeyword(kind);
1573
+ case 2 /* KeywordCompletionFilters.InterfaceElementKeywords */:
1574
+ return isInterfaceOrTypeLiteralCompletionKeyword(kind);
1575
+ case 4 /* KeywordCompletionFilters.TypeAssertionKeywords */:
1576
+ return isTypeKeyword(kind) || kind === SyntaxKind.ConstKeyword;
1577
+ case 5 /* KeywordCompletionFilters.TypeKeywords */:
1578
+ return isTypeKeyword(kind);
1579
+ default:
1580
+ return Debug.assertNever(keywordFilter);
1581
+ }
1582
+ }));
1583
+ }
1584
+ function isInterfaceOrTypeLiteralCompletionKeyword(kind) {
1585
+ return kind === SyntaxKind.ReadonlyKeyword;
1586
+ }
1587
+ /**
1588
+ * A palavra que começa um membro. Na tag, também o `abstract`, o `constructor`, o `get` e o `set`, e os modificadores de
1589
+ * membro de classe (o de acesso e o `static`), que a Linguagem não tem (CK-02); deles fica o `readonly`.
1590
+ */
1591
+ function isClassMemberCompletionKeyword(kind) {
1592
+ switch (kind) {
1593
+ case SyntaxKind.AsyncKeyword:
1594
+ case SyntaxKind.DeclareKeyword:
1595
+ case SyntaxKind.ReadonlyKeyword:
1596
+ return true;
1597
+ default:
1598
+ return false;
1599
+ }
1600
+ }
1601
+ function isFunctionLikeBodyKeyword(kind) {
1602
+ return kind === SyntaxKind.AsyncKeyword
1603
+ || kind === SyntaxKind.AwaitKeyword
1604
+ || !isContextualKeyword(kind) && !isClassMemberCompletionKeyword(kind);
1605
+ }
1606
+ function keywordForNode(node) {
1607
+ return isIdentifier(node) ? node.originalKeywordKind || SyntaxKind.Unknown : node.kind;
1608
+ }
1609
+ function getPropertiesForObjectExpression(contextualType, completionsType, obj, checker) {
1610
+ const hasCompletionsType = completionsType && completionsType !== contextualType;
1611
+ const type = hasCompletionsType && !(completionsType.flags & TypeFlags.AnyOrUnknown)
1612
+ ? checker.getUnionType([contextualType, completionsType])
1613
+ : contextualType;
1614
+ const properties = type.isUnion()
1615
+ ? checker.getAllPossiblePropertiesOfTypes(type.types.filter(memberType =>
1616
+ // If we're providing completions for an object literal, skip primitive, array-like, or callable types since those shouldn't be implemented by object literals.
1617
+ !(memberType.flags & TypeFlags.Primitive ||
1618
+ checker.isArrayLikeType(memberType) ||
1619
+ typeHasCallOrConstructSignatures(memberType, checker) ||
1620
+ checker.isTypeInvalidDueToUnionDiscriminant(memberType, obj))))
1621
+ : type.getApparentProperties();
1622
+ return hasCompletionsType ? properties.filter(hasDeclarationOtherThanSelf) : properties;
1623
+ // Filter out members whose only declaration is the object literal itself to avoid
1624
+ // self-fulfilling completions like:
1625
+ //
1626
+ // function f<T>(x: T) {}
1627
+ // f({ abc/**/: "" }) // `abc` is a member of `T` but only because it declares itself
1628
+ function hasDeclarationOtherThanSelf(member) {
1629
+ return some(member.declarations, decl => decl.parent !== obj);
1630
+ }
1631
+ }
1632
+ /**
1633
+ * Returns the immediate owning class declaration of a context token,
1634
+ * on the condition that one exists and that the context implies completion should be given.
1635
+ */
1636
+ function tryGetObjectTypeDeclarationCompletionContainer(sourceFile, contextToken, location, position) {
1637
+ // class c { method() { } | method2() { } }
1638
+ switch (location.kind) {
1639
+ case SyntaxKind.SyntaxList:
1640
+ return tryCast(location.parent, isObjectTypeDeclaration);
1641
+ case SyntaxKind.EndOfFileToken:
1642
+ const cls = tryCast(lastOrUndefined(cast(location.parent, isSourceFile).statements), isObjectTypeDeclaration);
1643
+ if (cls && !findChildOfKind(cls, SyntaxKind.CloseBraceToken, sourceFile)) {
1644
+ return cls;
1645
+ }
1646
+ break;
1647
+ case SyntaxKind.Identifier: {
1648
+ // type t = { a: () => 1\n compon| }
1649
+ if (isFromObjectTypeDeclaration(location)) {
1650
+ return findAncestor(location, isObjectTypeDeclaration);
1651
+ }
1652
+ }
1653
+ }
1654
+ if (!contextToken)
1655
+ return undefined;
1656
+ switch (contextToken.kind) {
1657
+ case SyntaxKind.EqualsToken: // class c { public prop = | /* global completions */ }
1658
+ return undefined;
1659
+ case SyntaxKind.SemicolonToken: // class c {getValue(): number; | }
1660
+ case SyntaxKind.CloseBraceToken: // class c { method() { } | }
1661
+ // class c { method() { } b| }
1662
+ return isFromObjectTypeDeclaration(location) && location.parent.name === location
1663
+ ? location.parent.parent
1664
+ : tryCast(location, isObjectTypeDeclaration);
1665
+ case SyntaxKind.OpenBraceToken: // class c { |
1666
+ case SyntaxKind.CommaToken: // class c {getValue(): number, | }
1667
+ return tryCast(contextToken.parent, isObjectTypeDeclaration);
1668
+ default:
1669
+ if (!isFromObjectTypeDeclaration(contextToken)) {
1670
+ // class c extends React.Component { a: () => 1\n| }
1671
+ if (getLineAndCharacterOfPosition(sourceFile, contextToken.getEnd()).line !== getLineAndCharacterOfPosition(sourceFile, position).line && isObjectTypeDeclaration(location)) {
1672
+ return location;
1673
+ }
1674
+ return undefined;
1675
+ }
1676
+ // Na tag, o corpo de uma classe aceitava também as palavras de membro de classe e o `*` do gerador (CK-02).
1677
+ const isValidKeyword = isInterfaceOrTypeLiteralCompletionKeyword;
1678
+ return (isValidKeyword(contextToken.kind) || isIdentifier(contextToken) && isValidKeyword(stringToToken(contextToken.text)))
1679
+ ? contextToken.parent.parent : undefined;
1680
+ }
1681
+ }
1682
+ /** Se o nó é parte de um membro de um tipo de objeto. Na tag, também de um membro de classe (CK-02). */
1683
+ function isFromObjectTypeDeclaration(node) {
1684
+ return node.parent && isTypeElement(node.parent) && isObjectTypeDeclaration(node.parent.parent);
1685
+ }
1686
+ function isValidTrigger(sourceFile, triggerCharacter, contextToken, position) {
1687
+ switch (triggerCharacter) {
1688
+ case ".":
1689
+ case "@":
1690
+ return true;
1691
+ case '"':
1692
+ case "'":
1693
+ case "`":
1694
+ // Only automatically bring up completions if this is an opening quote.
1695
+ return !!contextToken && isStringLiteralOrTemplate(contextToken) && position === contextToken.getStart(sourceFile) + 1;
1696
+ case "#":
1697
+ // O `#` abria o nome privado de uma classe, que a Linguagem não tem (CK-02).
1698
+ return false;
1699
+ case "<":
1700
+ // Opening JSX tag
1701
+ return !!contextToken && contextToken.kind === SyntaxKind.LessThanToken && (!isBinaryExpression(contextToken.parent) || binaryExpressionMayBeOpenTag(contextToken.parent));
1702
+ case "/":
1703
+ return !!contextToken && (isStringLiteralLike(contextToken)
1704
+ ? !!tryGetImportFromModuleSpecifier(contextToken)
1705
+ : contextToken.kind === SyntaxKind.SlashToken && isJsxClosingElement(contextToken.parent));
1706
+ default:
1707
+ return Debug.assertNever(triggerCharacter);
1708
+ }
1709
+ }
1710
+ function binaryExpressionMayBeOpenTag({ left }) {
1711
+ return nodeIsMissing(left);
1712
+ }
1713
+ function findAlias(typeChecker, symbol, predicate) {
1714
+ let currentAlias = symbol;
1715
+ while (currentAlias.flags & SymbolFlags.Alias && (currentAlias = typeChecker.getImmediateAliasedSymbol(currentAlias))) {
1716
+ if (predicate(currentAlias)) {
1717
+ return currentAlias;
1718
+ }
1719
+ }
1720
+ }