pull-pylance-with-pyright-1.1.244 (#3425)

Co-authored-by: Bill Schnurr <bschnurr@microsoft.com>
Co-authored-by: HeeJae Chang <hechang@microsoft.com>
Co-authored-by: Erik De Bonte <erikd@microsoft.com>
This commit is contained in:
PylanceBot 2022-05-04 10:17:49 -07:00 committed by GitHub
parent 80858f61dc
commit 4df1f74ba9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 119 additions and 1 deletions

View File

@ -625,13 +625,17 @@ export class CompletionProvider {
}
}
// This method will return false if it wants
// caller to walk up the tree. it will return
// CompletionResults or undefined if it wants caller
// to return.
private _tryGetNameCompletions(
curNode: NameNode,
offset: number,
priorWord: string,
priorText: string,
postText: string
) {
): false | CompletionResults | undefined {
if (!curNode.parent) {
return false;
}
@ -745,6 +749,20 @@ export class CompletionProvider {
return completionList;
}
// Defining class variables.
// ex) class A:
// variable = 1
if (
curNode.parent.nodeType === ParseNodeType.StatementList &&
curNode.parent.parent?.nodeType === ParseNodeType.Suite &&
curNode.parent.parent.parent?.nodeType === ParseNodeType.Class
) {
const completionList = this._getClassVariableCompletions(priorWord, curNode);
if (completionList) {
return completionList;
}
}
return false;
}
@ -866,6 +884,69 @@ export class CompletionProvider {
return { completionMap };
}
private _getClassVariableCompletions(priorWord: string, partialName: NameNode): CompletionResults | undefined {
const enclosingClass = ParseTreeUtils.getEnclosingClass(partialName, false);
if (!enclosingClass) {
return undefined;
}
const classResults = this._evaluator.getTypeOfClass(enclosingClass);
if (!classResults) {
return undefined;
}
const symbolTable = new Map<string, Symbol>();
for (const mroClass of classResults.classType.details.mro) {
if (isInstantiableClass(mroClass)) {
getMembersForClass(mroClass, symbolTable, /* includeInstanceVars */ false);
}
}
const printFlags = isStubFile(this._filePath)
? ParseTreeUtils.PrintExpressionFlags.ForwardDeclarations
: undefined;
const completionMap = new CompletionMap();
symbolTable.forEach((symbol, name) => {
if (
SymbolNameUtils.isPrivateName(name) ||
symbol.isPrivateMember() ||
symbol.isExternallyHidden() ||
!StringUtils.isPatternInSymbol(partialName.value, name)
) {
return;
}
const decls = symbol
.getDeclarations()
.filter((d) => isVariableDeclaration(d) && d.moduleName !== 'builtins') as VariableDeclaration[];
// Skip any symbols invalid such as defined in the same class.
if (
decls.length === 0 ||
decls.some((d) => d.node && ParseTreeUtils.getEnclosingClass(d.node, false) === enclosingClass)
) {
return;
}
let edits: Edits | undefined;
const declWithTypeAnnotations = decls.filter((d) => d.typeAnnotationNode);
if (declWithTypeAnnotations.length > 0) {
const text = `${name}: ${ParseTreeUtils.printExpression(
declWithTypeAnnotations[declWithTypeAnnotations.length - 1].typeAnnotationNode!,
printFlags
)}`;
edits = {
textEdit: this._createReplaceEdits(priorWord, partialName, text),
};
}
this._addSymbol(name, symbol, partialName.value, completionMap, { edits });
});
return completionMap.size > 0 ? { completionMap } : undefined;
}
private _getMethodOverloadsCompletions(priorWord: string, partialName: NameNode): CompletionResults | undefined {
const symbolTable = getSymbolTable(this._evaluator, partialName);
if (!symbolTable) {

View File

@ -0,0 +1,37 @@
/// <reference path="fourslash.ts" />
// @filename: test.py
//// class B:
//// var1 = 1
//// var2: int
//// var3: str = "hello"
//// __var4 = 4
////
//// def __init__(self):
//// self.var6 = 1
////
//// class T(B):
//// var5: bool
//// [|va/*marker*/|]
// @ts-ignore
await helper.verifyCompletion('included', 'markdown', {
marker: {
completions: [
{
label: 'var1',
kind: Consts.CompletionItemKind.Variable,
},
{
label: 'var2',
kind: Consts.CompletionItemKind.Variable,
textEdit: { range: helper.getPositionRange('marker'), newText: 'var2: int' },
},
{
label: 'var3',
kind: Consts.CompletionItemKind.Variable,
textEdit: { range: helper.getPositionRange('marker'), newText: 'var3: str' },
},
],
},
});