@zzzen/pyright-internal 1.2.0-dev.20230514 → 1.2.0-dev.20230528

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 (183) hide show
  1. package/dist/analyzer/analyzerFileInfo.d.ts +1 -0
  2. package/dist/analyzer/analyzerFileInfo.js +4 -3
  3. package/dist/analyzer/analyzerFileInfo.js.map +1 -1
  4. package/dist/analyzer/backgroundAnalysisProgram.d.ts +17 -15
  5. package/dist/analyzer/backgroundAnalysisProgram.js +43 -53
  6. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  7. package/dist/analyzer/binder.d.ts +0 -2
  8. package/dist/analyzer/binder.js +2 -20
  9. package/dist/analyzer/binder.js.map +1 -1
  10. package/dist/analyzer/checker.d.ts +1 -1
  11. package/dist/analyzer/checker.js +65 -32
  12. package/dist/analyzer/checker.js.map +1 -1
  13. package/dist/analyzer/commentUtils.js +15 -16
  14. package/dist/analyzer/commentUtils.js.map +1 -1
  15. package/dist/analyzer/constraintSolver.js +6 -2
  16. package/dist/analyzer/constraintSolver.js.map +1 -1
  17. package/dist/analyzer/constructorTransform.js +8 -4
  18. package/dist/analyzer/constructorTransform.js.map +1 -1
  19. package/dist/analyzer/constructors.js +128 -130
  20. package/dist/analyzer/constructors.js.map +1 -1
  21. package/dist/analyzer/dataClasses.js +4 -1
  22. package/dist/analyzer/dataClasses.js.map +1 -1
  23. package/dist/analyzer/declarationUtils.js +1 -0
  24. package/dist/analyzer/declarationUtils.js.map +1 -1
  25. package/dist/analyzer/docStringConversion.js +1 -1
  26. package/dist/analyzer/enums.js +1 -1
  27. package/dist/analyzer/enums.js.map +1 -1
  28. package/dist/analyzer/importResolver.d.ts +4 -4
  29. package/dist/analyzer/importResolver.js +46 -40
  30. package/dist/analyzer/importResolver.js.map +1 -1
  31. package/dist/analyzer/importResult.d.ts +2 -2
  32. package/dist/analyzer/importStatementUtils.js +2 -2
  33. package/dist/analyzer/importStatementUtils.js.map +1 -1
  34. package/dist/analyzer/packageTypeVerifier.js +1 -1
  35. package/dist/analyzer/packageTypeVerifier.js.map +1 -1
  36. package/dist/analyzer/parameterUtils.js +7 -7
  37. package/dist/analyzer/parameterUtils.js.map +1 -1
  38. package/dist/analyzer/parseTreeUtils.d.ts +1 -0
  39. package/dist/analyzer/parseTreeUtils.js +23 -40
  40. package/dist/analyzer/parseTreeUtils.js.map +1 -1
  41. package/dist/analyzer/parseTreeWalker.js +2 -2
  42. package/dist/analyzer/parseTreeWalker.js.map +1 -1
  43. package/dist/analyzer/patternMatching.js +1 -0
  44. package/dist/analyzer/patternMatching.js.map +1 -1
  45. package/dist/analyzer/program.d.ts +12 -18
  46. package/dist/analyzer/program.js +25 -12
  47. package/dist/analyzer/program.js.map +1 -1
  48. package/dist/analyzer/protocols.js +3 -1
  49. package/dist/analyzer/protocols.js.map +1 -1
  50. package/dist/analyzer/service.d.ts +4 -4
  51. package/dist/analyzer/service.js +29 -24
  52. package/dist/analyzer/service.js.map +1 -1
  53. package/dist/analyzer/sourceFile.d.ts +1 -6
  54. package/dist/analyzer/sourceFile.js +12 -27
  55. package/dist/analyzer/sourceFile.js.map +1 -1
  56. package/dist/analyzer/sourceMapper.js +1 -1
  57. package/dist/analyzer/sourceMapper.js.map +1 -1
  58. package/dist/analyzer/typeCacheUtils.d.ts +9 -2
  59. package/dist/analyzer/typeCacheUtils.js +52 -9
  60. package/dist/analyzer/typeCacheUtils.js.map +1 -1
  61. package/dist/analyzer/typeDocStringUtils.js +1 -1
  62. package/dist/analyzer/typeDocStringUtils.js.map +1 -1
  63. package/dist/analyzer/typeEvaluator.d.ts +2 -2
  64. package/dist/analyzer/typeEvaluator.js +257 -143
  65. package/dist/analyzer/typeEvaluator.js.map +1 -1
  66. package/dist/analyzer/typeEvaluatorTypes.d.ts +3 -2
  67. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  68. package/dist/analyzer/typeGuards.js +3 -2
  69. package/dist/analyzer/typeGuards.js.map +1 -1
  70. package/dist/analyzer/typePrinter.js +17 -10
  71. package/dist/analyzer/typePrinter.js.map +1 -1
  72. package/dist/analyzer/typeStubWriter.js +2 -2
  73. package/dist/analyzer/typeStubWriter.js.map +1 -1
  74. package/dist/analyzer/typeUtils.d.ts +1 -0
  75. package/dist/analyzer/typeUtils.js +20 -18
  76. package/dist/analyzer/typeUtils.js.map +1 -1
  77. package/dist/analyzer/typeVarContext.js +2 -2
  78. package/dist/analyzer/typeVarContext.js.map +1 -1
  79. package/dist/analyzer/typedDicts.js +140 -43
  80. package/dist/analyzer/typedDicts.js.map +1 -1
  81. package/dist/analyzer/types.d.ts +9 -1
  82. package/dist/analyzer/types.js +39 -16
  83. package/dist/analyzer/types.js.map +1 -1
  84. package/dist/backgroundAnalysisBase.d.ts +25 -19
  85. package/dist/backgroundAnalysisBase.js +145 -115
  86. package/dist/backgroundAnalysisBase.js.map +1 -1
  87. package/dist/backgroundThreadBase.d.ts +1 -1
  88. package/dist/backgroundThreadBase.js +1 -1
  89. package/dist/backgroundThreadBase.js.map +1 -1
  90. package/dist/commands/dumpFileDebugInfoCommand.js +5 -5
  91. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  92. package/dist/common/commandLineOptions.d.ts +1 -0
  93. package/dist/common/commandLineOptions.js.map +1 -1
  94. package/dist/common/configOptions.js +1 -1
  95. package/dist/common/configOptions.js.map +1 -1
  96. package/dist/common/extensibility.d.ts +2 -4
  97. package/dist/common/extensibility.js.map +1 -1
  98. package/dist/common/textRange.d.ts +3 -3
  99. package/dist/common/textRange.js +17 -8
  100. package/dist/common/textRange.js.map +1 -1
  101. package/dist/common/uriParser.d.ts +1 -0
  102. package/dist/common/uriParser.js +9 -0
  103. package/dist/common/uriParser.js.map +1 -1
  104. package/dist/common/workspaceEditUtils.d.ts +1 -1
  105. package/dist/common/workspaceEditUtils.js +5 -7
  106. package/dist/common/workspaceEditUtils.js.map +1 -1
  107. package/dist/languageServerBase.js +6 -4
  108. package/dist/languageServerBase.js.map +1 -1
  109. package/dist/languageService/analyzerServiceExecutor.js +1 -0
  110. package/dist/languageService/analyzerServiceExecutor.js.map +1 -1
  111. package/dist/languageService/autoImporter.d.ts +3 -3
  112. package/dist/languageService/autoImporter.js +3 -3
  113. package/dist/languageService/autoImporter.js.map +1 -1
  114. package/dist/languageService/callHierarchyProvider.js +3 -2
  115. package/dist/languageService/callHierarchyProvider.js.map +1 -1
  116. package/dist/languageService/completionProvider.d.ts +2 -2
  117. package/dist/languageService/completionProvider.js +42 -35
  118. package/dist/languageService/completionProvider.js.map +1 -1
  119. package/dist/languageService/documentSymbolCollector.js +9 -9
  120. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  121. package/dist/languageService/referencesProvider.js +1 -1
  122. package/dist/languageService/referencesProvider.js.map +1 -1
  123. package/dist/languageService/renameProvider.d.ts +3 -3
  124. package/dist/languageService/renameProvider.js +6 -6
  125. package/dist/languageService/renameProvider.js.map +1 -1
  126. package/dist/languageService/signatureHelpProvider.js +1 -1
  127. package/dist/languageService/signatureHelpProvider.js.map +1 -1
  128. package/dist/languageService/symbolIndexer.d.ts +0 -8
  129. package/dist/languageService/symbolIndexer.js.map +1 -1
  130. package/dist/localization/localize.d.ts +23 -3
  131. package/dist/localization/localize.js +13 -3
  132. package/dist/localization/localize.js.map +1 -1
  133. package/dist/localization/package.nls.en-us.json +15 -5
  134. package/dist/parser/parseNodes.d.ts +19 -11
  135. package/dist/parser/parseNodes.js +27 -19
  136. package/dist/parser/parseNodes.js.map +1 -1
  137. package/dist/parser/parser.d.ts +3 -3
  138. package/dist/parser/parser.js +146 -169
  139. package/dist/parser/parser.js.map +1 -1
  140. package/dist/parser/stringTokenUtils.d.ts +3 -13
  141. package/dist/parser/stringTokenUtils.js +8 -181
  142. package/dist/parser/stringTokenUtils.js.map +1 -1
  143. package/dist/parser/tokenizer.d.ts +3 -0
  144. package/dist/parser/tokenizer.js +212 -24
  145. package/dist/parser/tokenizer.js.map +1 -1
  146. package/dist/parser/tokenizerTypes.d.ts +31 -1
  147. package/dist/parser/tokenizerTypes.js +51 -1
  148. package/dist/parser/tokenizerTypes.js.map +1 -1
  149. package/dist/readonlyAugmentedFileSystem.js +1 -1
  150. package/dist/readonlyAugmentedFileSystem.js.map +1 -1
  151. package/dist/tests/docStringConversion.test.js +44 -0
  152. package/dist/tests/docStringConversion.test.js.map +1 -1
  153. package/dist/tests/fourslash/fourslash.d.ts +1 -1
  154. package/dist/tests/fourslash/rename.function.untitledFile.fourslash.d.ts +1 -0
  155. package/dist/tests/fourslash/rename.function.untitledFile.fourslash.js +17 -0
  156. package/dist/tests/fourslash/rename.function.untitledFile.fourslash.js.map +1 -0
  157. package/dist/tests/harness/fourslash/testLanguageService.js +1 -1
  158. package/dist/tests/harness/fourslash/testLanguageService.js.map +1 -1
  159. package/dist/tests/harness/fourslash/testState.d.ts +1 -1
  160. package/dist/tests/harness/fourslash/testState.js +4 -3
  161. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  162. package/dist/tests/importResolver.test.js +3 -3
  163. package/dist/tests/importResolver.test.js.map +1 -1
  164. package/dist/tests/textRange.test.d.ts +1 -0
  165. package/dist/tests/textRange.test.js +45 -0
  166. package/dist/tests/textRange.test.js.map +1 -0
  167. package/dist/tests/tokenizer.test.js +280 -58
  168. package/dist/tests/tokenizer.test.js.map +1 -1
  169. package/dist/tests/typeEvaluator1.test.js +5 -1
  170. package/dist/tests/typeEvaluator1.test.js.map +1 -1
  171. package/dist/tests/typeEvaluator2.test.js +9 -1
  172. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  173. package/dist/tests/typeEvaluator3.test.js +11 -1
  174. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  175. package/dist/tests/typeEvaluator4.test.js +7 -2
  176. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  177. package/dist/tests/typeEvaluator5.test.js +8 -0
  178. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  179. package/dist/tests/typePrinter.test.js +3 -3
  180. package/dist/tests/typePrinter.test.js.map +1 -1
  181. package/dist/workspaceFactory.js +7 -9
  182. package/dist/workspaceFactory.js.map +1 -1
  183. package/package.json +1 -1
@@ -813,7 +813,7 @@ class Parser {
813
813
  (0, debug_1.assert)(stringList.nodeType === 48 /* StringList */);
814
814
  // Check for f-strings, which are not allowed.
815
815
  stringList.strings.forEach((stringAtom) => {
816
- if (stringAtom.token.flags & 64 /* Format */) {
816
+ if (stringAtom.nodeType === 27 /* FormatString */) {
817
817
  this._addError(localize_1.Localizer.Diagnostic.formatStringInPattern(), stringAtom);
818
818
  }
819
819
  });
@@ -1498,7 +1498,7 @@ class Parser {
1498
1498
  }
1499
1499
  }
1500
1500
  paramList.push(param);
1501
- if (param.category === 1 /* VarArgList */) {
1501
+ if (param.category === 1 /* ArgsList */) {
1502
1502
  if (!param.name) {
1503
1503
  if (sawKeywordOnlySeparator) {
1504
1504
  this._addError(localize_1.Localizer.Diagnostic.duplicateKeywordOnly(), param);
@@ -1515,7 +1515,7 @@ class Parser {
1515
1515
  sawArgs = true;
1516
1516
  }
1517
1517
  }
1518
- if (param.category === 2 /* VarArgDictionary */) {
1518
+ if (param.category === 2 /* KwargsDict */) {
1519
1519
  if (sawKwArgs) {
1520
1520
  this._addError(localize_1.Localizer.Diagnostic.duplicateKwargsParam(), param);
1521
1521
  }
@@ -1544,7 +1544,7 @@ class Parser {
1544
1544
  }
1545
1545
  if (paramList.length > 0) {
1546
1546
  const lastParam = paramList[paramList.length - 1];
1547
- if (lastParam.category === 1 /* VarArgList */ && !lastParam.name) {
1547
+ if (lastParam.category === 1 /* ArgsList */ && !lastParam.name) {
1548
1548
  this._addError(localize_1.Localizer.Diagnostic.expectedNamedParameter(), lastParam);
1549
1549
  }
1550
1550
  }
@@ -1569,7 +1569,7 @@ class Parser {
1569
1569
  const paramName = this._getTokenIfIdentifier();
1570
1570
  if (!paramName) {
1571
1571
  if (starCount === 1) {
1572
- const paramNode = parseNodes_1.ParameterNode.create(firstToken, 1 /* VarArgList */);
1572
+ const paramNode = parseNodes_1.ParameterNode.create(firstToken, 1 /* ArgsList */);
1573
1573
  return paramNode;
1574
1574
  }
1575
1575
  else if (slashCount === 1) {
@@ -1590,10 +1590,10 @@ class Parser {
1590
1590
  }
1591
1591
  let paramType = 0 /* Simple */;
1592
1592
  if (starCount === 1) {
1593
- paramType = 1 /* VarArgList */;
1593
+ paramType = 1 /* ArgsList */;
1594
1594
  }
1595
1595
  else if (starCount === 2) {
1596
- paramType = 2 /* VarArgDictionary */;
1596
+ paramType = 2 /* KwargsDict */;
1597
1597
  }
1598
1598
  const paramNode = parseNodes_1.ParameterNode.create(firstToken, paramType);
1599
1599
  if (paramName) {
@@ -1602,7 +1602,7 @@ class Parser {
1602
1602
  (0, parseNodes_1.extendRange)(paramNode, paramName);
1603
1603
  }
1604
1604
  if (allowAnnotations && this._consumeTokenIfType(10 /* Colon */)) {
1605
- paramNode.typeAnnotation = this._parseTypeAnnotation(paramType === 1 /* VarArgList */);
1605
+ paramNode.typeAnnotation = this._parseTypeAnnotation(paramType === 1 /* ArgsList */);
1606
1606
  paramNode.typeAnnotation.parent = paramNode;
1607
1607
  (0, parseNodes_1.extendRange)(paramNode, paramNode.typeAnnotation);
1608
1608
  }
@@ -1937,7 +1937,7 @@ class Parser {
1937
1937
  nameNode: importFromNode.module,
1938
1938
  leadingDots: importFromNode.module.leadingDots,
1939
1939
  nameParts: importFromNode.module.nameParts.map((p) => p.value),
1940
- importedSymbols: importFromNode.imports.map((imp) => imp.name.value),
1940
+ importedSymbols: new Set(importFromNode.imports.map((imp) => imp.name.value)),
1941
1941
  });
1942
1942
  let isTypingImport = false;
1943
1943
  if (importFromNode.module.nameParts.length === 1) {
@@ -2990,7 +2990,7 @@ class Parser {
2990
2990
  if (nextToken.type === 7 /* Identifier */) {
2991
2991
  return parseNodes_1.NameNode.create(this._getNextToken());
2992
2992
  }
2993
- if (nextToken.type === 5 /* String */) {
2993
+ if (nextToken.type === 5 /* String */ || nextToken.type === 24 /* FStringStart */) {
2994
2994
  return this._parseStringList();
2995
2995
  }
2996
2996
  if (nextToken.type === 22 /* Backtick */) {
@@ -3015,10 +3015,13 @@ class Parser {
3015
3015
  diag.addMessage(localize_1.Localizer.DiagnosticAddendum.useTupleInstead());
3016
3016
  this._addError(localize_1.Localizer.Diagnostic.tupleInAnnotation() + diag.getString(), possibleTupleNode);
3017
3017
  }
3018
- if (possibleTupleNode.nodeType === 7 /* BinaryOperation */) {
3019
- // Mark the binary expression as parenthesized so we don't attempt
3018
+ if (possibleTupleNode.nodeType === 55 /* UnaryOperation */ ||
3019
+ possibleTupleNode.nodeType === 6 /* Await */ ||
3020
+ possibleTupleNode.nodeType === 7 /* BinaryOperation */) {
3021
+ // Mark binary expressions as parenthesized so we don't attempt
3020
3022
  // to use comparison chaining, which isn't appropriate when the
3021
- // expression is parenthesized.
3023
+ // expression is parenthesized. Unary and await expressions
3024
+ // are also marked to be able to display them unambiguously.
3022
3025
  possibleTupleNode.parenthesized = true;
3023
3026
  }
3024
3027
  if (possibleTupleNode.nodeType === 48 /* StringList */) {
@@ -3074,7 +3077,7 @@ class Parser {
3074
3077
  if (additionalStopTokens) {
3075
3078
  (0, collectionUtils_1.appendArray)(stopTokens, additionalStopTokens);
3076
3079
  }
3077
- // Using token that is not consumed by error node will mess up spans in parse node.
3080
+ // Using a token that is not included in the error node creates problems.
3078
3081
  // Sibling nodes in parse tree shouldn't overlap each other.
3079
3082
  const nextToken = this._peekToken();
3080
3083
  const initialRange = stopTokens.some((k) => nextToken.type === k)
@@ -3356,6 +3359,7 @@ class Parser {
3356
3359
  // augassign: ('+=' | '-=' | '*=' | '@=' | '/=' | '%=' | '&=' | '|=' | '^=' |
3357
3360
  // '<<=' | '>>=' | '**=' | '//=')
3358
3361
  _parseExpressionStatement() {
3362
+ var _a, _b;
3359
3363
  let leftExpr = this._parseTestOrStarListAsExpression(
3360
3364
  /* allowAssignmentExpression */ false,
3361
3365
  /* allowMultipleUnpack */ false, 2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedExpr());
@@ -3382,10 +3386,9 @@ class Parser {
3382
3386
  if (isTypeAliasDeclaration) {
3383
3387
  this._isParsingTypeAnnotation = true;
3384
3388
  }
3385
- const rightExpr = this._tryParseYieldExpression() ||
3386
- this._parseTestOrStarListAsExpression(
3387
- /* allowAssignmentExpression */ false,
3388
- /* allowMultipleUnpack */ true, 2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedAssignRightHandExpr());
3389
+ const rightExpr = (_a = this._tryParseYieldExpression()) !== null && _a !== void 0 ? _a : this._parseTestOrStarListAsExpression(
3390
+ /* allowAssignmentExpression */ false,
3391
+ /* allowMultipleUnpack */ true, 2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedAssignRightHandExpr());
3389
3392
  this._isParsingTypeAnnotation = wasParsingTypeAnnotation;
3390
3393
  return parseNodes_1.AssignmentNode.create(leftExpr, rightExpr);
3391
3394
  }
@@ -3395,8 +3398,7 @@ class Parser {
3395
3398
  }
3396
3399
  if (tokenizer_1.Tokenizer.isOperatorAssignment(this._peekOperatorType())) {
3397
3400
  const operatorToken = this._getNextToken();
3398
- const rightExpr = this._tryParseYieldExpression() ||
3399
- this._parseTestListAsExpression(2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedBinaryRightHandExpr());
3401
+ const rightExpr = (_b = this._tryParseYieldExpression()) !== null && _b !== void 0 ? _b : this._parseTestListAsExpression(2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedBinaryRightHandExpr());
3400
3402
  // Make a shallow copy of the dest expression but give it a new ID.
3401
3403
  const destExpr = Object.assign({}, leftExpr);
3402
3404
  destExpr.id = (0, parseNodes_1.getNextNodeId)();
@@ -3405,15 +3407,15 @@ class Parser {
3405
3407
  return leftExpr;
3406
3408
  }
3407
3409
  _parseChainAssignments(leftExpr) {
3410
+ var _a;
3408
3411
  // Make a list of assignment targets.
3409
3412
  const assignmentTargets = [leftExpr];
3410
3413
  let rightExpr;
3411
3414
  while (true) {
3412
3415
  rightExpr =
3413
- this._tryParseYieldExpression() ||
3414
- this._parseTestOrStarListAsExpression(
3415
- /* allowAssignmentExpression */ false,
3416
- /* allowMultipleUnpack */ true, 2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedAssignRightHandExpr());
3416
+ (_a = this._tryParseYieldExpression()) !== null && _a !== void 0 ? _a : this._parseTestOrStarListAsExpression(
3417
+ /* allowAssignmentExpression */ false,
3418
+ /* allowMultipleUnpack */ true, 2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedAssignRightHandExpr());
3417
3419
  if (rightExpr.nodeType === 0 /* Error */) {
3418
3420
  break;
3419
3421
  }
@@ -3517,7 +3519,7 @@ class Parser {
3517
3519
  if (stringToken.flags & 65536 /* Unterminated */) {
3518
3520
  this._addError(localize_1.Localizer.Diagnostic.stringUnterminated(), stringToken);
3519
3521
  }
3520
- if (unescapedResult.nonAsciiInBytes) {
3522
+ if (unescapedResult === null || unescapedResult === void 0 ? void 0 : unescapedResult.nonAsciiInBytes) {
3521
3523
  this._addError(localize_1.Localizer.Diagnostic.stringNonAsciiBytes(), stringToken);
3522
3524
  }
3523
3525
  if (stringToken.flags & 64 /* Format */) {
@@ -3535,7 +3537,7 @@ class Parser {
3535
3537
  _makeStringNode(stringToken) {
3536
3538
  const unescapedResult = StringTokenUtils.getUnescapedString(stringToken);
3537
3539
  this._reportStringTokenErrors(stringToken, unescapedResult);
3538
- return parseNodes_1.StringNode.create(stringToken, unescapedResult.value, unescapedResult.unescapeErrors.length > 0);
3540
+ return parseNodes_1.StringNode.create(stringToken, unescapedResult.value);
3539
3541
  }
3540
3542
  _getTypeAnnotationCommentText() {
3541
3543
  if (this._tokenIndex === 0) {
@@ -3601,154 +3603,123 @@ class Parser {
3601
3603
  functionAnnotation.parent = functionNode;
3602
3604
  (0, parseNodes_1.extendRange)(functionNode, functionAnnotation);
3603
3605
  }
3604
- _parseFormatStringSegment(stringToken, segment, segmentOffset, segmentLength) {
3605
- (0, debug_1.assert)(segment.isExpression);
3606
- const parser = new Parser();
3607
- const parseResults = parser.parseTextExpression(this._fileContents, stringToken.start + stringToken.prefixLength + stringToken.quoteMarkLength + segment.offset + segmentOffset, segmentLength, this._parseOptions, 0 /* Expression */,
3608
- /* initialParenDepth */ 1, this._typingSymbolAliases);
3609
- parseResults.diagnostics.forEach((diag) => {
3610
- const textRangeStart = (diag.range ? (0, positionUtils_1.convertPositionToOffset)(diag.range.start, parseResults.lines) : stringToken.start) ||
3611
- stringToken.start;
3612
- const textRangeEnd = (diag.range
3613
- ? ((0, positionUtils_1.convertPositionToOffset)(diag.range.end, parseResults.lines) || 0) + 1
3614
- : stringToken.start + stringToken.length) || stringToken.start + stringToken.length;
3615
- const textRange = { start: textRangeStart, length: textRangeEnd - textRangeStart };
3616
- this._addError(diag.message, textRange);
3617
- });
3618
- return parseResults.parseTree;
3606
+ _parseFStringReplacementField(fieldExpressions, middleTokens, formatExpressions, nestingDepth = 0) {
3607
+ var _a;
3608
+ let nextToken = this._getNextToken();
3609
+ // The caller should have already confirmed that the next token is an open brace.
3610
+ (0, debug_1.assert)(nextToken.type === 17 /* OpenCurlyBrace */);
3611
+ // Consume the expression.
3612
+ const expr = (_a = this._tryParseYieldExpression()) !== null && _a !== void 0 ? _a : this._parseTestOrStarListAsExpression(
3613
+ /* allowAssignmentExpression */ true,
3614
+ /* allowMultipleUnpack */ true, 2 /* MissingExpression */, () => localize_1.Localizer.Diagnostic.expectedExpr());
3615
+ fieldExpressions.push(expr);
3616
+ if (expr.nodeType === 0 /* Error */) {
3617
+ return false;
3618
+ }
3619
+ // Consume an optional "=" token after the expression.
3620
+ nextToken = this._peekToken();
3621
+ if (nextToken.type === 9 /* Operator */ &&
3622
+ nextToken.operatorType === 2 /* Assign */) {
3623
+ // This feature requires Python 3.8 or newer.
3624
+ if (this._parseOptions.pythonVersion < pythonVersion_1.PythonVersion.V3_8) {
3625
+ this._addError(localize_1.Localizer.Diagnostic.formatStringDebuggingIllegal(), nextToken);
3626
+ }
3627
+ this._getNextToken();
3628
+ nextToken = this._peekToken();
3629
+ }
3630
+ // Consume an optional !r, !s, or !a token.
3631
+ if (nextToken.type === 23 /* ExclamationMark */) {
3632
+ this._getNextToken();
3633
+ nextToken = this._peekToken();
3634
+ if (nextToken.type !== 7 /* Identifier */) {
3635
+ this._addError(localize_1.Localizer.Diagnostic.formatStringExpectedConversion(), nextToken);
3636
+ }
3637
+ else {
3638
+ this._getNextToken();
3639
+ nextToken = this._peekToken();
3640
+ }
3641
+ }
3642
+ if (nextToken.type === 10 /* Colon */) {
3643
+ this._getNextToken();
3644
+ this._parseFStringFormatString(fieldExpressions, middleTokens, formatExpressions, nestingDepth);
3645
+ nextToken = this._peekToken();
3646
+ }
3647
+ if (nextToken.type !== 18 /* CloseCurlyBrace */) {
3648
+ this._addError(localize_1.Localizer.Diagnostic.formatStringUnterminated(), nextToken);
3649
+ return false;
3650
+ }
3651
+ else {
3652
+ this._getNextToken();
3653
+ }
3654
+ // Indicate success.
3655
+ return true;
3619
3656
  }
3620
- _parseFormatString(stringToken) {
3621
- const unescapedResult = StringTokenUtils.getUnescapedString(stringToken);
3622
- this._reportStringTokenErrors(stringToken, unescapedResult);
3623
- const formatExpressions = [];
3624
- for (const segment of unescapedResult.formatStringSegments) {
3625
- if (segment.isExpression) {
3626
- // Determine if we need to truncate the expression because it
3627
- // contains formatting directives that start with a ! or :.
3628
- const segmentExprLength = this._getFormatStringExpressionLength(segment.value.trimEnd());
3629
- const parseTree = this._parseFormatStringSegment(stringToken, segment, 0, segmentExprLength);
3630
- if (parseTree) {
3631
- (0, debug_1.assert)(parseTree.nodeType !== 62 /* FunctionAnnotation */);
3632
- formatExpressions.push(parseTree);
3633
- }
3634
- // Look for additional expressions within the format directive.
3635
- const formatDirective = segment.value.substr(segmentExprLength);
3636
- let braceDepth = 0;
3637
- let startOfExprOffset = 0;
3638
- for (let i = 0; i < formatDirective.length; i++) {
3639
- if (formatDirective.charCodeAt(i) === 123 /* OpenBrace */) {
3640
- if (braceDepth === 0) {
3641
- startOfExprOffset = i + 1;
3642
- }
3643
- braceDepth++;
3644
- }
3645
- else if (formatDirective.charCodeAt(i) === 125 /* CloseBrace */) {
3646
- if (braceDepth > 0) {
3647
- braceDepth--;
3648
- if (braceDepth === 0) {
3649
- const formatSegmentLength = this._getFormatStringExpressionLength(segment.value.substr(segmentExprLength + startOfExprOffset, i - startOfExprOffset));
3650
- const parseTree = this._parseFormatStringSegment(stringToken, segment, segmentExprLength + startOfExprOffset, formatSegmentLength);
3651
- if (parseTree) {
3652
- (0, debug_1.assert)(parseTree.nodeType !== 62 /* FunctionAnnotation */);
3653
- formatExpressions.push(parseTree);
3654
- }
3655
- }
3656
- }
3657
- }
3657
+ _parseFStringFormatString(fieldExpressions, middleTokens, formatExpressions, nestingDepth) {
3658
+ while (true) {
3659
+ const nextToken = this._peekToken();
3660
+ if (nextToken.type === 18 /* CloseCurlyBrace */ || nextToken.type === 26 /* FStringEnd */) {
3661
+ break;
3662
+ }
3663
+ if (nextToken.type === 25 /* FStringMiddle */) {
3664
+ this._getNextToken();
3665
+ continue;
3666
+ }
3667
+ if (nextToken.type === 17 /* OpenCurlyBrace */) {
3668
+ // The Python interpreter reports an error at the point where the
3669
+ // nesting level exceeds 1. Don't report the error again for deeper nestings.
3670
+ if (nestingDepth === 2) {
3671
+ this._addError(localize_1.Localizer.Diagnostic.formatStringNestedFormatSpecifier(), nextToken);
3658
3672
  }
3673
+ this._parseFStringReplacementField(fieldExpressions, middleTokens, formatExpressions, nestingDepth + 1);
3674
+ continue;
3659
3675
  }
3676
+ break;
3660
3677
  }
3661
- return parseNodes_1.FormatStringNode.create(stringToken, unescapedResult.value, unescapedResult.unescapeErrors.length > 0, formatExpressions);
3662
3678
  }
3663
- _getFormatStringExpressionLength(segmentValue) {
3664
- let segmentExprLength = 0;
3665
- // PEP 498 says: Expressions cannot contain ':' or '!' outside of
3666
- // strings or parentheses, brackets, or braces. The exception is
3667
- // that the '!=' operator is allowed as a special case.
3668
- const quoteStack = [];
3669
- let braceCount = 0;
3670
- let parenCount = 0;
3671
- let bracketCount = 0;
3672
- let indexOfDebugEqual;
3673
- while (segmentExprLength < segmentValue.length) {
3674
- const curChar = segmentValue[segmentExprLength];
3675
- const ignoreSeparator = quoteStack.length > 0 || braceCount > 0 || parenCount > 0 || bracketCount > 0;
3676
- const inString = quoteStack.length > 0;
3677
- if (curChar === '=') {
3678
- indexOfDebugEqual = segmentExprLength;
3679
- }
3680
- else {
3681
- if (curChar === ':') {
3682
- if (!ignoreSeparator) {
3683
- break;
3684
- }
3679
+ _parseFormatString(startToken) {
3680
+ const middleTokens = [];
3681
+ const fieldExpressions = [];
3682
+ const formatExpressions = [];
3683
+ let endToken = undefined;
3684
+ // Consume middle tokens and expressions until we hit a "{" or "}" token.
3685
+ while (true) {
3686
+ const nextToken = this._peekToken();
3687
+ if (nextToken.type === 26 /* FStringEnd */) {
3688
+ endToken = nextToken;
3689
+ if ((endToken.flags & 65536 /* Unterminated */) !== 0) {
3690
+ this._addError(localize_1.Localizer.Diagnostic.stringUnterminated(), startToken);
3685
3691
  }
3686
- else if (curChar === '!') {
3687
- if (!ignoreSeparator) {
3688
- // Allow !=, as per PEP 498
3689
- if (segmentExprLength === segmentValue.length - 1 ||
3690
- segmentValue[segmentExprLength + 1] !== '=') {
3691
- break;
3692
+ this._getNextToken();
3693
+ break;
3694
+ }
3695
+ if (nextToken.type === 25 /* FStringMiddle */) {
3696
+ middleTokens.push(nextToken);
3697
+ this._getNextToken();
3698
+ continue;
3699
+ }
3700
+ if (nextToken.type === 17 /* OpenCurlyBrace */) {
3701
+ if (!this._parseFStringReplacementField(fieldExpressions, middleTokens, formatExpressions)) {
3702
+ // An error was reported. Try to recover the parse.
3703
+ if (this._consumeTokensUntilType([26 /* FStringEnd */, 2 /* NewLine */])) {
3704
+ if (this._peekToken().type === 26 /* FStringEnd */) {
3705
+ this._getNextToken();
3692
3706
  }
3693
3707
  }
3708
+ break;
3694
3709
  }
3695
- else if (curChar === "'" || curChar === '"') {
3696
- let quoteSequence = curChar;
3697
- if (segmentExprLength + 2 < segmentValue.length &&
3698
- segmentValue[segmentExprLength + 1] === curChar &&
3699
- segmentValue[segmentExprLength + 2] === curChar) {
3700
- quoteSequence = curChar + curChar + curChar;
3701
- segmentExprLength += 2;
3702
- }
3703
- if (quoteStack.length > 0 && quoteStack[quoteStack.length - 1] === quoteSequence) {
3704
- quoteStack.pop();
3705
- }
3706
- else if (quoteStack.length === 0) {
3707
- quoteStack.push(quoteSequence);
3708
- }
3709
- }
3710
- else if (curChar === '(') {
3711
- if (!inString) {
3712
- parenCount++;
3713
- }
3714
- }
3715
- else if (curChar === ')') {
3716
- if (!inString && parenCount > 0) {
3717
- parenCount--;
3718
- }
3719
- }
3720
- else if (curChar === '{') {
3721
- if (!inString) {
3722
- braceCount++;
3723
- }
3724
- }
3725
- else if (curChar === '}') {
3726
- if (!inString && braceCount > 0) {
3727
- braceCount--;
3728
- }
3729
- }
3730
- else if (curChar === '[') {
3731
- if (!inString) {
3732
- bracketCount++;
3733
- }
3734
- }
3735
- else if (curChar === ']') {
3736
- if (!inString && bracketCount > 0) {
3737
- bracketCount--;
3738
- }
3739
- }
3740
- if (curChar !== ' ') {
3741
- indexOfDebugEqual = undefined;
3742
- }
3710
+ continue;
3743
3711
  }
3744
- segmentExprLength++;
3745
- }
3746
- // Handle Python 3.8 f-string formatting expressions that
3747
- // end in an "=".
3748
- if (this._parseOptions.pythonVersion >= pythonVersion_1.PythonVersion.V3_8 && indexOfDebugEqual !== undefined) {
3749
- segmentExprLength = indexOfDebugEqual;
3712
+ // We've hit an error. Consume tokens until we find the end.
3713
+ if (this._consumeTokensUntilType([26 /* FStringEnd */])) {
3714
+ this._getNextToken();
3715
+ }
3716
+ this._addError(nextToken.type === 18 /* CloseCurlyBrace */
3717
+ ? localize_1.Localizer.Diagnostic.formatStringBrace()
3718
+ : localize_1.Localizer.Diagnostic.stringUnterminated(), nextToken);
3719
+ break;
3750
3720
  }
3751
- return segmentExprLength;
3721
+ this._reportStringTokenErrors(startToken);
3722
+ return parseNodes_1.FormatStringNode.create(startToken, endToken, middleTokens, fieldExpressions, formatExpressions);
3752
3723
  }
3753
3724
  _createBinaryOperationNode(leftExpression, rightExpression, operatorToken, operator) {
3754
3725
  // Determine if we're exceeding the max parse depth. If so, replace
@@ -3776,13 +3747,16 @@ class Parser {
3776
3747
  }
3777
3748
  _parseStringList() {
3778
3749
  const stringList = [];
3779
- while (this._peekTokenType() === 5 /* String */) {
3780
- const stringToken = this._getNextToken();
3781
- if (stringToken.flags & 64 /* Format */) {
3782
- stringList.push(this._parseFormatString(stringToken));
3750
+ while (true) {
3751
+ const nextToken = this._peekToken();
3752
+ if (nextToken.type === 5 /* String */) {
3753
+ stringList.push(this._makeStringNode(this._getNextToken()));
3754
+ }
3755
+ else if (nextToken.type === 24 /* FStringStart */) {
3756
+ stringList.push(this._parseFormatString(this._getNextToken()));
3783
3757
  }
3784
3758
  else {
3785
- stringList.push(this._makeStringNode(stringToken));
3759
+ break;
3786
3760
  }
3787
3761
  }
3788
3762
  const stringNode = parseNodes_1.StringListNode.create(stringList);
@@ -3793,7 +3767,7 @@ class Parser {
3793
3767
  if (stringNode.strings.length > 1) {
3794
3768
  this._addError(localize_1.Localizer.Diagnostic.annotationSpansStrings(), stringNode);
3795
3769
  }
3796
- else if (stringNode.strings[0].token.flags & 64 /* Format */) {
3770
+ else if (stringNode.strings[0].nodeType === 27 /* FormatString */) {
3797
3771
  this._addError(localize_1.Localizer.Diagnostic.annotationFormatString(), stringNode);
3798
3772
  }
3799
3773
  else {
@@ -3889,6 +3863,9 @@ class Parser {
3889
3863
  case 18 /* CloseCurlyBrace */:
3890
3864
  case 12 /* Comma */:
3891
3865
  case 10 /* Colon */:
3866
+ case 23 /* ExclamationMark */:
3867
+ case 25 /* FStringMiddle */:
3868
+ case 26 /* FStringEnd */:
3892
3869
  return true;
3893
3870
  }
3894
3871
  return false;