@zzzen/pyright-internal 1.2.0-dev.20231224 → 1.2.0-dev.20240107

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 (71) hide show
  1. package/dist/analyzer/binder.js +13 -6
  2. package/dist/analyzer/binder.js.map +1 -1
  3. package/dist/analyzer/checker.d.ts +3 -0
  4. package/dist/analyzer/checker.js +167 -42
  5. package/dist/analyzer/checker.js.map +1 -1
  6. package/dist/analyzer/codeFlowEngine.js +7 -4
  7. package/dist/analyzer/codeFlowEngine.js.map +1 -1
  8. package/dist/analyzer/constraintSolver.js +21 -17
  9. package/dist/analyzer/constraintSolver.js.map +1 -1
  10. package/dist/analyzer/dataClasses.js +2 -9
  11. package/dist/analyzer/dataClasses.js.map +1 -1
  12. package/dist/analyzer/enums.js +1 -1
  13. package/dist/analyzer/enums.js.map +1 -1
  14. package/dist/analyzer/namedTuples.js +14 -6
  15. package/dist/analyzer/namedTuples.js.map +1 -1
  16. package/dist/analyzer/protocols.d.ts +2 -0
  17. package/dist/analyzer/protocols.js +75 -6
  18. package/dist/analyzer/protocols.js.map +1 -1
  19. package/dist/analyzer/scopeUtils.d.ts +1 -0
  20. package/dist/analyzer/scopeUtils.js +12 -1
  21. package/dist/analyzer/scopeUtils.js.map +1 -1
  22. package/dist/analyzer/typeEvaluator.js +339 -219
  23. package/dist/analyzer/typeEvaluator.js.map +1 -1
  24. package/dist/analyzer/typeEvaluatorTypes.d.ts +2 -1
  25. package/dist/analyzer/typeEvaluatorTypes.js +2 -0
  26. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  27. package/dist/analyzer/typeGuards.js +10 -6
  28. package/dist/analyzer/typeGuards.js.map +1 -1
  29. package/dist/analyzer/typePrinter.js +4 -2
  30. package/dist/analyzer/typePrinter.js.map +1 -1
  31. package/dist/analyzer/typeUtils.d.ts +10 -9
  32. package/dist/analyzer/typeUtils.js +20 -14
  33. package/dist/analyzer/typeUtils.js.map +1 -1
  34. package/dist/analyzer/typedDicts.js +24 -36
  35. package/dist/analyzer/typedDicts.js.map +1 -1
  36. package/dist/analyzer/types.d.ts +8 -2
  37. package/dist/analyzer/types.js +58 -8
  38. package/dist/analyzer/types.js.map +1 -1
  39. package/dist/backgroundAnalysisBase.js +4 -3
  40. package/dist/backgroundAnalysisBase.js.map +1 -1
  41. package/dist/backgroundThreadBase.d.ts +1 -0
  42. package/dist/backgroundThreadBase.js +8 -1
  43. package/dist/backgroundThreadBase.js.map +1 -1
  44. package/dist/common/diagnostic.d.ts +1 -0
  45. package/dist/common/diagnostic.js +18 -1
  46. package/dist/common/diagnostic.js.map +1 -1
  47. package/dist/common/realFileSystem.js +44 -12
  48. package/dist/common/realFileSystem.js.map +1 -1
  49. package/dist/localization/localize.d.ts +45 -0
  50. package/dist/localization/localize.js +22 -0
  51. package/dist/localization/localize.js.map +1 -1
  52. package/dist/localization/package.nls.en-us.json +24 -2
  53. package/dist/parser/parser.js +1 -1
  54. package/dist/parser/parser.js.map +1 -1
  55. package/dist/pyright.js +6 -3
  56. package/dist/pyright.js.map +1 -1
  57. package/dist/tests/localizer.test.js +1 -1
  58. package/dist/tests/localizer.test.js.map +1 -1
  59. package/dist/tests/typeEvaluator1.test.js +2 -2
  60. package/dist/tests/typeEvaluator2.test.js +22 -10
  61. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  62. package/dist/tests/typeEvaluator3.test.js +3 -3
  63. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  64. package/dist/tests/typeEvaluator4.test.js +7 -3
  65. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  66. package/dist/tests/typeEvaluator5.test.js +1 -1
  67. package/dist/tests/typePrinter.test.js +2 -10
  68. package/dist/tests/typePrinter.test.js.map +1 -1
  69. package/dist/tests/uri.test.js +7 -0
  70. package/dist/tests/uri.test.js.map +1 -1
  71. package/package.json +1 -1
@@ -60,6 +60,7 @@ const parameterUtils_1 = require("./parameterUtils");
60
60
  const ParseTreeUtils = __importStar(require("./parseTreeUtils"));
61
61
  const parseTreeWalker_1 = require("./parseTreeWalker");
62
62
  const patternMatching_1 = require("./patternMatching");
63
+ const protocols_1 = require("./protocols");
63
64
  const regions_1 = require("./regions");
64
65
  const scopeUtils_1 = require("./scopeUtils");
65
66
  const sourceFile_1 = require("./sourceFile");
@@ -162,8 +163,8 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
162
163
  !types_1.ClassType.isBuiltIn(baseClassType, 'Generic')) {
163
164
  if (!types_1.ClassType.isProtocolClass(baseClassType)) {
164
165
  this._evaluator.addError(localize_1.Localizer.Diagnostic.protocolBaseClass().format({
165
- classType: this._evaluator.printType(classTypeResult.classType),
166
- baseType: this._evaluator.printType(baseClassType),
166
+ classType: classTypeResult.classType.details.name,
167
+ baseType: baseClassType.details.name,
167
168
  }), arg.valueExpression);
168
169
  }
169
170
  }
@@ -179,6 +180,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
179
180
  this._validateSlotsClassVarConflict(classTypeResult.classType);
180
181
  }
181
182
  this._validateBaseClassOverrides(classTypeResult.classType);
183
+ this._validateOverloadDecoratorConsistency(classTypeResult.classType);
182
184
  this._validateMultipleInheritanceBaseClasses(classTypeResult.classType, node.name);
183
185
  this._validateMultipleInheritanceCompatibility(classTypeResult.classType, node.name);
184
186
  this._validateConstructorConsistency(classTypeResult.classType, node.name);
@@ -386,6 +388,10 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
386
388
  this._validateFunctionTypeVarUsage(node, functionTypeResult);
387
389
  this._validateGeneratorReturnType(node, functionTypeResult.functionType);
388
390
  this._reportDeprecatedClassProperty(node, functionTypeResult);
391
+ // If this is not a method, @final is disallowed.
392
+ if (!containingClassNode && types_1.FunctionType.isFinal(functionTypeResult.functionType)) {
393
+ this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.finalNonMethod().format({ name: node.name.value }), node.name);
394
+ }
389
395
  }
390
396
  // If we're at the module level within a stub file, report a diagnostic
391
397
  // if there is a '__getattr__' function defined when in strict mode.
@@ -564,7 +570,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
564
570
  let diagAddendum = new diagnostic_1.DiagnosticAddendum();
565
571
  let returnTypeMatches = false;
566
572
  if (this._evaluator.assignType(declaredReturnType, returnTypeResult.type, diagAddendum, new typeVarContext_1.TypeVarContext(),
567
- /* srcTypeVarContext */ undefined, 64 /* AssignTypeFlags.AllowBoolTypeGuard */)) {
573
+ /* srcTypeVarContext */ undefined, 128 /* AssignTypeFlags.AllowBoolTypeGuard */)) {
568
574
  returnTypeMatches = true;
569
575
  }
570
576
  else {
@@ -587,7 +593,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
587
593
  const adjustedReturnType = (0, typeUtils_1.applySolvedTypeVars)(declaredReturnType, typeVarContext);
588
594
  if (this._evaluator.assignType(adjustedReturnType, returnTypeResult.type, diagAddendum,
589
595
  /* destTypeVarContext */ undefined,
590
- /* srcTypeVarContext */ undefined, 64 /* AssignTypeFlags.AllowBoolTypeGuard */)) {
596
+ /* srcTypeVarContext */ undefined, 128 /* AssignTypeFlags.AllowBoolTypeGuard */)) {
591
597
  returnTypeMatches = true;
592
598
  }
593
599
  }
@@ -1731,7 +1737,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
1731
1737
  _validateOverloadConsistency(node, functionType, prevOverloads) {
1732
1738
  for (let i = 0; i < prevOverloads.length; i++) {
1733
1739
  const prevOverload = prevOverloads[i];
1734
- if (this._isOverlappingOverload(functionType, prevOverload)) {
1740
+ if (this._isOverlappingOverload(functionType, prevOverload, /* partialOverlap */ false)) {
1735
1741
  this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportOverlappingOverload, diagnosticRules_1.DiagnosticRule.reportOverlappingOverload, localize_1.Localizer.Diagnostic.overlappingOverload().format({
1736
1742
  name: node.name.value,
1737
1743
  obscured: prevOverloads.length + 1,
@@ -1742,14 +1748,14 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
1742
1748
  }
1743
1749
  for (let i = 0; i < prevOverloads.length; i++) {
1744
1750
  const prevOverload = prevOverloads[i];
1745
- if (this._isOverlappingOverload(prevOverload, functionType)) {
1751
+ if (this._isOverlappingOverload(prevOverload, functionType, /* partialOverlap */ true)) {
1746
1752
  const prevReturnType = types_1.FunctionType.getSpecializedReturnType(prevOverload);
1747
1753
  const returnType = types_1.FunctionType.getSpecializedReturnType(functionType);
1748
1754
  if (prevReturnType &&
1749
1755
  returnType &&
1750
1756
  !this._evaluator.assignType(returnType, prevReturnType,
1751
1757
  /* diag */ undefined, new typeVarContext_1.TypeVarContext(),
1752
- /* srcTypeVarContext */ undefined, 8 /* AssignTypeFlags.SkipSolveTypeVars */ | 512 /* AssignTypeFlags.IgnoreTypeVarScope */)) {
1758
+ /* srcTypeVarContext */ undefined, 8 /* AssignTypeFlags.SkipSolveTypeVars */ | 1024 /* AssignTypeFlags.IgnoreTypeVarScope */)) {
1753
1759
  const altNode = this._findNodeForOverload(node, prevOverload);
1754
1760
  this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportOverlappingOverload, diagnosticRules_1.DiagnosticRule.reportOverlappingOverload, localize_1.Localizer.Diagnostic.overloadReturnTypeMismatch().format({
1755
1761
  name: node.name.value,
@@ -1779,7 +1785,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
1779
1785
  }
1780
1786
  return undefined;
1781
1787
  }
1782
- _isOverlappingOverload(functionType, prevOverload) {
1788
+ _isOverlappingOverload(functionType, prevOverload, partialOverlap) {
1783
1789
  // According to precedent, the __get__ method is special-cased and is
1784
1790
  // exempt from overlapping overload checks. It's not clear why this is
1785
1791
  // the case, but for consistency with other type checkers, we'll honor
@@ -1788,18 +1794,22 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
1788
1794
  if (types_1.FunctionType.isInstanceMethod(functionType) && functionType.details.name === '__get__') {
1789
1795
  return false;
1790
1796
  }
1797
+ let flags = 64 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */ | 16 /* AssignTypeFlags.OverloadOverlapCheck */;
1798
+ if (partialOverlap) {
1799
+ flags |= 32 /* AssignTypeFlags.PartialOverloadOverlapCheck */;
1800
+ }
1791
1801
  return this._evaluator.assignType(functionType, prevOverload,
1792
1802
  /* diag */ undefined, new typeVarContext_1.TypeVarContext((0, typeUtils_1.getTypeVarScopeId)(functionType)),
1793
- /* srcTypeVarContext */ undefined, 32 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */ | 16 /* AssignTypeFlags.OverloadOverlapCheck */);
1803
+ /* srcTypeVarContext */ undefined, flags);
1794
1804
  }
1795
1805
  _isLegalOverloadImplementation(overload, implementation, diag) {
1796
1806
  var _a;
1797
1807
  const implTypeVarContext = new typeVarContext_1.TypeVarContext((0, typeUtils_1.getTypeVarScopeId)(implementation));
1798
1808
  const overloadTypeVarContext = new typeVarContext_1.TypeVarContext((0, typeUtils_1.getTypeVarScopeId)(overload));
1799
1809
  // First check the parameters to see if they are assignable.
1800
- let isLegal = this._evaluator.assignType(overload, implementation, diag, overloadTypeVarContext, implTypeVarContext, 32 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */ |
1810
+ let isLegal = this._evaluator.assignType(overload, implementation, diag, overloadTypeVarContext, implTypeVarContext, 64 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */ |
1801
1811
  2 /* AssignTypeFlags.ReverseTypeVarMatching */ |
1802
- 256 /* AssignTypeFlags.SkipSelfClsTypeCheck */);
1812
+ 512 /* AssignTypeFlags.SkipSelfClsTypeCheck */);
1803
1813
  // Now check the return types.
1804
1814
  const overloadReturnType = (_a = overload.details.declaredReturnType) !== null && _a !== void 0 ? _a : this._evaluator.getFunctionInferredReturnType(overload);
1805
1815
  const implementationReturnType = (0, typeUtils_1.applySolvedTypeVars)(implementation.details.declaredReturnType || this._evaluator.getFunctionInferredReturnType(implementation), implTypeVarContext);
@@ -2538,6 +2548,23 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
2538
2548
  type: this._evaluator.printType(arg1Type),
2539
2549
  }) + diag.getString(), node.arguments[1]);
2540
2550
  }
2551
+ // If this call is an issubclass, check for the use of a "data protocol",
2552
+ // which PEP 544 says cannot be used in issubclass.
2553
+ if (!isInstanceCheck) {
2554
+ const diag = new diagnostic_1.DiagnosticAddendum();
2555
+ (0, typeUtils_1.doForEachSubtype)(arg1Type, (arg1Subtype) => {
2556
+ if ((0, types_1.isInstantiableClass)(arg1Subtype) &&
2557
+ types_1.ClassType.isProtocolClass(arg1Subtype) &&
2558
+ !(0, protocols_1.isMethodOnlyProtocol)(arg1Subtype)) {
2559
+ diag.addMessage(localize_1.Localizer.DiagnosticAddendum.dataProtocolUnsupported().format({
2560
+ name: arg1Subtype.details.name,
2561
+ }));
2562
+ }
2563
+ });
2564
+ if (!diag.isEmpty()) {
2565
+ this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.dataProtocolInSubclassCheck(), node.arguments[1]);
2566
+ }
2567
+ }
2541
2568
  // If this call is within an assert statement, we won't check whether
2542
2569
  // it's unnecessary.
2543
2570
  let curNode = node;
@@ -2573,6 +2600,9 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
2573
2600
  arg1IncludesSubclasses = true;
2574
2601
  }
2575
2602
  }
2603
+ if (arg0Type) {
2604
+ this._validateUnsafeProtocolOverlap(node.arguments[0].valueExpression, (0, typeUtils_1.convertToInstance)(arg1Subtype), isInstanceCheck ? arg0Type : (0, typeUtils_1.convertToInstance)(arg0Type));
2605
+ }
2576
2606
  }
2577
2607
  else {
2578
2608
  // The isinstance and issubclass call supports a variation where the second
@@ -2585,6 +2615,9 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
2585
2615
  if (typeArg.type.includeSubclasses) {
2586
2616
  arg1IncludesSubclasses = true;
2587
2617
  }
2618
+ if (arg0Type) {
2619
+ this._validateUnsafeProtocolOverlap(node.arguments[0].valueExpression, (0, typeUtils_1.convertToInstance)(typeArg.type), isInstanceCheck ? arg0Type : (0, typeUtils_1.convertToInstance)(arg0Type));
2620
+ }
2588
2621
  }
2589
2622
  else {
2590
2623
  isValidType = false;
@@ -2698,6 +2731,29 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
2698
2731
  }), node);
2699
2732
  }
2700
2733
  }
2734
+ _validateUnsafeProtocolOverlap(errorNode, protocol, testType) {
2735
+ // If this is a protocol class, check for an "unsafe overlap"
2736
+ // with the arg0 type.
2737
+ if (types_1.ClassType.isProtocolClass(protocol)) {
2738
+ let isUnsafeOverlap = false;
2739
+ const diag = new diagnostic_1.DiagnosticAddendum();
2740
+ (0, typeUtils_1.doForEachSubtype)(testType, (testSubtype) => {
2741
+ if ((0, types_1.isClassInstance)(testSubtype)) {
2742
+ if ((0, protocols_1.isProtocolUnsafeOverlap)(this._evaluator, protocol, testSubtype)) {
2743
+ isUnsafeOverlap = true;
2744
+ diag.addMessage(localize_1.Localizer.DiagnosticAddendum.protocolUnsafeOverlap().format({
2745
+ name: testSubtype.details.name,
2746
+ }));
2747
+ }
2748
+ }
2749
+ });
2750
+ if (isUnsafeOverlap) {
2751
+ this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.protocolUnsafeOverlap().format({
2752
+ name: protocol.details.name,
2753
+ }) + diag.getString(), errorNode);
2754
+ }
2755
+ }
2756
+ }
2701
2757
  // Determines whether the specified type is allowed as the second argument
2702
2758
  // to an isinstance or issubclass check.
2703
2759
  _isTypeSupportedTypeForIsInstance(type, isInstanceCheck, diag) {
@@ -2715,6 +2771,10 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
2715
2771
  diag.addMessage(localize_1.Localizer.DiagnosticAddendum.noneNotAllowed());
2716
2772
  isSupported = false;
2717
2773
  }
2774
+ else if (types_1.ClassType.isTypedDictClass(subtype)) {
2775
+ diag.addMessage(localize_1.Localizer.DiagnosticAddendum.typedDictClassNotAllowed());
2776
+ isSupported = false;
2777
+ }
2718
2778
  else if (subtype.isTypeArgumentExplicit && !subtype.includeSubclasses) {
2719
2779
  // If it's a class, make sure that it has not been given explicit
2720
2780
  // type arguments. This will result in a TypeError exception.
@@ -2730,6 +2790,10 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
2730
2790
  diag.addMessage(localize_1.Localizer.DiagnosticAddendum.protocolRequiresRuntimeCheckable());
2731
2791
  isSupported = false;
2732
2792
  }
2793
+ else if (types_1.ClassType.isNewTypeClass(subtype)) {
2794
+ diag.addMessage(localize_1.Localizer.DiagnosticAddendum.newTypeClassNotAllowed());
2795
+ isSupported = false;
2796
+ }
2733
2797
  break;
2734
2798
  case 4 /* TypeCategory.Function */:
2735
2799
  if (!types_1.TypeBase.isInstantiable(subtype) || subtype.isCallableWithTypeArgs) {
@@ -3782,11 +3846,11 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
3782
3846
  if (!this._evaluator.assignType(newMemberType, initMemberType,
3783
3847
  /* diag */ undefined,
3784
3848
  /* destTypeVarContext */ undefined,
3785
- /* srcTypeVarContext */ undefined, 32 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */) ||
3849
+ /* srcTypeVarContext */ undefined, 64 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */) ||
3786
3850
  !this._evaluator.assignType(initMemberType, newMemberType,
3787
3851
  /* diag */ undefined,
3788
3852
  /* destTypeVarContext */ undefined,
3789
- /* srcTypeVarContext */ undefined, 32 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */)) {
3853
+ /* srcTypeVarContext */ undefined, 64 /* AssignTypeFlags.SkipFunctionReturnTypeCheck */)) {
3790
3854
  const displayOnInit = types_1.ClassType.isSameGenericClass(initMethodResult.classType, classType);
3791
3855
  const initDecl = initMemberType.details.declaration;
3792
3856
  const newDecl = newMemberType.details.declaration;
@@ -4078,6 +4142,51 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4078
4142
  }), overrideDecl.uri, overrideDecl.range);
4079
4143
  }
4080
4144
  }
4145
+ // Validates that any overloaded methods are consistent in how they
4146
+ // are decorated. For example, if the first overload is not marked @final
4147
+ // but subsequent ones are, an error should be reported.
4148
+ _validateOverloadDecoratorConsistency(classType) {
4149
+ classType.details.fields.forEach((symbol, name) => {
4150
+ const primaryDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(symbol);
4151
+ if (!primaryDecl || primaryDecl.type !== 5 /* DeclarationType.Function */) {
4152
+ return;
4153
+ }
4154
+ const typeOfSymbol = this._evaluator.getEffectiveTypeOfSymbol(symbol);
4155
+ if (!(0, types_1.isOverloadedFunction)(typeOfSymbol)) {
4156
+ return;
4157
+ }
4158
+ const overloads = types_1.OverloadedFunctionType.getOverloads(typeOfSymbol);
4159
+ // If there's an implementation, it will determine whether the
4160
+ // function is @final.
4161
+ const implementation = types_1.OverloadedFunctionType.getImplementation(typeOfSymbol);
4162
+ if (implementation) {
4163
+ // If one or more of the overloads is marked @final but the
4164
+ // implementation is not, report an error.
4165
+ if (!types_1.FunctionType.isFinal(implementation)) {
4166
+ overloads.forEach((overload) => {
4167
+ var _a, _b;
4168
+ if (types_1.FunctionType.isFinal(overload) && ((_a = overload.details.declaration) === null || _a === void 0 ? void 0 : _a.node)) {
4169
+ this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.overloadFinalInconsistencyImpl().format({
4170
+ name: overload.details.name,
4171
+ }), (_b = (0, declarationUtils_1.getNameNodeForDeclaration)(overload.details.declaration)) !== null && _b !== void 0 ? _b : overload.details.declaration.node);
4172
+ }
4173
+ });
4174
+ }
4175
+ return;
4176
+ }
4177
+ if (!types_1.FunctionType.isFinal(overloads[0])) {
4178
+ overloads.slice(1).forEach((overload, index) => {
4179
+ var _a, _b;
4180
+ if (types_1.FunctionType.isFinal(overload) && ((_a = overload.details.declaration) === null || _a === void 0 ? void 0 : _a.node)) {
4181
+ this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.overloadFinalInconsistencyNoImpl().format({
4182
+ name: overload.details.name,
4183
+ index: index + 2,
4184
+ }), (_b = (0, declarationUtils_1.getNameNodeForDeclaration)(overload.details.declaration)) !== null && _b !== void 0 ? _b : overload.details.declaration.node);
4185
+ }
4186
+ });
4187
+ }
4188
+ });
4189
+ }
4081
4190
  // Validates that any overridden methods or variables contain the same
4082
4191
  // types as the original method. Also marks the class as abstract if one
4083
4192
  // or more abstract methods are not overridden.
@@ -4150,7 +4259,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4150
4259
  return;
4151
4260
  }
4152
4261
  // Constructors are exempt.
4153
- if (overrideFunction.details.name === '__init__' || overrideFunction.details.name === '__new__') {
4262
+ if (this._isMethodExemptFromLsp(overrideFunction.details.name)) {
4154
4263
  return;
4155
4264
  }
4156
4265
  // If the declaration for the override function is not the same as the
@@ -4164,6 +4273,11 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4164
4273
  className: this._evaluator.printType((0, typeUtils_1.convertToInstance)(baseMember.classType)),
4165
4274
  }), funcNode.name);
4166
4275
  }
4276
+ // Determines whether the name is exempt from Liskov Substitution Principle rules.
4277
+ _isMethodExemptFromLsp(name) {
4278
+ const exemptMethods = ['__init__', '__new__', '__init_subclass__', '__post_init__'];
4279
+ return exemptMethods.some((n) => n === name);
4280
+ }
4167
4281
  // Determines whether the type is a function or overloaded function with an @override
4168
4282
  // decorator. In this case, an error is reported because no base class has declared
4169
4283
  // a method of the same name.
@@ -4192,7 +4306,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4192
4306
  this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.overriddenMethodNotFound().format({ name: funcNode.name.value }), funcNode.name);
4193
4307
  }
4194
4308
  _validateBaseClassOverride(baseClassAndSymbol, overrideSymbol, overrideType, childClassType, memberName) {
4195
- var _a, _b;
4309
+ var _a, _b, _c, _d, _e, _f, _g, _h;
4196
4310
  if (!(0, types_1.isInstantiableClass)(baseClassAndSymbol.classType)) {
4197
4311
  return;
4198
4312
  }
@@ -4216,8 +4330,32 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4216
4330
  overrideType = (0, typeUtils_1.partiallySpecializeType)(overrideType, childClassType, childClassSelf);
4217
4331
  if ((0, types_1.isFunction)(baseType) || (0, types_1.isOverloadedFunction)(baseType)) {
4218
4332
  const diagAddendum = new diagnostic_1.DiagnosticAddendum();
4333
+ // Determine whether this is an attempt to override a method marked @final.
4334
+ let reportFinalMethodOverride = false;
4335
+ // Private names (starting with double underscore) are exempt from this check.
4336
+ if (!SymbolNameUtils.isPrivateName(memberName)) {
4337
+ if ((0, types_1.isFunction)(baseType) && types_1.FunctionType.isFinal(baseType)) {
4338
+ reportFinalMethodOverride = true;
4339
+ }
4340
+ else if ((0, types_1.isOverloadedFunction)(baseType) &&
4341
+ baseType.overloads.some((overload) => types_1.FunctionType.isFinal(overload))) {
4342
+ reportFinalMethodOverride = true;
4343
+ }
4344
+ }
4345
+ if (reportFinalMethodOverride) {
4346
+ const decl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(overrideSymbol);
4347
+ if (decl && decl.type === 5 /* DeclarationType.Function */) {
4348
+ const diag = this._evaluator.addError(localize_1.Localizer.Diagnostic.finalMethodOverride().format({
4349
+ name: memberName,
4350
+ className: baseClass.details.name,
4351
+ }), decl.node.name);
4352
+ const origDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(baseClassAndSymbol.symbol);
4353
+ if (diag && origDecl) {
4354
+ diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.finalMethod(), origDecl.uri, origDecl.range);
4355
+ }
4356
+ }
4357
+ }
4219
4358
  if ((0, types_1.isFunction)(overrideType) || (0, types_1.isOverloadedFunction)(overrideType)) {
4220
- const exemptMethods = ['__init__', '__new__', '__init_subclass__'];
4221
4359
  // Don't enforce parameter names for dundered methods. Many of them
4222
4360
  // are misnamed in typeshed stubs, so this would result in many
4223
4361
  // false positives.
@@ -4226,7 +4364,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4226
4364
  // Also, skip this check if the class is a TypedDict. The methods for a TypedDict
4227
4365
  // are synthesized, and they can result in many overloads. We assume they
4228
4366
  // are correct and will not produce any errors.
4229
- if (!exemptMethods.some((exempt) => exempt === memberName) &&
4367
+ if (!this._isMethodExemptFromLsp(memberName) &&
4230
4368
  !SymbolNameUtils.isPrivateName(memberName) &&
4231
4369
  !types_1.ClassType.isTypedDictClass(childClassType)) {
4232
4370
  if (!this._evaluator.validateOverrideMethod(baseType, overrideType, childClassType, diagAddendum, enforceParamNameMatch)) {
@@ -4237,7 +4375,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4237
4375
  const diag = this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportIncompatibleMethodOverride, diagnosticRules_1.DiagnosticRule.reportIncompatibleMethodOverride, localize_1.Localizer.Diagnostic.incompatibleMethodOverride().format({
4238
4376
  name: memberName,
4239
4377
  className: baseClass.details.name,
4240
- }) + diagAddendum.getString(), decl.type === 5 /* DeclarationType.Function */ ? decl.node.name : decl.node);
4378
+ }) + diagAddendum.getString(), (_a = (0, declarationUtils_1.getNameNodeForDeclaration)(decl)) !== null && _a !== void 0 ? _a : decl.node);
4241
4379
  const origDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(baseClassAndSymbol.symbol);
4242
4380
  if (diag && origDecl) {
4243
4381
  diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.overriddenMethod(), origDecl.uri, origDecl.range);
@@ -4245,22 +4383,6 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4245
4383
  }
4246
4384
  }
4247
4385
  }
4248
- if ((0, types_1.isFunction)(baseType)) {
4249
- // Private names (starting with double underscore) are exempt from this check.
4250
- if (!SymbolNameUtils.isPrivateName(memberName) && types_1.FunctionType.isFinal(baseType)) {
4251
- const decl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(overrideSymbol);
4252
- if (decl && decl.type === 5 /* DeclarationType.Function */) {
4253
- const diag = this._evaluator.addError(localize_1.Localizer.Diagnostic.finalMethodOverride().format({
4254
- name: memberName,
4255
- className: baseClass.details.name,
4256
- }), decl.node.name);
4257
- const origDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(baseClassAndSymbol.symbol);
4258
- if (diag && origDecl) {
4259
- diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.finalMethod(), origDecl.uri, origDecl.range);
4260
- }
4261
- }
4262
- }
4263
- }
4264
4386
  }
4265
4387
  else if (!(0, types_1.isAnyOrUnknown)(overrideType)) {
4266
4388
  // Special-case overrides of methods in '_TypedDict', since
@@ -4274,7 +4396,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4274
4396
  name: memberName,
4275
4397
  className: baseClass.details.name,
4276
4398
  type: this._evaluator.printType(overrideType),
4277
- }), lastDecl.node);
4399
+ }), (_b = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _b !== void 0 ? _b : lastDecl.node);
4278
4400
  const origDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(baseClassAndSymbol.symbol);
4279
4401
  if (diag && origDecl) {
4280
4402
  diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.overriddenMethod(), origDecl.uri, origDecl.range);
@@ -4288,10 +4410,11 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4288
4410
  if (!(0, typeUtils_1.isProperty)(overrideType)) {
4289
4411
  const decls = overrideSymbol.getDeclarations();
4290
4412
  if (decls.length > 0) {
4413
+ const lastDecl = decls[decls.length - 1];
4291
4414
  this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportIncompatibleMethodOverride, diagnosticRules_1.DiagnosticRule.reportIncompatibleMethodOverride, localize_1.Localizer.Diagnostic.propertyOverridden().format({
4292
4415
  name: memberName,
4293
4416
  className: baseClass.details.name,
4294
- }), decls[decls.length - 1].node);
4417
+ }), (_c = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _c !== void 0 ? _c : lastDecl.node);
4295
4418
  }
4296
4419
  }
4297
4420
  else {
@@ -4302,6 +4425,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4302
4425
  ['fdel', (c) => { var _a; return (_a = c.fdelInfo) === null || _a === void 0 ? void 0 : _a.methodType; }],
4303
4426
  ];
4304
4427
  propMethodInfo.forEach((info) => {
4428
+ var _a;
4305
4429
  const diagAddendum = new diagnostic_1.DiagnosticAddendum();
4306
4430
  const [methodName, methodAccessor] = info;
4307
4431
  const baseClassPropMethod = methodAccessor(baseType);
@@ -4317,10 +4441,11 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4317
4441
  }));
4318
4442
  const decls = overrideSymbol.getDeclarations();
4319
4443
  if (decls.length > 0) {
4444
+ const lastDecl = decls[decls.length - 1];
4320
4445
  const diag = this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportIncompatibleMethodOverride, diagnosticRules_1.DiagnosticRule.reportIncompatibleMethodOverride, localize_1.Localizer.Diagnostic.propertyOverridden().format({
4321
4446
  name: memberName,
4322
4447
  className: baseClassType.details.name,
4323
- }) + diagAddendum.getString(), decls[decls.length - 1].node);
4448
+ }) + diagAddendum.getString(), (_a = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _a !== void 0 ? _a : lastDecl.node);
4324
4449
  const origDecl = baseClassMethodType.details.declaration;
4325
4450
  if (diag && origDecl) {
4326
4451
  diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.overriddenMethod(), origDecl.uri, origDecl.range);
@@ -4398,7 +4523,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4398
4523
  const diag = this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportIncompatibleVariableOverride, diagnosticRules_1.DiagnosticRule.reportIncompatibleVariableOverride, localize_1.Localizer.Diagnostic.symbolOverridden().format({
4399
4524
  name: memberName,
4400
4525
  className: baseClass.details.name,
4401
- }) + diagAddendum.getString(), (_a = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _a !== void 0 ? _a : lastDecl.node);
4526
+ }) + diagAddendum.getString(), (_d = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _d !== void 0 ? _d : lastDecl.node);
4402
4527
  const origDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(baseClassAndSymbol.symbol);
4403
4528
  if (diag && origDecl) {
4404
4529
  diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.overriddenSymbol(), origDecl.uri, origDecl.range);
@@ -4419,14 +4544,14 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4419
4544
  const message = overrideTDEntry.isRequired
4420
4545
  ? localize_1.Localizer.Diagnostic.typedDictFieldRequiredRedefinition
4421
4546
  : localize_1.Localizer.Diagnostic.typedDictFieldNotRequiredRedefinition;
4422
- this._evaluator.addDiagnostic(AnalyzerNodeInfo.getFileInfo(lastDecl.node).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, message().format({ name: memberName }), lastDecl.node);
4547
+ this._evaluator.addDiagnostic(AnalyzerNodeInfo.getFileInfo(lastDecl.node).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, message().format({ name: memberName }), (_e = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _e !== void 0 ? _e : lastDecl.node);
4423
4548
  }
4424
4549
  // Make sure that the derived class isn't marking a previously writable
4425
4550
  // entry as read-only.
4426
4551
  if (!overriddenTDEntry.isReadOnly && overrideTDEntry.isReadOnly) {
4427
4552
  this._evaluator.addDiagnostic(AnalyzerNodeInfo.getFileInfo(lastDecl.node).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typedDictFieldReadOnlyRedefinition().format({
4428
4553
  name: memberName,
4429
- }), lastDecl.node);
4554
+ }), (_f = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _f !== void 0 ? _f : lastDecl.node);
4430
4555
  }
4431
4556
  }
4432
4557
  // Verify that there is not a Final mismatch.
@@ -4436,7 +4561,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4436
4561
  const diag = this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportIncompatibleVariableOverride, diagnosticRules_1.DiagnosticRule.reportIncompatibleVariableOverride, localize_1.Localizer.Diagnostic.variableFinalOverride().format({
4437
4562
  name: memberName,
4438
4563
  className: baseClass.details.name,
4439
- }), lastDecl.node);
4564
+ }), (_g = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _g !== void 0 ? _g : lastDecl.node);
4440
4565
  if (diag) {
4441
4566
  diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.overriddenSymbol(), overrideFinalVarDecl.uri, overrideFinalVarDecl.range);
4442
4567
  }
@@ -4465,7 +4590,7 @@ class Checker extends parseTreeWalker_1.ParseTreeWalker {
4465
4590
  const diag = this._evaluator.addDiagnostic(this._fileInfo.diagnosticRuleSet.reportIncompatibleVariableOverride, diagnosticRules_1.DiagnosticRule.reportIncompatibleVariableOverride, unformattedMessage.format({
4466
4591
  name: memberName,
4467
4592
  className: baseClass.details.name,
4468
- }), (_b = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _b !== void 0 ? _b : lastDecl.node);
4593
+ }), (_h = (0, declarationUtils_1.getNameNodeForDeclaration)(lastDecl)) !== null && _h !== void 0 ? _h : lastDecl.node);
4469
4594
  const origDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(baseClassAndSymbol.symbol);
4470
4595
  if (diag && origDecl) {
4471
4596
  diag.addRelatedInfo(localize_1.Localizer.DiagnosticAddendum.overriddenSymbol(), origDecl.uri, origDecl.range);