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

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 (231) hide show
  1. package/dist/analyzer/backgroundAnalysisProgram.d.ts +4 -1
  2. package/dist/analyzer/backgroundAnalysisProgram.js +12 -0
  3. package/dist/analyzer/backgroundAnalysisProgram.js.map +1 -1
  4. package/dist/analyzer/checker.d.ts +1 -0
  5. package/dist/analyzer/checker.js +89 -6
  6. package/dist/analyzer/checker.js.map +1 -1
  7. package/dist/analyzer/constraintSolver.js +14 -15
  8. package/dist/analyzer/constraintSolver.js.map +1 -1
  9. package/dist/analyzer/constructors.d.ts +6 -0
  10. package/dist/analyzer/constructors.js +513 -0
  11. package/dist/analyzer/constructors.js.map +1 -0
  12. package/dist/analyzer/dataClasses.js +86 -2
  13. package/dist/analyzer/dataClasses.js.map +1 -1
  14. package/dist/analyzer/docStringConversion.js +1 -1
  15. package/dist/analyzer/docStringConversion.js.map +1 -1
  16. package/dist/analyzer/enums.js +62 -8
  17. package/dist/analyzer/enums.js.map +1 -1
  18. package/dist/analyzer/importResolver.js +47 -29
  19. package/dist/analyzer/importResolver.js.map +1 -1
  20. package/dist/analyzer/importStatementUtils.d.ts +2 -2
  21. package/dist/analyzer/importStatementUtils.js.map +1 -1
  22. package/dist/analyzer/namedTuples.js +3 -6
  23. package/dist/analyzer/namedTuples.js.map +1 -1
  24. package/dist/analyzer/operations.d.ts +16 -0
  25. package/dist/analyzer/operations.js +749 -0
  26. package/dist/analyzer/operations.js.map +1 -0
  27. package/dist/analyzer/parseTreeUtils.d.ts +4 -2
  28. package/dist/analyzer/parseTreeUtils.js +32 -1
  29. package/dist/analyzer/parseTreeUtils.js.map +1 -1
  30. package/dist/analyzer/patternMatching.js +16 -0
  31. package/dist/analyzer/patternMatching.js.map +1 -1
  32. package/dist/analyzer/program.d.ts +11 -33
  33. package/dist/analyzer/program.js +73 -735
  34. package/dist/analyzer/program.js.map +1 -1
  35. package/dist/analyzer/protocols.js +1 -1
  36. package/dist/analyzer/protocols.js.map +1 -1
  37. package/dist/analyzer/service.d.ts +5 -21
  38. package/dist/analyzer/service.js +26 -33
  39. package/dist/analyzer/service.js.map +1 -1
  40. package/dist/analyzer/sourceFile.d.ts +9 -41
  41. package/dist/analyzer/sourceFile.js +219 -238
  42. package/dist/analyzer/sourceFile.js.map +1 -1
  43. package/dist/analyzer/sourceFileInfoUtils.d.ts +3 -9
  44. package/dist/analyzer/sourceFileInfoUtils.js.map +1 -1
  45. package/dist/analyzer/symbol.d.ts +3 -1
  46. package/dist/analyzer/symbol.js +5 -0
  47. package/dist/analyzer/symbol.js.map +1 -1
  48. package/dist/analyzer/typeEvaluator.js +460 -1425
  49. package/dist/analyzer/typeEvaluator.js.map +1 -1
  50. package/dist/analyzer/typeEvaluatorTypes.d.ts +42 -7
  51. package/dist/analyzer/typeEvaluatorTypes.js +33 -1
  52. package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
  53. package/dist/analyzer/typeGuards.js +2 -8
  54. package/dist/analyzer/typeGuards.js.map +1 -1
  55. package/dist/analyzer/typePrinter.d.ts +3 -3
  56. package/dist/analyzer/typePrinter.js +247 -100
  57. package/dist/analyzer/typePrinter.js.map +1 -1
  58. package/dist/analyzer/typeUtils.d.ts +14 -7
  59. package/dist/analyzer/typeUtils.js +204 -49
  60. package/dist/analyzer/typeUtils.js.map +1 -1
  61. package/dist/analyzer/typeVarContext.d.ts +6 -7
  62. package/dist/analyzer/typeVarContext.js +21 -32
  63. package/dist/analyzer/typeVarContext.js.map +1 -1
  64. package/dist/analyzer/typedDicts.js +2 -2
  65. package/dist/analyzer/typedDicts.js.map +1 -1
  66. package/dist/analyzer/types.d.ts +7 -4
  67. package/dist/analyzer/types.js +20 -10
  68. package/dist/analyzer/types.js.map +1 -1
  69. package/dist/backgroundAnalysisBase.d.ts +1 -1
  70. package/dist/backgroundAnalysisBase.js +16 -0
  71. package/dist/backgroundAnalysisBase.js.map +1 -1
  72. package/dist/commands/dumpFileDebugInfoCommand.js +0 -1
  73. package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
  74. package/dist/common/extensibility.d.ts +28 -4
  75. package/dist/common/extensibility.js.map +1 -1
  76. package/dist/common/logTracker.d.ts +2 -0
  77. package/dist/common/logTracker.js +8 -1
  78. package/dist/common/logTracker.js.map +1 -1
  79. package/dist/common/lspUtils.d.ts +4 -1
  80. package/dist/common/lspUtils.js +38 -1
  81. package/dist/common/lspUtils.js.map +1 -1
  82. package/dist/common/pathUtils.d.ts +11 -11
  83. package/dist/common/pathUtils.js.map +1 -1
  84. package/dist/common/pythonVersion.d.ts +2 -1
  85. package/dist/common/pythonVersion.js +1 -0
  86. package/dist/common/pythonVersion.js.map +1 -1
  87. package/dist/common/workspaceEditUtils.d.ts +8 -8
  88. package/dist/common/workspaceEditUtils.js +10 -10
  89. package/dist/common/workspaceEditUtils.js.map +1 -1
  90. package/dist/languageServerBase.d.ts +3 -7
  91. package/dist/languageServerBase.js +41 -73
  92. package/dist/languageServerBase.js.map +1 -1
  93. package/dist/languageService/autoImporter.d.ts +50 -51
  94. package/dist/languageService/autoImporter.js +125 -210
  95. package/dist/languageService/autoImporter.js.map +1 -1
  96. package/dist/languageService/callHierarchyProvider.d.ts +1 -1
  97. package/dist/languageService/callHierarchyProvider.js +11 -37
  98. package/dist/languageService/callHierarchyProvider.js.map +1 -1
  99. package/dist/languageService/completionProvider.d.ts +39 -81
  100. package/dist/languageService/completionProvider.js +572 -801
  101. package/dist/languageService/completionProvider.js.map +1 -1
  102. package/dist/languageService/documentHighlightProvider.js +1 -1
  103. package/dist/languageService/documentHighlightProvider.js.map +1 -1
  104. package/dist/languageService/documentSymbolCollector.d.ts +6 -7
  105. package/dist/languageService/documentSymbolCollector.js +47 -28
  106. package/dist/languageService/documentSymbolCollector.js.map +1 -1
  107. package/dist/languageService/documentSymbolProvider.d.ts +13 -35
  108. package/dist/languageService/documentSymbolProvider.js +52 -264
  109. package/dist/languageService/documentSymbolProvider.js.map +1 -1
  110. package/dist/languageService/hoverProvider.d.ts +5 -6
  111. package/dist/languageService/hoverProvider.js +40 -132
  112. package/dist/languageService/hoverProvider.js.map +1 -1
  113. package/dist/languageService/referencesProvider.d.ts +6 -11
  114. package/dist/languageService/referencesProvider.js +23 -17
  115. package/dist/languageService/referencesProvider.js.map +1 -1
  116. package/dist/languageService/renameProvider.d.ts +16 -0
  117. package/dist/languageService/renameProvider.js +139 -0
  118. package/dist/languageService/renameProvider.js.map +1 -0
  119. package/dist/languageService/symbolIndexer.d.ts +31 -0
  120. package/dist/languageService/symbolIndexer.js +105 -0
  121. package/dist/languageService/symbolIndexer.js.map +1 -0
  122. package/dist/languageService/tooltipUtils.d.ts +8 -1
  123. package/dist/languageService/tooltipUtils.js +102 -1
  124. package/dist/languageService/tooltipUtils.js.map +1 -1
  125. package/dist/languageService/workspaceSymbolProvider.d.ts +17 -0
  126. package/dist/languageService/workspaceSymbolProvider.js +133 -0
  127. package/dist/languageService/workspaceSymbolProvider.js.map +1 -0
  128. package/dist/localization/localize.d.ts +33 -15
  129. package/dist/localization/localize.js +13 -7
  130. package/dist/localization/localize.js.map +1 -1
  131. package/dist/localization/package.nls.en-us.json +14 -7
  132. package/dist/parser/parser.js +3 -0
  133. package/dist/parser/parser.js.map +1 -1
  134. package/dist/pyright.js +26 -4
  135. package/dist/pyright.js.map +1 -1
  136. package/dist/tests/chainedSourceFiles.test.js +15 -20
  137. package/dist/tests/chainedSourceFiles.test.js.map +1 -1
  138. package/dist/tests/checker.test.js +14 -0
  139. package/dist/tests/checker.test.js.map +1 -1
  140. package/dist/tests/completions.test.js +11 -236
  141. package/dist/tests/completions.test.js.map +1 -1
  142. package/dist/tests/docStringConversion.test.js +36 -2
  143. package/dist/tests/docStringConversion.test.js.map +1 -1
  144. package/dist/tests/documentSymbolCollector.test.js +3 -3
  145. package/dist/tests/documentSymbolCollector.test.js.map +1 -1
  146. package/dist/tests/fourslash/completions.override2.fourslash.js +1 -16
  147. package/dist/tests/fourslash/completions.override2.fourslash.js.map +1 -1
  148. package/dist/tests/fourslash/fourslash.d.ts +4 -4
  149. package/dist/tests/fourslash/missingTypeStub.codeAction.fourslash.js +1 -1
  150. package/dist/tests/fourslash/missingTypeStub.codeAction.fourslash.js.map +1 -1
  151. package/dist/tests/harness/fourslash/testState.d.ts +17 -11
  152. package/dist/tests/harness/fourslash/testState.js +39 -50
  153. package/dist/tests/harness/fourslash/testState.js.map +1 -1
  154. package/dist/tests/importResolver.test.js +81 -1
  155. package/dist/tests/importResolver.test.js.map +1 -1
  156. package/dist/tests/sourceFile.test.js +1 -1
  157. package/dist/tests/sourceFile.test.js.map +1 -1
  158. package/dist/tests/testStateUtils.d.ts +2 -2
  159. package/dist/tests/testStateUtils.js +38 -8
  160. package/dist/tests/testStateUtils.js.map +1 -1
  161. package/dist/tests/typeEvaluator2.test.js +13 -1
  162. package/dist/tests/typeEvaluator2.test.js.map +1 -1
  163. package/dist/tests/typeEvaluator3.test.js +5 -1
  164. package/dist/tests/typeEvaluator3.test.js.map +1 -1
  165. package/dist/tests/typeEvaluator4.test.js +9 -1
  166. package/dist/tests/typeEvaluator4.test.js.map +1 -1
  167. package/dist/tests/typeEvaluator5.test.js +25 -9
  168. package/dist/tests/typeEvaluator5.test.js.map +1 -1
  169. package/dist/tests/workspaceEditUtils.test.js +95 -6
  170. package/dist/tests/workspaceEditUtils.test.js.map +1 -1
  171. package/package.json +4 -4
  172. package/dist/languageService/importAdder.d.ts +0 -40
  173. package/dist/languageService/importAdder.js +0 -388
  174. package/dist/languageService/importAdder.js.map +0 -1
  175. package/dist/languageService/indentationUtils.d.ts +0 -16
  176. package/dist/languageService/indentationUtils.js +0 -727
  177. package/dist/languageService/indentationUtils.js.map +0 -1
  178. package/dist/languageService/insertionPointUtils.d.ts +0 -9
  179. package/dist/languageService/insertionPointUtils.js +0 -132
  180. package/dist/languageService/insertionPointUtils.js.map +0 -1
  181. package/dist/languageService/renameModuleProvider.d.ts +0 -65
  182. package/dist/languageService/renameModuleProvider.js +0 -939
  183. package/dist/languageService/renameModuleProvider.js.map +0 -1
  184. package/dist/tests/fourslash/completions.commitChars.fourslash.d.ts +0 -1
  185. package/dist/tests/fourslash/completions.commitChars.fourslash.js +0 -81
  186. package/dist/tests/fourslash/completions.commitChars.fourslash.js.map +0 -1
  187. package/dist/tests/importAdder.test.d.ts +0 -1
  188. package/dist/tests/importAdder.test.js +0 -1325
  189. package/dist/tests/importAdder.test.js.map +0 -1
  190. package/dist/tests/indentationUtils.ptvs.test.d.ts +0 -1
  191. package/dist/tests/indentationUtils.ptvs.test.js +0 -324
  192. package/dist/tests/indentationUtils.ptvs.test.js.map +0 -1
  193. package/dist/tests/indentationUtils.reindent.test.d.ts +0 -1
  194. package/dist/tests/indentationUtils.reindent.test.js +0 -372
  195. package/dist/tests/indentationUtils.reindent.test.js.map +0 -1
  196. package/dist/tests/indentationUtils.test.d.ts +0 -1
  197. package/dist/tests/indentationUtils.test.js +0 -502
  198. package/dist/tests/indentationUtils.test.js.map +0 -1
  199. package/dist/tests/insertionPointUtils.test.d.ts +0 -1
  200. package/dist/tests/insertionPointUtils.test.js +0 -154
  201. package/dist/tests/insertionPointUtils.test.js.map +0 -1
  202. package/dist/tests/moveSymbol.importAdder.test.d.ts +0 -1
  203. package/dist/tests/moveSymbol.importAdder.test.js +0 -298
  204. package/dist/tests/moveSymbol.importAdder.test.js.map +0 -1
  205. package/dist/tests/moveSymbol.insertion.test.d.ts +0 -1
  206. package/dist/tests/moveSymbol.insertion.test.js +0 -537
  207. package/dist/tests/moveSymbol.insertion.test.js.map +0 -1
  208. package/dist/tests/moveSymbol.misc.test.d.ts +0 -1
  209. package/dist/tests/moveSymbol.misc.test.js +0 -169
  210. package/dist/tests/moveSymbol.misc.test.js.map +0 -1
  211. package/dist/tests/moveSymbol.updateReference.test.d.ts +0 -1
  212. package/dist/tests/moveSymbol.updateReference.test.js +0 -1071
  213. package/dist/tests/moveSymbol.updateReference.test.js.map +0 -1
  214. package/dist/tests/renameModule.folder.test.d.ts +0 -1
  215. package/dist/tests/renameModule.folder.test.js +0 -229
  216. package/dist/tests/renameModule.folder.test.js.map +0 -1
  217. package/dist/tests/renameModule.fromImports.test.d.ts +0 -1
  218. package/dist/tests/renameModule.fromImports.test.js +0 -790
  219. package/dist/tests/renameModule.fromImports.test.js.map +0 -1
  220. package/dist/tests/renameModule.imports.test.d.ts +0 -1
  221. package/dist/tests/renameModule.imports.test.js +0 -380
  222. package/dist/tests/renameModule.imports.test.js.map +0 -1
  223. package/dist/tests/renameModule.misc.test.d.ts +0 -1
  224. package/dist/tests/renameModule.misc.test.js +0 -615
  225. package/dist/tests/renameModule.misc.test.js.map +0 -1
  226. package/dist/tests/renameModule.relativePath.test.d.ts +0 -1
  227. package/dist/tests/renameModule.relativePath.test.js +0 -231
  228. package/dist/tests/renameModule.relativePath.test.js.map +0 -1
  229. package/dist/tests/renameModuleTestUtils.d.ts +0 -4
  230. package/dist/tests/renameModuleTestUtils.js +0 -76
  231. package/dist/tests/renameModuleTestUtils.js.map +0 -1
@@ -0,0 +1,749 @@
1
+ "use strict";
2
+ /*
3
+ * operations.ts
4
+ * Copyright (c) Microsoft Corporation.
5
+ * Licensed under the MIT license.
6
+ * Author: Eric Traut
7
+ *
8
+ * Provides type evaluation logic for unary, binary, augmented assignment,
9
+ * and ternary operators.
10
+ */
11
+ Object.defineProperty(exports, "__esModule", { value: true });
12
+ exports.getTypeOfTernaryOperation = exports.getTypeOfUnaryOperation = exports.getTypeOfAugmentedAssignment = exports.getTypeOfBinaryOperation = exports.validateBinaryOperation = void 0;
13
+ const diagnostic_1 = require("../common/diagnostic");
14
+ const diagnosticRules_1 = require("../common/diagnosticRules");
15
+ const pythonVersion_1 = require("../common/pythonVersion");
16
+ const localize_1 = require("../localization/localize");
17
+ const analyzerNodeInfo_1 = require("./analyzerNodeInfo");
18
+ const parseTreeUtils_1 = require("./parseTreeUtils");
19
+ const staticExpressions_1 = require("./staticExpressions");
20
+ const typeUtils_1 = require("./typeUtils");
21
+ const types_1 = require("./types");
22
+ // Maps binary operators to the magic methods that implement them.
23
+ const binaryOperatorMap = {
24
+ [0 /* Add */]: ['__add__', '__radd__'],
25
+ [33 /* Subtract */]: ['__sub__', '__rsub__'],
26
+ [26 /* Multiply */]: ['__mul__', '__rmul__'],
27
+ [13 /* FloorDivide */]: ['__floordiv__', '__rfloordiv__'],
28
+ [10 /* Divide */]: ['__truediv__', '__rtruediv__'],
29
+ [24 /* Mod */]: ['__mod__', '__rmod__'],
30
+ [29 /* Power */]: ['__pow__', '__rpow__'],
31
+ [22 /* MatrixMultiply */]: ['__matmul__', '__rmatmul__'],
32
+ [3 /* BitwiseAnd */]: ['__and__', '__rand__'],
33
+ [6 /* BitwiseOr */]: ['__or__', '__ror__'],
34
+ [8 /* BitwiseXor */]: ['__xor__', '__rxor__'],
35
+ [17 /* LeftShift */]: ['__lshift__', '__rlshift__'],
36
+ [31 /* RightShift */]: ['__rshift__', '__rrshift__'],
37
+ [12 /* Equals */]: ['__eq__', '__eq__'],
38
+ [28 /* NotEquals */]: ['__ne__', '__ne__'],
39
+ [20 /* LessThan */]: ['__lt__', '__gt__'],
40
+ [21 /* LessThanOrEqual */]: ['__le__', '__ge__'],
41
+ [15 /* GreaterThan */]: ['__gt__', '__lt__'],
42
+ [16 /* GreaterThanOrEqual */]: ['__ge__', '__le__'],
43
+ };
44
+ // Map of operators that always return a bool result.
45
+ const booleanOperatorMap = {
46
+ [36 /* And */]: true,
47
+ [37 /* Or */]: true,
48
+ [39 /* Is */]: true,
49
+ [40 /* IsNot */]: true,
50
+ [41 /* In */]: true,
51
+ [42 /* NotIn */]: true,
52
+ };
53
+ // If the number of subtypes starts to explode when applying "literal math",
54
+ // cut off the literal union and fall back to the non-literal supertype.
55
+ const maxLiteralMathSubtypeCount = 64;
56
+ function validateBinaryOperation(evaluator, operator, leftTypeResult, rightTypeResult, errorNode, inferenceContext, diag, options) {
57
+ const leftType = leftTypeResult.type;
58
+ const rightType = rightTypeResult.type;
59
+ let type;
60
+ let concreteLeftType = evaluator.makeTopLevelTypeVarsConcrete(leftType);
61
+ if (booleanOperatorMap[operator] !== undefined) {
62
+ // If it's an AND or OR, we need to handle short-circuiting by
63
+ // eliminating any known-truthy or known-falsy types.
64
+ if (operator === 36 /* And */) {
65
+ // If the LHS evaluates to falsy, the And expression will
66
+ // always return the type of the left-hand side.
67
+ if (!evaluator.canBeTruthy(concreteLeftType)) {
68
+ return leftType;
69
+ }
70
+ // If the LHS evaluates to truthy, the And expression will
71
+ // always return the type of the right-hand side.
72
+ if (!evaluator.canBeFalsy(concreteLeftType)) {
73
+ return rightType;
74
+ }
75
+ concreteLeftType = evaluator.removeTruthinessFromType(concreteLeftType);
76
+ if ((0, types_1.isNever)(rightType)) {
77
+ return concreteLeftType;
78
+ }
79
+ }
80
+ else if (operator === 37 /* Or */) {
81
+ // If the LHS evaluates to truthy, the Or expression will
82
+ // always return the type of the left-hand side.
83
+ if (!evaluator.canBeFalsy(concreteLeftType)) {
84
+ return leftType;
85
+ }
86
+ // If the LHS evaluates to falsy, the Or expression will
87
+ // always return the type of the right-hand side.
88
+ if (!evaluator.canBeTruthy(concreteLeftType)) {
89
+ return rightType;
90
+ }
91
+ concreteLeftType = evaluator.removeFalsinessFromType(concreteLeftType);
92
+ if ((0, types_1.isNever)(rightType)) {
93
+ return concreteLeftType;
94
+ }
95
+ }
96
+ if ((0, types_1.isNever)(leftType) || (0, types_1.isNever)(rightType)) {
97
+ return types_1.NeverType.createNever();
98
+ }
99
+ // The "in" and "not in" operators make use of the __contains__
100
+ // magic method.
101
+ if (operator === 41 /* In */ || operator === 42 /* NotIn */) {
102
+ type = evaluator.mapSubtypesExpandTypeVars(rightType,
103
+ /* conditionFilter */ undefined, (rightSubtypeExpanded, rightSubtypeUnexpanded) => {
104
+ return evaluator.mapSubtypesExpandTypeVars(concreteLeftType, (0, typeUtils_1.getTypeCondition)(rightSubtypeExpanded), (leftSubtype) => {
105
+ var _a;
106
+ if ((0, types_1.isAnyOrUnknown)(leftSubtype) || (0, types_1.isAnyOrUnknown)(rightSubtypeUnexpanded)) {
107
+ return (0, typeUtils_1.preserveUnknown)(leftSubtype, rightSubtypeExpanded);
108
+ }
109
+ let returnType = evaluator.getTypeOfMagicMethodReturn(rightSubtypeExpanded, [{ type: leftSubtype, isIncomplete: leftTypeResult.isIncomplete }], '__contains__', errorNode,
110
+ /* inferenceContext */ undefined);
111
+ if (!returnType) {
112
+ // If __contains__ was not supported, fall back
113
+ // on an iterable.
114
+ const iteratorType = (_a = evaluator.getTypeOfIterator({ type: rightSubtypeExpanded, isIncomplete: rightTypeResult.isIncomplete },
115
+ /* isAsync */ false,
116
+ /* errorNode */ undefined)) === null || _a === void 0 ? void 0 : _a.type;
117
+ if (iteratorType && evaluator.assignType(iteratorType, leftSubtype)) {
118
+ returnType = evaluator.getBuiltInObject(errorNode, 'bool');
119
+ }
120
+ }
121
+ if (!returnType) {
122
+ diag.addMessage(localize_1.Localizer.Diagnostic.typeNotSupportBinaryOperator().format({
123
+ operator: (0, parseTreeUtils_1.printOperator)(operator),
124
+ leftType: evaluator.printType(leftSubtype),
125
+ rightType: evaluator.printType(rightSubtypeExpanded),
126
+ }));
127
+ }
128
+ return returnType;
129
+ });
130
+ });
131
+ // Assume that a bool is returned even if the type is unknown
132
+ if (type && !(0, types_1.isNever)(type)) {
133
+ type = evaluator.getBuiltInObject(errorNode, 'bool');
134
+ }
135
+ }
136
+ else {
137
+ type = evaluator.mapSubtypesExpandTypeVars(concreteLeftType,
138
+ /* conditionFilter */ undefined, (leftSubtypeExpanded, leftSubtypeUnexpanded) => {
139
+ return evaluator.mapSubtypesExpandTypeVars(rightType, (0, typeUtils_1.getTypeCondition)(leftSubtypeExpanded), (rightSubtypeExpanded, rightSubtypeUnexpanded) => {
140
+ // If the operator is an AND or OR, we need to combine the two types.
141
+ if (operator === 36 /* And */ || operator === 37 /* Or */) {
142
+ return (0, types_1.combineTypes)([leftSubtypeUnexpanded, rightSubtypeUnexpanded]);
143
+ }
144
+ // The other boolean operators always return a bool value.
145
+ return evaluator.getBuiltInObject(errorNode, 'bool');
146
+ });
147
+ });
148
+ }
149
+ }
150
+ else if (binaryOperatorMap[operator]) {
151
+ if ((0, types_1.isNever)(leftType) || (0, types_1.isNever)(rightType)) {
152
+ return types_1.NeverType.createNever();
153
+ }
154
+ // Handle certain operations on certain homogenous literal types
155
+ // using special-case math. For example, Literal[1, 2] + Literal[3, 4]
156
+ // should result in Literal[4, 5, 6].
157
+ if (options.isLiteralMathAllowed) {
158
+ const leftLiteralClassName = (0, typeUtils_1.getLiteralTypeClassName)(leftType);
159
+ if (leftLiteralClassName && !(0, typeUtils_1.getTypeCondition)(leftType)) {
160
+ const rightLiteralClassName = (0, typeUtils_1.getLiteralTypeClassName)(rightType);
161
+ if (leftLiteralClassName === rightLiteralClassName &&
162
+ !(0, typeUtils_1.getTypeCondition)(rightType) &&
163
+ (0, typeUtils_1.getUnionSubtypeCount)(leftType) * (0, typeUtils_1.getUnionSubtypeCount)(rightType) < maxLiteralMathSubtypeCount) {
164
+ if (leftLiteralClassName === 'str' || leftLiteralClassName === 'bytes') {
165
+ if (operator === 0 /* Add */) {
166
+ type = (0, typeUtils_1.mapSubtypes)(leftType, (leftSubtype) => {
167
+ return (0, typeUtils_1.mapSubtypes)(rightType, (rightSubtype) => {
168
+ const leftClassSubtype = leftSubtype;
169
+ const rightClassSubtype = rightSubtype;
170
+ return types_1.ClassType.cloneWithLiteral(leftClassSubtype, (leftClassSubtype.literalValue +
171
+ rightClassSubtype.literalValue));
172
+ });
173
+ });
174
+ }
175
+ }
176
+ else if (leftLiteralClassName === 'int') {
177
+ if (operator === 0 /* Add */ ||
178
+ operator === 33 /* Subtract */ ||
179
+ operator === 26 /* Multiply */ ||
180
+ operator === 13 /* FloorDivide */ ||
181
+ operator === 24 /* Mod */) {
182
+ let isValidResult = true;
183
+ type = (0, typeUtils_1.mapSubtypes)(leftType, (leftSubtype) => {
184
+ return (0, typeUtils_1.mapSubtypes)(rightType, (rightSubtype) => {
185
+ try {
186
+ const leftClassSubtype = leftSubtype;
187
+ const rightClassSubtype = rightSubtype;
188
+ const leftLiteralValue = BigInt(leftClassSubtype.literalValue);
189
+ const rightLiteralValue = BigInt(rightClassSubtype.literalValue);
190
+ let newValue;
191
+ if (operator === 0 /* Add */) {
192
+ newValue = leftLiteralValue + rightLiteralValue;
193
+ }
194
+ else if (operator === 33 /* Subtract */) {
195
+ newValue = leftLiteralValue - rightLiteralValue;
196
+ }
197
+ else if (operator === 26 /* Multiply */) {
198
+ newValue = leftLiteralValue * rightLiteralValue;
199
+ }
200
+ else if (operator === 13 /* FloorDivide */) {
201
+ if (rightLiteralValue !== BigInt(0)) {
202
+ newValue = leftLiteralValue / rightLiteralValue;
203
+ }
204
+ }
205
+ else if (operator === 24 /* Mod */) {
206
+ if (rightLiteralValue !== BigInt(0)) {
207
+ newValue = leftLiteralValue % rightLiteralValue;
208
+ }
209
+ }
210
+ if (newValue === undefined) {
211
+ isValidResult = false;
212
+ return undefined;
213
+ }
214
+ else if (typeof newValue === 'number' && isNaN(newValue)) {
215
+ isValidResult = false;
216
+ return undefined;
217
+ }
218
+ else {
219
+ // Convert back to a simple number if it fits. Leave as a bigint
220
+ // if it doesn't.
221
+ if (newValue >= Number.MIN_SAFE_INTEGER &&
222
+ newValue <= Number.MAX_SAFE_INTEGER) {
223
+ newValue = Number(newValue);
224
+ }
225
+ return types_1.ClassType.cloneWithLiteral(leftClassSubtype, newValue);
226
+ }
227
+ }
228
+ catch {
229
+ isValidResult = false;
230
+ return undefined;
231
+ }
232
+ });
233
+ });
234
+ if (!isValidResult) {
235
+ type = undefined;
236
+ }
237
+ }
238
+ }
239
+ }
240
+ }
241
+ }
242
+ if (!type) {
243
+ type = evaluator.mapSubtypesExpandTypeVars(leftType,
244
+ /* conditionFilter */ undefined, (leftSubtypeExpanded, leftSubtypeUnexpanded) => {
245
+ return evaluator.mapSubtypesExpandTypeVars(rightType, (0, typeUtils_1.getTypeCondition)(leftSubtypeExpanded), (rightSubtypeExpanded, rightSubtypeUnexpanded) => {
246
+ if ((0, types_1.isAnyOrUnknown)(leftSubtypeUnexpanded) || (0, types_1.isAnyOrUnknown)(rightSubtypeUnexpanded)) {
247
+ return (0, typeUtils_1.preserveUnknown)(leftSubtypeUnexpanded, rightSubtypeUnexpanded);
248
+ }
249
+ const tupleClassType = evaluator.getTupleClassType();
250
+ // Special-case __add__ for tuples when the types for both tuples are known.
251
+ if (options.isTupleAddAllowed &&
252
+ operator === 0 /* Add */ &&
253
+ (0, types_1.isClassInstance)(leftSubtypeExpanded) &&
254
+ (0, typeUtils_1.isTupleClass)(leftSubtypeExpanded) &&
255
+ leftSubtypeExpanded.tupleTypeArguments &&
256
+ !(0, typeUtils_1.isUnboundedTupleClass)(leftSubtypeExpanded) &&
257
+ (0, types_1.isClassInstance)(rightSubtypeExpanded) &&
258
+ (0, typeUtils_1.isTupleClass)(rightSubtypeExpanded) &&
259
+ rightSubtypeExpanded.tupleTypeArguments &&
260
+ !(0, typeUtils_1.isUnboundedTupleClass)(rightSubtypeExpanded) &&
261
+ tupleClassType &&
262
+ (0, types_1.isInstantiableClass)(tupleClassType)) {
263
+ return types_1.ClassType.cloneAsInstance((0, typeUtils_1.specializeTupleClass)(tupleClassType, [
264
+ ...leftSubtypeExpanded.tupleTypeArguments,
265
+ ...rightSubtypeExpanded.tupleTypeArguments,
266
+ ]));
267
+ }
268
+ const magicMethodName = binaryOperatorMap[operator][0];
269
+ let resultType = evaluator.getTypeOfMagicMethodReturn(convertFunctionToObject(evaluator, leftSubtypeUnexpanded), [{ type: rightSubtypeUnexpanded, isIncomplete: rightTypeResult.isIncomplete }], magicMethodName, errorNode, inferenceContext);
270
+ if (!resultType && leftSubtypeUnexpanded !== leftSubtypeExpanded) {
271
+ // Try the expanded left type.
272
+ resultType = evaluator.getTypeOfMagicMethodReturn(convertFunctionToObject(evaluator, leftSubtypeExpanded), [{ type: rightSubtypeUnexpanded, isIncomplete: rightTypeResult.isIncomplete }], magicMethodName, errorNode, inferenceContext);
273
+ }
274
+ if (!resultType && rightSubtypeUnexpanded !== rightSubtypeExpanded) {
275
+ // Try the expanded left and right type.
276
+ resultType = evaluator.getTypeOfMagicMethodReturn(convertFunctionToObject(evaluator, leftSubtypeExpanded), [{ type: rightSubtypeExpanded, isIncomplete: rightTypeResult.isIncomplete }], magicMethodName, errorNode, inferenceContext);
277
+ }
278
+ if (!resultType) {
279
+ // Try the alternate form (swapping right and left).
280
+ const altMagicMethodName = binaryOperatorMap[operator][1];
281
+ resultType = evaluator.getTypeOfMagicMethodReturn(convertFunctionToObject(evaluator, rightSubtypeUnexpanded), [{ type: leftSubtypeUnexpanded, isIncomplete: leftTypeResult.isIncomplete }], altMagicMethodName, errorNode, inferenceContext);
282
+ if (!resultType && rightSubtypeUnexpanded !== rightSubtypeExpanded) {
283
+ // Try the expanded right type.
284
+ resultType = evaluator.getTypeOfMagicMethodReturn(convertFunctionToObject(evaluator, rightSubtypeExpanded), [
285
+ {
286
+ type: leftSubtypeUnexpanded,
287
+ isIncomplete: leftTypeResult.isIncomplete,
288
+ },
289
+ ], altMagicMethodName, errorNode, inferenceContext);
290
+ }
291
+ if (!resultType && leftSubtypeUnexpanded !== leftSubtypeExpanded) {
292
+ // Try the expanded right and left type.
293
+ resultType = evaluator.getTypeOfMagicMethodReturn(convertFunctionToObject(evaluator, rightSubtypeExpanded), [{ type: leftSubtypeExpanded, isIncomplete: leftTypeResult.isIncomplete }], altMagicMethodName, errorNode, inferenceContext);
294
+ }
295
+ }
296
+ if (!resultType) {
297
+ if (inferenceContext) {
298
+ diag.addMessage(localize_1.Localizer.Diagnostic.typeNotSupportBinaryOperatorBidirectional().format({
299
+ operator: (0, parseTreeUtils_1.printOperator)(operator),
300
+ leftType: evaluator.printType(leftSubtypeExpanded),
301
+ rightType: evaluator.printType(rightSubtypeExpanded),
302
+ expectedType: evaluator.printType(inferenceContext.expectedType),
303
+ }));
304
+ }
305
+ else {
306
+ diag.addMessage(localize_1.Localizer.Diagnostic.typeNotSupportBinaryOperator().format({
307
+ operator: (0, parseTreeUtils_1.printOperator)(operator),
308
+ leftType: evaluator.printType(leftSubtypeExpanded),
309
+ rightType: evaluator.printType(rightSubtypeExpanded),
310
+ }));
311
+ }
312
+ }
313
+ return resultType;
314
+ });
315
+ });
316
+ }
317
+ }
318
+ return type && (0, types_1.isNever)(type) ? undefined : type;
319
+ }
320
+ exports.validateBinaryOperation = validateBinaryOperation;
321
+ function getTypeOfBinaryOperation(evaluator, node, inferenceContext, flags) {
322
+ const leftExpression = node.leftExpression;
323
+ let rightExpression = node.rightExpression;
324
+ let isIncomplete = false;
325
+ let typeErrors = false;
326
+ // If this is a comparison and the left expression is also a comparison,
327
+ // we need to change the behavior to accommodate python's "chained
328
+ // comparisons" feature.
329
+ if ((0, parseTreeUtils_1.operatorSupportsChaining)(node.operator)) {
330
+ if (rightExpression.nodeType === 7 /* BinaryOperation */ &&
331
+ !rightExpression.parenthesized &&
332
+ (0, parseTreeUtils_1.operatorSupportsChaining)(rightExpression.operator)) {
333
+ // Evaluate the right expression so it is type checked.
334
+ getTypeOfBinaryOperation(evaluator, rightExpression, inferenceContext, flags);
335
+ // Use the left side of the right expression for comparison purposes.
336
+ rightExpression = rightExpression.leftExpression;
337
+ }
338
+ }
339
+ // For most binary operations, the "expected type" is applied to the output
340
+ // of the magic method for that operation. However, the "or" and "and" operators
341
+ // have no magic method, so we apply the expected type directly to both operands.
342
+ let expectedOperandType = node.operator === 37 /* Or */ || node.operator === 36 /* And */
343
+ ? inferenceContext === null || inferenceContext === void 0 ? void 0 : inferenceContext.expectedType
344
+ : undefined;
345
+ // Handle the very special case where the expected type is a list
346
+ // and the operator is a multiply. This comes up in the common case
347
+ // of "x: List[Optional[X]] = [None] * y" where y is an integer literal.
348
+ let expectedLeftOperandType;
349
+ if (node.operator === 26 /* Multiply */ &&
350
+ inferenceContext &&
351
+ (0, types_1.isClassInstance)(inferenceContext.expectedType) &&
352
+ types_1.ClassType.isBuiltIn(inferenceContext.expectedType, 'list') &&
353
+ inferenceContext.expectedType.typeArguments &&
354
+ inferenceContext.expectedType.typeArguments.length >= 1 &&
355
+ node.leftExpression.nodeType === 31 /* List */) {
356
+ expectedLeftOperandType = inferenceContext.expectedType;
357
+ }
358
+ const effectiveExpectedType = expectedOperandType !== null && expectedOperandType !== void 0 ? expectedOperandType : expectedLeftOperandType;
359
+ const leftTypeResult = evaluator.getTypeOfExpression(leftExpression, flags, (0, typeUtils_1.makeInferenceContext)(effectiveExpectedType));
360
+ let leftType = leftTypeResult.type;
361
+ if (!expectedOperandType) {
362
+ if (node.operator === 37 /* Or */ || node.operator === 36 /* And */) {
363
+ // For "or" and "and", use the type of the left operand. This allows us to
364
+ // infer a better type for expressions like `x or []`.
365
+ expectedOperandType = leftType;
366
+ }
367
+ else if (node.operator === 0 /* Add */ && node.rightExpression.nodeType === 31 /* List */) {
368
+ // For the "+" operator , use this technique only if the right operand is
369
+ // a list expression. This heuristic handles the common case of `my_list + [0]`.
370
+ expectedOperandType = leftType;
371
+ }
372
+ else if (node.operator === 6 /* BitwiseOr */) {
373
+ // If this is a bitwise or ("|"), use the type of the left operand. This allows
374
+ // us to support the case where a TypedDict is being updated with a dict expression.
375
+ if ((0, types_1.isClassInstance)(leftType) && types_1.ClassType.isTypedDictClass(leftType)) {
376
+ expectedOperandType = leftType;
377
+ }
378
+ }
379
+ }
380
+ const rightTypeResult = evaluator.getTypeOfExpression(rightExpression, flags, (0, typeUtils_1.makeInferenceContext)(expectedOperandType));
381
+ let rightType = rightTypeResult.type;
382
+ if (leftTypeResult.isIncomplete || rightTypeResult.isIncomplete) {
383
+ isIncomplete = true;
384
+ }
385
+ // Is this a "|" operator used in a context where it is supposed to be
386
+ // interpreted as a union operator?
387
+ if (node.operator === 6 /* BitwiseOr */ &&
388
+ !customMetaclassSupportsMethod(leftType, '__or__') &&
389
+ !customMetaclassSupportsMethod(rightType, '__ror__')) {
390
+ let adjustedRightType = rightType;
391
+ let adjustedLeftType = leftType;
392
+ if (!(0, types_1.isNoneInstance)(leftType) && (0, types_1.isNoneInstance)(rightType)) {
393
+ // Handle the special case where "None" is being added to the union
394
+ // with something else. Even though "None" will normally be interpreted
395
+ // as the None singleton object in contexts where a type annotation isn't
396
+ // assumed, we'll allow it here.
397
+ adjustedRightType = types_1.NoneType.createType();
398
+ }
399
+ else if (!(0, types_1.isNoneInstance)(rightType) && (0, types_1.isNoneInstance)(leftType)) {
400
+ adjustedLeftType = types_1.NoneType.createType();
401
+ }
402
+ if ((0, typeUtils_1.isUnionableType)([adjustedLeftType, adjustedRightType])) {
403
+ const fileInfo = (0, analyzerNodeInfo_1.getFileInfo)(node);
404
+ const unionNotationSupported = fileInfo.isStubFile ||
405
+ (flags & 4 /* AllowForwardReferences */) !== 0 ||
406
+ fileInfo.executionEnvironment.pythonVersion >= pythonVersion_1.PythonVersion.V3_10;
407
+ if (!unionNotationSupported) {
408
+ // If the left type is Any, we can't say for sure whether this
409
+ // is an illegal syntax or a valid application of the "|" operator.
410
+ if (!(0, types_1.isAnyOrUnknown)(adjustedLeftType)) {
411
+ evaluator.addError(localize_1.Localizer.Diagnostic.unionSyntaxIllegal(), node, node.operatorToken);
412
+ }
413
+ }
414
+ if (!evaluator.validateTypeArg({ ...leftTypeResult, node: leftExpression }, { allowVariadicTypeVar: true, allowUnpackedTuples: true }) ||
415
+ !evaluator.validateTypeArg({ ...rightTypeResult, node: rightExpression }, { allowVariadicTypeVar: true, allowUnpackedTuples: true })) {
416
+ return { type: types_1.UnknownType.create() };
417
+ }
418
+ const newUnion = (0, types_1.combineTypes)([adjustedLeftType, adjustedRightType]);
419
+ if ((0, types_1.isUnion)(newUnion)) {
420
+ types_1.TypeBase.setSpecialForm(newUnion);
421
+ }
422
+ // Check for "stringified" forward reference type expressions. The "|" operator
423
+ // doesn't support these except in certain circumstances. Notably, it can't be used
424
+ // with other strings or with types that are not specialized using an index form.
425
+ if (!fileInfo.isStubFile) {
426
+ let stringNode;
427
+ let otherNode;
428
+ let otherType;
429
+ if (leftExpression.nodeType === 48 /* StringList */) {
430
+ stringNode = leftExpression;
431
+ otherNode = rightExpression;
432
+ otherType = rightType;
433
+ }
434
+ else if (rightExpression.nodeType === 48 /* StringList */) {
435
+ stringNode = rightExpression;
436
+ otherNode = leftExpression;
437
+ otherType = leftType;
438
+ }
439
+ if (stringNode && otherNode && otherType) {
440
+ let isAllowed = true;
441
+ if ((0, types_1.isClass)(otherType)) {
442
+ if (!otherType.isTypeArgumentExplicit || (0, types_1.isClassInstance)(otherType)) {
443
+ isAllowed = false;
444
+ }
445
+ }
446
+ if (!isAllowed) {
447
+ evaluator.addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.unionForwardReferenceNotAllowed(), stringNode);
448
+ }
449
+ }
450
+ }
451
+ return { type: newUnion };
452
+ }
453
+ }
454
+ // Optional checks apply to all operations except for boolean operations.
455
+ let isLeftOptionalType = false;
456
+ if (booleanOperatorMap[node.operator] === undefined) {
457
+ // None is a valid operand for == and != even if the type stub says otherwise.
458
+ if (node.operator === 12 /* Equals */ || node.operator === 28 /* NotEquals */) {
459
+ leftType = (0, types_1.removeNoneFromUnion)(leftType);
460
+ }
461
+ else {
462
+ isLeftOptionalType = (0, typeUtils_1.isOptionalType)(leftType);
463
+ }
464
+ // None is a valid operand for == and != even if the type stub says otherwise.
465
+ if (node.operator === 12 /* Equals */ || node.operator === 28 /* NotEquals */) {
466
+ rightType = (0, types_1.removeNoneFromUnion)(rightType);
467
+ }
468
+ }
469
+ const diag = new diagnostic_1.DiagnosticAddendum();
470
+ // Don't use literal math if either of the operation is within a loop
471
+ // because the literal values may change each time.
472
+ const isLiteralMathAllowed = !(0, parseTreeUtils_1.isWithinLoop)(node);
473
+ // Don't special-case tuple __add__ if the left type is a union. This
474
+ // can result in an infinite loop if we keep creating new tuple types
475
+ // within a loop construct using __add__.
476
+ const isTupleAddAllowed = !(0, types_1.isUnion)(leftType);
477
+ let type = validateBinaryOperation(evaluator, node.operator, { type: leftType, isIncomplete: leftTypeResult.isIncomplete }, { type: rightType, isIncomplete: rightTypeResult.isIncomplete }, node, inferenceContext, diag, { isLiteralMathAllowed, isTupleAddAllowed });
478
+ if (!diag.isEmpty() || !type) {
479
+ typeErrors = true;
480
+ if (!isIncomplete) {
481
+ const fileInfo = (0, analyzerNodeInfo_1.getFileInfo)(node);
482
+ if (isLeftOptionalType && diag.getMessages().length === 1) {
483
+ // If the left was an optional type and there is just one diagnostic,
484
+ // assume that it was due to a "None" not being supported. Report
485
+ // this as a reportOptionalOperand diagnostic rather than a
486
+ // reportGeneralTypeIssues diagnostic.
487
+ evaluator.addDiagnostic(fileInfo.diagnosticRuleSet.reportOptionalOperand, diagnosticRules_1.DiagnosticRule.reportOptionalOperand, localize_1.Localizer.Diagnostic.noneOperator().format({
488
+ operator: (0, parseTreeUtils_1.printOperator)(node.operator),
489
+ }), node.leftExpression);
490
+ }
491
+ else {
492
+ // If neither the LHS or RHS are unions, don't include a diagnostic addendum
493
+ // because it will be redundant with the main diagnostic message. The addenda
494
+ // are useful only if union expansion was used for one or both operands.
495
+ let diagString = '';
496
+ if ((0, types_1.isUnion)(evaluator.makeTopLevelTypeVarsConcrete(leftType)) ||
497
+ (0, types_1.isUnion)(evaluator.makeTopLevelTypeVarsConcrete(rightType))) {
498
+ diagString = diag.getString();
499
+ }
500
+ evaluator.addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeNotSupportBinaryOperator().format({
501
+ operator: (0, parseTreeUtils_1.printOperator)(node.operator),
502
+ leftType: evaluator.printType(leftType),
503
+ rightType: evaluator.printType(rightType),
504
+ }) + diagString, node);
505
+ }
506
+ }
507
+ type = types_1.UnknownType.create();
508
+ }
509
+ return { type, isIncomplete, typeErrors };
510
+ }
511
+ exports.getTypeOfBinaryOperation = getTypeOfBinaryOperation;
512
+ function getTypeOfAugmentedAssignment(evaluator, node, inferenceContext) {
513
+ const operatorMap = {
514
+ [1 /* AddEqual */]: ['__iadd__', 0 /* Add */],
515
+ [34 /* SubtractEqual */]: ['__isub__', 33 /* Subtract */],
516
+ [27 /* MultiplyEqual */]: ['__imul__', 26 /* Multiply */],
517
+ [14 /* FloorDivideEqual */]: ['__ifloordiv__', 13 /* FloorDivide */],
518
+ [11 /* DivideEqual */]: ['__itruediv__', 10 /* Divide */],
519
+ [25 /* ModEqual */]: ['__imod__', 24 /* Mod */],
520
+ [30 /* PowerEqual */]: ['__ipow__', 29 /* Power */],
521
+ [23 /* MatrixMultiplyEqual */]: ['__imatmul__', 22 /* MatrixMultiply */],
522
+ [4 /* BitwiseAndEqual */]: ['__iand__', 3 /* BitwiseAnd */],
523
+ [7 /* BitwiseOrEqual */]: ['__ior__', 6 /* BitwiseOr */],
524
+ [9 /* BitwiseXorEqual */]: ['__ixor__', 8 /* BitwiseXor */],
525
+ [18 /* LeftShiftEqual */]: ['__ilshift__', 17 /* LeftShift */],
526
+ [32 /* RightShiftEqual */]: ['__irshift__', 31 /* RightShift */],
527
+ };
528
+ let type;
529
+ let typeResult;
530
+ const diag = new diagnostic_1.DiagnosticAddendum();
531
+ const leftTypeResult = evaluator.getTypeOfExpression(node.leftExpression);
532
+ const leftType = leftTypeResult.type;
533
+ let expectedOperandType;
534
+ if (node.operator === 7 /* BitwiseOrEqual */) {
535
+ // If this is a bitwise or ("|="), use the type of the left operand. This allows
536
+ // us to support the case where a TypedDict is being updated with a dict expression.
537
+ expectedOperandType = leftType;
538
+ }
539
+ const rightTypeResult = evaluator.getTypeOfExpression(node.rightExpression,
540
+ /* flags */ undefined, (0, typeUtils_1.makeInferenceContext)(expectedOperandType));
541
+ const rightType = rightTypeResult.type;
542
+ const isIncomplete = !!rightTypeResult.isIncomplete || !!leftTypeResult.isIncomplete;
543
+ if ((0, types_1.isNever)(leftType) || (0, types_1.isNever)(rightType)) {
544
+ typeResult = { type: types_1.NeverType.createNever(), isIncomplete };
545
+ }
546
+ else {
547
+ type = evaluator.mapSubtypesExpandTypeVars(leftType,
548
+ /* conditionFilter */ undefined, (leftSubtypeExpanded, leftSubtypeUnexpanded) => {
549
+ return evaluator.mapSubtypesExpandTypeVars(rightType, (0, typeUtils_1.getTypeCondition)(leftSubtypeExpanded), (rightSubtypeExpanded, rightSubtypeUnexpanded) => {
550
+ if ((0, types_1.isAnyOrUnknown)(leftSubtypeUnexpanded) || (0, types_1.isAnyOrUnknown)(rightSubtypeUnexpanded)) {
551
+ return (0, typeUtils_1.preserveUnknown)(leftSubtypeUnexpanded, rightSubtypeUnexpanded);
552
+ }
553
+ const magicMethodName = operatorMap[node.operator][0];
554
+ let returnType = evaluator.getTypeOfMagicMethodReturn(leftSubtypeUnexpanded, [{ type: rightSubtypeUnexpanded, isIncomplete: rightTypeResult.isIncomplete }], magicMethodName, node, inferenceContext);
555
+ if (!returnType && leftSubtypeUnexpanded !== leftSubtypeExpanded) {
556
+ // Try with the expanded left type.
557
+ returnType = evaluator.getTypeOfMagicMethodReturn(leftSubtypeExpanded, [{ type: rightSubtypeUnexpanded, isIncomplete: rightTypeResult.isIncomplete }], magicMethodName, node, inferenceContext);
558
+ }
559
+ if (!returnType && rightSubtypeUnexpanded !== rightSubtypeExpanded) {
560
+ // Try with the expanded left and right type.
561
+ returnType = evaluator.getTypeOfMagicMethodReturn(leftSubtypeExpanded, [{ type: rightSubtypeExpanded, isIncomplete: rightTypeResult.isIncomplete }], magicMethodName, node, inferenceContext);
562
+ }
563
+ if (!returnType) {
564
+ // If the LHS class didn't support the magic method for augmented
565
+ // assignment, fall back on the normal binary expression evaluator.
566
+ const binaryOperator = operatorMap[node.operator][1];
567
+ // Don't use literal math if either of the operation is within a loop
568
+ // because the literal values may change each time.
569
+ const isLiteralMathAllowed = !(0, parseTreeUtils_1.isWithinLoop)(node) &&
570
+ (0, typeUtils_1.getUnionSubtypeCount)(leftType) * (0, typeUtils_1.getUnionSubtypeCount)(rightType) <
571
+ maxLiteralMathSubtypeCount;
572
+ // Don't special-case tuple __add__ if the left type is a union. This
573
+ // can result in an infinite loop if we keep creating new tuple types
574
+ // within a loop construct using __add__.
575
+ const isTupleAddAllowed = !(0, types_1.isUnion)(leftType);
576
+ returnType = validateBinaryOperation(evaluator, binaryOperator, { type: leftSubtypeUnexpanded, isIncomplete: leftTypeResult.isIncomplete }, { type: rightSubtypeUnexpanded, isIncomplete: rightTypeResult.isIncomplete }, node, inferenceContext, diag, { isLiteralMathAllowed, isTupleAddAllowed });
577
+ }
578
+ return returnType;
579
+ });
580
+ });
581
+ // If the LHS class didn't support the magic method for augmented
582
+ // assignment, fall back on the normal binary expression evaluator.
583
+ if (!diag.isEmpty() || !type || (0, types_1.isNever)(type)) {
584
+ if (!isIncomplete) {
585
+ const fileInfo = (0, analyzerNodeInfo_1.getFileInfo)(node);
586
+ evaluator.addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeNotSupportBinaryOperator().format({
587
+ operator: (0, parseTreeUtils_1.printOperator)(node.operator),
588
+ leftType: evaluator.printType(leftType),
589
+ rightType: evaluator.printType(rightType),
590
+ }) + diag.getString(), node);
591
+ }
592
+ type = types_1.UnknownType.create();
593
+ }
594
+ typeResult = { type, isIncomplete };
595
+ }
596
+ evaluator.assignTypeToExpression(node.destExpression, typeResult.type, !!typeResult.isIncomplete, node.rightExpression);
597
+ return typeResult;
598
+ }
599
+ exports.getTypeOfAugmentedAssignment = getTypeOfAugmentedAssignment;
600
+ function getTypeOfUnaryOperation(evaluator, node, inferenceContext) {
601
+ const exprTypeResult = evaluator.getTypeOfExpression(node.expression);
602
+ let exprType = evaluator.makeTopLevelTypeVarsConcrete(exprTypeResult.type);
603
+ const isIncomplete = exprTypeResult.isIncomplete;
604
+ if ((0, types_1.isNever)(exprType)) {
605
+ return { type: types_1.NeverType.createNever(), isIncomplete };
606
+ }
607
+ // Map unary operators to magic functions. Note that the bitwise
608
+ // invert has two magic functions that are aliases of each other.
609
+ const unaryOperatorMap = {
610
+ [0 /* Add */]: '__pos__',
611
+ [33 /* Subtract */]: '__neg__',
612
+ [5 /* BitwiseInvert */]: '__invert__',
613
+ };
614
+ let type;
615
+ if (node.operator !== 38 /* Not */) {
616
+ if ((0, typeUtils_1.isOptionalType)(exprType)) {
617
+ evaluator.addDiagnostic((0, analyzerNodeInfo_1.getFileInfo)(node).diagnosticRuleSet.reportOptionalOperand, diagnosticRules_1.DiagnosticRule.reportOptionalOperand, localize_1.Localizer.Diagnostic.noneOperator().format({
618
+ operator: (0, parseTreeUtils_1.printOperator)(node.operator),
619
+ }), node.expression);
620
+ exprType = (0, types_1.removeNoneFromUnion)(exprType);
621
+ }
622
+ }
623
+ // Handle certain operations on certain literal types
624
+ // using special-case math. Do not apply this if the input type
625
+ // is incomplete because we may be evaluating an expression within
626
+ // a loop, so the literal value may change each time.
627
+ if (!exprTypeResult.isIncomplete) {
628
+ const literalClassName = (0, typeUtils_1.getLiteralTypeClassName)(exprType);
629
+ if (literalClassName === 'int') {
630
+ if (node.operator === 0 /* Add */) {
631
+ type = exprType;
632
+ }
633
+ else if (node.operator === 33 /* Subtract */) {
634
+ type = (0, typeUtils_1.mapSubtypes)(exprType, (subtype) => {
635
+ const classSubtype = subtype;
636
+ return types_1.ClassType.cloneWithLiteral(classSubtype, -classSubtype.literalValue);
637
+ });
638
+ }
639
+ }
640
+ else if (literalClassName === 'bool') {
641
+ if (node.operator === 38 /* Not */) {
642
+ type = (0, typeUtils_1.mapSubtypes)(exprType, (subtype) => {
643
+ const classSubtype = subtype;
644
+ return types_1.ClassType.cloneWithLiteral(classSubtype, !classSubtype.literalValue);
645
+ });
646
+ }
647
+ }
648
+ }
649
+ if (!type) {
650
+ // __not__ always returns a boolean.
651
+ if (node.operator === 38 /* Not */) {
652
+ type = evaluator.getBuiltInObject(node, 'bool');
653
+ if (!type) {
654
+ type = types_1.UnknownType.create();
655
+ }
656
+ }
657
+ else {
658
+ if ((0, types_1.isAnyOrUnknown)(exprType)) {
659
+ type = exprType;
660
+ }
661
+ else {
662
+ const magicMethodName = unaryOperatorMap[node.operator];
663
+ type = evaluator.getTypeOfMagicMethodReturn(exprType, [], magicMethodName, node, inferenceContext);
664
+ }
665
+ if (!type) {
666
+ const fileInfo = (0, analyzerNodeInfo_1.getFileInfo)(node);
667
+ if (inferenceContext) {
668
+ evaluator.addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeNotSupportUnaryOperatorBidirectional().format({
669
+ operator: (0, parseTreeUtils_1.printOperator)(node.operator),
670
+ type: evaluator.printType(exprType),
671
+ expectedType: evaluator.printType(inferenceContext.expectedType),
672
+ }), node);
673
+ }
674
+ else {
675
+ evaluator.addDiagnostic(fileInfo.diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.typeNotSupportUnaryOperator().format({
676
+ operator: (0, parseTreeUtils_1.printOperator)(node.operator),
677
+ type: evaluator.printType(exprType),
678
+ }), node);
679
+ }
680
+ type = types_1.UnknownType.create();
681
+ }
682
+ }
683
+ }
684
+ return { type, isIncomplete };
685
+ }
686
+ exports.getTypeOfUnaryOperation = getTypeOfUnaryOperation;
687
+ function getTypeOfTernaryOperation(evaluator, node, flags, inferenceContext) {
688
+ evaluator.getTypeOfExpression(node.testExpression);
689
+ const typesToCombine = [];
690
+ let isIncomplete = false;
691
+ let typeErrors = false;
692
+ const fileInfo = (0, analyzerNodeInfo_1.getFileInfo)(node);
693
+ const constExprValue = (0, staticExpressions_1.evaluateStaticBoolExpression)(node.testExpression, fileInfo.executionEnvironment, fileInfo.definedConstants);
694
+ if (constExprValue !== false && evaluator.isNodeReachable(node.ifExpression)) {
695
+ const ifType = evaluator.getTypeOfExpression(node.ifExpression, flags, inferenceContext);
696
+ typesToCombine.push(ifType.type);
697
+ if (ifType.isIncomplete) {
698
+ isIncomplete = true;
699
+ }
700
+ if (ifType.typeErrors) {
701
+ typeErrors = true;
702
+ }
703
+ }
704
+ if (constExprValue !== true && evaluator.isNodeReachable(node.elseExpression)) {
705
+ const elseType = evaluator.getTypeOfExpression(node.elseExpression, flags, inferenceContext);
706
+ typesToCombine.push(elseType.type);
707
+ if (elseType.isIncomplete) {
708
+ isIncomplete = true;
709
+ }
710
+ if (elseType.typeErrors) {
711
+ typeErrors = true;
712
+ }
713
+ }
714
+ return { type: (0, types_1.combineTypes)(typesToCombine), isIncomplete, typeErrors };
715
+ }
716
+ exports.getTypeOfTernaryOperation = getTypeOfTernaryOperation;
717
+ function customMetaclassSupportsMethod(type, methodName) {
718
+ if (!(0, types_1.isInstantiableClass)(type)) {
719
+ return false;
720
+ }
721
+ const metaclass = type.details.effectiveMetaclass;
722
+ if (!metaclass || !(0, types_1.isInstantiableClass)(metaclass)) {
723
+ return false;
724
+ }
725
+ if (types_1.ClassType.isBuiltIn(metaclass, 'type')) {
726
+ return false;
727
+ }
728
+ const memberInfo = (0, typeUtils_1.lookUpClassMember)(metaclass, methodName);
729
+ if (!memberInfo) {
730
+ return false;
731
+ }
732
+ if ((0, types_1.isInstantiableClass)(memberInfo.classType) && types_1.ClassType.isBuiltIn(memberInfo.classType, 'type')) {
733
+ return false;
734
+ }
735
+ return true;
736
+ }
737
+ // All functions in Python derive from object, so they inherit all
738
+ // of the capabilities of an object. This function converts a function
739
+ // to an object instance.
740
+ function convertFunctionToObject(evaluator, type) {
741
+ if ((0, types_1.isFunction)(type) || (0, types_1.isOverloadedFunction)(type)) {
742
+ const objectType = evaluator.getObjectType();
743
+ if (objectType) {
744
+ return objectType;
745
+ }
746
+ }
747
+ return type;
748
+ }
749
+ //# sourceMappingURL=operations.js.map