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

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 (69) hide show
  1. package/dist/analyzer/binder.js +23 -3
  2. package/dist/analyzer/binder.js.map +1 -1
  3. package/dist/analyzer/checker.js +3 -3
  4. package/dist/analyzer/checker.js.map +1 -1
  5. package/dist/analyzer/commentUtils.js +11 -1
  6. package/dist/analyzer/commentUtils.js.map +1 -1
  7. package/dist/analyzer/constructorTransform.d.ts +1 -0
  8. package/dist/analyzer/constructorTransform.js +19 -2
  9. package/dist/analyzer/constructorTransform.js.map +1 -1
  10. package/dist/analyzer/packageTypeVerifier.js +40 -40
  11. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  12. package/dist/analyzer/patternMatching.js +13 -11
  13. package/dist/analyzer/patternMatching.js.map +1 -1
  14. package/dist/analyzer/program.js +5 -4
  15. package/dist/analyzer/program.js.map +1 -1
  16. package/dist/analyzer/sourceFile.js +12 -1
  17. package/dist/analyzer/sourceFile.js.map +1 -1
  18. package/dist/analyzer/typeEvaluator.js +156 -42
  19. package/dist/analyzer/typeEvaluator.js.map +1 -1
  20. package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -0
  21. package/dist/analyzer/typePrinter.js +63 -55
  22. package/dist/analyzer/typePrinter.js.map +1 -1
  23. package/dist/analyzer/typeUtils.d.ts +1 -0
  24. package/dist/analyzer/typeUtils.js +9 -3
  25. package/dist/analyzer/typeUtils.js.map +1 -1
  26. package/dist/analyzer/typedDicts.d.ts +2 -1
  27. package/dist/analyzer/typedDicts.js +57 -40
  28. package/dist/analyzer/typedDicts.js.map +1 -1
  29. package/dist/analyzer/types.d.ts +1 -0
  30. package/dist/analyzer/types.js +8 -0
  31. package/dist/analyzer/types.js.map +1 -1
  32. package/dist/commands/dumpFileDebugInfoCommand.js +78 -0
  33. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  34. package/dist/common/extensibility.js +25 -1
  35. package/dist/common/extensibility.js.map +1 -1
  36. package/dist/languageServerBase.js +3 -1
  37. package/dist/languageServerBase.js.map +1 -1
  38. package/dist/languageService/completionProvider.d.ts +4 -2
  39. package/dist/languageService/completionProvider.js +206 -151
  40. package/dist/languageService/completionProvider.js.map +1 -1
  41. package/dist/languageService/renameModuleProvider.d.ts +1 -1
  42. package/dist/languageService/renameModuleProvider.js +8 -1
  43. package/dist/languageService/renameModuleProvider.js.map +1 -1
  44. package/dist/languageService/tooltipUtils.js +2 -1
  45. package/dist/languageService/tooltipUtils.js.map +1 -1
  46. package/dist/localization/localize.d.ts +3 -0
  47. package/dist/localization/localize.js +1 -0
  48. package/dist/localization/localize.js.map +1 -1
  49. package/dist/localization/package.nls.en-us.json +1 -0
  50. package/dist/parser/parser.js +22 -7
  51. package/dist/parser/parser.js.map +1 -1
  52. package/dist/parser/tokenizer.js +1 -1
  53. package/dist/tests/completions.test.js +445 -0
  54. package/dist/tests/completions.test.js.map +1 -1
  55. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js +13 -3
  56. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js.map +1 -1
  57. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js +7 -2
  58. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js.map +1 -1
  59. package/dist/tests/hoverProvider.test.js +1 -1
  60. package/dist/tests/hoverProvider.test.js.map +1 -1
  61. package/dist/tests/moveSymbol.misc.test.js +27 -0
  62. package/dist/tests/moveSymbol.misc.test.js.map +1 -1
  63. package/dist/tests/typeEvaluator1.test.js +4 -0
  64. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  65. package/dist/tests/typeEvaluator2.test.js +4 -0
  66. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  67. package/dist/tests/typeEvaluator4.test.js +4 -0
  68. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  69. package/package.json +1 -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
  }
@@ -1108,7 +1110,7 @@ class CompletionProvider {
1108
1110
  return this._getExpressionCompletions(parseNode, priorWord, priorText, postText);
1109
1111
  }
1110
1112
  _getExpressionCompletions(parseNode, priorWord, priorText, postText) {
1111
- var _a, _b, _c, _d;
1113
+ var _a, _b;
1112
1114
  const isIndexArgument = this._isIndexArgument(parseNode);
1113
1115
  // If the user typed a "." as part of a number, don't present
1114
1116
  // any completion options.
@@ -1152,39 +1154,7 @@ class CompletionProvider {
1152
1154
  this._addAutoImportCompletions(priorWord, similarityLimit, this._options.lazyEdit, completionResults);
1153
1155
  }
1154
1156
  // 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
- }
1157
+ this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap);
1188
1158
  return completionResults;
1189
1159
  }
1190
1160
  _isIndexArgument(node) {
@@ -1213,11 +1183,11 @@ class CompletionProvider {
1213
1183
  this._addNamedParameters(signatureInfo, priorWord, completionMap);
1214
1184
  }
1215
1185
  // Add literals that apply to this parameter.
1216
- this._addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap);
1186
+ this._addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap);
1217
1187
  }
1218
1188
  }
1219
1189
  }
1220
- _addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap) {
1190
+ _addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap) {
1221
1191
  signatureInfo.signatures.forEach((signature) => {
1222
1192
  if (!signature.activeParam) {
1223
1193
  return undefined;
@@ -1228,12 +1198,12 @@ class CompletionProvider {
1228
1198
  return undefined;
1229
1199
  }
1230
1200
  const paramType = type.details.parameters[paramIndex].type;
1231
- this._addLiteralValuesForTargetType(paramType, priorText, priorWord, postText, completionMap);
1201
+ this._addLiteralValuesForTargetType(paramType, priorWord, priorText, postText, completionMap);
1232
1202
  return undefined;
1233
1203
  });
1234
1204
  }
1235
- _addLiteralValuesForTargetType(type, priorText, priorWord, postText, completionMap) {
1236
- const quoteValue = this._getQuoteInfo(priorText);
1205
+ _addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap) {
1206
+ const quoteValue = this._getQuoteInfo(priorWord, priorText);
1237
1207
  this._getSubTypesWithLiteralValues(type).forEach((v) => {
1238
1208
  if (types_1.ClassType.isBuiltIn(v, 'str')) {
1239
1209
  const value = (0, typePrinter_1.printLiteralValue)(v, quoteValue.quoteCharacter);
@@ -1243,7 +1213,7 @@ class CompletionProvider {
1243
1213
  });
1244
1214
  }
1245
1215
  else {
1246
- this._addStringLiteralToCompletions(value.substr(1, value.length - 2), quoteValue.stringValue, postText, quoteValue.quoteCharacter, completionMap);
1216
+ this._addStringLiteralToCompletions(value.substr(1, value.length - 2), quoteValue, postText, completionMap);
1247
1217
  }
1248
1218
  }
1249
1219
  });
@@ -1399,96 +1369,178 @@ class CompletionProvider {
1399
1369
  }
1400
1370
  return [...keys];
1401
1371
  }
1402
- _getLiteralCompletions(parseNode, priorWord, priorText, postText) {
1403
- var _a, _b, _c;
1404
- let parentNode = parseNode.parent;
1405
- if (!parentNode) {
1406
- return undefined;
1372
+ _getLiteralCompletions(parseNode, offset, priorWord, priorText, postText) {
1373
+ if (this._options.triggerCharacter === '"' || this._options.triggerCharacter === "'") {
1374
+ if (parseNode.start !== offset - 1) {
1375
+ // If completion is triggered by typing " or ', it must be the one that starts a string
1376
+ // literal. In another word, it can't be something inside of another string or comment
1377
+ return undefined;
1378
+ }
1407
1379
  }
1408
1380
  const completionMap = new CompletionMap();
1381
+ if (!this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap)) {
1382
+ return undefined;
1383
+ }
1384
+ return { completionMap };
1385
+ }
1386
+ _tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap) {
1387
+ var _a, _b, _c, _d, _e, _f;
1388
+ const parentAndChild = getParentSkippingStringList(parseNode);
1389
+ if (!parentAndChild) {
1390
+ return false;
1391
+ }
1409
1392
  // 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);
1393
+ // ex) a: Literal["str"] = /* here */
1394
+ const nodeForExpectedType = parentAndChild.parent.nodeType === 3 /* Assignment */
1395
+ ? parentAndChild.parent.rightExpression === parentAndChild.child
1396
+ ? parentAndChild.child
1397
+ : undefined
1398
+ : (0, parseNodes_1.isExpressionNode)(parentAndChild.child)
1399
+ ? parentAndChild.child
1400
+ : undefined;
1401
+ if (nodeForExpectedType) {
1402
+ const expectedTypeResult = this._evaluator.getExpectedType(nodeForExpectedType);
1412
1403
  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
- }
1404
+ this._addLiteralValuesForTargetType(expectedTypeResult.type, priorWord, priorText, postText, completionMap);
1405
+ return true;
1434
1406
  }
1435
1407
  }
1436
- if (parentNode.nodeType !== 1 /* Argument */) {
1437
- if (parentNode.nodeType !== 48 /* StringList */ || parentNode.strings.length > 1) {
1438
- return undefined;
1408
+ // ex) a: TypedDictType = { "/* here */" } or a: TypedDictType = { A/* here */ }
1409
+ const nodeForKey = parentAndChild.parent;
1410
+ if (nodeForKey) {
1411
+ // If the dictionary is not yet filled in, it will appear as though it's
1412
+ // a set initially.
1413
+ let dictOrSet;
1414
+ if (nodeForKey.nodeType === 17 /* DictionaryKeyEntry */ &&
1415
+ nodeForKey.keyExpression === parentAndChild.child &&
1416
+ ((_a = nodeForKey.parent) === null || _a === void 0 ? void 0 : _a.nodeType) === 15 /* Dictionary */) {
1417
+ dictOrSet = nodeForKey.parent;
1439
1418
  }
1440
- parentNode = parentNode.parent;
1441
- if (!parentNode) {
1442
- return undefined;
1419
+ else if ((nodeForKey === null || nodeForKey === void 0 ? void 0 : nodeForKey.nodeType) === 45 /* Set */) {
1420
+ dictOrSet = nodeForKey;
1421
+ }
1422
+ if (dictOrSet) {
1423
+ if (this._tryAddTypedDictKeysFromDictionary(dictOrSet, parseNode.nodeType === 49 /* String */ ? parseNode : undefined, priorWord, priorText, postText, completionMap)) {
1424
+ return true;
1425
+ }
1443
1426
  }
1444
1427
  }
1445
- if (parentNode.nodeType === 1 /* Argument */ && ((_c = parentNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 24 /* Index */) {
1428
+ // a: DictType = { .... }
1429
+ // a[/* here */] or a['/* here */'] or a[variable/*here*/]
1430
+ const argument = parentAndChild.parent;
1431
+ if (argument.nodeType === 1 /* Argument */ && ((_b = argument.parent) === null || _b === void 0 ? void 0 : _b.nodeType) === 24 /* Index */) {
1446
1432
  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
- }
1433
+ if (this._tryAddTypedDictKeysFromIndexer(argument.parent, priorWord, priorTextInString, postText, completionMap)) {
1434
+ return true;
1435
+ }
1436
+ const quoteInfo = this._getQuoteInfo(priorWord, priorTextInString);
1437
+ const keys = this._getIndexerKeys(argument.parent, parseNode);
1438
+ let keyFound = false;
1439
+ for (const key of keys) {
1440
+ if (completionMap.has(key)) {
1441
+ // Don't add key if it already exists in the completion.
1442
+ // ex) key = "dictKey"
1443
+ // dict[key] = 1
1444
+ // print(dict[<key will come from symbol table provider>]))
1445
+ continue;
1465
1446
  }
1466
- if (completionMap.size === 0) {
1467
- return undefined;
1447
+ const stringLiteral = /^["|'].*["|']$/.test(key);
1448
+ if (parseNode.nodeType === 49 /* String */ && !stringLiteral) {
1449
+ continue;
1450
+ }
1451
+ keyFound = true;
1452
+ if (stringLiteral) {
1453
+ const keyWithoutQuote = key.substr(1, key.length - 2);
1454
+ this._addStringLiteralToCompletions(keyWithoutQuote, quoteInfo, postText, completionMap, exports.dictionaryKeyDetail);
1468
1455
  }
1456
+ else {
1457
+ this._addNameToCompletions(key, vscode_languageserver_1.CompletionItemKind.Constant, priorWord, completionMap, {
1458
+ sortText: this._makeSortText(SortCategory.LiteralValue, key),
1459
+ itemDetail: exports.dictionaryKeyDetail,
1460
+ });
1461
+ }
1462
+ }
1463
+ if (keyFound) {
1464
+ return true;
1469
1465
  }
1470
1466
  }
1471
- else {
1472
- debug.assert(parseNode.nodeType === 49 /* String */);
1467
+ // if c == "/* here */"
1468
+ const comparison = parentAndChild.parent;
1469
+ const supportedOperators = [2 /* Assign */, 12 /* Equals */, 28 /* NotEquals */];
1470
+ if (comparison.nodeType === 7 /* BinaryOperation */ && supportedOperators.includes(comparison.operator)) {
1471
+ const type = this._evaluator.getType(comparison.leftExpression);
1472
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1473
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1474
+ return true;
1475
+ }
1476
+ }
1477
+ // if c := "/* here */"
1478
+ const assignmentExpression = parentAndChild.parent;
1479
+ if (assignmentExpression.nodeType === 4 /* AssignmentExpression */ &&
1480
+ assignmentExpression.rightExpression === parentAndChild.child) {
1481
+ const type = this._evaluator.getType(assignmentExpression.name);
1482
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1483
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1484
+ return true;
1485
+ }
1486
+ }
1487
+ // For now, we only support simple cases. no complex pattern matching.
1488
+ // match c:
1489
+ // case /* here */
1490
+ const caseNode = parentAndChild.parent;
1491
+ if (caseNode.nodeType === 64 /* Case */ &&
1492
+ caseNode.pattern.nodeType === 0 /* Error */ &&
1493
+ caseNode.pattern.category === 11 /* MissingPattern */ &&
1494
+ caseNode.suite === parentAndChild.child &&
1495
+ ((_c = caseNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 63 /* Match */) {
1496
+ const type = this._evaluator.getType(caseNode.parent.subjectExpression);
1497
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1498
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1499
+ return true;
1500
+ }
1501
+ }
1502
+ // match c:
1503
+ // case "/* here */"
1504
+ // case Sym/*here*/
1505
+ const patternLiteral = parentAndChild.parent;
1506
+ if ((patternLiteral.nodeType === 67 /* PatternLiteral */ ||
1507
+ patternLiteral.nodeType === 69 /* PatternCapture */) &&
1508
+ ((_d = patternLiteral.parent) === null || _d === void 0 ? void 0 : _d.nodeType) === 66 /* PatternAs */ &&
1509
+ ((_e = patternLiteral.parent.parent) === null || _e === void 0 ? void 0 : _e.nodeType) === 64 /* Case */ &&
1510
+ ((_f = patternLiteral.parent.parent.parent) === null || _f === void 0 ? void 0 : _f.nodeType) === 63 /* Match */) {
1511
+ const type = this._evaluator.getType(patternLiteral.parent.parent.parent.subjectExpression);
1512
+ if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
1513
+ this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
1514
+ return true;
1515
+ }
1516
+ }
1517
+ if (parseNode.nodeType === 49 /* String */) {
1473
1518
  const offset = (0, positionUtils_1.convertPositionToOffset)(this._position, this._parseResults.tokenizerOutput.lines);
1474
- const atArgument = parentNode.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
1519
+ const atArgument = parseNode.parent.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
1475
1520
  this._addCallArgumentCompletions(parseNode, priorWord, priorText, postText, atArgument, completionMap);
1521
+ return true;
1476
1522
  }
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;
1523
+ return false;
1524
+ function getParentSkippingStringList(node) {
1525
+ var _a;
1526
+ if (!node.parent) {
1527
+ return undefined;
1528
+ }
1529
+ if (node.nodeType !== 49 /* String */) {
1530
+ return { parent: node.parent, child: node };
1531
+ }
1532
+ if (!node.parent.parent) {
1533
+ return undefined;
1534
+ }
1535
+ if (((_a = node.parent) === null || _a === void 0 ? void 0 : _a.nodeType) !== 48 /* StringList */ || node.parent.strings.length > 1) {
1536
+ return undefined;
1537
+ }
1538
+ return { parent: node.parent.parent, child: node.parent };
1489
1539
  }
1540
+ }
1541
+ _tryAddTypedDictKeys(type, existingKeys, priorWord, priorText, postText, completionMap) {
1490
1542
  let typedDicts = [];
1491
- (0, typeUtils_1.doForEachSubtype)(expectedTypeResult.type, (subtype) => {
1543
+ (0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
1492
1544
  if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isTypedDictClass(subtype)) {
1493
1545
  typedDicts.push(subtype);
1494
1546
  }
@@ -1496,10 +1548,9 @@ class CompletionProvider {
1496
1548
  if (typedDicts.length === 0) {
1497
1549
  return false;
1498
1550
  }
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);
1551
+ typedDicts = this._tryNarrowTypedDicts(typedDicts, existingKeys);
1552
+ const quoteInfo = this._getQuoteInfo(priorWord, priorText);
1553
+ const excludes = new Set(existingKeys);
1503
1554
  typedDicts.forEach((typedDict) => {
1504
1555
  (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, typedDict, /* allowNarrowed */ true).forEach((_, key) => {
1505
1556
  // Unions of TypedDicts may define the same key.
@@ -1507,13 +1558,25 @@ class CompletionProvider {
1507
1558
  return;
1508
1559
  }
1509
1560
  excludes.add(key);
1510
- this._addStringLiteralToCompletions(key, quoteValue ? quoteValue.stringValue : undefined, postText, quoteValue
1511
- ? quoteValue.quoteCharacter
1512
- : this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter, completionMap);
1561
+ this._addStringLiteralToCompletions(key, quoteInfo, postText, completionMap);
1513
1562
  });
1514
1563
  });
1515
1564
  return true;
1516
1565
  }
1566
+ _tryAddTypedDictKeysFromDictionary(dictionaryNode, stringNode, priorWord, priorText, postText, completionMap) {
1567
+ var _a;
1568
+ const expectedTypeResult = this._evaluator.getExpectedType(dictionaryNode);
1569
+ if (!expectedTypeResult) {
1570
+ return false;
1571
+ }
1572
+ // If the expected type result is associated with a node above the
1573
+ // dictionaryNode in the parse tree, there are no typed dict keys to add.
1574
+ if (ParseTreeUtils.getNodeDepth(expectedTypeResult.node) < ParseTreeUtils.getNodeDepth(dictionaryNode)) {
1575
+ return false;
1576
+ }
1577
+ const keys = this._getDictExpressionStringKeys(dictionaryNode, stringNode ? new Set([(_a = stringNode.parent) === null || _a === void 0 ? void 0 : _a.id]) : undefined);
1578
+ return this._tryAddTypedDictKeys(expectedTypeResult.type, keys, priorWord, priorText, postText, completionMap);
1579
+ }
1517
1580
  _tryNarrowTypedDicts(types, keys) {
1518
1581
  const newTypes = types.flatMap((type) => {
1519
1582
  const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, type, /* allowNarrowed */ true);
@@ -1532,14 +1595,15 @@ class CompletionProvider {
1532
1595
  }
1533
1596
  // Find out quotation and string prefix to use for string literals
1534
1597
  // completion under current context.
1535
- _getQuoteInfo(priorText) {
1598
+ _getQuoteInfo(priorWord, priorText) {
1599
+ let filterText = priorWord;
1536
1600
  let stringValue = undefined;
1537
1601
  let quoteCharacter = this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
1538
1602
  // If completion is not inside of the existing string literal
1539
1603
  // ex) typedDict[ |<= here
1540
1604
  // use default quotation char without any string prefix.
1541
1605
  if (!this._insideStringLiteral) {
1542
- return { stringValue, quoteCharacter };
1606
+ return { priorWord, priorText, filterText, stringValue, quoteCharacter };
1543
1607
  }
1544
1608
  const singleQuote = "'";
1545
1609
  const doubleQuote = '"';
@@ -1569,9 +1633,12 @@ class CompletionProvider {
1569
1633
  if (this._insideStringLiteral.flags & 64 /* Format */) {
1570
1634
  quoteCharacter = this._insideStringLiteral.flags & 1 /* SingleQuote */ ? doubleQuote : singleQuote;
1571
1635
  }
1572
- return { stringValue, quoteCharacter };
1636
+ if (stringValue) {
1637
+ filterText = stringValue;
1638
+ }
1639
+ return { priorWord, priorText, filterText, stringValue, quoteCharacter };
1573
1640
  }
1574
- _tryAddTypedDictStringLiteral(indexNode, priorText, postText, completionMap) {
1641
+ _tryAddTypedDictKeysFromIndexer(indexNode, priorWord, priorText, postText, completionMap) {
1575
1642
  if (!indexNode) {
1576
1643
  return false;
1577
1644
  }
@@ -1579,26 +1646,11 @@ class CompletionProvider {
1579
1646
  if (!baseType) {
1580
1647
  return false;
1581
1648
  }
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;
1649
+ return this._tryAddTypedDictKeys(baseType, [], priorWord, priorText, postText, completionMap);
1598
1650
  }
1599
- _addStringLiteralToCompletions(value, priorString, postText, quoteCharacter, completionMap, detail) {
1600
- if (StringUtils.isPatternInSymbol(priorString || '', value)) {
1601
- const valueWithQuotes = `${quoteCharacter}${value}${quoteCharacter}`;
1651
+ _addStringLiteralToCompletions(value, quoteInfo, postText, completionMap, detail) {
1652
+ if (StringUtils.isPatternInSymbol(quoteInfo.filterText || '', value)) {
1653
+ const valueWithQuotes = `${quoteInfo.quoteCharacter}${value}${quoteInfo.quoteCharacter}`;
1602
1654
  if (completionMap.has(valueWithQuotes)) {
1603
1655
  return;
1604
1656
  }
@@ -1606,14 +1658,17 @@ class CompletionProvider {
1606
1658
  completionItem.kind = vscode_languageserver_1.CompletionItemKind.Constant;
1607
1659
  completionItem.sortText = this._makeSortText(SortCategory.LiteralValue, valueWithQuotes);
1608
1660
  let rangeStartCol = this._position.character;
1609
- if (priorString !== undefined) {
1610
- rangeStartCol -= priorString.length + 1;
1661
+ if (quoteInfo.stringValue !== undefined) {
1662
+ rangeStartCol -= quoteInfo.stringValue.length + 1;
1663
+ }
1664
+ else if (quoteInfo.priorWord) {
1665
+ rangeStartCol -= quoteInfo.priorWord.length;
1611
1666
  }
1612
1667
  // If the text after the insertion point is the closing quote,
1613
1668
  // replace it.
1614
1669
  let rangeEndCol = this._position.character;
1615
1670
  if (postText !== undefined) {
1616
- if (postText.startsWith(quoteCharacter)) {
1671
+ if (postText.startsWith(quoteInfo.quoteCharacter)) {
1617
1672
  rangeEndCol++;
1618
1673
  }
1619
1674
  }