@zzzen/pyright-internal 1.2.0-dev.20230226 → 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 (148) hide show
  1. package/dist/analyzer/binder.d.ts +0 -1
  2. package/dist/analyzer/binder.js +32 -95
  3. package/dist/analyzer/binder.js.map +1 -1
  4. package/dist/analyzer/checker.js +48 -31
  5. package/dist/analyzer/checker.js.map +1 -1
  6. package/dist/analyzer/codeFlowEngine.js +4 -4
  7. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  8. package/dist/analyzer/commentUtils.js +11 -1
  9. package/dist/analyzer/commentUtils.js.map +1 -1
  10. package/dist/analyzer/constructorTransform.d.ts +1 -0
  11. package/dist/analyzer/constructorTransform.js +19 -2
  12. package/dist/analyzer/constructorTransform.js.map +1 -1
  13. package/dist/analyzer/declaration.d.ts +2 -4
  14. package/dist/analyzer/declaration.js +6 -1
  15. package/dist/analyzer/declaration.js.map +1 -1
  16. package/dist/analyzer/declarationUtils.d.ts +1 -5
  17. package/dist/analyzer/declarationUtils.js +2 -47
  18. package/dist/analyzer/declarationUtils.js.map +1 -1
  19. package/dist/analyzer/docStringConversion.js +9 -3
  20. package/dist/analyzer/docStringConversion.js.map +1 -1
  21. package/dist/analyzer/packageTypeVerifier.js +40 -40
  22. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  23. package/dist/analyzer/parseTreeUtils.d.ts +4 -2
  24. package/dist/analyzer/parseTreeUtils.js +77 -2
  25. package/dist/analyzer/parseTreeUtils.js.map +1 -1
  26. package/dist/analyzer/patternMatching.js +20 -1
  27. package/dist/analyzer/patternMatching.js.map +1 -1
  28. package/dist/analyzer/program.d.ts +1 -0
  29. package/dist/analyzer/program.js +154 -13
  30. package/dist/analyzer/program.js.map +1 -1
  31. package/dist/analyzer/properties.js +3 -2
  32. package/dist/analyzer/properties.js.map +1 -1
  33. package/dist/analyzer/protocols.js +4 -2
  34. package/dist/analyzer/protocols.js.map +1 -1
  35. package/dist/analyzer/pythonPathUtils.js +27 -13
  36. package/dist/analyzer/pythonPathUtils.js.map +1 -1
  37. package/dist/analyzer/service.js +6 -1
  38. package/dist/analyzer/service.js.map +1 -1
  39. package/dist/analyzer/sourceFile.js +12 -1
  40. package/dist/analyzer/sourceFile.js.map +1 -1
  41. package/dist/analyzer/symbol.js +1 -4
  42. package/dist/analyzer/symbol.js.map +1 -1
  43. package/dist/analyzer/symbolUtils.d.ts +0 -3
  44. package/dist/analyzer/symbolUtils.js +1 -14
  45. package/dist/analyzer/symbolUtils.js.map +1 -1
  46. package/dist/analyzer/typeDocStringUtils.js +5 -3
  47. package/dist/analyzer/typeDocStringUtils.js.map +1 -1
  48. package/dist/analyzer/typeEvaluator.js +642 -259
  49. package/dist/analyzer/typeEvaluator.js.map +1 -1
  50. package/dist/analyzer/typeEvaluatorTypes.d.ts +11 -2
  51. package/dist/analyzer/typeGuards.js +2 -2
  52. package/dist/analyzer/typeGuards.js.map +1 -1
  53. package/dist/analyzer/typePrinter.js +63 -55
  54. package/dist/analyzer/typePrinter.js.map +1 -1
  55. package/dist/analyzer/typeUtils.d.ts +2 -0
  56. package/dist/analyzer/typeUtils.js +22 -3
  57. package/dist/analyzer/typeUtils.js.map +1 -1
  58. package/dist/analyzer/typedDicts.d.ts +2 -1
  59. package/dist/analyzer/typedDicts.js +83 -57
  60. package/dist/analyzer/typedDicts.js.map +1 -1
  61. package/dist/analyzer/types.d.ts +3 -1
  62. package/dist/analyzer/types.js +8 -0
  63. package/dist/analyzer/types.js.map +1 -1
  64. package/dist/commands/dumpFileDebugInfoCommand.js +78 -0
  65. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  66. package/dist/common/collectionUtils.d.ts +1 -0
  67. package/dist/common/collectionUtils.js +8 -1
  68. package/dist/common/collectionUtils.js.map +1 -1
  69. package/dist/common/extensibility.js +25 -1
  70. package/dist/common/extensibility.js.map +1 -1
  71. package/dist/common/positionUtils.d.ts +2 -0
  72. package/dist/common/positionUtils.js +15 -1
  73. package/dist/common/positionUtils.js.map +1 -1
  74. package/dist/languageServerBase.js +9 -1
  75. package/dist/languageServerBase.js.map +1 -1
  76. package/dist/languageService/callHierarchyProvider.js +4 -2
  77. package/dist/languageService/callHierarchyProvider.js.map +1 -1
  78. package/dist/languageService/completionProvider.d.ts +4 -2
  79. package/dist/languageService/completionProvider.js +252 -191
  80. package/dist/languageService/completionProvider.js.map +1 -1
  81. package/dist/languageService/completionProviderUtils.d.ts +1 -1
  82. package/dist/languageService/completionProviderUtils.js +3 -3
  83. package/dist/languageService/completionProviderUtils.js.map +1 -1
  84. package/dist/languageService/definitionProvider.js +2 -1
  85. package/dist/languageService/definitionProvider.js.map +1 -1
  86. package/dist/languageService/documentSymbolProvider.js +2 -1
  87. package/dist/languageService/documentSymbolProvider.js.map +1 -1
  88. package/dist/languageService/hoverProvider.js +11 -3
  89. package/dist/languageService/hoverProvider.js.map +1 -1
  90. package/dist/languageService/importAdder.js +4 -1
  91. package/dist/languageService/importAdder.js.map +1 -1
  92. package/dist/languageService/indentationUtils.d.ts +1 -1
  93. package/dist/languageService/indentationUtils.js +22 -12
  94. package/dist/languageService/indentationUtils.js.map +1 -1
  95. package/dist/languageService/renameModuleProvider.d.ts +1 -1
  96. package/dist/languageService/renameModuleProvider.js +28 -8
  97. package/dist/languageService/renameModuleProvider.js.map +1 -1
  98. package/dist/languageService/tooltipUtils.js +2 -1
  99. package/dist/languageService/tooltipUtils.js.map +1 -1
  100. package/dist/localization/localize.d.ts +12 -2
  101. package/dist/localization/localize.js +5 -1
  102. package/dist/localization/localize.js.map +1 -1
  103. package/dist/localization/package.nls.en-us.json +6 -2
  104. package/dist/parser/parser.js +40 -25
  105. package/dist/parser/parser.js.map +1 -1
  106. package/dist/parser/tokenizer.js +1 -1
  107. package/dist/pyright.js +1 -1
  108. package/dist/pyright.js.map +1 -1
  109. package/dist/tests/completions.test.js +445 -0
  110. package/dist/tests/completions.test.js.map +1 -1
  111. package/dist/tests/docStringConversion.test.js +23 -0
  112. package/dist/tests/docStringConversion.test.js.map +1 -1
  113. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js +13 -3
  114. package/dist/tests/fourslash/completions.dictionary.keys.expression.fourslash.js.map +1 -1
  115. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js +7 -2
  116. package/dist/tests/fourslash/completions.dictionary.keys.stringLiterals.fourslash.js.map +1 -1
  117. package/dist/tests/fourslash/completions.errorNodes.fourslash.d.ts +1 -0
  118. package/dist/tests/fourslash/completions.errorNodes.fourslash.js +24 -0
  119. package/dist/tests/fourslash/completions.errorNodes.fourslash.js.map +1 -0
  120. package/dist/tests/fourslash/hover.slots.fourslash.d.ts +1 -0
  121. package/dist/tests/fourslash/hover.slots.fourslash.js +16 -0
  122. package/dist/tests/fourslash/hover.slots.fourslash.js.map +1 -0
  123. package/dist/tests/hoverProvider.test.js +1 -1
  124. package/dist/tests/hoverProvider.test.js.map +1 -1
  125. package/dist/tests/importAdder.test.js +13 -0
  126. package/dist/tests/importAdder.test.js.map +1 -1
  127. package/dist/tests/indentationUtils.reindent.test.js +21 -0
  128. package/dist/tests/indentationUtils.reindent.test.js.map +1 -1
  129. package/dist/tests/moveSymbol.importAdder.test.js +137 -31
  130. package/dist/tests/moveSymbol.importAdder.test.js.map +1 -1
  131. package/dist/tests/moveSymbol.insertion.test.js +98 -0
  132. package/dist/tests/moveSymbol.insertion.test.js.map +1 -1
  133. package/dist/tests/moveSymbol.misc.test.js +27 -0
  134. package/dist/tests/moveSymbol.misc.test.js.map +1 -1
  135. package/dist/tests/renameModuleTestUtils.d.ts +1 -1
  136. package/dist/tests/renameModuleTestUtils.js +9 -5
  137. package/dist/tests/renameModuleTestUtils.js.map +1 -1
  138. package/dist/tests/typeEvaluator1.test.js +8 -0
  139. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  140. package/dist/tests/typeEvaluator2.test.js +5 -1
  141. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  142. package/dist/tests/typeEvaluator3.test.js +20 -4
  143. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  144. package/dist/tests/typeEvaluator4.test.js +4 -0
  145. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  146. package/dist/tests/typeEvaluator5.test.js +6 -0
  147. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  148. 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
@@ -554,53 +555,65 @@ class CompletionProvider {
554
555
  case 1 /* MissingElse */: {
555
556
  return this._createSingleKeywordCompletion('else');
556
557
  }
558
+ case 7 /* MissingMemberAccessName */:
557
559
  case 2 /* MissingExpression */: {
558
560
  // Don't show completion after random dots.
559
561
  const tokenizerOutput = this._parseResults.tokenizerOutput;
560
562
  const offset = (0, positionUtils_1.convertPositionToOffset)(this._position, tokenizerOutput.lines);
561
563
  const index = ParseTreeUtils.getTokenIndexAtLeft(tokenizerOutput.tokens, offset);
562
564
  const token = ParseTreeUtils.getTokenAtIndex(tokenizerOutput.tokens, index);
563
- if ((token === null || token === void 0 ? void 0 : token.type) === 20 /* Dot */ || (token === null || token === void 0 ? void 0 : token.type) === 19 /* Ellipsis */) {
564
- break;
565
- }
566
- // ex) class MyType:
567
- // def is_str(self): ...
568
- // myType = MyType()
569
- //
570
- // In incomplete code such as "myType.is" <= "is" will be tokenized as keyword not identifier,
571
- // so even if user's intention is writing "is_str", completion after "is" won't include "is_str"
572
- // since parser won't see "is" as partially written member name instead it will see it as
573
- // expression statement with missing expression after "is" keyword.
574
- // In such case, use "MyType." to get completion.
575
- if ((token === null || token === void 0 ? void 0 : token.type) !== 8 /* Keyword */ || textRange_2.TextRange.getEnd(token) !== offset) {
576
- return this._getExpressionCompletions(node, priorWord, priorText, postText);
577
- }
578
- const previousToken = ParseTreeUtils.getTokenAtIndex(tokenizerOutput.tokens, index - 1);
579
- if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.type) !== 20 /* Dot */) {
580
- return this._getExpressionCompletions(node, priorWord, priorText, postText);
565
+ const prevToken = ParseTreeUtils.getTokenAtIndex(tokenizerOutput.tokens, index - 1);
566
+ if (node.category === 2 /* MissingExpression */) {
567
+ // Skip dots on expressions.
568
+ if ((token === null || token === void 0 ? void 0 : token.type) === 20 /* Dot */ || (token === null || token === void 0 ? void 0 : token.type) === 19 /* Ellipsis */) {
569
+ break;
570
+ }
571
+ // ex) class MyType:
572
+ // def is_str(self): ...
573
+ // myType = MyType()
574
+ //
575
+ // In incomplete code such as "myType.is" <= "is" will be tokenized as keyword not identifier,
576
+ // so even if user's intention is writing "is_str", completion after "is" won't include "is_str"
577
+ // since parser won't see "is" as partially written member name instead it will see it as
578
+ // expression statement with missing expression after "is" keyword.
579
+ // In such case, use "MyType." to get completion.
580
+ if ((token === null || token === void 0 ? void 0 : token.type) !== 8 /* Keyword */ || textRange_2.TextRange.getEnd(token) !== offset) {
581
+ return this._getExpressionCompletions(node, priorWord, priorText, postText);
582
+ }
583
+ if ((prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) !== 20 /* Dot */) {
584
+ return this._getExpressionCompletions(node, priorWord, priorText, postText);
585
+ }
586
+ const previousOffset = textRange_2.TextRange.getEnd(prevToken);
587
+ const previousNode = ParseTreeUtils.findNodeByOffset(this._parseResults.parseTree, previousOffset);
588
+ if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.nodeType) !== 0 /* Error */ ||
589
+ previousNode.category !== 7 /* MissingMemberAccessName */) {
590
+ return this._getExpressionCompletions(node, priorWord, priorText, postText);
591
+ }
592
+ else {
593
+ // Update node to previous node so we get the member access completions.
594
+ node = previousNode;
595
+ }
581
596
  }
582
- const previousOffset = textRange_2.TextRange.getEnd(previousToken);
583
- const previousNode = ParseTreeUtils.findNodeByOffset(this._parseResults.parseTree, previousOffset);
584
- if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.nodeType) !== 0 /* Error */ ||
585
- previousNode.category !== 7 /* MissingMemberAccessName */) {
586
- return this._getExpressionCompletions(node, priorWord, priorText, postText);
597
+ else if (node.category === 7 /* MissingMemberAccessName */) {
598
+ // Skip double dots on member access.
599
+ if (((token === null || token === void 0 ? void 0 : token.type) === 20 /* Dot */ || (token === null || token === void 0 ? void 0 : token.type) === 19 /* Ellipsis */) &&
600
+ ((prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) === 20 /* Dot */ || (prevToken === null || prevToken === void 0 ? void 0 : prevToken.type) === 19 /* Ellipsis */)) {
601
+ return undefined;
602
+ }
587
603
  }
588
- return this._getMissingMemberAccessNameCompletions(previousNode, previousOffset, priorWord);
604
+ return this._getMissingMemberAccessNameCompletions(node, priorWord);
589
605
  }
590
606
  case 4 /* MissingDecoratorCallName */: {
591
607
  return this._getExpressionCompletions(node, priorWord, priorText, postText);
592
608
  }
609
+ case 11 /* MissingPattern */:
593
610
  case 3 /* MissingIndexOrSlice */: {
594
- let completionResults = this._getLiteralCompletions(node, priorWord, priorText, postText);
611
+ let completionResults = this._getLiteralCompletions(node, offset, priorWord, priorText, postText);
595
612
  if (!completionResults) {
596
613
  completionResults = this._getExpressionCompletions(node, priorWord, priorText, postText);
597
614
  }
598
615
  return completionResults;
599
616
  }
600
- case 7 /* MissingMemberAccessName */: {
601
- const offset = (0, positionUtils_1.convertPositionToOffset)(this._position, this._parseResults.tokenizerOutput.lines);
602
- return this._getMissingMemberAccessNameCompletions(node, offset, priorWord);
603
- }
604
617
  case 10 /* MissingFunctionParameterList */: {
605
618
  if (node.child && node.child.nodeType === 38 /* Name */) {
606
619
  if ((_a = node.decorators) === null || _a === void 0 ? void 0 : _a.some((d) => this._isOverload(d))) {
@@ -615,13 +628,7 @@ class CompletionProvider {
615
628
  }
616
629
  return undefined;
617
630
  }
618
- _getMissingMemberAccessNameCompletions(node, offset, priorWord) {
619
- const index = ParseTreeUtils.getTokenIndexAtLeft(this._parseResults.tokenizerOutput.tokens, offset) - 1;
620
- const previousToken = ParseTreeUtils.getTokenAtIndex(this._parseResults.tokenizerOutput.tokens, index);
621
- if ((previousToken === null || previousToken === void 0 ? void 0 : previousToken.type) === 20 /* Dot */ || (previousToken === null || previousToken === void 0 ? void 0 : previousToken.type) === 19 /* Ellipsis */) {
622
- // Don't allow multiple dot bring up completions.
623
- return undefined;
624
- }
631
+ _getMissingMemberAccessNameCompletions(node, priorWord) {
625
632
  if (!node.child || !(0, parseNodes_1.isExpressionNode)(node.child)) {
626
633
  return undefined;
627
634
  }
@@ -824,10 +831,11 @@ class CompletionProvider {
824
831
  const classmethod = (_b = decorators === null || decorators === void 0 ? void 0 : decorators.some((d) => this._checkDecorator(d, 'classmethod'))) !== null && _b !== void 0 ? _b : false;
825
832
  const completionMap = new CompletionMap();
826
833
  symbolTable.forEach((symbol, name) => {
834
+ var _a;
827
835
  let decl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(symbol);
828
836
  if (decl && decl.type === 5 /* Function */) {
829
837
  if (StringUtils.isPatternInSymbol(partialName.value, name)) {
830
- const declaredType = this._evaluator.getTypeForDeclaration(decl);
838
+ const declaredType = (_a = this._evaluator.getTypeForDeclaration(decl)) === null || _a === void 0 ? void 0 : _a.type;
831
839
  if (!declaredType) {
832
840
  return;
833
841
  }
@@ -1102,7 +1110,7 @@ class CompletionProvider {
1102
1110
  return this._getExpressionCompletions(parseNode, priorWord, priorText, postText);
1103
1111
  }
1104
1112
  _getExpressionCompletions(parseNode, priorWord, priorText, postText) {
1105
- var _a, _b, _c, _d;
1113
+ var _a, _b;
1106
1114
  const isIndexArgument = this._isIndexArgument(parseNode);
1107
1115
  // If the user typed a "." as part of a number, don't present
1108
1116
  // any completion options.
@@ -1146,39 +1154,7 @@ class CompletionProvider {
1146
1154
  this._addAutoImportCompletions(priorWord, similarityLimit, this._options.lazyEdit, completionResults);
1147
1155
  }
1148
1156
  // Add literal values if appropriate.
1149
- if (parseNode.nodeType === 0 /* Error */) {
1150
- if (parseNode.category === 3 /* MissingIndexOrSlice */ &&
1151
- ((_c = parseNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 24 /* Index */) {
1152
- this._tryAddTypedDictStringLiteral(parseNode.parent,
1153
- /* priorText */ undefined,
1154
- /* postText */ undefined, completionMap);
1155
- }
1156
- else if (parseNode.category === 2 /* MissingExpression */) {
1157
- if (parseNode.parent && parseNode.parent.nodeType === 3 /* Assignment */) {
1158
- const declaredTypeOfTarget = (_d = this._evaluator.getExpectedType(parseNode)) === null || _d === void 0 ? void 0 : _d.type;
1159
- if (declaredTypeOfTarget) {
1160
- this._addLiteralValuesForTargetType(declaredTypeOfTarget, priorText, priorWord, postText, completionMap);
1161
- }
1162
- }
1163
- }
1164
- }
1165
- if (isIndexArgument) {
1166
- // Completion for dict key (ex, dict_variable[<here>])
1167
- const indexNode = parseNode.parent.parent;
1168
- this._getIndexerKeys(indexNode, parseNode).forEach((key) => {
1169
- if (completionMap.has(key)) {
1170
- // Don't add key if it already exists in the completion.
1171
- // ex) key = "dictKey"
1172
- // dict[key] = 1
1173
- // print(dict[<key will come from symbol table provider>]))
1174
- return;
1175
- }
1176
- this._addNameToCompletions(key, vscode_languageserver_1.CompletionItemKind.Constant, priorWord, completionMap, {
1177
- sortText: this._makeSortText(SortCategory.LiteralValue, key),
1178
- itemDetail: exports.dictionaryKeyDetail,
1179
- });
1180
- });
1181
- }
1157
+ this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap);
1182
1158
  return completionResults;
1183
1159
  }
1184
1160
  _isIndexArgument(node) {
@@ -1207,11 +1183,11 @@ class CompletionProvider {
1207
1183
  this._addNamedParameters(signatureInfo, priorWord, completionMap);
1208
1184
  }
1209
1185
  // Add literals that apply to this parameter.
1210
- this._addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap);
1186
+ this._addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap);
1211
1187
  }
1212
1188
  }
1213
1189
  }
1214
- _addLiteralValuesForArgument(signatureInfo, priorText, priorWord, postText, completionMap) {
1190
+ _addLiteralValuesForArgument(signatureInfo, priorWord, priorText, postText, completionMap) {
1215
1191
  signatureInfo.signatures.forEach((signature) => {
1216
1192
  if (!signature.activeParam) {
1217
1193
  return undefined;
@@ -1222,12 +1198,12 @@ class CompletionProvider {
1222
1198
  return undefined;
1223
1199
  }
1224
1200
  const paramType = type.details.parameters[paramIndex].type;
1225
- this._addLiteralValuesForTargetType(paramType, priorText, priorWord, postText, completionMap);
1201
+ this._addLiteralValuesForTargetType(paramType, priorWord, priorText, postText, completionMap);
1226
1202
  return undefined;
1227
1203
  });
1228
1204
  }
1229
- _addLiteralValuesForTargetType(type, priorText, priorWord, postText, completionMap) {
1230
- const quoteValue = this._getQuoteInfo(priorText);
1205
+ _addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap) {
1206
+ const quoteValue = this._getQuoteInfo(priorWord, priorText);
1231
1207
  this._getSubTypesWithLiteralValues(type).forEach((v) => {
1232
1208
  if (types_1.ClassType.isBuiltIn(v, 'str')) {
1233
1209
  const value = (0, typePrinter_1.printLiteralValue)(v, quoteValue.quoteCharacter);
@@ -1237,7 +1213,7 @@ class CompletionProvider {
1237
1213
  });
1238
1214
  }
1239
1215
  else {
1240
- 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);
1241
1217
  }
1242
1218
  }
1243
1219
  });
@@ -1281,7 +1257,7 @@ class CompletionProvider {
1281
1257
  return values;
1282
1258
  }
1283
1259
  _getIndexerKeyType(baseType) {
1284
- var _a;
1260
+ var _a, _b;
1285
1261
  // Handle dict type
1286
1262
  if (types_1.ClassType.isBuiltIn(baseType, 'dict') || types_1.ClassType.isBuiltIn(baseType, 'Mapping')) {
1287
1263
  if (((_a = baseType.typeArguments) === null || _a === void 0 ? void 0 : _a.length) === 2) {
@@ -1293,7 +1269,7 @@ class CompletionProvider {
1293
1269
  if (member === null || member === void 0 ? void 0 : member.symbol.hasDeclarations()) {
1294
1270
  const declaration = member.symbol.getDeclarations()[0];
1295
1271
  if ((0, declaration_1.isFunctionDeclaration)(declaration) && declaration.isMethod) {
1296
- const getItemType = this._evaluator.getTypeForDeclaration(declaration);
1272
+ const getItemType = (_b = this._evaluator.getTypeForDeclaration(declaration)) === null || _b === void 0 ? void 0 : _b.type;
1297
1273
  if (getItemType && (0, types_1.isFunction)(getItemType) && getItemType.details.parameters.length === 2) {
1298
1274
  return getItemType.details.parameters[1].type;
1299
1275
  }
@@ -1393,96 +1369,178 @@ class CompletionProvider {
1393
1369
  }
1394
1370
  return [...keys];
1395
1371
  }
1396
- _getLiteralCompletions(parseNode, priorWord, priorText, postText) {
1397
- var _a, _b, _c;
1398
- let parentNode = parseNode.parent;
1399
- if (!parentNode) {
1400
- 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
+ }
1401
1379
  }
1402
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
+ }
1403
1392
  // See if the type evaluator can determine the expected type for this node.
1404
- if ((0, parseNodes_1.isExpressionNode)(parentNode)) {
1405
- 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);
1406
1403
  if (expectedTypeResult && (0, typeUtils_1.isLiteralTypeOrUnion)(expectedTypeResult.type)) {
1407
- this._addLiteralValuesForTargetType(expectedTypeResult.type, priorText, priorWord, postText, completionMap);
1408
- return { completionMap };
1409
- }
1410
- if (parseNode.nodeType === 49 /* String */ && ((_a = parseNode.parent) === null || _a === void 0 ? void 0 : _a.parent)) {
1411
- const stringParent = parseNode.parent.parent;
1412
- // If the dictionary is not yet filled in, it will appear as though it's
1413
- // a set initially.
1414
- let dictOrSet;
1415
- if (stringParent.nodeType === 17 /* DictionaryKeyEntry */ &&
1416
- stringParent.keyExpression === parseNode.parent &&
1417
- ((_b = stringParent.parent) === null || _b === void 0 ? void 0 : _b.nodeType) === 15 /* Dictionary */) {
1418
- dictOrSet = stringParent.parent;
1419
- }
1420
- else if ((stringParent === null || stringParent === void 0 ? void 0 : stringParent.nodeType) === 45 /* Set */) {
1421
- dictOrSet = stringParent;
1422
- }
1423
- if (dictOrSet) {
1424
- if (this._addTypedDictKeys(dictOrSet, parseNode, priorText, postText, completionMap)) {
1425
- return { completionMap };
1426
- }
1427
- }
1404
+ this._addLiteralValuesForTargetType(expectedTypeResult.type, priorWord, priorText, postText, completionMap);
1405
+ return true;
1428
1406
  }
1429
1407
  }
1430
- if (parentNode.nodeType !== 1 /* Argument */) {
1431
- if (parentNode.nodeType !== 48 /* StringList */ || parentNode.strings.length > 1) {
1432
- 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;
1433
1418
  }
1434
- parentNode = parentNode.parent;
1435
- if (!parentNode) {
1436
- 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
+ }
1437
1426
  }
1438
1427
  }
1439
- 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 */) {
1440
1432
  const priorTextInString = parseNode.nodeType === 49 /* String */ ? priorText : '';
1441
- if (!this._tryAddTypedDictStringLiteral(parentNode.parent, priorTextInString, postText, completionMap)) {
1442
- const keys = this._getIndexerKeys(parentNode.parent, parseNode);
1443
- const quoteValue = this._getQuoteInfo(priorTextInString);
1444
- for (const key of keys) {
1445
- const stringLiteral = /^["|'].*["|']$/.test(key);
1446
- if (parseNode.nodeType === 49 /* String */ && !stringLiteral) {
1447
- continue;
1448
- }
1449
- if (stringLiteral) {
1450
- const keyWithoutQuote = key.substr(1, key.length - 2);
1451
- this._addStringLiteralToCompletions(keyWithoutQuote, quoteValue.stringValue, postText, quoteValue.quoteCharacter, completionMap, exports.dictionaryKeyDetail);
1452
- }
1453
- else {
1454
- this._addNameToCompletions(key, vscode_languageserver_1.CompletionItemKind.Constant, priorWord, completionMap, {
1455
- sortText: this._makeSortText(SortCategory.LiteralValue, key),
1456
- itemDetail: exports.dictionaryKeyDetail,
1457
- });
1458
- }
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;
1459
1446
  }
1460
- if (completionMap.size === 0) {
1461
- 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);
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
+ });
1462
1461
  }
1463
1462
  }
1463
+ if (keyFound) {
1464
+ return true;
1465
+ }
1464
1466
  }
1465
- else {
1466
- 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 */) {
1467
1518
  const offset = (0, positionUtils_1.convertPositionToOffset)(this._position, this._parseResults.tokenizerOutput.lines);
1468
- const atArgument = parentNode.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
1519
+ const atArgument = parseNode.parent.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
1469
1520
  this._addCallArgumentCompletions(parseNode, priorWord, priorText, postText, atArgument, completionMap);
1521
+ return true;
1470
1522
  }
1471
- return { completionMap };
1472
- }
1473
- _addTypedDictKeys(dictionaryNode, stringNode, priorText, postText, completionMap) {
1474
- var _a;
1475
- const expectedTypeResult = this._evaluator.getExpectedType(dictionaryNode);
1476
- if (!expectedTypeResult) {
1477
- return false;
1478
- }
1479
- // If the expected type result is associated with a node above the
1480
- // dictionaryNode in the parse tree, there are no typed dict keys to add.
1481
- if (ParseTreeUtils.getNodeDepth(expectedTypeResult.node) < ParseTreeUtils.getNodeDepth(dictionaryNode)) {
1482
- 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 };
1483
1539
  }
1540
+ }
1541
+ _tryAddTypedDictKeys(type, existingKeys, priorWord, priorText, postText, completionMap) {
1484
1542
  let typedDicts = [];
1485
- (0, typeUtils_1.doForEachSubtype)(expectedTypeResult.type, (subtype) => {
1543
+ (0, typeUtils_1.doForEachSubtype)(type, (subtype) => {
1486
1544
  if ((0, types_1.isClassInstance)(subtype) && types_1.ClassType.isTypedDictClass(subtype)) {
1487
1545
  typedDicts.push(subtype);
1488
1546
  }
@@ -1490,10 +1548,9 @@ class CompletionProvider {
1490
1548
  if (typedDicts.length === 0) {
1491
1549
  return false;
1492
1550
  }
1493
- const keys = this._getDictExpressionStringKeys(dictionaryNode, stringNode ? new Set([(_a = stringNode.parent) === null || _a === void 0 ? void 0 : _a.id]) : undefined);
1494
- typedDicts = this._tryNarrowTypedDicts(typedDicts, keys);
1495
- const quoteValue = this._getQuoteInfo(priorText);
1496
- const excludes = new Set(keys);
1551
+ typedDicts = this._tryNarrowTypedDicts(typedDicts, existingKeys);
1552
+ const quoteInfo = this._getQuoteInfo(priorWord, priorText);
1553
+ const excludes = new Set(existingKeys);
1497
1554
  typedDicts.forEach((typedDict) => {
1498
1555
  (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, typedDict, /* allowNarrowed */ true).forEach((_, key) => {
1499
1556
  // Unions of TypedDicts may define the same key.
@@ -1501,13 +1558,25 @@ class CompletionProvider {
1501
1558
  return;
1502
1559
  }
1503
1560
  excludes.add(key);
1504
- this._addStringLiteralToCompletions(key, quoteValue ? quoteValue.stringValue : undefined, postText, quoteValue
1505
- ? quoteValue.quoteCharacter
1506
- : this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter, completionMap);
1561
+ this._addStringLiteralToCompletions(key, quoteInfo, postText, completionMap);
1507
1562
  });
1508
1563
  });
1509
1564
  return true;
1510
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
+ }
1511
1580
  _tryNarrowTypedDicts(types, keys) {
1512
1581
  const newTypes = types.flatMap((type) => {
1513
1582
  const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, type, /* allowNarrowed */ true);
@@ -1526,14 +1595,15 @@ class CompletionProvider {
1526
1595
  }
1527
1596
  // Find out quotation and string prefix to use for string literals
1528
1597
  // completion under current context.
1529
- _getQuoteInfo(priorText) {
1598
+ _getQuoteInfo(priorWord, priorText) {
1599
+ let filterText = priorWord;
1530
1600
  let stringValue = undefined;
1531
1601
  let quoteCharacter = this._parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
1532
1602
  // If completion is not inside of the existing string literal
1533
1603
  // ex) typedDict[ |<= here
1534
1604
  // use default quotation char without any string prefix.
1535
1605
  if (!this._insideStringLiteral) {
1536
- return { stringValue, quoteCharacter };
1606
+ return { priorWord, priorText, filterText, stringValue, quoteCharacter };
1537
1607
  }
1538
1608
  const singleQuote = "'";
1539
1609
  const doubleQuote = '"';
@@ -1563,9 +1633,12 @@ class CompletionProvider {
1563
1633
  if (this._insideStringLiteral.flags & 64 /* Format */) {
1564
1634
  quoteCharacter = this._insideStringLiteral.flags & 1 /* SingleQuote */ ? doubleQuote : singleQuote;
1565
1635
  }
1566
- return { stringValue, quoteCharacter };
1636
+ if (stringValue) {
1637
+ filterText = stringValue;
1638
+ }
1639
+ return { priorWord, priorText, filterText, stringValue, quoteCharacter };
1567
1640
  }
1568
- _tryAddTypedDictStringLiteral(indexNode, priorText, postText, completionMap) {
1641
+ _tryAddTypedDictKeysFromIndexer(indexNode, priorWord, priorText, postText, completionMap) {
1569
1642
  if (!indexNode) {
1570
1643
  return false;
1571
1644
  }
@@ -1573,26 +1646,11 @@ class CompletionProvider {
1573
1646
  if (!baseType) {
1574
1647
  return false;
1575
1648
  }
1576
- let foundTypedDict = false;
1577
- (0, typeUtils_1.doForEachSubtype)(baseType, (subtype) => {
1578
- if (!(0, types_1.isClassInstance)(subtype)) {
1579
- return;
1580
- }
1581
- if (!types_1.ClassType.isTypedDictClass(subtype)) {
1582
- return;
1583
- }
1584
- const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this._evaluator, subtype, /* allowNarrowed */ true);
1585
- const quoteValue = this._getQuoteInfo(priorText);
1586
- entries.forEach((_, key) => {
1587
- this._addStringLiteralToCompletions(key, quoteValue.stringValue, postText, quoteValue.quoteCharacter, completionMap);
1588
- });
1589
- foundTypedDict = true;
1590
- });
1591
- return foundTypedDict;
1649
+ return this._tryAddTypedDictKeys(baseType, [], priorWord, priorText, postText, completionMap);
1592
1650
  }
1593
- _addStringLiteralToCompletions(value, priorString, postText, quoteCharacter, completionMap, detail) {
1594
- if (StringUtils.isPatternInSymbol(priorString || '', value)) {
1595
- 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}`;
1596
1654
  if (completionMap.has(valueWithQuotes)) {
1597
1655
  return;
1598
1656
  }
@@ -1600,14 +1658,17 @@ class CompletionProvider {
1600
1658
  completionItem.kind = vscode_languageserver_1.CompletionItemKind.Constant;
1601
1659
  completionItem.sortText = this._makeSortText(SortCategory.LiteralValue, valueWithQuotes);
1602
1660
  let rangeStartCol = this._position.character;
1603
- if (priorString !== undefined) {
1604
- 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;
1605
1666
  }
1606
1667
  // If the text after the insertion point is the closing quote,
1607
1668
  // replace it.
1608
1669
  let rangeEndCol = this._position.character;
1609
1670
  if (postText !== undefined) {
1610
- if (postText.startsWith(quoteCharacter)) {
1671
+ if (postText.startsWith(quoteInfo.quoteCharacter)) {
1611
1672
  rangeEndCol++;
1612
1673
  }
1613
1674
  }
@@ -1878,7 +1939,7 @@ class CompletionProvider {
1878
1939
  boundObjectOrClass: detail.boundObjectOrClass,
1879
1940
  });
1880
1941
  if (this._options.format === vscode_languageserver_1.MarkupKind.Markdown || this._options.format === vscode_languageserver_1.MarkupKind.PlainText) {
1881
- this._itemToResolve.documentation = (0, completionProviderUtils_1.getCompletionItemDocumention)(typeDetail, documentation, this._options.format);
1942
+ this._itemToResolve.documentation = (0, completionProviderUtils_1.getCompletionItemDocumentation)(typeDetail, documentation, this._options.format);
1882
1943
  }
1883
1944
  else {
1884
1945
  (0, debug_1.fail)(`Unsupported markup type: ${this._options.format}`);
@@ -1955,7 +2016,7 @@ class CompletionProvider {
1955
2016
  filePath: this._filePath,
1956
2017
  position: this._position,
1957
2018
  };
1958
- if (detail === null || detail === void 0 ? void 0 : detail.funcParensDisabled) {
2019
+ if ((detail === null || detail === void 0 ? void 0 : detail.funcParensDisabled) || !this._options.snippet) {
1959
2020
  completionItemData.funcParensDisabled = true;
1960
2021
  }
1961
2022
  if (detail === null || detail === void 0 ? void 0 : detail.modulePath) {