@zzzen/pyright-internal 1.2.0-dev.20230507 → 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.
- package/dist/analyzer/backgroundAnalysisProgram.d.ts +1 -1
- package/dist/analyzer/checker.js +37 -2
- package/dist/analyzer/checker.js.map +1 -1
- package/dist/analyzer/constraintSolver.js +14 -15
- package/dist/analyzer/constraintSolver.js.map +1 -1
- package/dist/analyzer/constructors.js +246 -189
- package/dist/analyzer/constructors.js.map +1 -1
- package/dist/analyzer/dataClasses.js +2 -2
- package/dist/analyzer/dataClasses.js.map +1 -1
- package/dist/analyzer/docStringConversion.js +1 -1
- package/dist/analyzer/docStringConversion.js.map +1 -1
- package/dist/analyzer/enums.js +8 -0
- package/dist/analyzer/enums.js.map +1 -1
- package/dist/analyzer/importResolver.js +47 -29
- package/dist/analyzer/importResolver.js.map +1 -1
- package/dist/analyzer/namedTuples.js +2 -5
- package/dist/analyzer/namedTuples.js.map +1 -1
- package/dist/analyzer/program.d.ts +7 -17
- package/dist/analyzer/program.js +32 -247
- package/dist/analyzer/program.js.map +1 -1
- package/dist/analyzer/protocols.js +1 -1
- package/dist/analyzer/protocols.js.map +1 -1
- package/dist/analyzer/service.d.ts +4 -12
- package/dist/analyzer/service.js +12 -23
- package/dist/analyzer/service.js.map +1 -1
- package/dist/analyzer/sourceFile.d.ts +2 -11
- package/dist/analyzer/sourceFile.js +11 -74
- package/dist/analyzer/sourceFile.js.map +1 -1
- package/dist/analyzer/symbol.d.ts +3 -1
- package/dist/analyzer/symbol.js +5 -0
- package/dist/analyzer/symbol.js.map +1 -1
- package/dist/analyzer/typeEvaluator.js +362 -142
- package/dist/analyzer/typeEvaluator.js.map +1 -1
- package/dist/analyzer/typeEvaluatorTypes.d.ts +4 -0
- package/dist/analyzer/typeEvaluatorTypes.js.map +1 -1
- package/dist/analyzer/typePrinter.d.ts +3 -3
- package/dist/analyzer/typePrinter.js +247 -100
- package/dist/analyzer/typePrinter.js.map +1 -1
- package/dist/analyzer/typeUtils.d.ts +12 -7
- package/dist/analyzer/typeUtils.js +173 -48
- package/dist/analyzer/typeUtils.js.map +1 -1
- package/dist/analyzer/typeVarContext.d.ts +1 -2
- package/dist/analyzer/typeVarContext.js +14 -32
- package/dist/analyzer/typeVarContext.js.map +1 -1
- package/dist/analyzer/types.d.ts +3 -2
- package/dist/analyzer/types.js +13 -10
- package/dist/analyzer/types.js.map +1 -1
- package/dist/backgroundAnalysisBase.d.ts +1 -1
- package/dist/backgroundAnalysisBase.js +16 -0
- package/dist/backgroundAnalysisBase.js.map +1 -1
- package/dist/commands/dumpFileDebugInfoCommand.js +0 -1
- package/dist/commands/dumpFileDebugInfoCommand.js.map +1 -1
- package/dist/common/extensibility.d.ts +26 -3
- package/dist/common/extensibility.js.map +1 -1
- package/dist/common/logTracker.d.ts +2 -0
- package/dist/common/logTracker.js +8 -1
- package/dist/common/logTracker.js.map +1 -1
- package/dist/common/lspUtils.d.ts +4 -1
- package/dist/common/lspUtils.js +38 -1
- package/dist/common/lspUtils.js.map +1 -1
- package/dist/common/pythonVersion.d.ts +2 -1
- package/dist/common/pythonVersion.js +1 -0
- package/dist/common/pythonVersion.js.map +1 -1
- package/dist/common/workspaceEditUtils.d.ts +3 -3
- package/dist/common/workspaceEditUtils.js +10 -10
- package/dist/common/workspaceEditUtils.js.map +1 -1
- package/dist/languageServerBase.d.ts +2 -5
- package/dist/languageServerBase.js +33 -60
- package/dist/languageServerBase.js.map +1 -1
- package/dist/languageService/autoImporter.d.ts +50 -51
- package/dist/languageService/autoImporter.js +125 -210
- package/dist/languageService/autoImporter.js.map +1 -1
- package/dist/languageService/callHierarchyProvider.js +6 -32
- package/dist/languageService/callHierarchyProvider.js.map +1 -1
- package/dist/languageService/completionProvider.d.ts +40 -79
- package/dist/languageService/completionProvider.js +571 -811
- package/dist/languageService/completionProvider.js.map +1 -1
- package/dist/languageService/documentSymbolCollector.d.ts +2 -2
- package/dist/languageService/documentSymbolCollector.js +33 -23
- package/dist/languageService/documentSymbolCollector.js.map +1 -1
- package/dist/languageService/documentSymbolProvider.d.ts +13 -35
- package/dist/languageService/documentSymbolProvider.js +52 -264
- package/dist/languageService/documentSymbolProvider.js.map +1 -1
- package/dist/languageService/hoverProvider.d.ts +1 -3
- package/dist/languageService/hoverProvider.js +11 -97
- package/dist/languageService/hoverProvider.js.map +1 -1
- package/dist/languageService/referencesProvider.d.ts +3 -3
- package/dist/languageService/referencesProvider.js +5 -7
- package/dist/languageService/referencesProvider.js.map +1 -1
- package/dist/languageService/renameProvider.d.ts +0 -1
- package/dist/languageService/renameProvider.js +2 -6
- package/dist/languageService/renameProvider.js.map +1 -1
- package/dist/languageService/symbolIndexer.d.ts +31 -0
- package/dist/languageService/symbolIndexer.js +105 -0
- package/dist/languageService/symbolIndexer.js.map +1 -0
- package/dist/languageService/tooltipUtils.d.ts +8 -1
- package/dist/languageService/tooltipUtils.js +102 -1
- package/dist/languageService/tooltipUtils.js.map +1 -1
- package/dist/languageService/workspaceSymbolProvider.d.ts +17 -0
- package/dist/languageService/workspaceSymbolProvider.js +133 -0
- package/dist/languageService/workspaceSymbolProvider.js.map +1 -0
- package/dist/localization/localize.d.ts +16 -1
- package/dist/localization/localize.js +9 -1
- package/dist/localization/localize.js.map +1 -1
- package/dist/localization/package.nls.en-us.json +9 -1
- package/dist/parser/parser.js +3 -0
- package/dist/parser/parser.js.map +1 -1
- package/dist/pyright.js +26 -4
- package/dist/pyright.js.map +1 -1
- package/dist/tests/chainedSourceFiles.test.js +15 -20
- package/dist/tests/chainedSourceFiles.test.js.map +1 -1
- package/dist/tests/checker.test.js +14 -0
- package/dist/tests/checker.test.js.map +1 -1
- package/dist/tests/completions.test.js +11 -236
- package/dist/tests/completions.test.js.map +1 -1
- package/dist/tests/docStringConversion.test.js +36 -2
- package/dist/tests/docStringConversion.test.js.map +1 -1
- package/dist/tests/fourslash/completions.override2.fourslash.js +1 -16
- package/dist/tests/fourslash/completions.override2.fourslash.js.map +1 -1
- package/dist/tests/harness/fourslash/testState.d.ts +14 -8
- package/dist/tests/harness/fourslash/testState.js +25 -36
- package/dist/tests/harness/fourslash/testState.js.map +1 -1
- package/dist/tests/importResolver.test.js +81 -1
- package/dist/tests/importResolver.test.js.map +1 -1
- package/dist/tests/typeEvaluator2.test.js +12 -0
- package/dist/tests/typeEvaluator2.test.js.map +1 -1
- package/dist/tests/typeEvaluator3.test.js +4 -0
- package/dist/tests/typeEvaluator3.test.js.map +1 -1
- package/dist/tests/typeEvaluator5.test.js +21 -9
- package/dist/tests/typeEvaluator5.test.js.map +1 -1
- package/dist/tests/workspaceEditUtils.test.js +15 -10
- package/dist/tests/workspaceEditUtils.test.js.map +1 -1
- package/package.json +1 -1
- package/dist/languageService/importAdder.d.ts +0 -40
- package/dist/languageService/importAdder.js +0 -388
- package/dist/languageService/importAdder.js.map +0 -1
- package/dist/tests/fourslash/completions.commitChars.fourslash.d.ts +0 -1
- package/dist/tests/fourslash/completions.commitChars.fourslash.js +0 -81
- package/dist/tests/fourslash/completions.commitChars.fourslash.js.map +0 -1
- package/dist/tests/importAdder.test.d.ts +0 -1
- package/dist/tests/importAdder.test.js +0 -1325
- package/dist/tests/importAdder.test.js.map +0 -1
@@ -37,7 +37,6 @@ const docStringConversion_1 = require("../analyzer/docStringConversion");
|
|
37
37
|
const parameterUtils_1 = require("../analyzer/parameterUtils");
|
38
38
|
const ParseTreeUtils = __importStar(require("../analyzer/parseTreeUtils"));
|
39
39
|
const parseTreeUtils_1 = require("../analyzer/parseTreeUtils");
|
40
|
-
const pythonPathUtils_1 = require("../analyzer/pythonPathUtils");
|
41
40
|
const scopeUtils_1 = require("../analyzer/scopeUtils");
|
42
41
|
const sourceMapper_1 = require("../analyzer/sourceMapper");
|
43
42
|
const SymbolNameUtils = __importStar(require("../analyzer/symbolNameUtils"));
|
@@ -48,23 +47,19 @@ const typePrinter_1 = require("../analyzer/typePrinter");
|
|
48
47
|
const types_1 = require("../analyzer/types");
|
49
48
|
const typeUtils_1 = require("../analyzer/typeUtils");
|
50
49
|
const cancellationUtils_1 = require("../common/cancellationUtils");
|
51
|
-
const collectionUtils_1 = require("../common/collectionUtils");
|
52
50
|
const debug = __importStar(require("../common/debug"));
|
53
51
|
const debug_1 = require("../common/debug");
|
54
52
|
const lspUtils_1 = require("../common/lspUtils");
|
55
|
-
const pathUtils_1 = require("../common/pathUtils");
|
56
53
|
const positionUtils_1 = require("../common/positionUtils");
|
57
54
|
const pythonVersion_1 = require("../common/pythonVersion");
|
58
55
|
const StringUtils = __importStar(require("../common/stringUtils"));
|
59
56
|
const textRange_1 = require("../common/textRange");
|
60
57
|
const textRange_2 = require("../common/textRange");
|
61
|
-
const timing_1 = require("../common/timing");
|
62
58
|
const workspaceEditUtils_1 = require("../common/workspaceEditUtils");
|
63
59
|
const parseNodes_1 = require("../parser/parseNodes");
|
64
60
|
const autoImporter_1 = require("./autoImporter");
|
65
61
|
const completionProviderUtils_1 = require("./completionProviderUtils");
|
66
62
|
const documentSymbolCollector_1 = require("./documentSymbolCollector");
|
67
|
-
const importAdder_1 = require("./importAdder");
|
68
63
|
const tooltipUtils_1 = require("./tooltipUtils");
|
69
64
|
var Keywords;
|
70
65
|
(function (Keywords) {
|
@@ -158,29 +153,438 @@ const similarityLimit = 0.25;
|
|
158
153
|
// We'll remember this many completions in the MRU list.
|
159
154
|
const maxRecentCompletions = 128;
|
160
155
|
class CompletionProvider {
|
161
|
-
constructor(
|
162
|
-
this.
|
156
|
+
constructor(program, _workspacePath, filePath, position, options, cancellationToken) {
|
157
|
+
this.program = program;
|
163
158
|
this._workspacePath = _workspacePath;
|
164
|
-
this.
|
165
|
-
this.
|
166
|
-
this.
|
167
|
-
this.
|
168
|
-
this._autoImportMaps = _autoImportMaps;
|
169
|
-
this._cancellationToken = _cancellationToken;
|
159
|
+
this.filePath = filePath;
|
160
|
+
this.position = position;
|
161
|
+
this.options = options;
|
162
|
+
this.cancellationToken = cancellationToken;
|
170
163
|
// Indicate whether invocation is inside of string literal.
|
171
164
|
this._insideStringLiteral = undefined;
|
172
|
-
this.
|
173
|
-
this.
|
174
|
-
this.
|
175
|
-
/* mapCompiled */ true);
|
165
|
+
this.execEnv = this.configOptions.findExecEnvironment(this.filePath);
|
166
|
+
this.parseResults = this.program.getParseResults(this.filePath);
|
167
|
+
this.sourceMapper = this.program.getSourceMapper(this.filePath, this.cancellationToken, /* mapCompiled */ true);
|
176
168
|
}
|
177
|
-
|
169
|
+
getCompletions() {
|
170
|
+
if (!this.program.getSourceFileInfo(this.filePath)) {
|
171
|
+
return null;
|
172
|
+
}
|
173
|
+
const completionMap = this._getCompletions();
|
174
|
+
return vscode_languageserver_1.CompletionList.create(completionMap === null || completionMap === void 0 ? void 0 : completionMap.toArray());
|
175
|
+
}
|
176
|
+
// When the user selects a completion, this callback is invoked,
|
177
|
+
// allowing us to record what was selected. This allows us to
|
178
|
+
// build our MRU cache so we can better predict entries.
|
179
|
+
resolveCompletionItem(completionItem) {
|
180
|
+
(0, cancellationUtils_1.throwIfCancellationRequested)(this.cancellationToken);
|
181
|
+
const completionItemData = (0, lspUtils_1.fromLSPAny)(completionItem.data);
|
182
|
+
const label = completionItem.label;
|
183
|
+
let autoImportText = '';
|
184
|
+
if (completionItemData.autoImportText) {
|
185
|
+
autoImportText = completionItemData.autoImportText;
|
186
|
+
}
|
187
|
+
const curIndex = CompletionProvider._mostRecentCompletions.findIndex((item) => item.label === label && item.autoImportText === autoImportText);
|
188
|
+
if (curIndex > 0) {
|
189
|
+
// If there's an existing entry with the same name that's not at the
|
190
|
+
// beginning of the array, remove it.
|
191
|
+
CompletionProvider._mostRecentCompletions = CompletionProvider._mostRecentCompletions.splice(curIndex, 1);
|
192
|
+
}
|
193
|
+
if (curIndex !== 0) {
|
194
|
+
// Add to the start of the array.
|
195
|
+
CompletionProvider._mostRecentCompletions.unshift({ label, autoImportText });
|
196
|
+
}
|
197
|
+
if (CompletionProvider._mostRecentCompletions.length > maxRecentCompletions) {
|
198
|
+
// Prevent the MRU list from growing indefinitely.
|
199
|
+
CompletionProvider._mostRecentCompletions.pop();
|
200
|
+
}
|
201
|
+
if (!completionItemData.symbolLabel) {
|
202
|
+
return;
|
203
|
+
}
|
204
|
+
if (completionItemData.modulePath) {
|
205
|
+
const documentation = (0, typeDocStringUtils_1.getModuleDocStringFromPaths)([completionItemData.modulePath], this.sourceMapper);
|
206
|
+
if (!documentation) {
|
207
|
+
return;
|
208
|
+
}
|
209
|
+
if (this.options.format === vscode_languageserver_1.MarkupKind.Markdown) {
|
210
|
+
const markdownString = (0, docStringConversion_1.convertDocStringToMarkdown)(documentation);
|
211
|
+
completionItem.documentation = {
|
212
|
+
kind: vscode_languageserver_1.MarkupKind.Markdown,
|
213
|
+
value: markdownString,
|
214
|
+
};
|
215
|
+
}
|
216
|
+
else if (this.options.format === vscode_languageserver_1.MarkupKind.PlainText) {
|
217
|
+
const plainTextString = (0, docStringConversion_1.convertDocStringToPlainText)(documentation);
|
218
|
+
completionItem.documentation = {
|
219
|
+
kind: vscode_languageserver_1.MarkupKind.PlainText,
|
220
|
+
value: plainTextString,
|
221
|
+
};
|
222
|
+
}
|
223
|
+
return;
|
224
|
+
}
|
225
|
+
this._itemToResolve = completionItem;
|
226
|
+
if (!completionItemData.autoImportText) {
|
227
|
+
// Rerun the completion lookup. It will fill in additional information
|
228
|
+
// about the item to be resolved. We'll ignore the rest of the returned
|
229
|
+
// list. This is a bit wasteful, but all of that information should be
|
230
|
+
// cached, so it's not as bad as it might seem.
|
231
|
+
this.getCompletions();
|
232
|
+
}
|
233
|
+
else if (!completionItem.additionalTextEdits) {
|
234
|
+
const completionMap = new CompletionMap();
|
235
|
+
this.addAutoImportCompletions(completionItemData.symbolLabel,
|
236
|
+
/* similarityLimit */ 1,
|
237
|
+
/* lazyEdit */ false, completionMap);
|
238
|
+
}
|
239
|
+
}
|
240
|
+
get evaluator() {
|
241
|
+
return this.program.evaluator;
|
242
|
+
}
|
243
|
+
get importResolver() {
|
244
|
+
return this.program.importResolver;
|
245
|
+
}
|
246
|
+
get configOptions() {
|
247
|
+
return this.program.configOptions;
|
248
|
+
}
|
249
|
+
isSimpleDefault(node) {
|
250
|
+
switch (node.nodeType) {
|
251
|
+
case 40 /* Number */:
|
252
|
+
case 11 /* Constant */:
|
253
|
+
case 35 /* MemberAccess */:
|
254
|
+
return true;
|
255
|
+
case 49 /* String */:
|
256
|
+
return (node.token.flags & 64 /* Format */) === 0;
|
257
|
+
case 48 /* StringList */:
|
258
|
+
return node.strings.every(this.isSimpleDefault);
|
259
|
+
case 55 /* UnaryOperation */:
|
260
|
+
return this.isSimpleDefault(node.expression);
|
261
|
+
case 7 /* BinaryOperation */:
|
262
|
+
return this.isSimpleDefault(node.leftExpression) && this.isSimpleDefault(node.rightExpression);
|
263
|
+
default:
|
264
|
+
return false;
|
265
|
+
}
|
266
|
+
}
|
267
|
+
getMethodOverrideCompletions(priorWord, partialName, decorators) {
|
268
|
+
var _a, _b;
|
269
|
+
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, /* stopAtFunction */ true);
|
270
|
+
if (!enclosingClass) {
|
271
|
+
return undefined;
|
272
|
+
}
|
273
|
+
const classResults = this.evaluator.getTypeOfClass(enclosingClass);
|
274
|
+
if (!classResults) {
|
275
|
+
return undefined;
|
276
|
+
}
|
277
|
+
const symbolTable = new Map();
|
278
|
+
for (let i = 1; i < classResults.classType.details.mro.length; i++) {
|
279
|
+
const mroClass = classResults.classType.details.mro[i];
|
280
|
+
if ((0, types_1.isInstantiableClass)(mroClass)) {
|
281
|
+
(0, typeUtils_1.getMembersForClass)(mroClass, symbolTable, /* includeInstanceVars */ false);
|
282
|
+
}
|
283
|
+
}
|
284
|
+
const staticmethod = (_a = decorators === null || decorators === void 0 ? void 0 : decorators.some((d) => this.checkDecorator(d, 'staticmethod'))) !== null && _a !== void 0 ? _a : false;
|
285
|
+
const classmethod = (_b = decorators === null || decorators === void 0 ? void 0 : decorators.some((d) => this.checkDecorator(d, 'classmethod'))) !== null && _b !== void 0 ? _b : false;
|
286
|
+
const completionMap = new CompletionMap();
|
287
|
+
symbolTable.forEach((symbol, name) => {
|
288
|
+
var _a;
|
289
|
+
let decl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(symbol);
|
290
|
+
if (decl && decl.type === 5 /* Function */) {
|
291
|
+
if (StringUtils.isPatternInSymbol(partialName.value, name)) {
|
292
|
+
const declaredType = (_a = this.evaluator.getTypeForDeclaration(decl)) === null || _a === void 0 ? void 0 : _a.type;
|
293
|
+
if (!declaredType) {
|
294
|
+
return;
|
295
|
+
}
|
296
|
+
let isProperty = (0, types_1.isClassInstance)(declaredType) && types_1.ClassType.isPropertyClass(declaredType);
|
297
|
+
if (SymbolNameUtils.isDunderName(name)) {
|
298
|
+
// Don't offer suggestions for built-in properties like "__class__", etc.
|
299
|
+
isProperty = false;
|
300
|
+
}
|
301
|
+
if (!(0, types_1.isFunction)(declaredType) && !isProperty) {
|
302
|
+
return;
|
303
|
+
}
|
304
|
+
if (isProperty) {
|
305
|
+
// For properties, we should override the "getter", which is typically
|
306
|
+
// the first declaration.
|
307
|
+
const typedDecls = symbol.getTypedDeclarations();
|
308
|
+
if (typedDecls.length > 0 && typedDecls[0].type === 5 /* Function */) {
|
309
|
+
decl = typedDecls[0];
|
310
|
+
}
|
311
|
+
}
|
312
|
+
const isDeclaredStaticMethod = (0, types_1.isFunction)(declaredType) && types_1.FunctionType.isStaticMethod(declaredType);
|
313
|
+
// Special-case the "__init__subclass__" method because it's an implicit
|
314
|
+
// classmethod that the type evaluator flags as a real classmethod.
|
315
|
+
const isDeclaredClassMethod = (0, types_1.isFunction)(declaredType) &&
|
316
|
+
types_1.FunctionType.isClassMethod(declaredType) &&
|
317
|
+
name !== '__init_subclass__';
|
318
|
+
if (staticmethod !== isDeclaredStaticMethod || classmethod !== isDeclaredClassMethod) {
|
319
|
+
return;
|
320
|
+
}
|
321
|
+
const methodSignature = this._printMethodSignature(classResults.classType, decl);
|
322
|
+
let text;
|
323
|
+
if ((0, sourceMapper_1.isStubFile)(this.filePath)) {
|
324
|
+
text = `${methodSignature}: ...`;
|
325
|
+
}
|
326
|
+
else {
|
327
|
+
const methodBody = this.printOverriddenMethodBody(classResults.classType, isDeclaredStaticMethod, isProperty, decl);
|
328
|
+
text = `${methodSignature}:\n${methodBody}`;
|
329
|
+
}
|
330
|
+
const textEdit = this.createReplaceEdits(priorWord, partialName, text);
|
331
|
+
this.addSymbol(name, symbol, partialName.value, completionMap, {
|
332
|
+
// method signature already contains ()
|
333
|
+
funcParensDisabled: true,
|
334
|
+
edits: {
|
335
|
+
format: this.options.snippet ? vscode_languageserver_1.InsertTextFormat.Snippet : undefined,
|
336
|
+
textEdit,
|
337
|
+
},
|
338
|
+
});
|
339
|
+
}
|
340
|
+
}
|
341
|
+
});
|
342
|
+
return completionMap;
|
343
|
+
}
|
344
|
+
printOverriddenMethodBody(classType, isStaticMethod, isProperty, decl) {
|
345
|
+
let sb = this.parseResults.tokenizerOutput.predominantTabSequence;
|
346
|
+
if (classType.details.baseClasses.length === 1 &&
|
347
|
+
(0, types_1.isClass)(classType.details.baseClasses[0]) &&
|
348
|
+
classType.details.baseClasses[0].details.fullName === 'builtins.object') {
|
349
|
+
sb += this.options.snippet ? '${0:pass}' : 'pass';
|
350
|
+
return sb;
|
351
|
+
}
|
352
|
+
if (decl.node.parameters.length === 0) {
|
353
|
+
sb += this.options.snippet ? '${0:pass}' : 'pass';
|
354
|
+
return sb;
|
355
|
+
}
|
356
|
+
const parameters = getParameters(isStaticMethod ? decl.node.parameters : decl.node.parameters.slice(1));
|
357
|
+
if (decl.node.name.value !== '__init__') {
|
358
|
+
sb += 'return ';
|
359
|
+
}
|
360
|
+
if (decl.node.isAsync) {
|
361
|
+
sb += 'await ';
|
362
|
+
}
|
363
|
+
if (isProperty) {
|
364
|
+
return sb + `super().${decl.node.name.value}`;
|
365
|
+
}
|
366
|
+
return sb + `super().${decl.node.name.value}(${parameters.map(convertToString).join(', ')})`;
|
367
|
+
function getParameters(parameters) {
|
368
|
+
const results = [];
|
369
|
+
let sawKeywordOnlySeparator = false;
|
370
|
+
for (const parameter of parameters) {
|
371
|
+
if (parameter.name) {
|
372
|
+
results.push([
|
373
|
+
parameter,
|
374
|
+
parameter.category === 0 /* Simple */ && !!parameter.name && sawKeywordOnlySeparator,
|
375
|
+
]);
|
376
|
+
}
|
377
|
+
// All simple parameters after a `*` or `*args` parameter
|
378
|
+
// are considered keyword only.
|
379
|
+
if (parameter.category === 1 /* VarArgList */) {
|
380
|
+
sawKeywordOnlySeparator = true;
|
381
|
+
}
|
382
|
+
}
|
383
|
+
return results;
|
384
|
+
}
|
385
|
+
function convertToString(parameter) {
|
386
|
+
var _a;
|
387
|
+
const name = (_a = parameter[0].name) === null || _a === void 0 ? void 0 : _a.value;
|
388
|
+
if (parameter[0].category === 1 /* VarArgList */) {
|
389
|
+
return `*${name}`;
|
390
|
+
}
|
391
|
+
if (parameter[0].category === 2 /* VarArgDictionary */) {
|
392
|
+
return `**${name}`;
|
393
|
+
}
|
394
|
+
return parameter[1] ? `${name}=${name}` : name;
|
395
|
+
}
|
396
|
+
}
|
397
|
+
createReplaceEdits(priorWord, node, text) {
|
398
|
+
const replaceOrInsertEndChar = (node === null || node === void 0 ? void 0 : node.nodeType) === 38 /* Name */
|
399
|
+
? this.position.character - priorWord.length + node.value.length
|
400
|
+
: this.position.character;
|
401
|
+
const range = {
|
402
|
+
start: { line: this.position.line, character: this.position.character - priorWord.length },
|
403
|
+
end: { line: this.position.line, character: replaceOrInsertEndChar },
|
404
|
+
};
|
405
|
+
return vscode_languageserver_1.TextEdit.replace(range, text);
|
406
|
+
}
|
407
|
+
addSymbol(name, symbol, priorWord, completionMap, detail) {
|
408
|
+
var _a, _b, _c, _d;
|
409
|
+
let primaryDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(symbol);
|
410
|
+
if (!primaryDecl) {
|
411
|
+
const declarations = symbol.getDeclarations();
|
412
|
+
if (declarations.length > 0) {
|
413
|
+
primaryDecl = declarations[declarations.length - 1];
|
414
|
+
}
|
415
|
+
}
|
416
|
+
primaryDecl = primaryDecl
|
417
|
+
? (_a = this.evaluator.resolveAliasDeclaration(primaryDecl, /* resolveLocalNames */ true)) !== null && _a !== void 0 ? _a : primaryDecl
|
418
|
+
: undefined;
|
419
|
+
const autoImportText = detail.autoImportSource
|
420
|
+
? this._getAutoImportText(name, detail.autoImportSource, detail.autoImportAlias)
|
421
|
+
: undefined;
|
422
|
+
// Are we resolving a completion item? If so, see if this symbol
|
423
|
+
// is the one that we're trying to match.
|
424
|
+
if (this._itemToResolve) {
|
425
|
+
const completionItemData = (0, lspUtils_1.fromLSPAny)(this._itemToResolve.data);
|
426
|
+
if (completionItemData.symbolLabel !== name) {
|
427
|
+
// It's not what we are looking for.
|
428
|
+
return;
|
429
|
+
}
|
430
|
+
if (completionItemData.autoImportText) {
|
431
|
+
if (completionItemData.autoImportText === (autoImportText === null || autoImportText === void 0 ? void 0 : autoImportText.importText) &&
|
432
|
+
((_b = detail.edits) === null || _b === void 0 ? void 0 : _b.additionalTextEdits)) {
|
433
|
+
this._itemToResolve.additionalTextEdits = (0, workspaceEditUtils_1.convertToTextEdits)(detail.edits.additionalTextEdits);
|
434
|
+
}
|
435
|
+
return;
|
436
|
+
}
|
437
|
+
// This call can be expensive to perform on every completion item
|
438
|
+
// that we return, so we do it lazily in the "resolve" callback.
|
439
|
+
const type = this.evaluator.getEffectiveTypeOfSymbol(symbol);
|
440
|
+
if (!type) {
|
441
|
+
// Can't resolve. so bail out.
|
442
|
+
return;
|
443
|
+
}
|
444
|
+
const typeDetail = (0, completionProviderUtils_1.getTypeDetail)(this.evaluator, primaryDecl, type, name, detail, this.configOptions.functionSignatureDisplay);
|
445
|
+
const documentation = (0, tooltipUtils_1.getDocumentationPartsForTypeAndDecl)(this.sourceMapper, type, primaryDecl, this.evaluator, {
|
446
|
+
name,
|
447
|
+
symbol,
|
448
|
+
boundObjectOrClass: detail.boundObjectOrClass,
|
449
|
+
});
|
450
|
+
if (this.options.format === vscode_languageserver_1.MarkupKind.Markdown || this.options.format === vscode_languageserver_1.MarkupKind.PlainText) {
|
451
|
+
this._itemToResolve.documentation = (0, completionProviderUtils_1.getCompletionItemDocumentation)(typeDetail, documentation, this.options.format);
|
452
|
+
}
|
453
|
+
else {
|
454
|
+
(0, debug_1.fail)(`Unsupported markup type: ${this.options.format}`);
|
455
|
+
}
|
456
|
+
// Bail out. We don't need to add items to completion.
|
457
|
+
return;
|
458
|
+
}
|
459
|
+
if (primaryDecl) {
|
460
|
+
let itemKind = this._convertDeclarationTypeToItemKind(primaryDecl);
|
461
|
+
// Handle enum members specially. Enum members normally look like
|
462
|
+
// variables, but the are declared using assignment expressions
|
463
|
+
// within an enum class.
|
464
|
+
if (primaryDecl.type === 1 /* Variable */ &&
|
465
|
+
detail.boundObjectOrClass &&
|
466
|
+
(0, types_1.isInstantiableClass)(detail.boundObjectOrClass) &&
|
467
|
+
types_1.ClassType.isEnumClass(detail.boundObjectOrClass) &&
|
468
|
+
((_c = primaryDecl.node.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 3 /* Assignment */) {
|
469
|
+
itemKind = vscode_languageserver_1.CompletionItemKind.EnumMember;
|
470
|
+
}
|
471
|
+
this._addNameToCompletions((_d = detail.autoImportAlias) !== null && _d !== void 0 ? _d : name, itemKind, priorWord, completionMap, {
|
472
|
+
autoImportText,
|
473
|
+
extraCommitChars: detail.extraCommitChars,
|
474
|
+
funcParensDisabled: detail.funcParensDisabled,
|
475
|
+
edits: detail.edits,
|
476
|
+
});
|
477
|
+
}
|
478
|
+
else {
|
479
|
+
// Does the symbol have no declaration but instead has a synthesized type?
|
480
|
+
const synthesizedType = symbol.getSynthesizedType();
|
481
|
+
if (synthesizedType) {
|
482
|
+
const itemKind = this._convertTypeToItemKind(synthesizedType);
|
483
|
+
this._addNameToCompletions(name, itemKind, priorWord, completionMap, {
|
484
|
+
extraCommitChars: detail.extraCommitChars,
|
485
|
+
funcParensDisabled: detail.funcParensDisabled,
|
486
|
+
edits: detail.edits,
|
487
|
+
});
|
488
|
+
}
|
489
|
+
}
|
490
|
+
}
|
491
|
+
getMemberAccessCompletions(leftExprNode, priorWord) {
|
492
|
+
const symbolTable = new Map();
|
493
|
+
const completionMap = new CompletionMap();
|
494
|
+
let leftType = this.evaluator.getType(leftExprNode);
|
495
|
+
if (!leftType) {
|
496
|
+
return completionMap;
|
497
|
+
}
|
498
|
+
leftType = this.evaluator.makeTopLevelTypeVarsConcrete(leftType);
|
499
|
+
// If this is an unknown type with a "possible type" associated with
|
500
|
+
// it, use the possible type.
|
501
|
+
if ((0, types_1.isUnknown)(leftType) && leftType.possibleType) {
|
502
|
+
leftType = this.evaluator.makeTopLevelTypeVarsConcrete(leftType.possibleType);
|
503
|
+
}
|
504
|
+
(0, typeUtils_1.doForEachSubtype)(leftType, (subtype) => {
|
505
|
+
subtype = this.evaluator.makeTopLevelTypeVarsConcrete(subtype);
|
506
|
+
if ((0, types_1.isClass)(subtype)) {
|
507
|
+
(0, typeUtils_1.getMembersForClass)(subtype, symbolTable, /* includeInstanceVars */ types_1.TypeBase.isInstance(subtype));
|
508
|
+
}
|
509
|
+
else if ((0, types_1.isModule)(subtype)) {
|
510
|
+
(0, typeUtils_1.getMembersForModule)(subtype, symbolTable);
|
511
|
+
}
|
512
|
+
else if ((0, types_1.isFunction)(subtype) || (0, types_1.isOverloadedFunction)(subtype)) {
|
513
|
+
const functionClass = this.evaluator.getBuiltInType(leftExprNode, 'function');
|
514
|
+
if (functionClass && (0, types_1.isInstantiableClass)(functionClass)) {
|
515
|
+
(0, typeUtils_1.getMembersForClass)(functionClass, symbolTable, /* includeInstanceVars */ true);
|
516
|
+
}
|
517
|
+
}
|
518
|
+
else if ((0, types_1.isNoneInstance)(subtype)) {
|
519
|
+
const objectClass = this.evaluator.getBuiltInType(leftExprNode, 'object');
|
520
|
+
if (objectClass && (0, types_1.isInstantiableClass)(objectClass)) {
|
521
|
+
(0, typeUtils_1.getMembersForClass)(objectClass, symbolTable, types_1.TypeBase.isInstance(subtype));
|
522
|
+
}
|
523
|
+
}
|
524
|
+
this._addSymbolsForSymbolTable(symbolTable, () => true, priorWord, leftExprNode,
|
525
|
+
/* isInImport */ false, (0, types_1.isClass)(subtype) ? subtype : undefined, completionMap);
|
526
|
+
});
|
527
|
+
return completionMap;
|
528
|
+
}
|
529
|
+
addAutoImportCompletions(priorWord, similarityLimit, lazyEdit, completionMap) {
|
530
|
+
if (!this.configOptions.autoImportCompletions) {
|
531
|
+
// If auto import on the server is turned off or this particular invocation
|
532
|
+
// is turned off (ex, notebook), don't do any thing.
|
533
|
+
return;
|
534
|
+
}
|
535
|
+
const currentFile = this.program.getSourceFileInfo(this.filePath);
|
536
|
+
const moduleSymbolMap = (0, autoImporter_1.buildModuleSymbolsMap)(this.program.getSourceFileInfoList().filter((s) => s !== currentFile));
|
537
|
+
const autoImporter = new autoImporter_1.AutoImporter(this.execEnv, this.importResolver, this.parseResults, this.position, completionMap, moduleSymbolMap, {
|
538
|
+
lazyEdit,
|
539
|
+
});
|
540
|
+
const results = [];
|
541
|
+
results.push(...autoImporter.getAutoImportCandidates(priorWord, similarityLimit,
|
542
|
+
/* abbrFromUsers */ undefined, this.cancellationToken));
|
543
|
+
this.addImportResults(results, priorWord, completionMap);
|
544
|
+
}
|
545
|
+
addImportResults(results, priorWord, completionMap) {
|
178
546
|
var _a, _b;
|
179
|
-
const
|
547
|
+
for (const result of results) {
|
548
|
+
if (result.symbol) {
|
549
|
+
this.addSymbol(result.name, result.symbol, priorWord, completionMap, {
|
550
|
+
extraCommitChars: true,
|
551
|
+
autoImportSource: result.source,
|
552
|
+
autoImportAlias: result.alias,
|
553
|
+
edits: {
|
554
|
+
textEdit: this.createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
|
555
|
+
additionalTextEdits: result.edits,
|
556
|
+
},
|
557
|
+
});
|
558
|
+
}
|
559
|
+
else {
|
560
|
+
this._addNameToCompletions((_a = result.alias) !== null && _a !== void 0 ? _a : result.name, (_b = result.kind) !== null && _b !== void 0 ? _b : vscode_languageserver_1.CompletionItemKind.Module, priorWord, completionMap, {
|
561
|
+
extraCommitChars: true,
|
562
|
+
autoImportText: this._getAutoImportText(result.name, result.source, result.alias),
|
563
|
+
edits: {
|
564
|
+
textEdit: this.createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
|
565
|
+
additionalTextEdits: result.edits,
|
566
|
+
},
|
567
|
+
});
|
568
|
+
}
|
569
|
+
}
|
570
|
+
}
|
571
|
+
checkDecorator(node, value) {
|
572
|
+
return node.expression.nodeType === 38 /* Name */ && node.expression.value === value;
|
573
|
+
}
|
574
|
+
addExtraCommitChar(item) {
|
575
|
+
// extra commit char is not supported.
|
576
|
+
}
|
577
|
+
get _fileContents() {
|
578
|
+
var _a, _b;
|
579
|
+
return (_b = (_a = this.parseResults) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '';
|
580
|
+
}
|
581
|
+
_getCompletions() {
|
582
|
+
var _a, _b;
|
583
|
+
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
180
584
|
if (offset === undefined) {
|
181
585
|
return undefined;
|
182
586
|
}
|
183
|
-
const token = ParseTreeUtils.getTokenOverlapping(this.
|
587
|
+
const token = ParseTreeUtils.getTokenOverlapping(this.parseResults.tokenizerOutput.tokens, offset);
|
184
588
|
if ((token === null || token === void 0 ? void 0 : token.type) === 5 /* String */) {
|
185
589
|
const stringToken = token;
|
186
590
|
this._insideStringLiteral = textRange_2.TextRange.contains(stringToken, offset)
|
@@ -189,7 +593,7 @@ class CompletionProvider {
|
|
189
593
|
? stringToken
|
190
594
|
: undefined;
|
191
595
|
}
|
192
|
-
let node = ParseTreeUtils.findNodeByOffset(this.
|
596
|
+
let node = ParseTreeUtils.findNodeByOffset(this.parseResults.parseTree, offset);
|
193
597
|
// See if we can get to a "better" node by backing up a few columns.
|
194
598
|
// A "better" node is defined as one that's deeper than the current
|
195
599
|
// node.
|
@@ -208,7 +612,7 @@ class CompletionProvider {
|
|
208
612
|
if (curChar === ',') {
|
209
613
|
sawComma = true;
|
210
614
|
}
|
211
|
-
const curNode = ParseTreeUtils.findNodeByOffset(this.
|
615
|
+
const curNode = ParseTreeUtils.findNodeByOffset(this.parseResults.parseTree, curOffset);
|
212
616
|
if (curNode && curNode !== initialNode) {
|
213
617
|
if (ParseTreeUtils.getNodeDepth(curNode) > initialDepth) {
|
214
618
|
node = curNode;
|
@@ -226,10 +630,10 @@ class CompletionProvider {
|
|
226
630
|
return undefined;
|
227
631
|
}
|
228
632
|
// Get the text on that line prior to the insertion point.
|
229
|
-
const lineTextRange = this.
|
633
|
+
const lineTextRange = this.parseResults.tokenizerOutput.lines.getItemAt(this.position.line);
|
230
634
|
const textOnLine = this._fileContents.substr(lineTextRange.start, lineTextRange.length);
|
231
|
-
const priorText = textOnLine.substr(0, this.
|
232
|
-
const postText = textOnLine.substr(this.
|
635
|
+
const priorText = textOnLine.substr(0, this.position.character);
|
636
|
+
const postText = textOnLine.substr(this.position.character);
|
233
637
|
const priorWordIndex = priorText.search(/\w+$/);
|
234
638
|
const priorWord = priorWordIndex >= 0 ? priorText.substr(priorWordIndex) : '';
|
235
639
|
// Don't offer completions if we're within a comment.
|
@@ -249,7 +653,7 @@ class CompletionProvider {
|
|
249
653
|
// that of its ancestors.
|
250
654
|
let curNode = errorNode || node;
|
251
655
|
while (true) {
|
252
|
-
(0, cancellationUtils_1.throwIfCancellationRequested)(this.
|
656
|
+
(0, cancellationUtils_1.throwIfCancellationRequested)(this.cancellationToken);
|
253
657
|
if (curNode.nodeType === 49 /* String */) {
|
254
658
|
return this._getLiteralCompletions(curNode, offset, priorWord, priorText, postText);
|
255
659
|
}
|
@@ -263,13 +667,13 @@ class CompletionProvider {
|
|
263
667
|
return this._getExpressionErrorCompletions(curNode, offset, priorWord, priorText, postText);
|
264
668
|
}
|
265
669
|
if (curNode.nodeType === 35 /* MemberAccess */) {
|
266
|
-
return this.
|
670
|
+
return this.getMemberAccessCompletions(curNode.leftExpression, priorWord);
|
267
671
|
}
|
268
672
|
if (curNode.nodeType === 15 /* Dictionary */) {
|
269
673
|
const completionMap = new CompletionMap();
|
270
674
|
if (this._tryAddTypedDictKeysFromDictionary(curNode,
|
271
675
|
/* stringNode */ undefined, priorWord, priorText, postText, completionMap)) {
|
272
|
-
return
|
676
|
+
return completionMap;
|
273
677
|
}
|
274
678
|
}
|
275
679
|
const dictionaryEntry = ParseTreeUtils.getFirstAncestorOrSelfOfKind(curNode, 17 /* DictionaryKeyEntry */);
|
@@ -280,7 +684,7 @@ class CompletionProvider {
|
|
280
684
|
const completionMap = new CompletionMap();
|
281
685
|
if (this._tryAddTypedDictKeysFromDictionary(dictionaryNode,
|
282
686
|
/* stringNode */ undefined, priorWord, priorText, postText, completionMap)) {
|
283
|
-
return
|
687
|
+
return completionMap;
|
284
688
|
}
|
285
689
|
}
|
286
690
|
}
|
@@ -294,7 +698,7 @@ class CompletionProvider {
|
|
294
698
|
return result;
|
295
699
|
}
|
296
700
|
}
|
297
|
-
if (curNode.nodeType === 31 /* List */ && this.
|
701
|
+
if (curNode.nodeType === 31 /* List */ && this.options.triggerCharacter === '[') {
|
298
702
|
// If this is an empty list, don't start putting completions up yet.
|
299
703
|
return undefined;
|
300
704
|
}
|
@@ -341,84 +745,6 @@ class CompletionProvider {
|
|
341
745
|
}
|
342
746
|
return undefined;
|
343
747
|
}
|
344
|
-
// When the user selects a completion, this callback is invoked,
|
345
|
-
// allowing us to record what was selected. This allows us to
|
346
|
-
// build our MRU cache so we can better predict entries.
|
347
|
-
resolveCompletionItem(completionItem) {
|
348
|
-
(0, cancellationUtils_1.throwIfCancellationRequested)(this._cancellationToken);
|
349
|
-
const completionItemData = (0, lspUtils_1.fromLSPAny)(completionItem.data);
|
350
|
-
const label = completionItem.label;
|
351
|
-
let autoImportText = '';
|
352
|
-
if (completionItemData.autoImportText) {
|
353
|
-
autoImportText = completionItemData.autoImportText;
|
354
|
-
}
|
355
|
-
const curIndex = CompletionProvider._mostRecentCompletions.findIndex((item) => item.label === label && item.autoImportText === autoImportText);
|
356
|
-
if (curIndex > 0) {
|
357
|
-
// If there's an existing entry with the same name that's not at the
|
358
|
-
// beginning of the array, remove it.
|
359
|
-
CompletionProvider._mostRecentCompletions = CompletionProvider._mostRecentCompletions.splice(curIndex, 1);
|
360
|
-
}
|
361
|
-
if (curIndex !== 0) {
|
362
|
-
// Add to the start of the array.
|
363
|
-
CompletionProvider._mostRecentCompletions.unshift({ label, autoImportText });
|
364
|
-
}
|
365
|
-
if (CompletionProvider._mostRecentCompletions.length > maxRecentCompletions) {
|
366
|
-
// Prevent the MRU list from growing indefinitely.
|
367
|
-
CompletionProvider._mostRecentCompletions.pop();
|
368
|
-
}
|
369
|
-
if (!completionItemData.symbolLabel) {
|
370
|
-
return;
|
371
|
-
}
|
372
|
-
if (completionItemData.modulePath) {
|
373
|
-
const documentation = (0, typeDocStringUtils_1.getModuleDocStringFromPaths)([completionItemData.modulePath], this._sourceMapper);
|
374
|
-
if (!documentation) {
|
375
|
-
return;
|
376
|
-
}
|
377
|
-
if (this._options.format === vscode_languageserver_1.MarkupKind.Markdown) {
|
378
|
-
const markdownString = (0, docStringConversion_1.convertDocStringToMarkdown)(documentation);
|
379
|
-
completionItem.documentation = {
|
380
|
-
kind: vscode_languageserver_1.MarkupKind.Markdown,
|
381
|
-
value: markdownString,
|
382
|
-
};
|
383
|
-
}
|
384
|
-
else if (this._options.format === vscode_languageserver_1.MarkupKind.PlainText) {
|
385
|
-
const plainTextString = (0, docStringConversion_1.convertDocStringToPlainText)(documentation);
|
386
|
-
completionItem.documentation = {
|
387
|
-
kind: vscode_languageserver_1.MarkupKind.PlainText,
|
388
|
-
value: plainTextString,
|
389
|
-
};
|
390
|
-
}
|
391
|
-
return;
|
392
|
-
}
|
393
|
-
this._itemToResolve = completionItem;
|
394
|
-
if (!completionItemData.autoImportText) {
|
395
|
-
// Rerun the completion lookup. It will fill in additional information
|
396
|
-
// about the item to be resolved. We'll ignore the rest of the returned
|
397
|
-
// list. This is a bit wasteful, but all of that information should be
|
398
|
-
// cached, so it's not as bad as it might seem.
|
399
|
-
this.getCompletionsForPosition();
|
400
|
-
}
|
401
|
-
else if (!completionItem.additionalTextEdits) {
|
402
|
-
const completionMap = new CompletionMap();
|
403
|
-
const completionResults = { completionMap };
|
404
|
-
this._addAutoImportCompletions(completionItemData.symbolLabel,
|
405
|
-
/* similarityLimit */ 1,
|
406
|
-
/* lazyEdit */ false, completionResults);
|
407
|
-
}
|
408
|
-
}
|
409
|
-
get _importResolver() {
|
410
|
-
return this._program.importResolver;
|
411
|
-
}
|
412
|
-
get _configOptions() {
|
413
|
-
return this._program.configOptions;
|
414
|
-
}
|
415
|
-
get _evaluator() {
|
416
|
-
return this._program.evaluator;
|
417
|
-
}
|
418
|
-
get _fileContents() {
|
419
|
-
var _a, _b;
|
420
|
-
return (_b = (_a = this._parseResults) === null || _a === void 0 ? void 0 : _a.text) !== null && _b !== void 0 ? _b : '';
|
421
|
-
}
|
422
748
|
// This method will return false if it wants1
|
423
749
|
// caller to walk up the tree. it will return
|
424
750
|
// CompletionResults or undefined if it wants caller
|
@@ -463,7 +789,7 @@ class CompletionProvider {
|
|
463
789
|
return false;
|
464
790
|
}
|
465
791
|
if (curNode.parent.nodeType === 35 /* MemberAccess */ && curNode === curNode.parent.memberName) {
|
466
|
-
return this.
|
792
|
+
return this.getMemberAccessCompletions(curNode.parent.leftExpression, priorWord);
|
467
793
|
}
|
468
794
|
if (curNode.parent.nodeType === 25 /* Except */ && curNode === curNode.parent.name) {
|
469
795
|
return undefined;
|
@@ -497,15 +823,15 @@ class CompletionProvider {
|
|
497
823
|
if (leftNode !== curNode || priorWord.length === 0) {
|
498
824
|
return false;
|
499
825
|
}
|
500
|
-
const decls = this.
|
826
|
+
const decls = this.evaluator.getDeclarationsForNameNode(curNode);
|
501
827
|
if ((decls === null || decls === void 0 ? void 0 : decls.length) !== 1 || !(0, declaration_1.isVariableDeclaration)(decls[0]) || decls[0].node !== curNode) {
|
502
828
|
return false;
|
503
829
|
}
|
504
|
-
const
|
505
|
-
if (
|
506
|
-
|
830
|
+
const completionMap = this._getExpressionCompletions(curNode, priorWord, priorText, postText);
|
831
|
+
if (completionMap) {
|
832
|
+
completionMap.delete(curNode.value);
|
507
833
|
}
|
508
|
-
return
|
834
|
+
return completionMap;
|
509
835
|
}
|
510
836
|
// Defining class variables.
|
511
837
|
// ex) class A:
|
@@ -522,7 +848,7 @@ class CompletionProvider {
|
|
522
848
|
}
|
523
849
|
_isWithinComment(offset) {
|
524
850
|
var _a, _b;
|
525
|
-
const token = getTokenAfter(offset, this.
|
851
|
+
const token = getTokenAfter(offset, this.parseResults.tokenizerOutput.tokens);
|
526
852
|
if (!token) {
|
527
853
|
// If we're in the middle of a token, we're not in a comment.
|
528
854
|
return false;
|
@@ -572,8 +898,8 @@ class CompletionProvider {
|
|
572
898
|
case 7 /* MissingMemberAccessName */:
|
573
899
|
case 2 /* MissingExpression */: {
|
574
900
|
// Don't show completion after random dots.
|
575
|
-
const tokenizerOutput = this.
|
576
|
-
const offset = (0, positionUtils_1.convertPositionToOffset)(this.
|
901
|
+
const tokenizerOutput = this.parseResults.tokenizerOutput;
|
902
|
+
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, tokenizerOutput.lines);
|
577
903
|
const index = ParseTreeUtils.getTokenIndexAtLeft(tokenizerOutput.tokens, offset);
|
578
904
|
const token = ParseTreeUtils.getTokenAtIndex(tokenizerOutput.tokens, index);
|
579
905
|
const prevToken = ParseTreeUtils.getTokenAtIndex(tokenizerOutput.tokens, index - 1);
|
@@ -598,7 +924,7 @@ class CompletionProvider {
|
|
598
924
|
return this._getExpressionCompletions(node, priorWord, priorText, postText);
|
599
925
|
}
|
600
926
|
const previousOffset = textRange_2.TextRange.getEnd(prevToken);
|
601
|
-
const previousNode = ParseTreeUtils.findNodeByOffset(this.
|
927
|
+
const previousNode = ParseTreeUtils.findNodeByOffset(this.parseResults.parseTree, previousOffset);
|
602
928
|
if ((previousNode === null || previousNode === void 0 ? void 0 : previousNode.nodeType) !== 0 /* Error */ ||
|
603
929
|
previousNode.category !== 7 /* MissingMemberAccessName */) {
|
604
930
|
return this._getExpressionCompletions(node, priorWord, priorText, postText);
|
@@ -635,7 +961,7 @@ class CompletionProvider {
|
|
635
961
|
}
|
636
962
|
// Determine if the partial name is a method that's overriding
|
637
963
|
// a method in a base class.
|
638
|
-
return this.
|
964
|
+
return this.getMethodOverrideCompletions(priorWord, node.child, node.decorators);
|
639
965
|
}
|
640
966
|
break;
|
641
967
|
}
|
@@ -646,13 +972,10 @@ class CompletionProvider {
|
|
646
972
|
if (!node.child || !(0, parseNodes_1.isExpressionNode)(node.child)) {
|
647
973
|
return undefined;
|
648
974
|
}
|
649
|
-
return this.
|
975
|
+
return this.getMemberAccessCompletions(node.child, priorWord);
|
650
976
|
}
|
651
977
|
_isOverload(node) {
|
652
|
-
return this.
|
653
|
-
}
|
654
|
-
_checkDecorator(node, value) {
|
655
|
-
return node.expression.nodeType === 38 /* Name */ && node.expression.value === value;
|
978
|
+
return this.checkDecorator(node, 'overload');
|
656
979
|
}
|
657
980
|
_createSingleKeywordCompletion(keyword) {
|
658
981
|
const completionItem = vscode_languageserver_1.CompletionItem.create(keyword);
|
@@ -660,7 +983,7 @@ class CompletionProvider {
|
|
660
983
|
completionItem.sortText = this._makeSortText(SortCategory.LikelyKeyword, keyword);
|
661
984
|
const completionMap = new CompletionMap();
|
662
985
|
completionMap.set(completionItem);
|
663
|
-
return
|
986
|
+
return completionMap;
|
664
987
|
}
|
665
988
|
_addClassVariableTypeAnnotationCompletions(priorWord, parseNode, completionMap) {
|
666
989
|
var _a, _b, _c, _d;
|
@@ -679,7 +1002,7 @@ class CompletionProvider {
|
|
679
1002
|
if (!enclosingClass) {
|
680
1003
|
return;
|
681
1004
|
}
|
682
|
-
const classResults = this.
|
1005
|
+
const classResults = this.evaluator.getTypeOfClass(enclosingClass);
|
683
1006
|
if (!classResults) {
|
684
1007
|
return undefined;
|
685
1008
|
}
|
@@ -687,8 +1010,8 @@ class CompletionProvider {
|
|
687
1010
|
const classMember = (0, typeUtils_1.lookUpClassMember)(classResults.classType, classVariableName, 8 /* SkipInstanceVariables */ | 1 /* SkipOriginalClass */);
|
688
1011
|
// First, see whether we can use semantic info to get variable type.
|
689
1012
|
if (classMember) {
|
690
|
-
const memberType = this.
|
691
|
-
const text = this.
|
1013
|
+
const memberType = this.evaluator.getTypeOfMember(classMember);
|
1014
|
+
const text = this.evaluator.printType(memberType, {
|
692
1015
|
enforcePythonSyntax: true,
|
693
1016
|
expandTypeAlias: false,
|
694
1017
|
});
|
@@ -724,7 +1047,7 @@ class CompletionProvider {
|
|
724
1047
|
if (declWithTypeAnnotations.length === 0) {
|
725
1048
|
return;
|
726
1049
|
}
|
727
|
-
const printFlags = (0, sourceMapper_1.isStubFile)(this.
|
1050
|
+
const printFlags = (0, sourceMapper_1.isStubFile)(this.filePath)
|
728
1051
|
? 1 /* ForwardDeclarations */ |
|
729
1052
|
2 /* DoNotLimitStringLength */
|
730
1053
|
: 2 /* DoNotLimitStringLength */;
|
@@ -738,7 +1061,7 @@ class CompletionProvider {
|
|
738
1061
|
if (!enclosingClass) {
|
739
1062
|
return undefined;
|
740
1063
|
}
|
741
|
-
const classResults = this.
|
1064
|
+
const classResults = this.evaluator.getTypeOfClass(enclosingClass);
|
742
1065
|
if (!classResults) {
|
743
1066
|
return undefined;
|
744
1067
|
}
|
@@ -764,13 +1087,13 @@ class CompletionProvider {
|
|
764
1087
|
decls.some((d) => d.node && ParseTreeUtils.getEnclosingClass(d.node, false) === enclosingClass)) {
|
765
1088
|
return;
|
766
1089
|
}
|
767
|
-
this.
|
1090
|
+
this.addSymbol(name, symbol, partialName.value, completionMap, {});
|
768
1091
|
});
|
769
|
-
return completionMap.size > 0 ?
|
1092
|
+
return completionMap.size > 0 ? completionMap : undefined;
|
770
1093
|
}
|
771
1094
|
_getMethodOverloadsCompletions(priorWord, partialName) {
|
772
1095
|
var _a;
|
773
|
-
const symbolTable = getSymbolTable(this.
|
1096
|
+
const symbolTable = getSymbolTable(this.evaluator, partialName);
|
774
1097
|
if (!symbolTable) {
|
775
1098
|
return undefined;
|
776
1099
|
}
|
@@ -792,14 +1115,14 @@ class CompletionProvider {
|
|
792
1115
|
return;
|
793
1116
|
}
|
794
1117
|
if (StringUtils.isPatternInSymbol(partialName.value, name)) {
|
795
|
-
const textEdit = this.
|
796
|
-
this.
|
1118
|
+
const textEdit = this.createReplaceEdits(priorWord, partialName, decl.node.name.value);
|
1119
|
+
this.addSymbol(name, symbol, partialName.value, completionMap, {
|
797
1120
|
funcParensDisabled,
|
798
1121
|
edits: { textEdit },
|
799
1122
|
});
|
800
1123
|
}
|
801
1124
|
});
|
802
|
-
return
|
1125
|
+
return completionMap;
|
803
1126
|
function getSymbolTable(evaluator, partialName) {
|
804
1127
|
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, false);
|
805
1128
|
if (enclosingClass) {
|
@@ -810,153 +1133,37 @@ class CompletionProvider {
|
|
810
1133
|
const symbolTable = new Map();
|
811
1134
|
for (const mroClass of classResults.classType.details.mro) {
|
812
1135
|
if ((0, types_1.isInstantiableClass)(mroClass)) {
|
813
|
-
(0, typeUtils_1.getMembersForClass)(mroClass, symbolTable, /* includeInstanceVars */ false);
|
814
|
-
}
|
815
|
-
}
|
816
|
-
return symbolTable;
|
817
|
-
}
|
818
|
-
// For function overload, we only care about top level functions
|
819
|
-
const moduleNode = ParseTreeUtils.getEnclosingModule(partialName);
|
820
|
-
if (moduleNode) {
|
821
|
-
const moduleScope = AnalyzerNodeInfo.getScope(moduleNode);
|
822
|
-
return moduleScope === null || moduleScope === void 0 ? void 0 : moduleScope.symbolTable;
|
823
|
-
}
|
824
|
-
return undefined;
|
825
|
-
}
|
826
|
-
}
|
827
|
-
_getMethodOverrideCompletions(priorWord, partialName, decorators) {
|
828
|
-
var _a, _b;
|
829
|
-
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, /* stopAtFunction */ true);
|
830
|
-
if (!enclosingClass) {
|
831
|
-
return undefined;
|
832
|
-
}
|
833
|
-
const classResults = this._evaluator.getTypeOfClass(enclosingClass);
|
834
|
-
if (!classResults) {
|
835
|
-
return undefined;
|
836
|
-
}
|
837
|
-
const staticmethod = (_a = decorators === null || decorators === void 0 ? void 0 : decorators.some((d) => this._checkDecorator(d, 'staticmethod'))) !== null && _a !== void 0 ? _a : false;
|
838
|
-
const classmethod = (_b = decorators === null || decorators === void 0 ? void 0 : decorators.some((d) => this._checkDecorator(d, 'classmethod'))) !== null && _b !== void 0 ? _b : false;
|
839
|
-
const fallbackPath = (0, pythonPathUtils_1.getTypeShedFallbackPath)(this._importResolver.fileSystem);
|
840
|
-
const typingFilePath = fallbackPath ? (0, pathUtils_1.combinePaths)(fallbackPath, 'stdlib/typing.pyi') : undefined;
|
841
|
-
const appendMember = (map, member, name) => {
|
842
|
-
if (!(0, types_1.isInstantiableClass)(member.classType) ||
|
843
|
-
member.classType.details === classResults.classType.details ||
|
844
|
-
!StringUtils.isPatternInSymbol(partialName.value, name)) {
|
845
|
-
// Quick bail out if member is something we don't want to override.
|
846
|
-
return;
|
847
|
-
}
|
848
|
-
const symbol = member.symbol;
|
849
|
-
const decl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(symbol);
|
850
|
-
if (!decl || decl.type !== 5 /* Function */) {
|
851
|
-
return;
|
852
|
-
}
|
853
|
-
const declaredType = this._evaluator.getTypeOfMember(member);
|
854
|
-
if (!declaredType) {
|
855
|
-
return;
|
856
|
-
}
|
857
|
-
const isDeclaredStaticMethod = (0, types_1.isFunction)(declaredType) && types_1.FunctionType.isStaticMethod(declaredType);
|
858
|
-
// Special-case the "__init__subclass__" method because it's an implicit
|
859
|
-
// classmethod that the type evaluator flags as a real classmethod.
|
860
|
-
const isDeclaredClassMethod = (0, types_1.isFunction)(declaredType) && types_1.FunctionType.isClassMethod(declaredType) && name !== '__init_subclass__';
|
861
|
-
if (staticmethod !== isDeclaredStaticMethod || classmethod !== isDeclaredClassMethod) {
|
862
|
-
return;
|
863
|
-
}
|
864
|
-
let isProperty = (0, types_1.isClassInstance)(declaredType) && types_1.ClassType.isPropertyClass(declaredType);
|
865
|
-
if (SymbolNameUtils.isDunderName(name)) {
|
866
|
-
// Don't offer suggestions for built-in properties like "__class__", etc.
|
867
|
-
isProperty = false;
|
868
|
-
}
|
869
|
-
let funcType = undefined;
|
870
|
-
if ((0, types_1.isFunction)(declaredType)) {
|
871
|
-
funcType = declaredType;
|
872
|
-
}
|
873
|
-
else if (isProperty) {
|
874
|
-
const getter = (0, typeUtils_1.lookUpClassMember)(declaredType, 'fget');
|
875
|
-
if (!getter) {
|
876
|
-
return;
|
877
|
-
}
|
878
|
-
const member = this._evaluator.getTypeOfMember(getter);
|
879
|
-
if (!(0, types_1.isFunction)(member)) {
|
880
|
-
return;
|
1136
|
+
(0, typeUtils_1.getMembersForClass)(mroClass, symbolTable, /* includeInstanceVars */ false);
|
1137
|
+
}
|
881
1138
|
}
|
882
|
-
|
883
|
-
}
|
884
|
-
if (!funcType || !funcType.details.declaration) {
|
885
|
-
return;
|
1139
|
+
return symbolTable;
|
886
1140
|
}
|
887
|
-
|
888
|
-
const
|
889
|
-
|
890
|
-
|
891
|
-
|
1141
|
+
// For function overload, we only care about top level functions
|
1142
|
+
const moduleNode = ParseTreeUtils.getEnclosingModule(partialName);
|
1143
|
+
if (moduleNode) {
|
1144
|
+
const moduleScope = AnalyzerNodeInfo.getScope(moduleNode);
|
1145
|
+
return moduleScope === null || moduleScope === void 0 ? void 0 : moduleScope.symbolTable;
|
892
1146
|
}
|
893
|
-
|
894
|
-
const methodBody = this._printOverriddenMethodBody(classResults.classType, isDeclaredStaticMethod, isProperty, decl);
|
895
|
-
text = `${result.methodSignature}:\n${methodBody}`;
|
896
|
-
}
|
897
|
-
const textEdit = this._createReplaceEdits(priorWord, partialName, text);
|
898
|
-
// This will add new import statements, but for now, it won't add new
|
899
|
-
// `TypeVar` statement such as TypeVar, TypeVarTuple, ParamSpec even if
|
900
|
-
// the overridden method uses them.
|
901
|
-
const additionalTextEdits = importAdder.applyImports(result.importData, this._filePath, this._parseResults, this._parseResults.parseTree.length, "absolute" /* Absolute */, this._cancellationToken);
|
902
|
-
this._addSymbol(name, symbol, partialName.value, map, {
|
903
|
-
// method signature already contains ()
|
904
|
-
funcParensDisabled: true,
|
905
|
-
edits: {
|
906
|
-
format: this._options.snippet ? vscode_languageserver_1.InsertTextFormat.Snippet : undefined,
|
907
|
-
textEdit,
|
908
|
-
additionalTextEdits,
|
909
|
-
},
|
910
|
-
});
|
911
|
-
};
|
912
|
-
const completionMap = new CompletionMap();
|
913
|
-
const classMemberMap = (0, typeUtils_1.getClassFieldsRecursive)(classResults.classType);
|
914
|
-
classMemberMap.forEach((member, name) => appendMember(completionMap, member, name));
|
915
|
-
if (classResults.classType.details.effectiveMetaclass &&
|
916
|
-
!(0, types_1.isUnknown)(classResults.classType.details.effectiveMetaclass)) {
|
917
|
-
const metaClassMemberMap = (0, typeUtils_1.getClassFieldsRecursive)(classResults.classType.details.effectiveMetaclass);
|
918
|
-
metaClassMemberMap.forEach((member, name) => appendMember(completionMap, member, name));
|
1147
|
+
return undefined;
|
919
1148
|
}
|
920
|
-
return { completionMap };
|
921
|
-
}
|
922
|
-
_createReplaceEdits(priorWord, node, text) {
|
923
|
-
const replaceOrInsertEndChar = (node === null || node === void 0 ? void 0 : node.nodeType) === 38 /* Name */
|
924
|
-
? this._position.character - priorWord.length + node.value.length
|
925
|
-
: this._position.character;
|
926
|
-
const range = {
|
927
|
-
start: { line: this._position.line, character: this._position.character - priorWord.length },
|
928
|
-
end: { line: this._position.line, character: replaceOrInsertEndChar },
|
929
|
-
};
|
930
|
-
return vscode_languageserver_1.TextEdit.replace(range, text);
|
931
1149
|
}
|
932
|
-
_printMethodSignature(
|
933
|
-
const
|
1150
|
+
_printMethodSignature(classType, decl) {
|
1151
|
+
const node = decl.node;
|
934
1152
|
let ellipsisForDefault;
|
935
|
-
if ((0, sourceMapper_1.isStubFile)(this.
|
1153
|
+
if ((0, sourceMapper_1.isStubFile)(this.filePath)) {
|
936
1154
|
// In stubs, always use "...".
|
937
1155
|
ellipsisForDefault = true;
|
938
1156
|
}
|
939
|
-
else if (classType.details.moduleName ===
|
1157
|
+
else if (classType.details.moduleName === decl.moduleName) {
|
940
1158
|
// In the same file, always print the full default.
|
941
1159
|
ellipsisForDefault = false;
|
942
1160
|
}
|
943
|
-
const
|
1161
|
+
const printFlags = (0, sourceMapper_1.isStubFile)(this.filePath)
|
944
1162
|
? 1 /* ForwardDeclarations */ |
|
945
1163
|
2 /* DoNotLimitStringLength */
|
946
1164
|
: 2 /* DoNotLimitStringLength */;
|
947
|
-
const
|
948
|
-
|
949
|
-
expandTypeAlias: false,
|
950
|
-
omitTypeArgumentsIfUnknown: true,
|
951
|
-
printUnknownWithAny: true,
|
952
|
-
};
|
953
|
-
const getTypeToPrint = (mainType, fallbackType) => {
|
954
|
-
return mainType && (!(0, types_1.isUnknown)(mainType) || (fallbackType === null || fallbackType === void 0 ? void 0 : fallbackType.category) === 10 /* TypeVar */)
|
955
|
-
? mainType
|
956
|
-
: fallbackType;
|
957
|
-
};
|
958
|
-
const importData = createImportData(importAdder, funcType, declaration, typingFilePath, (t) => this._sourceMapper.findClassDeclarationsByType(this._filePath, t), this._cancellationToken);
|
959
|
-
const paramList = funcType.details.parameters.map((param, index) => {
|
1165
|
+
const paramList = node.parameters
|
1166
|
+
.map((param, index) => {
|
960
1167
|
let paramString = '';
|
961
1168
|
if (param.category === 1 /* VarArgList */) {
|
962
1169
|
paramString += '*';
|
@@ -965,325 +1172,35 @@ class CompletionProvider {
|
|
965
1172
|
paramString += '**';
|
966
1173
|
}
|
967
1174
|
if (param.name) {
|
968
|
-
paramString += param.name;
|
969
|
-
}
|
970
|
-
if (param.typeAnnotation) {
|
971
|
-
const originalType = funcType.details.parameters[index].type;
|
972
|
-
const typeToPrint = getTypeToPrint(types_1.FunctionType.getEffectiveParameterType(funcType, index), originalType);
|
973
|
-
// If we have actual type, then use type to generate string representation of the type, otherwise, use syntax (text).
|
974
|
-
const strType = isTypeUsableForPrint(typeToPrint, originalType)
|
975
|
-
? this._evaluator.printType(typeToPrint, printOptionsUsingType)
|
976
|
-
: ParseTreeUtils.printExpression(param.typeAnnotation, printOptionsUsingSyntax);
|
977
|
-
paramString += ': ' + strType;
|
978
|
-
}
|
979
|
-
if (param.defaultValueExpression) {
|
980
|
-
paramString += param.typeAnnotation ? ' = ' : '=';
|
981
|
-
const useEllipsis = ellipsisForDefault !== null && ellipsisForDefault !== void 0 ? ellipsisForDefault : !isSimpleDefault(param.defaultValueExpression);
|
982
|
-
paramString += useEllipsis
|
983
|
-
? '...'
|
984
|
-
: ParseTreeUtils.printExpression(param.defaultValueExpression, printOptionsUsingSyntax);
|
985
|
-
}
|
986
|
-
if (!paramString &&
|
987
|
-
!param.name &&
|
988
|
-
param.category === 0 /* Simple */ &&
|
989
|
-
index < funcType.details.parameters.length - 1) {
|
990
|
-
return '/';
|
991
|
-
}
|
992
|
-
return paramString;
|
993
|
-
});
|
994
|
-
// Remove empty parameters at the end.
|
995
|
-
for (let i = paramList.length - 1; i >= 0; i--) {
|
996
|
-
if (paramList[i] !== '') {
|
997
|
-
break;
|
998
|
-
}
|
999
|
-
paramList.pop();
|
1000
|
-
}
|
1001
|
-
let methodSignature = funcType.details.name + '(' + paramList.join(', ') + ')';
|
1002
|
-
const strReturnType = getReturnTypeStr(this._evaluator, funcType, printOptionsUsingSyntax);
|
1003
|
-
if (strReturnType) {
|
1004
|
-
methodSignature += ' -> ' + strReturnType;
|
1005
|
-
}
|
1006
|
-
return { methodSignature, importData };
|
1007
|
-
function createImportData(importAdder, funcType, declaration, typingFilePath, declarationGetter, token) {
|
1008
|
-
var _a, _b;
|
1009
|
-
// Handle regular case. In this case, we can get import info from
|
1010
|
-
// import used in the file where the function is declared.
|
1011
|
-
const ranges = [];
|
1012
|
-
(0, collectionUtils_1.addIfNotNull)(ranges, textRange_2.TextRange.combine(declaration.node.parameters));
|
1013
|
-
(0, collectionUtils_1.addIfNotNull)(ranges, declaration.node.returnTypeAnnotation);
|
1014
|
-
(0, collectionUtils_1.addIfNotNull)(ranges, declaration.node.functionAnnotationComment);
|
1015
|
-
const moduleNode = ParseTreeUtils.getModuleNode(declaration.node);
|
1016
|
-
const importData = importAdder.collectImportsForSymbolsUsed(moduleNode, ranges, token);
|
1017
|
-
// Handle special case where function has type arguments. In this case,
|
1018
|
-
// we can't use the file the function is declared in because it doesn't
|
1019
|
-
// have those type arguments. It just has the type vars.
|
1020
|
-
// We could walk the mro to discover imports for the type arguments, but
|
1021
|
-
// for now, instead, this creates import statement out of type arguments itself.
|
1022
|
-
const effectiveTypes = [];
|
1023
|
-
funcType.details.parameters.forEach((param, index) => {
|
1024
|
-
if (!param.typeAnnotation) {
|
1025
|
-
return;
|
1026
|
-
}
|
1027
|
-
const originalType = funcType.details.parameters[index].type;
|
1028
|
-
if (!(0, types_1.isTypeVar)(originalType)) {
|
1029
|
-
return;
|
1030
|
-
}
|
1031
|
-
const effectiveType = types_1.FunctionType.getEffectiveParameterType(funcType, index);
|
1032
|
-
effectiveTypes.push([effectiveType, param.typeAnnotation]);
|
1033
|
-
});
|
1034
|
-
const node = declaration.node;
|
1035
|
-
const originalType = funcType.details.declaredReturnType;
|
1036
|
-
if (originalType &&
|
1037
|
-
(0, types_1.isTypeVar)(originalType) &&
|
1038
|
-
(node.returnTypeAnnotation || ((_a = node.functionAnnotationComment) === null || _a === void 0 ? void 0 : _a.returnTypeAnnotation))) {
|
1039
|
-
effectiveTypes.push([
|
1040
|
-
types_1.FunctionType.getSpecializedReturnType(funcType),
|
1041
|
-
(_b = node.returnTypeAnnotation) !== null && _b !== void 0 ? _b : node.functionAnnotationComment.returnTypeAnnotation,
|
1042
|
-
]);
|
1043
|
-
}
|
1044
|
-
const visited = new Set();
|
1045
|
-
const addImport = (t, n) => {
|
1046
|
-
var _a, _b;
|
1047
|
-
if (visited.has(t)) {
|
1048
|
-
return;
|
1049
|
-
}
|
1050
|
-
visited.add(t);
|
1051
|
-
// We need to special case `Any` since we can't get decl from `Any`.
|
1052
|
-
if ((0, types_1.isAny)(t)) {
|
1053
|
-
if (!typingFilePath) {
|
1054
|
-
return;
|
1055
|
-
}
|
1056
|
-
importAdder.addImportInfo({ filePath: typingFilePath, nameInfo: { name: 'Any' } }, importData);
|
1057
|
-
}
|
1058
|
-
if (!(0, types_1.isClass)(t)) {
|
1059
|
-
return;
|
1060
|
-
}
|
1061
|
-
// We need to special case `List`, `Dict` and `Tuple` since user might have
|
1062
|
-
// used typing.List or typing.Dict in the code, but we internally already
|
1063
|
-
// converted them to built-in `list` and `dict`.
|
1064
|
-
// We could avoid doing this if class type holds onto decl it was created from
|
1065
|
-
// if it is not synthesized like func type.
|
1066
|
-
if (typingFilePath && types_1.ClassType.isBuiltIn(t)) {
|
1067
|
-
const name = (_a = t.aliasName) !== null && _a !== void 0 ? _a : t.details.name;
|
1068
|
-
if (t.details.moduleName === 'typing' && name) {
|
1069
|
-
importAdder.addImportInfo({
|
1070
|
-
filePath: typingFilePath,
|
1071
|
-
nameInfo: { name },
|
1072
|
-
}, importData);
|
1073
|
-
}
|
1074
|
-
else if (t.details.moduleName === 'builtins' && t.aliasName) {
|
1075
|
-
importAdder.addImportInfo({
|
1076
|
-
filePath: typingFilePath,
|
1077
|
-
nameInfo: { name },
|
1078
|
-
}, importData);
|
1079
|
-
}
|
1080
|
-
}
|
1081
|
-
else {
|
1082
|
-
const decls = declarationGetter(t);
|
1083
|
-
if (decls.length === 0) {
|
1084
|
-
return;
|
1085
|
-
}
|
1086
|
-
importAdder.addDeclaration(decls[0], n, importData);
|
1087
|
-
}
|
1088
|
-
if (t.isTypeArgumentExplicit) {
|
1089
|
-
(_b = t.typeArguments) === null || _b === void 0 ? void 0 : _b.forEach((ta) => {
|
1090
|
-
addImport(ta, n);
|
1091
|
-
(0, typeUtils_1.doForEachSubtype)(ta, (subtype) => {
|
1092
|
-
addImport(subtype, n);
|
1093
|
-
});
|
1094
|
-
});
|
1095
|
-
}
|
1096
|
-
};
|
1097
|
-
effectiveTypes.forEach(([t, n]) => {
|
1098
|
-
addImport(t, n);
|
1099
|
-
(0, typeUtils_1.doForEachSubtype)(t, (subtype) => {
|
1100
|
-
addImport(subtype, n);
|
1101
|
-
});
|
1102
|
-
});
|
1103
|
-
return importData;
|
1104
|
-
}
|
1105
|
-
function getReturnTypeStr(evaluator, funcType, printFlags) {
|
1106
|
-
var _a;
|
1107
|
-
const originalType = funcType.details.declaredReturnType;
|
1108
|
-
const typeToPrint = getTypeToPrint(types_1.FunctionType.getSpecializedReturnType(funcType), originalType);
|
1109
|
-
const node = funcType.details.declaration.node;
|
1110
|
-
if (!node.returnTypeAnnotation && !((_a = node.functionAnnotationComment) === null || _a === void 0 ? void 0 : _a.returnTypeAnnotation)) {
|
1111
|
-
return undefined;
|
1112
|
-
}
|
1113
|
-
if (typeToPrint && isTypeUsableForPrint(typeToPrint, originalType)) {
|
1114
|
-
return evaluator.printType(typeToPrint, printOptionsUsingType);
|
1115
|
-
}
|
1116
|
-
if (node.returnTypeAnnotation) {
|
1117
|
-
return ParseTreeUtils.printExpression(node.returnTypeAnnotation, printFlags);
|
1118
|
-
}
|
1119
|
-
if (node.functionAnnotationComment) {
|
1120
|
-
return ParseTreeUtils.printExpression(node.functionAnnotationComment.returnTypeAnnotation, printFlags);
|
1121
|
-
}
|
1122
|
-
return undefined;
|
1123
|
-
}
|
1124
|
-
function isTypeUsableForPrint(effectiveType, originalType) {
|
1125
|
-
if (!effectiveType) {
|
1126
|
-
return false;
|
1127
|
-
}
|
1128
|
-
// If original type was `TypeVar`, we want to use `Unknown` as `Any`
|
1129
|
-
return !(0, types_1.isUnknown)(effectiveType) || (originalType === null || originalType === void 0 ? void 0 : originalType.category) === 10 /* TypeVar */;
|
1130
|
-
}
|
1131
|
-
function isSimpleDefault(node) {
|
1132
|
-
switch (node.nodeType) {
|
1133
|
-
case 40 /* Number */:
|
1134
|
-
case 11 /* Constant */:
|
1135
|
-
case 35 /* MemberAccess */:
|
1136
|
-
return true;
|
1137
|
-
case 49 /* String */:
|
1138
|
-
return (node.token.flags & 64 /* Format */) === 0;
|
1139
|
-
case 48 /* StringList */:
|
1140
|
-
return node.strings.every(isSimpleDefault);
|
1141
|
-
case 55 /* UnaryOperation */:
|
1142
|
-
return isSimpleDefault(node.expression);
|
1143
|
-
case 7 /* BinaryOperation */:
|
1144
|
-
return isSimpleDefault(node.leftExpression) && isSimpleDefault(node.rightExpression);
|
1145
|
-
default:
|
1146
|
-
return false;
|
1147
|
-
}
|
1148
|
-
}
|
1149
|
-
}
|
1150
|
-
_printOverriddenMethodBody(classType, isStaticMethod, isProperty, decl) {
|
1151
|
-
let sb = this._parseResults.tokenizerOutput.predominantTabSequence;
|
1152
|
-
if (classType.details.baseClasses.length === 1 &&
|
1153
|
-
(0, types_1.isClass)(classType.details.baseClasses[0]) &&
|
1154
|
-
classType.details.baseClasses[0].details.fullName === 'builtins.object') {
|
1155
|
-
sb += this._options.snippet ? '${0:pass}' : 'pass';
|
1156
|
-
return sb;
|
1157
|
-
}
|
1158
|
-
if (decl.node.parameters.length === 0) {
|
1159
|
-
sb += this._options.snippet ? '${0:pass}' : 'pass';
|
1160
|
-
return sb;
|
1161
|
-
}
|
1162
|
-
const parameters = getParameters(isStaticMethod ? decl.node.parameters : decl.node.parameters.slice(1));
|
1163
|
-
if (decl.node.name.value !== '__init__') {
|
1164
|
-
sb += 'return ';
|
1165
|
-
}
|
1166
|
-
if (decl.node.isAsync) {
|
1167
|
-
sb += 'await ';
|
1168
|
-
}
|
1169
|
-
if (isProperty) {
|
1170
|
-
return sb + `super().${decl.node.name.value}`;
|
1171
|
-
}
|
1172
|
-
return sb + `super().${decl.node.name.value}(${parameters.map(convertToString).join(', ')})`;
|
1173
|
-
function getParameters(parameters) {
|
1174
|
-
const results = [];
|
1175
|
-
let sawKeywordOnlySeparator = false;
|
1176
|
-
for (const parameter of parameters) {
|
1177
|
-
if (parameter.name) {
|
1178
|
-
results.push([
|
1179
|
-
parameter,
|
1180
|
-
parameter.category === 0 /* Simple */ && !!parameter.name && sawKeywordOnlySeparator,
|
1181
|
-
]);
|
1182
|
-
}
|
1183
|
-
// All simple parameters after a `*` or `*args` parameter
|
1184
|
-
// are considered keyword only.
|
1185
|
-
if (parameter.category === 1 /* VarArgList */) {
|
1186
|
-
sawKeywordOnlySeparator = true;
|
1187
|
-
}
|
1188
|
-
}
|
1189
|
-
return results;
|
1190
|
-
}
|
1191
|
-
function convertToString(parameter) {
|
1192
|
-
var _a;
|
1193
|
-
const name = (_a = parameter[0].name) === null || _a === void 0 ? void 0 : _a.value;
|
1194
|
-
if (parameter[0].category === 1 /* VarArgList */) {
|
1195
|
-
return `*${name}`;
|
1196
|
-
}
|
1197
|
-
if (parameter[0].category === 2 /* VarArgDictionary */) {
|
1198
|
-
return `**${name}`;
|
1175
|
+
paramString += param.name.value;
|
1199
1176
|
}
|
1200
|
-
|
1201
|
-
|
1202
|
-
|
1203
|
-
|
1204
|
-
|
1205
|
-
const completionMap = new CompletionMap();
|
1206
|
-
let memberAccessInfo = {};
|
1207
|
-
let leftType = this._evaluator.getType(leftExprNode);
|
1208
|
-
if (leftType) {
|
1209
|
-
leftType = this._evaluator.makeTopLevelTypeVarsConcrete(leftType);
|
1210
|
-
// If this is an unknown type with a "possible type" associated with
|
1211
|
-
// it, use the possible type.
|
1212
|
-
if ((0, types_1.isUnknown)(leftType) && leftType.possibleType) {
|
1213
|
-
leftType = this._evaluator.makeTopLevelTypeVarsConcrete(leftType.possibleType);
|
1214
|
-
}
|
1215
|
-
(0, typeUtils_1.doForEachSubtype)(leftType, (subtype) => {
|
1216
|
-
subtype = this._evaluator.makeTopLevelTypeVarsConcrete(subtype);
|
1217
|
-
if ((0, types_1.isClass)(subtype)) {
|
1218
|
-
(0, typeUtils_1.getMembersForClass)(subtype, symbolTable, /* includeInstanceVars */ types_1.TypeBase.isInstance(subtype));
|
1219
|
-
}
|
1220
|
-
else if ((0, types_1.isModule)(subtype)) {
|
1221
|
-
(0, typeUtils_1.getMembersForModule)(subtype, symbolTable);
|
1222
|
-
}
|
1223
|
-
else if ((0, types_1.isFunction)(subtype) || (0, types_1.isOverloadedFunction)(subtype)) {
|
1224
|
-
const functionClass = this._evaluator.getBuiltInType(leftExprNode, 'function');
|
1225
|
-
if (functionClass && (0, types_1.isInstantiableClass)(functionClass)) {
|
1226
|
-
(0, typeUtils_1.getMembersForClass)(functionClass, symbolTable, /* includeInstanceVars */ true);
|
1227
|
-
}
|
1228
|
-
}
|
1229
|
-
else if ((0, types_1.isNoneInstance)(subtype)) {
|
1230
|
-
const objectClass = this._evaluator.getBuiltInType(leftExprNode, 'object');
|
1231
|
-
if (objectClass && (0, types_1.isInstantiableClass)(objectClass)) {
|
1232
|
-
(0, typeUtils_1.getMembersForClass)(objectClass, symbolTable, types_1.TypeBase.isInstance(subtype));
|
1233
|
-
}
|
1234
|
-
}
|
1235
|
-
this._addSymbolsForSymbolTable(symbolTable, () => true, priorWord, leftExprNode,
|
1236
|
-
/* isInImport */ false, (0, types_1.isClass)(subtype) ? subtype : undefined, completionMap);
|
1237
|
-
});
|
1238
|
-
}
|
1239
|
-
// Save member access info for every request
|
1240
|
-
memberAccessInfo = this._getLastKnownModule(leftExprNode, leftType);
|
1241
|
-
return { completionMap, memberAccessInfo };
|
1242
|
-
}
|
1243
|
-
_getLastKnownModule(leftExprNode, leftType) {
|
1244
|
-
var _a;
|
1245
|
-
let curNode = leftExprNode;
|
1246
|
-
let curType = leftType;
|
1247
|
-
let unknownMemberName = leftExprNode.nodeType === 35 /* MemberAccess */ ? leftExprNode === null || leftExprNode === void 0 ? void 0 : leftExprNode.memberName.value : undefined;
|
1248
|
-
// Walk left of the expression scope till we find a known type. A.B.Unknown.<-- return B.
|
1249
|
-
while (curNode) {
|
1250
|
-
if (curNode.nodeType === 9 /* Call */ || curNode.nodeType === 35 /* MemberAccess */) {
|
1251
|
-
// Move left
|
1252
|
-
curNode = curNode.leftExpression;
|
1253
|
-
// First time in the loop remember the name of the unknown type.
|
1254
|
-
if (unknownMemberName === undefined) {
|
1255
|
-
unknownMemberName =
|
1256
|
-
curNode.nodeType === 35 /* MemberAccess */ ? (_a = curNode === null || curNode === void 0 ? void 0 : curNode.memberName.value) !== null && _a !== void 0 ? _a : '' : '';
|
1257
|
-
}
|
1177
|
+
// Currently, we don't automatically add import if the type used in the annotation is not imported
|
1178
|
+
// in current file.
|
1179
|
+
const paramTypeAnnotation = ParseTreeUtils.getTypeAnnotationForParameter(node, index);
|
1180
|
+
if (paramTypeAnnotation) {
|
1181
|
+
paramString += ': ' + ParseTreeUtils.printExpression(paramTypeAnnotation, printFlags);
|
1258
1182
|
}
|
1259
|
-
|
1260
|
-
|
1183
|
+
if (param.defaultValue) {
|
1184
|
+
paramString += paramTypeAnnotation ? ' = ' : '=';
|
1185
|
+
const useEllipsis = ellipsisForDefault !== null && ellipsisForDefault !== void 0 ? ellipsisForDefault : !this.isSimpleDefault(param.defaultValue);
|
1186
|
+
paramString += useEllipsis ? '...' : ParseTreeUtils.printExpression(param.defaultValue, printFlags);
|
1261
1187
|
}
|
1262
|
-
if (
|
1263
|
-
|
1264
|
-
// Breakout if we found a known type.
|
1265
|
-
if (curType !== undefined && !(0, types_1.isUnknown)(curType) && !(0, types_1.isUnbound)(curType)) {
|
1266
|
-
break;
|
1267
|
-
}
|
1188
|
+
if (!paramString && !param.name && param.category === 0 /* Simple */) {
|
1189
|
+
return '/';
|
1268
1190
|
}
|
1191
|
+
return paramString;
|
1192
|
+
})
|
1193
|
+
.join(', ');
|
1194
|
+
let methodSignature = node.name.value + '(' + paramList + ')';
|
1195
|
+
if (node.returnTypeAnnotation) {
|
1196
|
+
methodSignature += ' -> ' + ParseTreeUtils.printExpression(node.returnTypeAnnotation, printFlags);
|
1269
1197
|
}
|
1270
|
-
|
1271
|
-
|
1272
|
-
|
1273
|
-
|
1274
|
-
memberAccessInfo.lastKnownModule = moduleNamesForType.find((n) => n !== 'typing');
|
1275
|
-
if (curNode.nodeType === 35 /* MemberAccess */) {
|
1276
|
-
memberAccessInfo.lastKnownMemberName = curNode.memberName.value;
|
1277
|
-
}
|
1278
|
-
else if (curNode.nodeType === 38 /* Name */ && (0, types_1.isInstantiableClass)(curType)) {
|
1279
|
-
memberAccessInfo.lastKnownMemberName = curType.details.name;
|
1280
|
-
}
|
1281
|
-
else if (curNode.nodeType === 38 /* Name */ && (0, types_1.isClassInstance)(curType)) {
|
1282
|
-
memberAccessInfo.lastKnownMemberName = curType.details.name;
|
1283
|
-
}
|
1284
|
-
memberAccessInfo.unknownMemberName = unknownMemberName;
|
1198
|
+
else if (node.functionAnnotationComment) {
|
1199
|
+
methodSignature +=
|
1200
|
+
' -> ' +
|
1201
|
+
ParseTreeUtils.printExpression(node.functionAnnotationComment.returnTypeAnnotation, printFlags);
|
1285
1202
|
}
|
1286
|
-
return
|
1203
|
+
return methodSignature;
|
1287
1204
|
}
|
1288
1205
|
_getStatementCompletions(parseNode, priorWord, priorText, postText) {
|
1289
1206
|
// For now, use the same logic for expressions and statements.
|
@@ -1304,10 +1221,9 @@ class CompletionProvider {
|
|
1304
1221
|
return undefined;
|
1305
1222
|
}
|
1306
1223
|
const completionMap = new CompletionMap();
|
1307
|
-
const completionResults = { completionMap };
|
1308
1224
|
// Return empty completionList for Ellipsis
|
1309
1225
|
if (priorText.slice(-2) === '..') {
|
1310
|
-
return
|
1226
|
+
return completionMap;
|
1311
1227
|
}
|
1312
1228
|
// Defining type annotation for class variables.
|
1313
1229
|
// ex) class A:
|
@@ -1319,7 +1235,7 @@ class CompletionProvider {
|
|
1319
1235
|
// Add symbols that are in scope.
|
1320
1236
|
this._addSymbols(parseNode, priorWord, completionMap);
|
1321
1237
|
// Add keywords.
|
1322
|
-
this._findMatchingKeywords(Keywords.forVersion(this.
|
1238
|
+
this._findMatchingKeywords(Keywords.forVersion(this.execEnv.pythonVersion), priorWord).map((keyword) => {
|
1323
1239
|
if (completionMap.has(keyword)) {
|
1324
1240
|
return;
|
1325
1241
|
}
|
@@ -1331,11 +1247,11 @@ class CompletionProvider {
|
|
1331
1247
|
// Add auto-import suggestions from other modules.
|
1332
1248
|
// Ignore this check for privates, since they are not imported.
|
1333
1249
|
if (!priorWord.startsWith('_') && !this._itemToResolve) {
|
1334
|
-
this.
|
1250
|
+
this.addAutoImportCompletions(priorWord, similarityLimit, this.options.lazyEdit, completionMap);
|
1335
1251
|
}
|
1336
1252
|
// Add literal values if appropriate.
|
1337
1253
|
this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap);
|
1338
|
-
return
|
1254
|
+
return completionMap;
|
1339
1255
|
}
|
1340
1256
|
_isIndexArgument(node) {
|
1341
1257
|
const currentNode = node.parent;
|
@@ -1349,16 +1265,16 @@ class CompletionProvider {
|
|
1349
1265
|
}
|
1350
1266
|
_addCallArgumentCompletions(parseNode, priorWord, priorText, postText, atArgument, completionMap) {
|
1351
1267
|
// If we're within the argument list of a call, add parameter names.
|
1352
|
-
const offset = (0, positionUtils_1.convertPositionToOffset)(this.
|
1353
|
-
const callInfo = (0, parseTreeUtils_1.getCallNodeAndActiveParameterIndex)(parseNode, offset, this.
|
1268
|
+
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
1269
|
+
const callInfo = (0, parseTreeUtils_1.getCallNodeAndActiveParameterIndex)(parseNode, offset, this.parseResults.tokenizerOutput.tokens);
|
1354
1270
|
if (!callInfo) {
|
1355
1271
|
return;
|
1356
1272
|
}
|
1357
|
-
const signatureInfo = this.
|
1273
|
+
const signatureInfo = this.evaluator.getCallSignatureInfo(callInfo.callNode, callInfo.activeIndex, callInfo.activeOrFake);
|
1358
1274
|
if (signatureInfo) {
|
1359
1275
|
// Are we past the call expression and within the argument list?
|
1360
|
-
const callNameEnd = (0, positionUtils_1.convertOffsetToPosition)(signatureInfo.callNode.leftExpression.start + signatureInfo.callNode.leftExpression.length, this.
|
1361
|
-
if ((0, textRange_1.comparePositions)(this.
|
1276
|
+
const callNameEnd = (0, positionUtils_1.convertOffsetToPosition)(signatureInfo.callNode.leftExpression.start + signatureInfo.callNode.leftExpression.length, this.parseResults.tokenizerOutput.lines);
|
1277
|
+
if ((0, textRange_1.comparePositions)(this.position, callNameEnd) > 0) {
|
1362
1278
|
if (!atArgument) {
|
1363
1279
|
this._addNamedParameters(signatureInfo, priorWord, completionMap);
|
1364
1280
|
}
|
@@ -1449,7 +1365,7 @@ class CompletionProvider {
|
|
1449
1365
|
if (member === null || member === void 0 ? void 0 : member.symbol.hasDeclarations()) {
|
1450
1366
|
const declaration = member.symbol.getDeclarations()[0];
|
1451
1367
|
if ((0, declaration_1.isFunctionDeclaration)(declaration) && declaration.isMethod) {
|
1452
|
-
const getItemType = (_b = this.
|
1368
|
+
const getItemType = (_b = this.evaluator.getTypeForDeclaration(declaration)) === null || _b === void 0 ? void 0 : _b.type;
|
1453
1369
|
if (getItemType && (0, types_1.isFunction)(getItemType) && getItemType.details.parameters.length === 2) {
|
1454
1370
|
return getItemType.details.parameters[1].type;
|
1455
1371
|
}
|
@@ -1459,7 +1375,7 @@ class CompletionProvider {
|
|
1459
1375
|
}
|
1460
1376
|
_getIndexerKeys(indexNode, invocationNode) {
|
1461
1377
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
1462
|
-
const baseType = this.
|
1378
|
+
const baseType = this.evaluator.getType(indexNode.baseExpression);
|
1463
1379
|
if (!baseType || !(0, types_1.isClassInstance)(baseType)) {
|
1464
1380
|
return [];
|
1465
1381
|
}
|
@@ -1475,7 +1391,7 @@ class CompletionProvider {
|
|
1475
1391
|
!types_1.ClassType.isEnumClass(v)) {
|
1476
1392
|
return;
|
1477
1393
|
}
|
1478
|
-
keys.push((0, typePrinter_1.printLiteralValue)(v, this.
|
1394
|
+
keys.push((0, typePrinter_1.printLiteralValue)(v, this.parseResults.tokenizerOutput.predominantSingleQuoteCharacter));
|
1479
1395
|
});
|
1480
1396
|
if (keys.length > 0) {
|
1481
1397
|
return keys;
|
@@ -1486,13 +1402,13 @@ class CompletionProvider {
|
|
1486
1402
|
return [];
|
1487
1403
|
}
|
1488
1404
|
// Must be local variable/parameter
|
1489
|
-
const declarations = (_a = this.
|
1405
|
+
const declarations = (_a = this.evaluator.getDeclarationsForNameNode(indexNode.baseExpression)) !== null && _a !== void 0 ? _a : [];
|
1490
1406
|
const declaration = declarations.length > 0 ? declarations[0] : undefined;
|
1491
1407
|
if (!declaration ||
|
1492
1408
|
(declaration.type !== 1 /* Variable */ && declaration.type !== 2 /* Parameter */)) {
|
1493
1409
|
return [];
|
1494
1410
|
}
|
1495
|
-
if (declaration.path !== this.
|
1411
|
+
if (declaration.path !== this.filePath) {
|
1496
1412
|
return [];
|
1497
1413
|
}
|
1498
1414
|
let startingNode = indexNode.baseExpression;
|
@@ -1504,7 +1420,7 @@ class CompletionProvider {
|
|
1504
1420
|
startingNode = scopeRoot;
|
1505
1421
|
}
|
1506
1422
|
}
|
1507
|
-
const results = documentSymbolCollector_1.DocumentSymbolCollector.collectFromNode(this.
|
1423
|
+
const results = documentSymbolCollector_1.DocumentSymbolCollector.collectFromNode(this.program, indexNode.baseExpression, this.cancellationToken, startingNode);
|
1508
1424
|
const keys = new Set();
|
1509
1425
|
for (const result of results) {
|
1510
1426
|
const node = ((_d = result.node.parent) === null || _d === void 0 ? void 0 : _d.nodeType) === 54 /* TypeAnnotation */ ? result.node.parent : result.node;
|
@@ -1513,7 +1429,7 @@ class CompletionProvider {
|
|
1513
1429
|
if (node.parent.rightExpression.nodeType === 15 /* Dictionary */) {
|
1514
1430
|
const dictionary = node.parent.rightExpression;
|
1515
1431
|
for (const entry of dictionary.entries.filter((e) => e.nodeType === 17 /* DictionaryKeyEntry */)) {
|
1516
|
-
const key = this.
|
1432
|
+
const key = this.parseResults.text
|
1517
1433
|
.substr(entry.keyExpression.start, entry.keyExpression.length)
|
1518
1434
|
.trim();
|
1519
1435
|
if (key.length > 0)
|
@@ -1522,13 +1438,13 @@ class CompletionProvider {
|
|
1522
1438
|
}
|
1523
1439
|
if (node.parent.rightExpression.nodeType === 9 /* Call */) {
|
1524
1440
|
const call = node.parent.rightExpression;
|
1525
|
-
const type = this.
|
1441
|
+
const type = this.evaluator.getType(call.leftExpression);
|
1526
1442
|
if (!type || !(0, types_1.isInstantiableClass)(type) || !types_1.ClassType.isBuiltIn(type, 'dict')) {
|
1527
1443
|
continue;
|
1528
1444
|
}
|
1529
1445
|
for (const arg of call.arguments) {
|
1530
1446
|
const key = (_h = (_g = arg.name) === null || _g === void 0 ? void 0 : _g.value.trim()) !== null && _h !== void 0 ? _h : '';
|
1531
|
-
const quote = this.
|
1447
|
+
const quote = this.parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
|
1532
1448
|
if (key.length > 0) {
|
1533
1449
|
keys.add(`${quote}${key}${quote}`);
|
1534
1450
|
}
|
@@ -1540,7 +1456,7 @@ class CompletionProvider {
|
|
1540
1456
|
node.parent.items[0].valueExpression.nodeType !== 0 /* Error */ &&
|
1541
1457
|
!textRange_2.TextRange.containsRange(node.parent, invocationNode)) {
|
1542
1458
|
const indexArgument = node.parent.items[0];
|
1543
|
-
const key = this.
|
1459
|
+
const key = this.parseResults.text
|
1544
1460
|
.substr(indexArgument.valueExpression.start, indexArgument.valueExpression.length)
|
1545
1461
|
.trim();
|
1546
1462
|
if (key.length > 0)
|
@@ -1550,7 +1466,7 @@ class CompletionProvider {
|
|
1550
1466
|
return [...keys];
|
1551
1467
|
}
|
1552
1468
|
_getLiteralCompletions(parseNode, offset, priorWord, priorText, postText) {
|
1553
|
-
if (this.
|
1469
|
+
if (this.options.triggerCharacter === '"' || this.options.triggerCharacter === "'") {
|
1554
1470
|
if (parseNode.start !== offset - 1) {
|
1555
1471
|
// If completion is triggered by typing " or ', it must be the one that starts a string
|
1556
1472
|
// literal. In another word, it can't be something inside of another string or comment
|
@@ -1561,7 +1477,7 @@ class CompletionProvider {
|
|
1561
1477
|
if (!this._tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap)) {
|
1562
1478
|
return undefined;
|
1563
1479
|
}
|
1564
|
-
return
|
1480
|
+
return completionMap;
|
1565
1481
|
}
|
1566
1482
|
_tryAddLiterals(parseNode, priorWord, priorText, postText, completionMap) {
|
1567
1483
|
var _a, _b, _c, _d, _e, _f;
|
@@ -1579,7 +1495,7 @@ class CompletionProvider {
|
|
1579
1495
|
? parentAndChild.child
|
1580
1496
|
: undefined;
|
1581
1497
|
if (nodeForExpectedType) {
|
1582
|
-
const expectedTypeResult = this.
|
1498
|
+
const expectedTypeResult = this.evaluator.getExpectedType(nodeForExpectedType);
|
1583
1499
|
if (expectedTypeResult && (0, typeUtils_1.isLiteralTypeOrUnion)(expectedTypeResult.type)) {
|
1584
1500
|
this._addLiteralValuesForTargetType(expectedTypeResult.type, priorWord, priorText, postText, completionMap);
|
1585
1501
|
return true;
|
@@ -1648,7 +1564,7 @@ class CompletionProvider {
|
|
1648
1564
|
const comparison = parentAndChild.parent;
|
1649
1565
|
const supportedOperators = [2 /* Assign */, 12 /* Equals */, 28 /* NotEquals */];
|
1650
1566
|
if (comparison.nodeType === 7 /* BinaryOperation */ && supportedOperators.includes(comparison.operator)) {
|
1651
|
-
const type = this.
|
1567
|
+
const type = this.evaluator.getType(comparison.leftExpression);
|
1652
1568
|
if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
|
1653
1569
|
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
1654
1570
|
return true;
|
@@ -1658,7 +1574,7 @@ class CompletionProvider {
|
|
1658
1574
|
const assignmentExpression = parentAndChild.parent;
|
1659
1575
|
if (assignmentExpression.nodeType === 4 /* AssignmentExpression */ &&
|
1660
1576
|
assignmentExpression.rightExpression === parentAndChild.child) {
|
1661
|
-
const type = this.
|
1577
|
+
const type = this.evaluator.getType(assignmentExpression.name);
|
1662
1578
|
if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
|
1663
1579
|
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
1664
1580
|
return true;
|
@@ -1673,7 +1589,7 @@ class CompletionProvider {
|
|
1673
1589
|
caseNode.pattern.category === 11 /* MissingPattern */ &&
|
1674
1590
|
caseNode.suite === parentAndChild.child &&
|
1675
1591
|
((_c = caseNode.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 63 /* Match */) {
|
1676
|
-
const type = this.
|
1592
|
+
const type = this.evaluator.getType(caseNode.parent.subjectExpression);
|
1677
1593
|
if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
|
1678
1594
|
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
1679
1595
|
return true;
|
@@ -1688,14 +1604,14 @@ class CompletionProvider {
|
|
1688
1604
|
((_d = patternLiteral.parent) === null || _d === void 0 ? void 0 : _d.nodeType) === 66 /* PatternAs */ &&
|
1689
1605
|
((_e = patternLiteral.parent.parent) === null || _e === void 0 ? void 0 : _e.nodeType) === 64 /* Case */ &&
|
1690
1606
|
((_f = patternLiteral.parent.parent.parent) === null || _f === void 0 ? void 0 : _f.nodeType) === 63 /* Match */) {
|
1691
|
-
const type = this.
|
1607
|
+
const type = this.evaluator.getType(patternLiteral.parent.parent.parent.subjectExpression);
|
1692
1608
|
if (type && (0, typeUtils_1.isLiteralTypeOrUnion)(type)) {
|
1693
1609
|
this._addLiteralValuesForTargetType(type, priorWord, priorText, postText, completionMap);
|
1694
1610
|
return true;
|
1695
1611
|
}
|
1696
1612
|
}
|
1697
1613
|
if (parseNode.nodeType === 49 /* String */) {
|
1698
|
-
const offset = (0, positionUtils_1.convertPositionToOffset)(this.
|
1614
|
+
const offset = (0, positionUtils_1.convertPositionToOffset)(this.position, this.parseResults.tokenizerOutput.lines);
|
1699
1615
|
const atArgument = parseNode.parent.start < offset && offset < textRange_2.TextRange.getEnd(parseNode);
|
1700
1616
|
this._addCallArgumentCompletions(parseNode, priorWord, priorText, postText, atArgument, completionMap);
|
1701
1617
|
return true;
|
@@ -1732,7 +1648,7 @@ class CompletionProvider {
|
|
1732
1648
|
const quoteInfo = this._getQuoteInfo(priorWord, priorText);
|
1733
1649
|
const excludes = new Set(existingKeys);
|
1734
1650
|
typedDicts.forEach((typedDict) => {
|
1735
|
-
(0, typedDicts_1.getTypedDictMembersForClass)(this.
|
1651
|
+
(0, typedDicts_1.getTypedDictMembersForClass)(this.evaluator, typedDict, /* allowNarrowed */ true).forEach((_, key) => {
|
1736
1652
|
// Unions of TypedDicts may define the same key.
|
1737
1653
|
if (excludes.has(key) || completionMap.has(key)) {
|
1738
1654
|
return;
|
@@ -1745,7 +1661,7 @@ class CompletionProvider {
|
|
1745
1661
|
}
|
1746
1662
|
_tryAddTypedDictKeysFromDictionary(dictionaryNode, stringNode, priorWord, priorText, postText, completionMap) {
|
1747
1663
|
var _a;
|
1748
|
-
const expectedTypeResult = this.
|
1664
|
+
const expectedTypeResult = this.evaluator.getExpectedType(dictionaryNode);
|
1749
1665
|
if (!expectedTypeResult) {
|
1750
1666
|
return false;
|
1751
1667
|
}
|
@@ -1759,7 +1675,7 @@ class CompletionProvider {
|
|
1759
1675
|
}
|
1760
1676
|
_tryNarrowTypedDicts(types, keys) {
|
1761
1677
|
const newTypes = types.flatMap((type) => {
|
1762
|
-
const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this.
|
1678
|
+
const entries = (0, typedDicts_1.getTypedDictMembersForClass)(this.evaluator, type, /* allowNarrowed */ true);
|
1763
1679
|
for (let index = 0; index < keys.length; index++) {
|
1764
1680
|
if (!entries.has(keys[index])) {
|
1765
1681
|
return [];
|
@@ -1778,7 +1694,7 @@ class CompletionProvider {
|
|
1778
1694
|
_getQuoteInfo(priorWord, priorText) {
|
1779
1695
|
let filterText = priorWord;
|
1780
1696
|
let stringValue = undefined;
|
1781
|
-
let quoteCharacter = this.
|
1697
|
+
let quoteCharacter = this.parseResults.tokenizerOutput.predominantSingleQuoteCharacter;
|
1782
1698
|
// If completion is not inside of the existing string literal
|
1783
1699
|
// ex) typedDict[ |<= here
|
1784
1700
|
// use default quotation char without any string prefix.
|
@@ -1822,7 +1738,7 @@ class CompletionProvider {
|
|
1822
1738
|
if (!indexNode) {
|
1823
1739
|
return false;
|
1824
1740
|
}
|
1825
|
-
const baseType = this.
|
1741
|
+
const baseType = this.evaluator.getType(indexNode.baseExpression);
|
1826
1742
|
if (!baseType) {
|
1827
1743
|
return false;
|
1828
1744
|
}
|
@@ -1837,7 +1753,7 @@ class CompletionProvider {
|
|
1837
1753
|
const completionItem = vscode_languageserver_1.CompletionItem.create(valueWithQuotes);
|
1838
1754
|
completionItem.kind = vscode_languageserver_1.CompletionItemKind.Constant;
|
1839
1755
|
completionItem.sortText = this._makeSortText(SortCategory.LiteralValue, valueWithQuotes);
|
1840
|
-
let rangeStartCol = this.
|
1756
|
+
let rangeStartCol = this.position.character;
|
1841
1757
|
if (quoteInfo.stringValue !== undefined) {
|
1842
1758
|
rangeStartCol -= quoteInfo.stringValue.length + 1;
|
1843
1759
|
}
|
@@ -1846,80 +1762,23 @@ class CompletionProvider {
|
|
1846
1762
|
}
|
1847
1763
|
// If the text after the insertion point is the closing quote,
|
1848
1764
|
// replace it.
|
1849
|
-
let rangeEndCol = this.
|
1765
|
+
let rangeEndCol = this.position.character;
|
1850
1766
|
if (postText !== undefined) {
|
1851
1767
|
if (postText.startsWith(quoteInfo.quoteCharacter)) {
|
1852
1768
|
rangeEndCol++;
|
1853
1769
|
}
|
1854
1770
|
}
|
1855
1771
|
const range = {
|
1856
|
-
start: { line: this.
|
1857
|
-
end: { line: this.
|
1772
|
+
start: { line: this.position.line, character: rangeStartCol },
|
1773
|
+
end: { line: this.position.line, character: rangeEndCol },
|
1858
1774
|
};
|
1859
1775
|
completionItem.textEdit = vscode_languageserver_1.TextEdit.replace(range, valueWithQuotes);
|
1860
1776
|
completionItem.detail = detail;
|
1861
1777
|
completionMap.set(completionItem);
|
1862
1778
|
}
|
1863
1779
|
}
|
1864
|
-
_addAutoImportCompletions(priorWord, similarityLimit, lazyEdit, completionResults) {
|
1865
|
-
var _a, _b, _c;
|
1866
|
-
if (!this._configOptions.autoImportCompletions || !this._options.autoImport) {
|
1867
|
-
// If auto import on the server is turned off or this particular invocation
|
1868
|
-
// is turned off (ex, notebook), don't do any thing.
|
1869
|
-
return;
|
1870
|
-
}
|
1871
|
-
const moduleSymbolMap = this._autoImportMaps.getModuleSymbolsMap();
|
1872
|
-
const autoImporter = new autoImporter_1.AutoImporter(this._execEnv, this._importResolver, this._parseResults, this._position, completionResults.completionMap, moduleSymbolMap, {
|
1873
|
-
libraryMap: this._autoImportMaps.libraryMap,
|
1874
|
-
lazyEdit,
|
1875
|
-
importFormat: this._options.importFormat,
|
1876
|
-
});
|
1877
|
-
const results = [];
|
1878
|
-
const info = (_a = this._autoImportMaps.nameMap) === null || _a === void 0 ? void 0 : _a.get(priorWord);
|
1879
|
-
if (info && priorWord.length > 1 && !completionResults.completionMap.has(priorWord)) {
|
1880
|
-
(0, collectionUtils_1.appendArray)(results, autoImporter.getAutoImportCandidatesForAbbr(priorWord, info, this._cancellationToken));
|
1881
|
-
}
|
1882
|
-
results.push(...autoImporter.getAutoImportCandidates(priorWord, similarityLimit,
|
1883
|
-
/* abbrFromUsers */ undefined, this._cancellationToken));
|
1884
|
-
const perfInfo = autoImporter.getPerfInfo();
|
1885
|
-
const additionDuration = new timing_1.Duration();
|
1886
|
-
for (const result of results) {
|
1887
|
-
if (result.symbol) {
|
1888
|
-
this._addSymbol(result.name, result.symbol, priorWord, completionResults.completionMap, {
|
1889
|
-
extraCommitChars: true,
|
1890
|
-
autoImportSource: result.source,
|
1891
|
-
autoImportAlias: result.alias,
|
1892
|
-
edits: {
|
1893
|
-
textEdit: this._createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
|
1894
|
-
additionalTextEdits: result.edits,
|
1895
|
-
},
|
1896
|
-
});
|
1897
|
-
}
|
1898
|
-
else {
|
1899
|
-
this._addNameToCompletions((_b = result.alias) !== null && _b !== void 0 ? _b : result.name, (_c = result.kind) !== null && _c !== void 0 ? _c : vscode_languageserver_1.CompletionItemKind.Module, priorWord, completionResults.completionMap, {
|
1900
|
-
extraCommitChars: true,
|
1901
|
-
autoImportText: this._getAutoImportText(result.name, result.source, result.alias),
|
1902
|
-
edits: {
|
1903
|
-
textEdit: this._createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
|
1904
|
-
additionalTextEdits: result.edits,
|
1905
|
-
},
|
1906
|
-
});
|
1907
|
-
}
|
1908
|
-
}
|
1909
|
-
completionResults.autoImportInfo = {
|
1910
|
-
indexUsed: perfInfo.indexUsed,
|
1911
|
-
totalTimeInMS: perfInfo.totalInMs,
|
1912
|
-
moduleTimeInMS: perfInfo.moduleTimeInMS,
|
1913
|
-
indexTimeInMS: perfInfo.indexTimeInMS,
|
1914
|
-
importAliasTimeInMS: perfInfo.importAliasTimeInMS,
|
1915
|
-
itemCount: results.length,
|
1916
|
-
symbolCount: perfInfo.symbolCount,
|
1917
|
-
indexCount: perfInfo.indexCount,
|
1918
|
-
importAliasCount: perfInfo.importAliasCount,
|
1919
|
-
additionTimeInMS: additionDuration.getDurationInMilliseconds(),
|
1920
|
-
};
|
1921
|
-
}
|
1922
1780
|
_getImportFromCompletions(importFromNode, priorWord) {
|
1781
|
+
var _a;
|
1923
1782
|
// Don't attempt to provide completions for "from X import *".
|
1924
1783
|
if (importFromNode.isWildcardImport) {
|
1925
1784
|
return undefined;
|
@@ -1932,16 +1791,21 @@ class CompletionProvider {
|
|
1932
1791
|
}
|
1933
1792
|
const completionMap = new CompletionMap();
|
1934
1793
|
const resolvedPath = importInfo.resolvedPaths.length > 0 ? importInfo.resolvedPaths[importInfo.resolvedPaths.length - 1] : '';
|
1935
|
-
const
|
1936
|
-
if (
|
1937
|
-
|
1938
|
-
// Don't suggest built in symbols or ones that have already been imported.
|
1939
|
-
return (symbol.getDeclarations().some((d) => !(0, declaration_1.isIntrinsicDeclaration)(d)) &&
|
1940
|
-
!importFromNode.imports.find((imp) => imp.name.value === name));
|
1941
|
-
}, priorWord, importFromNode,
|
1942
|
-
/* isInImport */ true,
|
1943
|
-
/* boundObject */ undefined, completionMap);
|
1794
|
+
const parseResults = this.program.getParseResults(resolvedPath);
|
1795
|
+
if (!parseResults) {
|
1796
|
+
return completionMap;
|
1944
1797
|
}
|
1798
|
+
const symbolTable = (_a = AnalyzerNodeInfo.getScope(parseResults.parseTree)) === null || _a === void 0 ? void 0 : _a.symbolTable;
|
1799
|
+
if (!symbolTable) {
|
1800
|
+
return completionMap;
|
1801
|
+
}
|
1802
|
+
this._addSymbolsForSymbolTable(symbolTable, (symbol, name) => {
|
1803
|
+
// Don't suggest built in symbols or ones that have already been imported.
|
1804
|
+
return (symbol.getDeclarations().some((d) => !(0, declaration_1.isIntrinsicDeclaration)(d)) &&
|
1805
|
+
!importFromNode.imports.find((imp) => imp.name.value === name));
|
1806
|
+
}, priorWord, importFromNode,
|
1807
|
+
/* isInImport */ true,
|
1808
|
+
/* boundObject */ undefined, completionMap);
|
1945
1809
|
// Add the implicit imports.
|
1946
1810
|
importInfo.implicitImports.forEach((implImport) => {
|
1947
1811
|
if (!importFromNode.imports.find((imp) => imp.name.value === implImport.name)) {
|
@@ -1950,7 +1814,7 @@ class CompletionProvider {
|
|
1950
1814
|
});
|
1951
1815
|
}
|
1952
1816
|
});
|
1953
|
-
return
|
1817
|
+
return completionMap;
|
1954
1818
|
}
|
1955
1819
|
_findMatchingKeywords(keywordList, partialMatch) {
|
1956
1820
|
return keywordList.filter((keyword) => {
|
@@ -1984,8 +1848,8 @@ class CompletionProvider {
|
|
1984
1848
|
completionItem.kind = vscode_languageserver_1.CompletionItemKind.Variable;
|
1985
1849
|
const completionItemData = {
|
1986
1850
|
workspacePath: this._workspacePath,
|
1987
|
-
filePath: this.
|
1988
|
-
position: this.
|
1851
|
+
filePath: this.filePath,
|
1852
|
+
position: this.position,
|
1989
1853
|
};
|
1990
1854
|
completionItem.data = (0, lspUtils_1.toLSPAny)(completionItemData);
|
1991
1855
|
completionItem.sortText = this._makeSortText(SortCategory.NamedParameter, argName);
|
@@ -2024,7 +1888,7 @@ class CompletionProvider {
|
|
2024
1888
|
}
|
2025
1889
|
// If this is a class scope, add symbols from parent classes.
|
2026
1890
|
if (curNode.nodeType === 10 /* Class */) {
|
2027
|
-
const classType = this.
|
1891
|
+
const classType = this.evaluator.getTypeOfClass(curNode);
|
2028
1892
|
if (classType && (0, types_1.isInstantiableClass)(classType.classType)) {
|
2029
1893
|
classType.classType.details.mro.forEach((baseClass, index) => {
|
2030
1894
|
if ((0, types_1.isInstantiableClass)(baseClass)) {
|
@@ -2056,14 +1920,14 @@ class CompletionProvider {
|
|
2056
1920
|
// exported from this scope, don't include it in the
|
2057
1921
|
// suggestion list unless we are in the same file.
|
2058
1922
|
const hidden = !(0, symbolUtils_1.isVisibleExternally)(symbol) &&
|
2059
|
-
!symbol.getDeclarations().some((d) => (0, declarationUtils_1.isDefinedInFile)(d, this.
|
1923
|
+
!symbol.getDeclarations().some((d) => (0, declarationUtils_1.isDefinedInFile)(d, this.filePath));
|
2060
1924
|
if (!hidden && includeSymbolCallback(symbol, name)) {
|
2061
1925
|
// Don't add a symbol more than once. It may have already been
|
2062
1926
|
// added from an inner scope's symbol table.
|
2063
1927
|
if (!completionMap.has(name)) {
|
2064
1928
|
// Skip func parens for classes when not a direct assignment or an argument (passed as a value)
|
2065
1929
|
const skipForClass = !this._shouldShowAutoParensForClass(symbol, node);
|
2066
|
-
this.
|
1930
|
+
this.addSymbol(name, symbol, priorWord, completionMap, {
|
2067
1931
|
boundObjectOrClass,
|
2068
1932
|
funcParensDisabled: isInImport || insideTypeAnnotation || skipForClass,
|
2069
1933
|
extraCommitChars: !isInImport && !!priorWord,
|
@@ -2083,107 +1947,23 @@ class CompletionProvider {
|
|
2083
1947
|
return true;
|
2084
1948
|
}
|
2085
1949
|
// Otherwise only show when the class is being assigned to a variable.
|
2086
|
-
const nodeIndex = ParseTreeUtils.getTokenIndexAtLeft(this.
|
2087
|
-
const prevToken = ParseTreeUtils.getTokenAtIndex(this.
|
1950
|
+
const nodeIndex = ParseTreeUtils.getTokenIndexAtLeft(this.parseResults.tokenizerOutput.tokens, node.start);
|
1951
|
+
const prevToken = ParseTreeUtils.getTokenAtIndex(this.parseResults.tokenizerOutput.tokens, nodeIndex);
|
2088
1952
|
return (prevToken &&
|
2089
1953
|
prevToken.type === 9 /* Operator */ &&
|
2090
1954
|
prevToken.operatorType === 2 /* Assign */);
|
2091
1955
|
}
|
2092
|
-
_addSymbol(name, symbol, priorWord, completionMap, detail) {
|
2093
|
-
var _a, _b, _c, _d;
|
2094
|
-
let primaryDecl = (0, symbolUtils_1.getLastTypedDeclaredForSymbol)(symbol);
|
2095
|
-
if (!primaryDecl) {
|
2096
|
-
const declarations = symbol.getDeclarations();
|
2097
|
-
if (declarations.length > 0) {
|
2098
|
-
primaryDecl = declarations[declarations.length - 1];
|
2099
|
-
}
|
2100
|
-
}
|
2101
|
-
primaryDecl = primaryDecl
|
2102
|
-
? (_a = this._evaluator.resolveAliasDeclaration(primaryDecl, /* resolveLocalNames */ true)) !== null && _a !== void 0 ? _a : primaryDecl
|
2103
|
-
: undefined;
|
2104
|
-
const autoImportText = detail.autoImportSource
|
2105
|
-
? this._getAutoImportText(name, detail.autoImportSource, detail.autoImportAlias)
|
2106
|
-
: undefined;
|
2107
|
-
// Are we resolving a completion item? If so, see if this symbol
|
2108
|
-
// is the one that we're trying to match.
|
2109
|
-
if (this._itemToResolve) {
|
2110
|
-
const completionItemData = (0, lspUtils_1.fromLSPAny)(this._itemToResolve.data);
|
2111
|
-
if (completionItemData.symbolLabel !== name) {
|
2112
|
-
// It's not what we are looking for.
|
2113
|
-
return;
|
2114
|
-
}
|
2115
|
-
if (completionItemData.autoImportText) {
|
2116
|
-
if (completionItemData.autoImportText === (autoImportText === null || autoImportText === void 0 ? void 0 : autoImportText.importText) &&
|
2117
|
-
((_b = detail.edits) === null || _b === void 0 ? void 0 : _b.additionalTextEdits)) {
|
2118
|
-
this._itemToResolve.additionalTextEdits = (0, workspaceEditUtils_1.convertToTextEdits)(detail.edits.additionalTextEdits);
|
2119
|
-
}
|
2120
|
-
return;
|
2121
|
-
}
|
2122
|
-
// This call can be expensive to perform on every completion item
|
2123
|
-
// that we return, so we do it lazily in the "resolve" callback.
|
2124
|
-
const type = this._evaluator.getEffectiveTypeOfSymbol(symbol);
|
2125
|
-
if (!type) {
|
2126
|
-
// Can't resolve. so bail out.
|
2127
|
-
return;
|
2128
|
-
}
|
2129
|
-
const typeDetail = (0, completionProviderUtils_1.getTypeDetail)(this._evaluator, primaryDecl, type, name, detail, this._configOptions.functionSignatureDisplay);
|
2130
|
-
const documentation = (0, tooltipUtils_1.getDocumentationPartsForTypeAndDecl)(this._sourceMapper, type, primaryDecl, this._evaluator, {
|
2131
|
-
name,
|
2132
|
-
symbol,
|
2133
|
-
boundObjectOrClass: detail.boundObjectOrClass,
|
2134
|
-
});
|
2135
|
-
if (this._options.format === vscode_languageserver_1.MarkupKind.Markdown || this._options.format === vscode_languageserver_1.MarkupKind.PlainText) {
|
2136
|
-
this._itemToResolve.documentation = (0, completionProviderUtils_1.getCompletionItemDocumentation)(typeDetail, documentation, this._options.format);
|
2137
|
-
}
|
2138
|
-
else {
|
2139
|
-
(0, debug_1.fail)(`Unsupported markup type: ${this._options.format}`);
|
2140
|
-
}
|
2141
|
-
// Bail out. We don't need to add items to completion.
|
2142
|
-
return;
|
2143
|
-
}
|
2144
|
-
if (primaryDecl) {
|
2145
|
-
let itemKind = this._convertDeclarationTypeToItemKind(primaryDecl);
|
2146
|
-
// Handle enum members specially. Enum members normally look like
|
2147
|
-
// variables, but the are declared using assignment expressions
|
2148
|
-
// within an enum class.
|
2149
|
-
if (primaryDecl.type === 1 /* Variable */ &&
|
2150
|
-
detail.boundObjectOrClass &&
|
2151
|
-
(0, types_1.isInstantiableClass)(detail.boundObjectOrClass) &&
|
2152
|
-
types_1.ClassType.isEnumClass(detail.boundObjectOrClass) &&
|
2153
|
-
((_c = primaryDecl.node.parent) === null || _c === void 0 ? void 0 : _c.nodeType) === 3 /* Assignment */) {
|
2154
|
-
itemKind = vscode_languageserver_1.CompletionItemKind.EnumMember;
|
2155
|
-
}
|
2156
|
-
this._addNameToCompletions((_d = detail.autoImportAlias) !== null && _d !== void 0 ? _d : name, itemKind, priorWord, completionMap, {
|
2157
|
-
autoImportText,
|
2158
|
-
extraCommitChars: detail.extraCommitChars,
|
2159
|
-
funcParensDisabled: detail.funcParensDisabled,
|
2160
|
-
edits: detail.edits,
|
2161
|
-
});
|
2162
|
-
}
|
2163
|
-
else {
|
2164
|
-
// Does the symbol have no declaration but instead has a synthesized type?
|
2165
|
-
const synthesizedType = symbol.getSynthesizedType();
|
2166
|
-
if (synthesizedType) {
|
2167
|
-
const itemKind = this._convertTypeToItemKind(synthesizedType);
|
2168
|
-
this._addNameToCompletions(name, itemKind, priorWord, completionMap, {
|
2169
|
-
extraCommitChars: detail.extraCommitChars,
|
2170
|
-
funcParensDisabled: detail.funcParensDisabled,
|
2171
|
-
edits: detail.edits,
|
2172
|
-
});
|
2173
|
-
}
|
2174
|
-
}
|
2175
|
-
}
|
2176
1956
|
_getAutoImportText(importName, importFrom, importAlias) {
|
2177
1957
|
const autoImportText = (0, tooltipUtils_1.getAutoImportText)(importName, importFrom, importAlias);
|
2178
1958
|
let importText = '';
|
2179
|
-
if (this.
|
1959
|
+
if (this.options.format === vscode_languageserver_1.MarkupKind.Markdown) {
|
2180
1960
|
importText = `\`\`\`\n${autoImportText}\n\`\`\``;
|
2181
1961
|
}
|
2182
|
-
else if (this.
|
1962
|
+
else if (this.options.format === vscode_languageserver_1.MarkupKind.PlainText) {
|
2183
1963
|
importText = autoImportText;
|
2184
1964
|
}
|
2185
1965
|
else {
|
2186
|
-
(0, debug_1.fail)(`Unsupported markup type: ${this.
|
1966
|
+
(0, debug_1.fail)(`Unsupported markup type: ${this.options.format}`);
|
2187
1967
|
}
|
2188
1968
|
return {
|
2189
1969
|
source: importFrom !== null && importFrom !== void 0 ? importFrom : '',
|
@@ -2203,14 +1983,14 @@ class CompletionProvider {
|
|
2203
1983
|
const completionItem = vscode_languageserver_1.CompletionItem.create(name);
|
2204
1984
|
completionItem.kind = itemKind;
|
2205
1985
|
if (detail === null || detail === void 0 ? void 0 : detail.extraCommitChars) {
|
2206
|
-
this.
|
1986
|
+
this.addExtraCommitChar(completionItem);
|
2207
1987
|
}
|
2208
1988
|
const completionItemData = {
|
2209
1989
|
workspacePath: this._workspacePath,
|
2210
|
-
filePath: this.
|
2211
|
-
position: this.
|
1990
|
+
filePath: this.filePath,
|
1991
|
+
position: this.position,
|
2212
1992
|
};
|
2213
|
-
if ((detail === null || detail === void 0 ? void 0 : detail.funcParensDisabled) || !this.
|
1993
|
+
if ((detail === null || detail === void 0 ? void 0 : detail.funcParensDisabled) || !this.options.snippet) {
|
2214
1994
|
completionItemData.funcParensDisabled = true;
|
2215
1995
|
}
|
2216
1996
|
if (detail === null || detail === void 0 ? void 0 : detail.modulePath) {
|
@@ -2248,7 +2028,7 @@ class CompletionProvider {
|
|
2248
2028
|
completionItem.sortText = this._makeSortText(SortCategory.NormalSymbol, name);
|
2249
2029
|
}
|
2250
2030
|
completionItemData.symbolLabel = name;
|
2251
|
-
if (this.
|
2031
|
+
if (this.options.format === vscode_languageserver_1.MarkupKind.Markdown) {
|
2252
2032
|
let markdownString = '';
|
2253
2033
|
if (detail === null || detail === void 0 ? void 0 : detail.autoImportText) {
|
2254
2034
|
markdownString += detail.autoImportText.importText;
|
@@ -2272,7 +2052,7 @@ class CompletionProvider {
|
|
2272
2052
|
};
|
2273
2053
|
}
|
2274
2054
|
}
|
2275
|
-
else if (this.
|
2055
|
+
else if (this.options.format === vscode_languageserver_1.MarkupKind.PlainText) {
|
2276
2056
|
let plainTextString = '';
|
2277
2057
|
if (detail === null || detail === void 0 ? void 0 : detail.autoImportText) {
|
2278
2058
|
plainTextString += detail.autoImportText.importText;
|
@@ -2296,7 +2076,7 @@ class CompletionProvider {
|
|
2296
2076
|
}
|
2297
2077
|
}
|
2298
2078
|
else {
|
2299
|
-
(0, debug_1.fail)(`Unsupported markup type: ${this.
|
2079
|
+
(0, debug_1.fail)(`Unsupported markup type: ${this.options.format}`);
|
2300
2080
|
}
|
2301
2081
|
if ((_b = detail === null || detail === void 0 ? void 0 : detail.edits) === null || _b === void 0 ? void 0 : _b.format) {
|
2302
2082
|
completionItem.insertTextFormat = detail.edits.format;
|
@@ -2358,7 +2138,7 @@ class CompletionProvider {
|
|
2358
2138
|
return result;
|
2359
2139
|
}
|
2360
2140
|
_convertDeclarationTypeToItemKind(declaration) {
|
2361
|
-
const resolvedDeclaration = this.
|
2141
|
+
const resolvedDeclaration = this.evaluator.resolveAliasDeclaration(declaration, /* resolveLocalNames */ true);
|
2362
2142
|
if (!resolvedDeclaration) {
|
2363
2143
|
return vscode_languageserver_1.CompletionItemKind.Variable;
|
2364
2144
|
}
|
@@ -2379,7 +2159,7 @@ class CompletionProvider {
|
|
2379
2159
|
return vscode_languageserver_1.CompletionItemKind.Variable;
|
2380
2160
|
case 5 /* Function */: {
|
2381
2161
|
if (this._isPossiblePropertyDeclaration(resolvedDeclaration)) {
|
2382
|
-
const functionType = this.
|
2162
|
+
const functionType = this.evaluator.getTypeOfFunction(resolvedDeclaration.node);
|
2383
2163
|
if (functionType &&
|
2384
2164
|
(0, typeUtils_1.isMaybeDescriptorInstance)(functionType.decoratedType, /* requireSetter */ false)) {
|
2385
2165
|
return vscode_languageserver_1.CompletionItemKind.Property;
|
@@ -2419,7 +2199,7 @@ class CompletionProvider {
|
|
2419
2199
|
nameParts: node.nameParts.map((part) => part.value),
|
2420
2200
|
importedSymbols: [],
|
2421
2201
|
};
|
2422
|
-
const completions = this.
|
2202
|
+
const completions = this.importResolver.getCompletionSuggestions(this.filePath, this.execEnv, moduleDescriptor);
|
2423
2203
|
const completionMap = new CompletionMap();
|
2424
2204
|
// If we're in the middle of a "from X import Y" statement, offer
|
2425
2205
|
// the "import" keyword as a completion.
|
@@ -2439,27 +2219,7 @@ class CompletionProvider {
|
|
2439
2219
|
modulePath,
|
2440
2220
|
});
|
2441
2221
|
});
|
2442
|
-
return
|
2443
|
-
}
|
2444
|
-
_getExtraCommitCharsForKind(kind) {
|
2445
|
-
switch (kind) {
|
2446
|
-
case vscode_languageserver_1.CompletionItemKind.Class:
|
2447
|
-
return ['.', '('];
|
2448
|
-
case vscode_languageserver_1.CompletionItemKind.Function:
|
2449
|
-
case vscode_languageserver_1.CompletionItemKind.Method:
|
2450
|
-
return ['('];
|
2451
|
-
case vscode_languageserver_1.CompletionItemKind.Module:
|
2452
|
-
case vscode_languageserver_1.CompletionItemKind.Enum:
|
2453
|
-
return ['.'];
|
2454
|
-
default:
|
2455
|
-
return [];
|
2456
|
-
}
|
2457
|
-
}
|
2458
|
-
_addExtraCommitChar(item, ...commitChars) {
|
2459
|
-
if (!this._options.extraCommitChars || commitChars.length === 0) {
|
2460
|
-
return;
|
2461
|
-
}
|
2462
|
-
item.commitCharacters = commitChars;
|
2222
|
+
return completionMap;
|
2463
2223
|
}
|
2464
2224
|
_isPossiblePropertyDeclaration(decl) {
|
2465
2225
|
// Do cheap check using only nodes that will cover 99.9% cases
|