@zzzen/pyright-internal 1.2.0-dev.20230813 → 1.2.0-dev.20230820
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.
- package/dist/analyzer/binder.js +8 -2
- package/dist/analyzer/binder.js.map +1 -1
- package/dist/analyzer/checker.d.ts +1 -0
- package/dist/analyzer/checker.js +77 -6
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/dataClasses.js +242 -236
- package/dist/analyzer/dataClasses.js.map +1 -1
- package/dist/analyzer/enums.js +12 -0
- package/dist/analyzer/enums.js.map +1 -1
- package/dist/analyzer/importResolver.js +3 -1
- package/dist/analyzer/importResolver.js.map +1 -1
- package/dist/analyzer/namedTuples.js +6 -0
- package/dist/analyzer/namedTuples.js.map +1 -1
- package/dist/analyzer/operations.d.ts +1 -1
- package/dist/analyzer/operations.js +2 -2
- package/dist/analyzer/operations.js.map +1 -1
- package/dist/analyzer/parameterUtils.d.ts +2 -1
- package/dist/analyzer/parameterUtils.js +15 -0
- package/dist/analyzer/parameterUtils.js.map +1 -1
- package/dist/analyzer/protocols.js +14 -0
- package/dist/analyzer/protocols.js.map +1 -1
- package/dist/analyzer/service.js +2 -2
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +194 -108
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +1 -1
- package/dist/analyzer/typeEvaluatorTypes.js +2 -2
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typeGuards.js +3 -0
- package/dist/analyzer/typeGuards.js.map +1 -1
- package/dist/analyzer/typePrinter.js +3 -0
- package/dist/analyzer/typePrinter.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +1 -0
- package/dist/analyzer/typeUtils.js +20 -2
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/types.js +1 -0
- package/dist/analyzer/types.js.map +1 -1
- package/dist/common/serviceProvider.d.ts +4 -3
- package/dist/languageServerBase.d.ts +2 -2
- package/dist/languageServerBase.js +4 -2
- package/dist/languageServerBase.js.map +1 -1
- package/dist/localization/localize.d.ts +22 -4
- package/dist/localization/localize.js +7 -2
- package/dist/localization/localize.js.map +1 -1
- package/dist/localization/package.nls.cs.json +3 -2
- package/dist/localization/package.nls.de.json +3 -2
- package/dist/localization/package.nls.en-us.json +16 -11
- package/dist/localization/package.nls.es.json +3 -2
- package/dist/localization/package.nls.fr.json +3 -2
- package/dist/localization/package.nls.it.json +3 -2
- package/dist/localization/package.nls.ja.json +3 -2
- package/dist/localization/package.nls.ko.json +3 -2
- package/dist/localization/package.nls.pl.json +3 -2
- package/dist/localization/package.nls.pt-br.json +3 -2
- package/dist/localization/package.nls.qps-ploc.json +3 -2
- package/dist/localization/package.nls.ru.json +3 -2
- package/dist/localization/package.nls.tr.json +3 -2
- package/dist/localization/package.nls.zh-cn.json +3 -2
- package/dist/localization/package.nls.zh-tw.json +2 -1
- package/dist/parser/parser.d.ts +1 -0
- package/dist/parser/parser.js +78 -18
- package/dist/parser/parser.js.map +1 -1
- package/dist/server.js +1 -1
- package/dist/server.js.map +1 -1
- package/dist/tests/harness/fourslash/testState.d.ts +1 -1
- package/dist/tests/harness/fourslash/testState.js +2 -2
- package/dist/tests/harness/fourslash/testState.js.map +1 -1
- package/dist/tests/typeEvaluator1.test.js +4 -4
- package/dist/tests/typeEvaluator1.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +9 -1
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +7 -3
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator4.test.js +9 -1
- package/dist/tests/typeEvaluator4.test.js.map +1 -1
- package/dist/tests/typeEvaluator5.test.js +9 -1
- package/dist/tests/typeEvaluator5.test.js.map +1 -1
- package/package.json +1 -1
@@ -86,270 +86,276 @@ function synthesizeDataClassMethods(evaluator, node, classType, skipSynthesizeIn
|
|
86
86
|
}
|
87
87
|
const localEntryTypeEvaluator = [];
|
88
88
|
let sawKeywordOnlySeparator = false;
|
89
|
-
classType.details.fields.forEach((symbol) => {
|
89
|
+
classType.details.fields.forEach((symbol, name) => {
|
90
90
|
var _a, _b, _c;
|
91
|
-
if (
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
91
|
+
if (symbol.isIgnoredForProtocolMatch()) {
|
92
|
+
return;
|
93
|
+
}
|
94
|
+
// Apparently, `__hash__` is special-cased in a dataclass. I can't find
|
95
|
+
// this in the spec, but the runtime seems to treat is specially.
|
96
|
+
if (name === '__hash__') {
|
97
|
+
return;
|
98
|
+
}
|
99
|
+
// Only variables (not functions, classes, etc.) are considered.
|
100
|
+
const classVarDecl = symbol.getTypedDeclarations().find((decl) => {
|
101
|
+
if (decl.type !== 1 /* Variable */) {
|
102
|
+
return false;
|
103
|
+
}
|
104
|
+
const container = (0, parseTreeUtils_1.getEnclosingClassOrFunction)(decl.node);
|
105
|
+
if (!container || container.nodeType !== 10 /* Class */) {
|
106
|
+
return false;
|
107
|
+
}
|
108
|
+
return true;
|
109
|
+
});
|
110
|
+
if (classVarDecl) {
|
111
|
+
let statement = classVarDecl.node;
|
112
|
+
while (statement) {
|
113
|
+
if (statement.nodeType === 3 /* Assignment */) {
|
114
|
+
break;
|
100
115
|
}
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
let statement = classVarDecl.node;
|
105
|
-
while (statement) {
|
106
|
-
if (statement.nodeType === 3 /* Assignment */) {
|
107
|
-
break;
|
116
|
+
if (statement.nodeType === 54 /* TypeAnnotation */) {
|
117
|
+
if (((_a = statement.parent) === null || _a === void 0 ? void 0 : _a.nodeType) === 3 /* Assignment */) {
|
118
|
+
statement = statement.parent;
|
108
119
|
}
|
109
|
-
|
110
|
-
if (((_a = statement.parent) === null || _a === void 0 ? void 0 : _a.nodeType) === 3 /* Assignment */) {
|
111
|
-
statement = statement.parent;
|
112
|
-
}
|
113
|
-
break;
|
114
|
-
}
|
115
|
-
statement = statement.parent;
|
120
|
+
break;
|
116
121
|
}
|
117
|
-
|
118
|
-
|
122
|
+
statement = statement.parent;
|
123
|
+
}
|
124
|
+
if (!statement) {
|
125
|
+
return;
|
126
|
+
}
|
127
|
+
let variableNameNode;
|
128
|
+
let aliasName;
|
129
|
+
let variableTypeEvaluator;
|
130
|
+
let hasDefaultValue = false;
|
131
|
+
let isKeywordOnly = types_1.ClassType.isDataClassKeywordOnlyParams(classType) || sawKeywordOnlySeparator;
|
132
|
+
let defaultValueExpression;
|
133
|
+
let includeInInit = true;
|
134
|
+
let converter;
|
135
|
+
if (statement.nodeType === 3 /* Assignment */) {
|
136
|
+
if (statement.leftExpression.nodeType === 54 /* TypeAnnotation */ &&
|
137
|
+
statement.leftExpression.valueExpression.nodeType === 38 /* Name */) {
|
138
|
+
variableNameNode = statement.leftExpression.valueExpression;
|
139
|
+
const assignmentStatement = statement;
|
140
|
+
variableTypeEvaluator = () => evaluator.getTypeOfAnnotation(assignmentStatement.leftExpression.typeAnnotation, {
|
141
|
+
isVariableAnnotation: true,
|
142
|
+
allowFinal: true,
|
143
|
+
allowClassVar: true,
|
144
|
+
});
|
119
145
|
}
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
-
isVariableAnnotation: true,
|
135
|
-
allowFinal: true,
|
136
|
-
allowClassVar: true,
|
137
|
-
});
|
138
|
-
}
|
139
|
-
hasDefaultValue = true;
|
140
|
-
defaultValueExpression = statement.rightExpression;
|
141
|
-
// If the RHS of the assignment is assigning a field instance where the
|
142
|
-
// "init" parameter is set to false, do not include it in the init method.
|
143
|
-
if (statement.rightExpression.nodeType === 9 /* Call */) {
|
144
|
-
const callTypeResult = evaluator.getTypeOfExpression(statement.rightExpression.leftExpression, 16777218 /* CallBaseDefaults */);
|
145
|
-
const callType = callTypeResult.type;
|
146
|
-
if (isDataclassFieldConstructor(callType, ((_b = classType.details.dataClassBehaviors) === null || _b === void 0 ? void 0 : _b.fieldDescriptorNames) || [])) {
|
147
|
-
const initArg = statement.rightExpression.arguments.find((arg) => { var _a; return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'init'; });
|
148
|
-
if (initArg && initArg.valueExpression) {
|
149
|
-
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
|
150
|
-
const value = (0, staticExpressions_1.evaluateStaticBoolExpression)(initArg.valueExpression, fileInfo.executionEnvironment, fileInfo.definedConstants);
|
151
|
-
if (value === false) {
|
152
|
-
includeInInit = false;
|
153
|
-
}
|
146
|
+
hasDefaultValue = true;
|
147
|
+
defaultValueExpression = statement.rightExpression;
|
148
|
+
// If the RHS of the assignment is assigning a field instance where the
|
149
|
+
// "init" parameter is set to false, do not include it in the init method.
|
150
|
+
if (statement.rightExpression.nodeType === 9 /* Call */) {
|
151
|
+
const callTypeResult = evaluator.getTypeOfExpression(statement.rightExpression.leftExpression, 16777218 /* CallBaseDefaults */);
|
152
|
+
const callType = callTypeResult.type;
|
153
|
+
if (isDataclassFieldConstructor(callType, ((_b = classType.details.dataClassBehaviors) === null || _b === void 0 ? void 0 : _b.fieldDescriptorNames) || [])) {
|
154
|
+
const initArg = statement.rightExpression.arguments.find((arg) => { var _a; return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'init'; });
|
155
|
+
if (initArg && initArg.valueExpression) {
|
156
|
+
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
|
157
|
+
const value = (0, staticExpressions_1.evaluateStaticBoolExpression)(initArg.valueExpression, fileInfo.executionEnvironment, fileInfo.definedConstants);
|
158
|
+
if (value === false) {
|
159
|
+
includeInInit = false;
|
154
160
|
}
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
161
|
-
|
162
|
-
|
163
|
-
|
164
|
-
}
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
else if ((0, types_1.isOverloadedFunction)(initCall)) {
|
172
|
-
callTarget = evaluator.getBestOverloadForArguments(statement.rightExpression, { type: initCall }, statement.rightExpression.arguments);
|
173
|
-
}
|
161
|
+
}
|
162
|
+
else {
|
163
|
+
// See if the field constructor has an `init` parameter with
|
164
|
+
// a default value.
|
165
|
+
let callTarget;
|
166
|
+
if ((0, types_1.isFunction)(callType)) {
|
167
|
+
callTarget = callType;
|
168
|
+
}
|
169
|
+
else if ((0, types_1.isOverloadedFunction)(callType)) {
|
170
|
+
callTarget = evaluator.getBestOverloadForArguments(statement.rightExpression, { type: callType, isIncomplete: callTypeResult.isIncomplete }, statement.rightExpression.arguments);
|
171
|
+
}
|
172
|
+
else if ((0, types_1.isInstantiableClass)(callType)) {
|
173
|
+
const initCall = evaluator.getBoundMethod(callType, '__init__');
|
174
|
+
if (initCall) {
|
175
|
+
if ((0, types_1.isFunction)(initCall)) {
|
176
|
+
callTarget = initCall;
|
174
177
|
}
|
175
|
-
|
176
|
-
|
177
|
-
const initParam = callTarget.details.parameters.find((p) => p.name === 'init');
|
178
|
-
if (initParam && initParam.defaultValueExpression && initParam.hasDeclaredType) {
|
179
|
-
if ((0, types_1.isClass)(initParam.type) &&
|
180
|
-
types_1.ClassType.isBuiltIn(initParam.type, 'bool') &&
|
181
|
-
(0, typeUtils_1.isLiteralType)(initParam.type)) {
|
182
|
-
if (initParam.type.literalValue === false) {
|
183
|
-
includeInInit = false;
|
184
|
-
}
|
185
|
-
}
|
178
|
+
else if ((0, types_1.isOverloadedFunction)(initCall)) {
|
179
|
+
callTarget = evaluator.getBestOverloadForArguments(statement.rightExpression, { type: initCall }, statement.rightExpression.arguments);
|
186
180
|
}
|
187
181
|
}
|
188
182
|
}
|
189
|
-
|
190
|
-
|
191
|
-
|
192
|
-
|
193
|
-
|
194
|
-
|
195
|
-
|
196
|
-
|
197
|
-
|
183
|
+
if (callTarget) {
|
184
|
+
const initParam = callTarget.details.parameters.find((p) => p.name === 'init');
|
185
|
+
if (initParam && initParam.defaultValueExpression && initParam.hasDeclaredType) {
|
186
|
+
if ((0, types_1.isClass)(initParam.type) &&
|
187
|
+
types_1.ClassType.isBuiltIn(initParam.type, 'bool') &&
|
188
|
+
(0, typeUtils_1.isLiteralType)(initParam.type)) {
|
189
|
+
if (initParam.type.literalValue === false) {
|
190
|
+
includeInInit = false;
|
191
|
+
}
|
192
|
+
}
|
198
193
|
}
|
199
194
|
}
|
200
|
-
|
201
|
-
|
202
|
-
|
203
|
-
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
if (defaultArg === null || defaultArg === void 0 ? void 0 : defaultArg.valueExpression) {
|
208
|
-
defaultValueExpression = defaultArg.valueExpression;
|
209
|
-
}
|
210
|
-
const aliasArg = statement.rightExpression.arguments.find((arg) => { var _a; return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'alias'; });
|
211
|
-
if (aliasArg) {
|
212
|
-
const valueType = evaluator.getTypeOfExpression(aliasArg.valueExpression).type;
|
213
|
-
if ((0, types_1.isClassInstance)(valueType) &&
|
214
|
-
types_1.ClassType.isBuiltIn(valueType, 'str') &&
|
215
|
-
(0, typeUtils_1.isLiteralType)(valueType)) {
|
216
|
-
aliasName = valueType.literalValue;
|
217
|
-
}
|
195
|
+
}
|
196
|
+
const kwOnlyArg = statement.rightExpression.arguments.find((arg) => { var _a; return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'kw_only'; });
|
197
|
+
if (kwOnlyArg && kwOnlyArg.valueExpression) {
|
198
|
+
const fileInfo = AnalyzerNodeInfo.getFileInfo(node);
|
199
|
+
const value = (0, staticExpressions_1.evaluateStaticBoolExpression)(kwOnlyArg.valueExpression, fileInfo.executionEnvironment, fileInfo.definedConstants);
|
200
|
+
if (value === false) {
|
201
|
+
isKeywordOnly = false;
|
218
202
|
}
|
219
|
-
|
220
|
-
|
221
|
-
converter = converterArg;
|
203
|
+
else if (value === true) {
|
204
|
+
isKeywordOnly = true;
|
222
205
|
}
|
223
206
|
}
|
224
|
-
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
229
|
-
const annotationStatement = statement;
|
230
|
-
variableTypeEvaluator = () => evaluator.getTypeOfAnnotation(annotationStatement.typeAnnotation, {
|
231
|
-
isVariableAnnotation: true,
|
232
|
-
allowFinal: true,
|
233
|
-
allowClassVar: true,
|
207
|
+
const defaultArg = statement.rightExpression.arguments.find((arg) => {
|
208
|
+
var _a, _b, _c;
|
209
|
+
return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'default' ||
|
210
|
+
((_b = arg.name) === null || _b === void 0 ? void 0 : _b.value) === 'default_factory' ||
|
211
|
+
((_c = arg.name) === null || _c === void 0 ? void 0 : _c.value) === 'factory';
|
234
212
|
});
|
235
|
-
|
236
|
-
if (
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
213
|
+
hasDefaultValue = !!defaultArg;
|
214
|
+
if (defaultArg === null || defaultArg === void 0 ? void 0 : defaultArg.valueExpression) {
|
215
|
+
defaultValueExpression = defaultArg.valueExpression;
|
216
|
+
}
|
217
|
+
const aliasArg = statement.rightExpression.arguments.find((arg) => { var _a; return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'alias'; });
|
218
|
+
if (aliasArg) {
|
219
|
+
const valueType = evaluator.getTypeOfExpression(aliasArg.valueExpression).type;
|
220
|
+
if ((0, types_1.isClassInstance)(valueType) &&
|
221
|
+
types_1.ClassType.isBuiltIn(valueType, 'str') &&
|
222
|
+
(0, typeUtils_1.isLiteralType)(valueType)) {
|
223
|
+
aliasName = valueType.literalValue;
|
242
224
|
}
|
243
225
|
}
|
226
|
+
const converterArg = statement.rightExpression.arguments.find((arg) => { var _a; return ((_a = arg.name) === null || _a === void 0 ? void 0 : _a.value) === 'converter'; });
|
227
|
+
if (converterArg && converterArg.valueExpression) {
|
228
|
+
converter = converterArg;
|
229
|
+
}
|
244
230
|
}
|
245
231
|
}
|
246
|
-
|
247
|
-
|
248
|
-
|
249
|
-
|
250
|
-
const
|
251
|
-
|
252
|
-
|
253
|
-
|
254
|
-
|
255
|
-
|
256
|
-
|
257
|
-
|
258
|
-
|
259
|
-
|
232
|
+
}
|
233
|
+
else if (statement.nodeType === 54 /* TypeAnnotation */) {
|
234
|
+
if (statement.valueExpression.nodeType === 38 /* Name */) {
|
235
|
+
variableNameNode = statement.valueExpression;
|
236
|
+
const annotationStatement = statement;
|
237
|
+
variableTypeEvaluator = () => evaluator.getTypeOfAnnotation(annotationStatement.typeAnnotation, {
|
238
|
+
isVariableAnnotation: true,
|
239
|
+
allowFinal: true,
|
240
|
+
allowClassVar: true,
|
241
|
+
});
|
242
|
+
// Is this a KW_ONLY separator introduced in Python 3.10?
|
243
|
+
if (statement.valueExpression.value === '_') {
|
244
|
+
const annotatedType = variableTypeEvaluator();
|
245
|
+
if ((0, types_1.isClassInstance)(annotatedType) && types_1.ClassType.isBuiltIn(annotatedType, 'KW_ONLY')) {
|
246
|
+
sawKeywordOnlySeparator = true;
|
247
|
+
variableNameNode = undefined;
|
248
|
+
variableTypeEvaluator = undefined;
|
260
249
|
}
|
261
|
-
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
266
|
-
|
267
|
-
|
268
|
-
|
269
|
-
|
270
|
-
|
271
|
-
|
272
|
-
|
273
|
-
|
274
|
-
|
250
|
+
}
|
251
|
+
}
|
252
|
+
}
|
253
|
+
if (variableNameNode && variableTypeEvaluator) {
|
254
|
+
const variableName = variableNameNode.value;
|
255
|
+
// Don't include class vars. PEP 557 indicates that they shouldn't
|
256
|
+
// be considered data class entries.
|
257
|
+
const variableSymbol = classType.details.fields.get(variableName);
|
258
|
+
const isFinal = variableSymbol === null || variableSymbol === void 0 ? void 0 : variableSymbol.getDeclarations().some((decl) => decl.type === 1 /* Variable */ && decl.isFinal);
|
259
|
+
if ((variableSymbol === null || variableSymbol === void 0 ? void 0 : variableSymbol.isClassVar()) && !isFinal) {
|
260
|
+
// If an ancestor class declared an instance variable but this dataclass
|
261
|
+
// declares a ClassVar, delete the older one from the full data class entries.
|
262
|
+
// We exclude final variables here because a Final type annotation is implicitly
|
263
|
+
// considered a ClassVar by the binder, but dataclass rules are different.
|
264
|
+
const index = fullDataClassEntries.findIndex((p) => p.name === variableName);
|
265
|
+
if (index >= 0) {
|
266
|
+
fullDataClassEntries.splice(index, 1);
|
267
|
+
}
|
268
|
+
const dataClassEntry = {
|
269
|
+
name: variableName,
|
270
|
+
classType,
|
271
|
+
alias: aliasName,
|
272
|
+
isKeywordOnly: false,
|
273
|
+
hasDefault: hasDefaultValue,
|
274
|
+
defaultValueExpression,
|
275
|
+
includeInInit,
|
276
|
+
nameNode: variableNameNode,
|
277
|
+
type: types_1.UnknownType.create(),
|
278
|
+
isClassVar: true,
|
279
|
+
converter,
|
280
|
+
};
|
281
|
+
localDataClassEntries.push(dataClassEntry);
|
282
|
+
}
|
283
|
+
else {
|
284
|
+
// Create a new data class entry, but defer evaluation of the type until
|
285
|
+
// we've compiled the full list of data class entries for this class. This
|
286
|
+
// allows us to handle circular references in types.
|
287
|
+
const dataClassEntry = {
|
288
|
+
name: variableName,
|
289
|
+
classType,
|
290
|
+
alias: aliasName,
|
291
|
+
isKeywordOnly,
|
292
|
+
hasDefault: hasDefaultValue,
|
293
|
+
defaultValueExpression,
|
294
|
+
includeInInit,
|
295
|
+
nameNode: variableNameNode,
|
296
|
+
type: types_1.UnknownType.create(),
|
297
|
+
isClassVar: false,
|
298
|
+
converter,
|
299
|
+
};
|
300
|
+
localEntryTypeEvaluator.push({ entry: dataClassEntry, evaluator: variableTypeEvaluator });
|
301
|
+
// Add the new entry to the local entry list.
|
302
|
+
let insertIndex = localDataClassEntries.findIndex((e) => e.name === variableName);
|
303
|
+
if (insertIndex >= 0) {
|
304
|
+
localDataClassEntries[insertIndex] = dataClassEntry;
|
275
305
|
}
|
276
306
|
else {
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
type: types_1.UnknownType.create(),
|
290
|
-
isClassVar: false,
|
291
|
-
converter,
|
292
|
-
};
|
293
|
-
localEntryTypeEvaluator.push({ entry: dataClassEntry, evaluator: variableTypeEvaluator });
|
294
|
-
// Add the new entry to the local entry list.
|
295
|
-
let insertIndex = localDataClassEntries.findIndex((e) => e.name === variableName);
|
296
|
-
if (insertIndex >= 0) {
|
297
|
-
localDataClassEntries[insertIndex] = dataClassEntry;
|
298
|
-
}
|
299
|
-
else {
|
300
|
-
localDataClassEntries.push(dataClassEntry);
|
301
|
-
}
|
302
|
-
// Add the new entry to the full entry list.
|
303
|
-
insertIndex = fullDataClassEntries.findIndex((p) => p.name === variableName);
|
304
|
-
if (insertIndex >= 0) {
|
305
|
-
const oldEntry = fullDataClassEntries[insertIndex];
|
306
|
-
// While this isn't documented behavior, it appears that the dataclass implementation
|
307
|
-
// causes overridden variables to "inherit" default values from parent classes.
|
308
|
-
if (!dataClassEntry.hasDefault && oldEntry.hasDefault && oldEntry.includeInInit) {
|
309
|
-
dataClassEntry.hasDefault = true;
|
310
|
-
dataClassEntry.defaultValueExpression = oldEntry.defaultValueExpression;
|
311
|
-
hasDefaultValue = true;
|
312
|
-
}
|
313
|
-
fullDataClassEntries[insertIndex] = dataClassEntry;
|
314
|
-
}
|
315
|
-
else {
|
316
|
-
fullDataClassEntries.push(dataClassEntry);
|
317
|
-
insertIndex = fullDataClassEntries.length - 1;
|
307
|
+
localDataClassEntries.push(dataClassEntry);
|
308
|
+
}
|
309
|
+
// Add the new entry to the full entry list.
|
310
|
+
insertIndex = fullDataClassEntries.findIndex((p) => p.name === variableName);
|
311
|
+
if (insertIndex >= 0) {
|
312
|
+
const oldEntry = fullDataClassEntries[insertIndex];
|
313
|
+
// While this isn't documented behavior, it appears that the dataclass implementation
|
314
|
+
// causes overridden variables to "inherit" default values from parent classes.
|
315
|
+
if (!dataClassEntry.hasDefault && oldEntry.hasDefault && oldEntry.includeInInit) {
|
316
|
+
dataClassEntry.hasDefault = true;
|
317
|
+
dataClassEntry.defaultValueExpression = oldEntry.defaultValueExpression;
|
318
|
+
hasDefaultValue = true;
|
318
319
|
}
|
319
|
-
|
320
|
-
|
321
|
-
|
322
|
-
|
323
|
-
|
324
|
-
|
325
|
-
|
320
|
+
fullDataClassEntries[insertIndex] = dataClassEntry;
|
321
|
+
}
|
322
|
+
else {
|
323
|
+
fullDataClassEntries.push(dataClassEntry);
|
324
|
+
insertIndex = fullDataClassEntries.length - 1;
|
325
|
+
}
|
326
|
+
// If we've already seen a entry with a default value defined,
|
327
|
+
// all subsequent entries must also have default values.
|
328
|
+
if (!isKeywordOnly && includeInInit && !skipSynthesizeInit && !hasDefaultValue) {
|
329
|
+
const firstDefaultValueIndex = fullDataClassEntries.findIndex((p) => p.hasDefault && p.includeInInit && !p.isKeywordOnly);
|
330
|
+
if (firstDefaultValueIndex >= 0 && firstDefaultValueIndex < insertIndex) {
|
331
|
+
evaluator.addDiagnostic(AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.dataClassFieldWithDefault(), variableNameNode);
|
326
332
|
}
|
327
333
|
}
|
328
334
|
}
|
329
335
|
}
|
330
|
-
|
331
|
-
|
332
|
-
|
333
|
-
|
334
|
-
|
335
|
-
|
336
|
-
|
337
|
-
|
338
|
-
|
339
|
-
|
340
|
-
|
341
|
-
|
342
|
-
|
343
|
-
|
344
|
-
|
345
|
-
|
346
|
-
|
347
|
-
|
348
|
-
|
349
|
-
|
350
|
-
|
351
|
-
|
352
|
-
|
336
|
+
}
|
337
|
+
else {
|
338
|
+
// The symbol had no declared type, so it is (mostly) ignored by dataclasses.
|
339
|
+
// However, if it is assigned a field descriptor, it will result in a
|
340
|
+
// runtime exception.
|
341
|
+
const declarations = symbol.getDeclarations();
|
342
|
+
if (declarations.length === 0) {
|
343
|
+
return;
|
344
|
+
}
|
345
|
+
const lastDecl = declarations[declarations.length - 1];
|
346
|
+
if (lastDecl.type !== 1 /* Variable */) {
|
347
|
+
return;
|
348
|
+
}
|
349
|
+
const statement = lastDecl.node.parent;
|
350
|
+
if (!statement || statement.nodeType !== 3 /* Assignment */) {
|
351
|
+
return;
|
352
|
+
}
|
353
|
+
// If the RHS of the assignment is assigning a field instance where the
|
354
|
+
// "init" parameter is set to false, do not include it in the init method.
|
355
|
+
if (statement.rightExpression.nodeType === 9 /* Call */) {
|
356
|
+
const callType = evaluator.getTypeOfExpression(statement.rightExpression.leftExpression, 16777218 /* CallBaseDefaults */).type;
|
357
|
+
if (isDataclassFieldConstructor(callType, ((_c = classType.details.dataClassBehaviors) === null || _c === void 0 ? void 0 : _c.fieldDescriptorNames) || [])) {
|
358
|
+
evaluator.addDiagnostic(AnalyzerNodeInfo.getFileInfo(node).diagnosticRuleSet.reportGeneralTypeIssues, diagnosticRules_1.DiagnosticRule.reportGeneralTypeIssues, localize_1.Localizer.Diagnostic.dataClassFieldWithoutAnnotation(), statement.rightExpression);
|
353
359
|
}
|
354
360
|
}
|
355
361
|
}
|