@zzzen/pyright-internal 1.2.0-dev.20230305 → 1.2.0-dev.20230319

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 (157) hide show
  1. package/dist/analyzer/backgroundAnalysisProgram.d.ts +1 -1
  2. package/dist/analyzer/backgroundAnalysisProgram.js +1 -1
  3. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  4. package/dist/analyzer/binder.js +23 -3
  5. package/dist/analyzer/binder.js.map +1 -1
  6. package/dist/analyzer/cacheManager.d.ts +4 -0
  7. package/dist/analyzer/cacheManager.js +13 -0
  8. package/dist/analyzer/cacheManager.js.map +1 -1
  9. package/dist/analyzer/checker.d.ts +2 -1
  10. package/dist/analyzer/checker.js +73 -29
  11. package/dist/analyzer/checker.js.map +1 -1
  12. package/dist/analyzer/codeFlowEngine.js +17 -11
  13. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  14. package/dist/analyzer/commentUtils.js +11 -1
  15. package/dist/analyzer/commentUtils.js.map +1 -1
  16. package/dist/analyzer/constructorTransform.d.ts +1 -0
  17. package/dist/analyzer/constructorTransform.js +19 -2
  18. package/dist/analyzer/constructorTransform.js.map +1 -1
  19. package/dist/analyzer/packageTypeVerifier.js +40 -40
  20. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  21. package/dist/analyzer/patternMatching.js +13 -11
  22. package/dist/analyzer/patternMatching.js.map +1 -1
  23. package/dist/analyzer/program.d.ts +1 -1
  24. package/dist/analyzer/program.js +21 -19
  25. package/dist/analyzer/program.js.map +1 -1
  26. package/dist/analyzer/properties.js +0 -1
  27. package/dist/analyzer/properties.js.map +1 -1
  28. package/dist/analyzer/service.d.ts +2 -1
  29. package/dist/analyzer/service.js +9 -3
  30. package/dist/analyzer/service.js.map +1 -1
  31. package/dist/analyzer/sourceFile.d.ts +2 -2
  32. package/dist/analyzer/sourceFile.js +14 -3
  33. package/dist/analyzer/sourceFile.js.map +1 -1
  34. package/dist/analyzer/sourceFileInfoUtils.d.ts +1 -0
  35. package/dist/analyzer/sourceFileInfoUtils.js +17 -1
  36. package/dist/analyzer/sourceFileInfoUtils.js.map +1 -1
  37. package/dist/analyzer/typeEvaluator.js +195 -87
  38. package/dist/analyzer/typeEvaluator.js.map +1 -1
  39. package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -2
  40. package/dist/analyzer/typeEvaluatorTypes.js +0 -3
  41. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  42. package/dist/analyzer/typePrinter.js +63 -55
  43. package/dist/analyzer/typePrinter.js.map +1 -1
  44. package/dist/analyzer/typeStubWriter.js +2 -0
  45. package/dist/analyzer/typeStubWriter.js.map +1 -1
  46. package/dist/analyzer/typeUtils.d.ts +1 -0
  47. package/dist/analyzer/typeUtils.js +29 -3
  48. package/dist/analyzer/typeUtils.js.map +1 -1
  49. package/dist/analyzer/typedDicts.d.ts +2 -1
  50. package/dist/analyzer/typedDicts.js +84 -40
  51. package/dist/analyzer/typedDicts.js.map +1 -1
  52. package/dist/analyzer/types.d.ts +5 -1
  53. package/dist/analyzer/types.js +11 -1
  54. package/dist/analyzer/types.js.map +1 -1
  55. package/dist/commands/dumpFileDebugInfoCommand.js +82 -4
  56. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  57. package/dist/commands/quickActionCommand.js +2 -2
  58. package/dist/commands/quickActionCommand.js.map +1 -1
  59. package/dist/common/configOptions.d.ts +1 -0
  60. package/dist/common/configOptions.js +4 -0
  61. package/dist/common/configOptions.js.map +1 -1
  62. package/dist/common/console.d.ts +1 -0
  63. package/dist/common/console.js +19 -1
  64. package/dist/common/console.js.map +1 -1
  65. package/dist/common/diagnosticRules.d.ts +2 -1
  66. package/dist/common/diagnosticRules.js +1 -0
  67. package/dist/common/diagnosticRules.js.map +1 -1
  68. package/dist/common/extensibility.d.ts +2 -2
  69. package/dist/common/extensibility.js +25 -1
  70. package/dist/common/extensibility.js.map +1 -1
  71. package/dist/common/extensions.js +3 -1
  72. package/dist/common/extensions.js.map +1 -1
  73. package/dist/languageServerBase.d.ts +21 -46
  74. package/dist/languageServerBase.js +112 -152
  75. package/dist/languageServerBase.js.map +1 -1
  76. package/dist/languageService/analyzerServiceExecutor.d.ts +4 -3
  77. package/dist/languageService/analyzerServiceExecutor.js +9 -7
  78. package/dist/languageService/analyzerServiceExecutor.js.map +1 -1
  79. package/dist/languageService/codeActionProvider.d.ts +2 -2
  80. package/dist/languageService/codeActionProvider.js +4 -4
  81. package/dist/languageService/codeActionProvider.js.map +1 -1
  82. package/dist/languageService/completionProvider.d.ts +4 -2
  83. package/dist/languageService/completionProvider.js +209 -156
  84. package/dist/languageService/completionProvider.js.map +1 -1
  85. package/dist/languageService/definitionProvider.js +1 -1
  86. package/dist/languageService/definitionProvider.js.map +1 -1
  87. package/dist/languageService/documentSymbolCollector.d.ts +2 -1
  88. package/dist/languageService/documentSymbolCollector.js +23 -2
  89. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  90. package/dist/languageService/hoverProvider.d.ts +2 -1
  91. package/dist/languageService/hoverProvider.js +21 -5
  92. package/dist/languageService/hoverProvider.js.map +1 -1
  93. package/dist/languageService/referencesProvider.d.ts +3 -2
  94. package/dist/languageService/referencesProvider.js +4 -4
  95. package/dist/languageService/referencesProvider.js.map +1 -1
  96. package/dist/languageService/renameModuleProvider.d.ts +1 -1
  97. package/dist/languageService/renameModuleProvider.js +8 -1
  98. package/dist/languageService/renameModuleProvider.js.map +1 -1
  99. package/dist/languageService/tooltipUtils.js +2 -1
  100. package/dist/languageService/tooltipUtils.js.map +1 -1
  101. package/dist/localization/localize.d.ts +17 -6
  102. package/dist/localization/localize.js +6 -4
  103. package/dist/localization/localize.js.map +1 -1
  104. package/dist/localization/package.nls.en-us.json +8 -6
  105. package/dist/parser/parser.js +24 -7
  106. package/dist/parser/parser.js.map +1 -1
  107. package/dist/parser/tokenizer.js +1 -1
  108. package/dist/server.d.ts +3 -2
  109. package/dist/server.js +1 -4
  110. package/dist/server.js.map +1 -1
  111. package/dist/tests/cacheManager.test.d.ts +1 -0
  112. package/dist/tests/cacheManager.test.js +69 -0
  113. package/dist/tests/cacheManager.test.js.map +1 -0
  114. package/dist/tests/checker.test.js +2 -2
  115. package/dist/tests/completions.test.js +445 -0
  116. package/dist/tests/completions.test.js.map +1 -1
  117. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js +13 -3
  118. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js.map +1 -1
  119. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js +7 -2
  120. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js.map +1 -1
  121. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.d.ts +7 -0
  122. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.js +45 -0
  123. package/dist/tests/fourslash/missingTypeStub.command.trycatchImport.fourslash.js.map +1 -0
  124. package/dist/tests/harness/fourslash/testLanguageService.d.ts +7 -6
  125. package/dist/tests/harness/fourslash/testLanguageService.js +14 -13
  126. package/dist/tests/harness/fourslash/testLanguageService.js.map +1 -1
  127. package/dist/tests/harness/fourslash/testState.d.ts +5 -4
  128. package/dist/tests/harness/fourslash/testState.js +14 -13
  129. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  130. package/dist/tests/hoverProvider.test.js +1 -1
  131. package/dist/tests/hoverProvider.test.js.map +1 -1
  132. package/dist/tests/moveSymbol.misc.test.js +27 -0
  133. package/dist/tests/moveSymbol.misc.test.js.map +1 -1
  134. package/dist/tests/service.test.js +4 -4
  135. package/dist/tests/service.test.js.map +1 -1
  136. package/dist/tests/signatureHelp.test.js +2 -2
  137. package/dist/tests/signatureHelp.test.js.map +1 -1
  138. package/dist/tests/sourceFile.test.js +3 -3
  139. package/dist/tests/sourceFile.test.js.map +1 -1
  140. package/dist/tests/typeEvaluator1.test.js +4 -0
  141. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  142. package/dist/tests/typeEvaluator2.test.js +6 -2
  143. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  144. package/dist/tests/typeEvaluator3.test.js +1 -1
  145. package/dist/tests/typeEvaluator4.test.js +5 -1
  146. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  147. package/dist/tests/typeEvaluator5.test.js +12 -0
  148. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  149. package/dist/tests/workspaceEditUtils.test.js +2 -2
  150. package/dist/tests/workspaceEditUtils.test.js.map +1 -1
  151. package/dist/workspaceFactory.d.ts +72 -0
  152. package/dist/workspaceFactory.js +421 -0
  153. package/dist/workspaceFactory.js.map +1 -0
  154. package/package.json +4 -4
  155. package/dist/workspaceMap.d.ts +0 -14
  156. package/dist/workspaceMap.js +0 -172
  157. package/dist/workspaceMap.js.map +0 -1
@@ -250,7 +250,7 @@ class CompletionProvider {
250
250
  while (true) {
251
251
  (0, cancellationUtils_1.throwIfCancellationRequested)(this._cancellationToken);
252
252
  if (curNode.nodeType === 49 /* String */) {
253
- return this._getLiteralCompletions(curNode, priorWord, priorText, postText);
253
+ return this._getLiteralCompletions(curNode, offset, priorWord, priorText, postText);
254
254
  }
255
255
  if (curNode.nodeType === 48 /* StringList */ || curNode.nodeType === 27 /* FormatString */) {
256
256
  return undefined;
@@ -259,14 +259,15 @@ class CompletionProvider {
259
259
  return this._getImportModuleCompletions(curNode);
260
260
  }
261
261
  if (curNode.nodeType === 0 /* Error */) {
262
- return this._getExpressionErrorCompletions(curNode, priorWord, priorText, postText);
262
+ return this._getExpressionErrorCompletions(curNode, offset, priorWord, priorText, postText);
263
263
  }
264
264
  if (curNode.nodeType === 35 /* MemberAccess */) {
265
265
  return this._getMemberAccessCompletions(curNode.leftExpression, priorWord);
266
266
  }
267
267
  if (curNode.nodeType === 15 /* Dictionary */) {
268
268
  const completionMap = new CompletionMap();
269
- if (this._addTypedDictKeys(curNode, /* stringNode */ undefined, priorText, postText, completionMap)) {
269
+ if (this._tryAddTypedDictKeysFromDictionary(curNode,
270
+ /* stringNode */ undefined, priorWord, priorText, postText, completionMap)) {
270
271
  return { completionMap };
271
272
  }
272
273
  }
@@ -276,8 +277,8 @@ class CompletionProvider {
276
277
  const dictionaryNode = dictionaryEntry.parent;
277
278
  if (dictionaryNode.trailingCommaToken && dictionaryNode.trailingCommaToken.start < offset) {
278
279
  const completionMap = new CompletionMap();
279
- if (this._addTypedDictKeys(dictionaryNode,
280
- /* stringNode */ undefined, priorText, postText, completionMap)) {
280
+ if (this._tryAddTypedDictKeysFromDictionary(dictionaryNode,
281
+ /* stringNode */ undefined, priorWord, priorText, postText, completionMap)) {
281
282
  return { completionMap };
282
283
  }
283
284
  }
@@ -542,7 +543,7 @@ class CompletionProvider {
542
543
  return tokens.getItemAt(tokenIndex + 1);
543
544
  }
544
545
  }
545
- _getExpressionErrorCompletions(node, priorWord, priorText, postText) {
546
+ _getExpressionErrorCompletions(node, offset, priorWord, priorText, postText) {
546
547
  var _a;
547
548
  // Is the error due to a missing member access name? If so,
548
549
  // we can evaluate the left side of the member access expression
@@ -605,8 +606,9 @@ class CompletionProvider {
605
606
  case 4 /* MissingDecoratorCallName */: {
606
607
  return this._getExpressionCompletions(node, priorWord, priorText, postText);
607
608
  }
609
+ case 11 /* MissingPattern */:
608
610
  case 3 /* MissingIndexOrSlice */: {
609
- let completionResults = this._getLiteralCompletions(node, priorWord, priorText, postText);
611
+ let completionResults = this._getLiteralCompletions(node, offset, priorWord, priorText, postText);
610
612
  if (!completionResults) {
611
613
  completionResults = this._getExpressionCompletions(node, priorWord, priorText, postText);
612
614
  }
@@ -1052,10 +1054,8 @@ class CompletionProvider {
1052
1054
  /* isInImport */ false, (0, types_1.isClass)(subtype) ? subtype : undefined, completionMap);
1053
1055
  });
1054
1056
  }
1055
- // If we don't know this type, look for a module we should stub.
1056
- if (!leftType || (0, types_1.isUnknown)(leftType) || (0, types_1.isUnbound)(leftType)) {
1057
- memberAccessInfo = this._getLastKnownModule(leftExprNode, leftType);
1058
- }
1057
+ // Save member access info for every request
1058
+ memberAccessInfo = this._getLastKnownModule(leftExprNode, leftType);
1059
1059
  return { completionMap, memberAccessInfo };
1060
1060
  }
1061
1061
  _getLastKnownModule(leftExprNode, leftType) {
@@ -1075,7 +1075,7 @@ class CompletionProvider {
1075
1075
  }
1076
1076
  }
1077
1077
  else {
1078
- curNode = undefined;
1078
+ break;
1079
1079
  }
1080
1080
  if (curNode) {
1081
1081
  curType = this._evaluator.getType(curNode);
@@ -1108,7 +1108,7 @@ class CompletionProvider {
1108
1108
  return this._getExpressionCompletions(parseNode, priorWord, priorText, postText);
1109
1109
  }
1110
1110
  _getExpressionCompletions(parseNode, priorWord, priorText, postText) {
1111
- var _a, _b, _c, _d;
1111
+ var _a, _b;
1112
1112
  const isIndexArgument = this._isIndexArgument(parseNode);
1113
1113
  // If the user typed a "." as part of a number, don't present
1114
1114
  // any completion options.
@@ -1152,39 +1152,7 @@ class CompletionProvider {
1152
1152
  this._addAutoImportCompletions(priorWord, similarityLimit, this._options.lazyEdit, completionResults);
1153
1153
  }
1154
1154
  // Add literal values if appropriate.
1155
- if (parseNode.nodeType === 0 /* Error */) {
1156
- if (parseNode.category === 3 /* MissingIndexOrSlice */ &&
1157
- ((_c = parseNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 24 /* Index */) {
1158
- this._tryAddTypedDictStringLiteral(parseNode.parent,
1159
- /* priorText */ undefined,
1160
- /* postText */ undefined, completionMap);
1161
- }
1162
- else if (parseNode.category === 2 /* MissingExpression */) {
1163
- if (parseNode.parent && parseNode.parent.nodeType === 3 /* Assignment */) {
1164
- const declaredTypeOfTarget = (_d = this._evaluator.getExpectedType(parseNode)) === null || _d === void 0 ? void 0 : _d.type;
1165
- if (declaredTypeOfTarget) {
1166
- this._addLiteralValuesForTargetType(declaredTypeOfTarget, priorText, priorWord, postText, completionMap);
1167
- }
1168
- }
1169
- }
1170
- }
1171
- if (isIndexArgument) {
1172
- // Completion for dict key (ex, dict_variable[<here>])
1173
- const indexNode = parseNode.parent.parent;
1174
- this._getIndexerKeys(indexNode, parseNode).forEach((key) => {
1175
- if (completionMap.has(key)) {
1176
- // Don't add key if it already exists in the completion.
1177
- // ex) key = "dictKey"
1178
- // dict[key] = 1
1179
- // print(dict[<key will come from symbol table provider>]))
1180
- return;
1181
- }
1182
- this._addNameToCompletions(key, vscode_languageserver_1.CompletionItemKind.Constant, priorWord, completionMap, {
1183
- sortText: this._makeSortText(SortCategory.LiteralValue, key),
1184
- itemDetail: exports.dictionaryKeyDetail,
1185
- });
1186
- });
1187
- }
1155
+ this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap);
1188
1156
  return completionResults;
1189
1157
  }
1190
1158
  _isIndexArgument(node) {
@@ -1213,11 +1181,11 @@ class CompletionProvider {
1213
1181
  this._addNamedParameters(signatureInfo, priorWord, completionMap);
1214
1182
  }
1215
1183
  // Add literals that apply to this parameter.
1216
- this._addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap);
1184
+ this._addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap);
1217
1185
  }
1218
1186
  }
1219
1187
  }
1220
- _addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap) {
1188
+ _addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap) {
1221
1189
  signatureInfo.signatures.forEach((signature) => {
1222
1190
  if (!signature.activeParam) {
1223
1191
  return undefined;
@@ -1228,12 +1196,12 @@ class CompletionProvider {
1228
1196
  return undefined;
1229
1197
  }
1230
1198
  const paramType = type.details.parameters[paramIndex].type;
1231
- this._addLiteralValuesForTargetType(paramType, priorText, priorWord, postText, completionMap);
1199
+ this._addLiteralValuesForTargetType(paramType, priorWord, priorText, postText, completionMap);
1232
1200
  return undefined;
1233
1201
  });
1234
1202
  }
1235
- _addLiteralValuesForTargetType(type, priorText, priorWord, postText, completionMap) {
1236
- const quoteValue = this._getQuoteInfo(priorText);
1203
+ _addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap) {
1204
+ const quoteValue = this._getQuoteInfo(priorWord, priorText);
1237
1205
  this._getSubTypesWithLiteralValues(type).forEach((v) => {
1238
1206
  if (types_1.ClassType.isBuiltIn(v, 'str')) {
1239
1207
  const value = (0, typePrinter_1.printLiteralValue)(v, quoteValue.quoteCharacter);
@@ -1243,7 +1211,7 @@ class CompletionProvider {
1243
1211
  });
1244
1212
  }
1245
1213
  else {
1246
- this._addStringLiteralToCompletions(value.substr(1, value.length - 2), quoteValue.stringValue, postText, quoteValue.quoteCharacter, completionMap);
1214
+ this._addStringLiteralToCompletions(value.substr(1, value.length - 2), quoteValue, postText, completionMap);
1247
1215
  }
1248
1216
  }
1249
1217
  });
@@ -1399,96 +1367,178 @@ class CompletionProvider {
1399
1367
  }
1400
1368
  return [...keys];
1401
1369
  }
1402
- _getLiteralCompletions(parseNode, priorWord, priorText, postText) {
1403
- var _a, _b, _c;
1404
- let parentNode = parseNode.parent;
1405
- if (!parentNode) {
1406
- return undefined;
1370
+ _getLiteralCompletions(parseNode, offset, priorWord, priorText, postText) {
1371
+ if (this._options.triggerCharacter === '"' || this._options.triggerCharacter === "'") {
1372
+ if (parseNode.start !== offset - 1) {
1373
+ // If completion is triggered by typing " or ', it must be the one that starts a string
1374
+ // literal. In another word, it can't be something inside of another string or comment
1375
+ return undefined;
1376
+ }
1407
1377
  }
1408
1378
  const completionMap = new CompletionMap();
1379
+ if (!this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap)) {
1380
+ return undefined;
1381
+ }
1382
+ return { completionMap };
1383
+ }
1384
+ _tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap) {
1385
+ var _a, _b, _c, _d, _e, _f;
1386
+ const parentAndChild = getParentSkippingStringList(parseNode);
1387
+ if (!parentAndChild) {
1388
+ return false;
1389
+ }
1409
1390
  // See if the type evaluator can determine the expected type for this node.
1410
- if ((0, parseNodes_1.isExpressionNode)(parentNode)) {
1411
- const expectedTypeResult = this._evaluator.getExpectedType(parentNode);
1391
+ // ex) a: Literal["str"] = /* here */
1392
+ const nodeForExpectedType = parentAndChild.parent.nodeType === 3 /* Assignment */
1393
+ ? parentAndChild.parent.rightExpression === parentAndChild.child
1394
+ ? parentAndChild.child
1395
+ : undefined
1396
+ : (0, parseNodes_1.isExpressionNode)(parentAndChild.child)
1397
+ ? parentAndChild.child
1398
+ : undefined;
1399
+ if (nodeForExpectedType) {
1400
+ const expectedTypeResult = this._evaluator.getExpectedType(nodeForExpectedType);
1412
1401
  if (expectedTypeResult && (0, typeUtils_1.isLiteralTypeOrUnion)(expectedTypeResult.type)) {
1413
- this._addLiteralValuesForTargetType(expectedTypeResult.type, priorText, priorWord, postText, completionMap);
1414
- return { completionMap };
1415
- }
1416
- if (parseNode.nodeType === 49 /* String */ && ((_a = parseNode.parent) === null || _a === void 0 ? void 0 : _a.parent)) {
1417
- const stringParent = parseNode.parent.parent;
1418
- // If the dictionary is not yet filled in, it will appear as though it's
1419
- // a set initially.
1420
- let dictOrSet;
1421
- if (stringParent.nodeType === 17 /* DictionaryKeyEntry */ &&
1422
- stringParent.keyExpression === parseNode.parent &&
1423
- ((_b = stringParent.parent) === null || _b === void 0 ? void 0 : _b.nodeType) === 15 /* Dictionary */) {
1424
- dictOrSet = stringParent.parent;
1425
- }
1426
- else if ((stringParent === null || stringParent === void 0 ? void 0 : stringParent.nodeType) === 45 /* Set */) {
1427
- dictOrSet = stringParent;
1428
- }
1429
- if (dictOrSet) {
1430
- if (this._addTypedDictKeys(dictOrSet, parseNode, priorText, postText, completionMap)) {
1431
- return { completionMap };
1432
- }
1433
- }
1402
+ this._addLiteralValuesForTargetType(expectedTypeResult.type, priorWord, priorText, postText, completionMap);
1403
+ return true;
1434
1404
  }
1435
1405
  }
1436
- if (parentNode.nodeType !== 1 /* Argument */) {
1437
- if (parentNode.nodeType !== 48 /* StringList */ || parentNode.strings.length > 1) {
1438
- return undefined;
1406
+ // ex) a: TypedDictType = { "/* here */" } or a: TypedDictType = { A/* here */ }
1407
+ const nodeForKey = parentAndChild.parent;
1408
+ if (nodeForKey) {
1409
+ // If the dictionary is not yet filled in, it will appear as though it's
1410
+ // a set initially.
1411
+ let dictOrSet;
1412
+ if (nodeForKey.nodeType === 17 /* DictionaryKeyEntry */ &&
1413
+ nodeForKey.keyExpression === parentAndChild.child &&
1414
+ ((_a = nodeForKey.parent) === null || _a === void 0 ? void 0 : _a.nodeType) === 15 /* Dictionary */) {
1415
+ dictOrSet = nodeForKey.parent;
1439
1416
  }
1440
- parentNode = parentNode.parent;
1441
- if (!parentNode) {
1442
- return undefined;
1417
+ else if ((nodeForKey === null || nodeForKey === void 0 ? void 0 : nodeForKey.nodeType) === 45 /* Set */) {
1418
+ dictOrSet = nodeForKey;
1419
+ }
1420
+ if (dictOrSet) {
1421
+ if (this._tryAddTypedDictKeysFromDictionary(dictOrSet, parseNode.nodeType === 49 /* String */ ? parseNode : undefined, priorWord, priorText, postText, completionMap)) {
1422
+ return true;
1423
+ }
1443
1424
  }
1444
1425
  }
1445
- if (parentNode.nodeType === 1 /* Argument */ && ((_c = parentNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 24 /* Index */) {
1426
+ // a: DictType = { .... }
1427
+ // a[/* here */] or a['/* here */'] or a[variable/*here*/]
1428
+ const argument = parentAndChild.parent;
1429
+ if (argument.nodeType === 1 /* Argument */ && ((_b = argument.parent) === null || _b === void 0 ? void 0 : _b.nodeType) === 24 /* Index */) {
1446
1430
  const priorTextInString = parseNode.nodeType === 49 /* String */ ? priorText : '';
1447
- if (!this._tryAddTypedDictStringLiteral(parentNode.parent, priorTextInString, postText, completionMap)) {
1448
- const keys = this._getIndexerKeys(parentNode.parent, parseNode);
1449
- const quoteValue = this._getQuoteInfo(priorTextInString);
1450
- for (const key of keys) {
1451
- const stringLiteral = /^["|'].*["|']$/.test(key);
1452
- if (parseNode.nodeType === 49 /* String */ && !stringLiteral) {
1453
- continue;
1454
- }
1455
- if (stringLiteral) {
1456
- const keyWithoutQuote = key.substr(1, key.length - 2);
1457
- this._addStringLiteralToCompletions(keyWithoutQuote, quoteValue.stringValue, postText, quoteValue.quoteCharacter, completionMap, exports.dictionaryKeyDetail);
1458
- }
1459
- else {
1460
- this._addNameToCompletions(key, vscode_languageserver_1.CompletionItemKind.Constant, priorWord, completionMap, {
1461
- sortText: this._makeSortText(SortCategory.LiteralValue, key),
1462
- itemDetail: exports.dictionaryKeyDetail,
1463
- });
1464
- }
1431
+ if (this._tryAddTypedDictKeysFromIndexer(argument.parent, priorWord, priorTextInString, postText, completionMap)) {
1432
+ return true;
1433
+ }
1434
+ const quoteInfo = this._getQuoteInfo(priorWord, priorTextInString);
1435
+ const keys = this._getIndexerKeys(argument.parent, parseNode);
1436
+ let keyFound = false;
1437
+ for (const key of keys) {
1438
+ if (completionMap.has(key)) {
1439
+ // Don't add key if it already exists in the completion.
1440
+ // ex) key = "dictKey"
1441
+ // dict[key] = 1
1442
+ // print(dict[<key will come from symbol table provider>]))
1443
+ continue;
1465
1444
  }
1466
- if (completionMap.size === 0) {
1467
- return undefined;
1445
+ const stringLiteral = /^["|'].*["|']$/.test(key);
1446
+ if (parseNode.nodeType === 49 /* String */ && !stringLiteral) {
1447
+ continue;
1468
1448
  }
1449
+ keyFound = true;
1450
+ if (stringLiteral) {
1451
+ const keyWithoutQuote = key.substr(1, key.length - 2);
1452
+ this._addStringLiteralToCompletions(keyWithoutQuote, quoteInfo, postText, completionMap, exports.dictionaryKeyDetail);
1453
+ }
1454
+ else {
1455
+ this._addNameToCompletions(key, vscode_languageserver_1.CompletionItemKind.Constant, priorWord, completionMap, {
1456
+ sortText: this._makeSortText(SortCategory.LiteralValue, key),
1457
+ itemDetail: exports.dictionaryKeyDetail,
1458
+ });
1459
+ }
1460
+ }
1461
+ if (keyFound) {
1462
+ return true;
1469
1463
  }
1470
1464
  }
1471
- else {
1472
- debug.assert(parseNode.nodeType === 49 /* String */);
1465
+ // if c == "/* here */"
1466
+ const comparison = parentAndChild.parent;
1467
+ const supportedOperators = [2 /* Assign */, 12 /* Equals */, 28 /* NotEquals */];
1468
+ if (comparison.nodeType === 7 /* BinaryOperation */ && supportedOperators.includes(comparison.operator)) {
1469
+ const type = this._evaluator.getType(comparison.leftExpression);
1470
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1471
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1472
+ return true;
1473
+ }
1474
+ }
1475
+ // if c := "/* here */"
1476
+ const assignmentExpression = parentAndChild.parent;
1477
+ if (assignmentExpression.nodeType === 4 /* AssignmentExpression */ &&
1478
+ assignmentExpression.rightExpression === parentAndChild.child) {
1479
+ const type = this._evaluator.getType(assignmentExpression.name);
1480
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1481
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1482
+ return true;
1483
+ }
1484
+ }
1485
+ // For now, we only support simple cases. no complex pattern matching.
1486
+ // match c:
1487
+ // case /* here */
1488
+ const caseNode = parentAndChild.parent;
1489
+ if (caseNode.nodeType === 64 /* Case */ &&
1490
+ caseNode.pattern.nodeType === 0 /* Error */ &&
1491
+ caseNode.pattern.category === 11 /* MissingPattern */ &&
1492
+ caseNode.suite === parentAndChild.child &&
1493
+ ((_c = caseNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 63 /* Match */) {
1494
+ const type = this._evaluator.getType(caseNode.parent.subjectExpression);
1495
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1496
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1497
+ return true;
1498
+ }
1499
+ }
1500
+ // match c:
1501
+ // case "/* here */"
1502
+ // case Sym/*here*/
1503
+ const patternLiteral = parentAndChild.parent;
1504
+ if ((patternLiteral.nodeType === 67 /* PatternLiteral */ ||
1505
+ patternLiteral.nodeType === 69 /* PatternCapture */) &&
1506
+ ((_d = patternLiteral.parent) === null || _d === void 0 ? void 0 : _d.nodeType) === 66 /* PatternAs */ &&
1507
+ ((_e = patternLiteral.parent.parent) === null || _e === void 0 ? void 0 : _e.nodeType) === 64 /* Case */ &&
1508
+ ((_f = patternLiteral.parent.parent.parent) === null || _f === void 0 ? void 0 : _f.nodeType) === 63 /* Match */) {
1509
+ const type = this._evaluator.getType(patternLiteral.parent.parent.parent.subjectExpression);
1510
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1511
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1512
+ return true;
1513
+ }
1514
+ }
1515
+ if (parseNode.nodeType === 49 /* String */) {
1473
1516
  const offset = (0, positionUtils_1.convertPositionToOffset)(this._position, this._parseResults.tokenizerOutput.lines);
1474
- const atArgument = parentNode.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
1517
+ const atArgument = parseNode.parent.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
1475
1518
  this._addCallArgumentCompletions(parseNode, priorWord, priorText, postText, atArgument, completionMap);
1519
+ return true;
1476
1520
  }
1477
- return { completionMap };
1478
- }
1479
- _addTypedDictKeys(dictionaryNode, stringNode, priorText, postText, completionMap) {
1480
- var _a;
1481
- const expectedTypeResult = this._evaluator.getExpectedType(dictionaryNode);
1482
- if (!expectedTypeResult) {
1483
- return false;
1484
- }
1485
- // If the expected type result is associated with a node above the
1486
- // dictionaryNode in the parse tree, there are no typed dict keys to add.
1487
- if (ParseTreeUtils.getNodeDepth(expectedTypeResult.node) < ParseTreeUtils.getNodeDepth(dictionaryNode)) {
1488
- return false;
1521
+ return false;
1522
+ function getParentSkippingStringList(node) {
1523
+ var _a;
1524
+ if (!node.parent) {
1525
+ return undefined;
1526
+ }
1527
+ if (node.nodeType !== 49 /* String */) {
1528
+ return { parent: node.parent, child: node };
1529
+ }
1530
+ if (!node.parent.parent) {
1531
+ return undefined;
1532
+ }
1533
+ if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.nodeType) !== 48 /* StringList */ || node.parent.strings.length > 1) {
1534
+ return undefined;
1535
+ }
1536
+ return { parent: node.parent.parent, child: node.parent };
1489
1537
  }
1538
+ }
1539
+ _tryAddTypedDictKeys(type, existingKeys, priorWord, priorText, postText, completionMap) {
1490
1540
  let typedDicts = [];
1491
- (0, typeUtils_1.doForEachSubtype)(expectedTypeResult.type, (subtype) => {
1541
+ (0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
1492
1542
  if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isTypedDictClass(subtype)) {
1493
1543
  typedDicts.push(subtype);
1494
1544
  }
@@ -1496,10 +1546,9 @@ class CompletionProvider {
1496
1546
  if (typedDicts.length === 0) {
1497
1547
  return false;
1498
1548
  }
1499
- const keys = this._getDictExpressionStringKeys(dictionaryNode, stringNode ? new Set([(_a = stringNode.parent) === null || _a === void 0 ? void 0 : _a.id]) : undefined);
1500
- typedDicts = this._tryNarrowTypedDicts(typedDicts, keys);
1501
- const quoteValue = this._getQuoteInfo(priorText);
1502
- const excludes = new Set(keys);
1549
+ typedDicts = this._tryNarrowTypedDicts(typedDicts, existingKeys);
1550
+ const quoteInfo = this._getQuoteInfo(priorWord, priorText);
1551
+ const excludes = new Set(existingKeys);
1503
1552
  typedDicts.forEach((typedDict) => {
1504
1553
  (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, typedDict, /* allowNarrowed */ true).forEach((_, key) => {
1505
1554
  // Unions of TypedDicts may define the same key.
@@ -1507,13 +1556,25 @@ class CompletionProvider {
1507
1556
  return;
1508
1557
  }
1509
1558
  excludes.add(key);
1510
- this._addStringLiteralToCompletions(key, quoteValue ? quoteValue.stringValue : undefined, postText, quoteValue
1511
- ? quoteValue.quoteCharacter
1512
- : this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter, completionMap);
1559
+ this._addStringLiteralToCompletions(key, quoteInfo, postText, completionMap);
1513
1560
  });
1514
1561
  });
1515
1562
  return true;
1516
1563
  }
1564
+ _tryAddTypedDictKeysFromDictionary(dictionaryNode, stringNode, priorWord, priorText, postText, completionMap) {
1565
+ var _a;
1566
+ const expectedTypeResult = this._evaluator.getExpectedType(dictionaryNode);
1567
+ if (!expectedTypeResult) {
1568
+ return false;
1569
+ }
1570
+ // If the expected type result is associated with a node above the
1571
+ // dictionaryNode in the parse tree, there are no typed dict keys to add.
1572
+ if (ParseTreeUtils.getNodeDepth(expectedTypeResult.node) < ParseTreeUtils.getNodeDepth(dictionaryNode)) {
1573
+ return false;
1574
+ }
1575
+ const keys = this._getDictExpressionStringKeys(dictionaryNode, stringNode ? new Set([(_a = stringNode.parent) === null || _a === void 0 ? void 0 : _a.id]) : undefined);
1576
+ return this._tryAddTypedDictKeys(expectedTypeResult.type, keys, priorWord, priorText, postText, completionMap);
1577
+ }
1517
1578
  _tryNarrowTypedDicts(types, keys) {
1518
1579
  const newTypes = types.flatMap((type) => {
1519
1580
  const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, type, /* allowNarrowed */ true);
@@ -1532,14 +1593,15 @@ class CompletionProvider {
1532
1593
  }
1533
1594
  // Find out quotation and string prefix to use for string literals
1534
1595
  // completion under current context.
1535
- _getQuoteInfo(priorText) {
1596
+ _getQuoteInfo(priorWord, priorText) {
1597
+ let filterText = priorWord;
1536
1598
  let stringValue = undefined;
1537
1599
  let quoteCharacter = this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
1538
1600
  // If completion is not inside of the existing string literal
1539
1601
  // ex) typedDict[ |<= here
1540
1602
  // use default quotation char without any string prefix.
1541
1603
  if (!this._insideStringLiteral) {
1542
- return { stringValue, quoteCharacter };
1604
+ return { priorWord, priorText, filterText, stringValue, quoteCharacter };
1543
1605
  }
1544
1606
  const singleQuote = "'";
1545
1607
  const doubleQuote = '"';
@@ -1569,9 +1631,12 @@ class CompletionProvider {
1569
1631
  if (this._insideStringLiteral.flags & 64 /* Format */) {
1570
1632
  quoteCharacter = this._insideStringLiteral.flags & 1 /* SingleQuote */ ? doubleQuote : singleQuote;
1571
1633
  }
1572
- return { stringValue, quoteCharacter };
1634
+ if (stringValue) {
1635
+ filterText = stringValue;
1636
+ }
1637
+ return { priorWord, priorText, filterText, stringValue, quoteCharacter };
1573
1638
  }
1574
- _tryAddTypedDictStringLiteral(indexNode, priorText, postText, completionMap) {
1639
+ _tryAddTypedDictKeysFromIndexer(indexNode, priorWord, priorText, postText, completionMap) {
1575
1640
  if (!indexNode) {
1576
1641
  return false;
1577
1642
  }
@@ -1579,26 +1644,11 @@ class CompletionProvider {
1579
1644
  if (!baseType) {
1580
1645
  return false;
1581
1646
  }
1582
- let foundTypedDict = false;
1583
- (0, typeUtils_1.doForEachSubtype)(baseType, (subtype) => {
1584
- if (!(0, types_1.isClassInstance)(subtype)) {
1585
- return;
1586
- }
1587
- if (!types_1.ClassType.isTypedDictClass(subtype)) {
1588
- return;
1589
- }
1590
- const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, subtype, /* allowNarrowed */ true);
1591
- const quoteValue = this._getQuoteInfo(priorText);
1592
- entries.forEach((_, key) => {
1593
- this._addStringLiteralToCompletions(key, quoteValue.stringValue, postText, quoteValue.quoteCharacter, completionMap);
1594
- });
1595
- foundTypedDict = true;
1596
- });
1597
- return foundTypedDict;
1647
+ return this._tryAddTypedDictKeys(baseType, [], priorWord, priorText, postText, completionMap);
1598
1648
  }
1599
- _addStringLiteralToCompletions(value, priorString, postText, quoteCharacter, completionMap, detail) {
1600
- if (StringUtils.isPatternInSymbol(priorString || '', value)) {
1601
- const valueWithQuotes = `${quoteCharacter}${value}${quoteCharacter}`;
1649
+ _addStringLiteralToCompletions(value, quoteInfo, postText, completionMap, detail) {
1650
+ if (StringUtils.isPatternInSymbol(quoteInfo.filterText || '', value)) {
1651
+ const valueWithQuotes = `${quoteInfo.quoteCharacter}${value}${quoteInfo.quoteCharacter}`;
1602
1652
  if (completionMap.has(valueWithQuotes)) {
1603
1653
  return;
1604
1654
  }
@@ -1606,14 +1656,17 @@ class CompletionProvider {
1606
1656
  completionItem.kind = vscode_languageserver_1.CompletionItemKind.Constant;
1607
1657
  completionItem.sortText = this._makeSortText(SortCategory.LiteralValue, valueWithQuotes);
1608
1658
  let rangeStartCol = this._position.character;
1609
- if (priorString !== undefined) {
1610
- rangeStartCol -= priorString.length + 1;
1659
+ if (quoteInfo.stringValue !== undefined) {
1660
+ rangeStartCol -= quoteInfo.stringValue.length + 1;
1661
+ }
1662
+ else if (quoteInfo.priorWord) {
1663
+ rangeStartCol -= quoteInfo.priorWord.length;
1611
1664
  }
1612
1665
  // If the text after the insertion point is the closing quote,
1613
1666
  // replace it.
1614
1667
  let rangeEndCol = this._position.character;
1615
1668
  if (postText !== undefined) {
1616
- if (postText.startsWith(quoteCharacter)) {
1669
+ if (postText.startsWith(quoteInfo.quoteCharacter)) {
1617
1670
  rangeEndCol++;
1618
1671
  }
1619
1672
  }