Skip to content

Commit ac36ce7

Browse files
pull-pylance-with-pyright-1.1.402-20250611-232709
1 parent b249d11 commit ac36ce7

File tree

8 files changed

+127
-86
lines changed

8 files changed

+127
-86
lines changed

packages/pyright-internal/src/analyzer/sourceFile.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1406,6 +1406,8 @@ export class SourceFile {
14061406
builtinsImportResult = resolveAndAddIfNotSelf(['builtins']);
14071407
}
14081408

1409+
resolveAndAddIfNotSelf(['_typeshed', '_type_checker_internals'], /* skipMissingImport */ true);
1410+
14091411
for (const moduleImport of moduleImports) {
14101412
const importResult = importResolver.resolveImport(this._uri, execEnv, {
14111413
leadingDots: moduleImport.leadingDots,

packages/pyright-internal/src/analyzer/sourceMapper.ts

Lines changed: 27 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -126,6 +126,32 @@ export class SourceMapper {
126126
return result;
127127
}
128128

129+
getSourcePathsFromStub(stubFileUri: Uri, fromFile: Uri | undefined): Uri[] {
130+
// Attempt our stubFileUri to see if we can resolve it as a source file path
131+
let results = this._importResolver.getSourceFilesFromStub(stubFileUri, this._execEnv, this._mapCompiled);
132+
if (results.length > 0) {
133+
return results;
134+
}
135+
136+
// If that didn't work, try looking through the graph up to our fromFile.
137+
// One of them should be able to resolve to an actual file.
138+
const stubFileImportTree = this._getStubFileImportTree(stubFileUri, fromFile);
139+
140+
// Go through the items in this tree until we find at least one path.
141+
for (let i = 0; i < stubFileImportTree.length; i++) {
142+
results = this._importResolver.getSourceFilesFromStub(
143+
stubFileImportTree[i],
144+
this._execEnv,
145+
this._mapCompiled
146+
);
147+
if (results.length > 0) {
148+
return results;
149+
}
150+
}
151+
152+
return [];
153+
}
154+
129155
private _findSpecialBuiltInClassDeclarations(
130156
stubDecl: SpecialBuiltInClassDeclaration,
131157
recursiveDeclCache = new Set<string>()
@@ -738,36 +764,10 @@ export class SourceMapper {
738764
}
739765

740766
private _getBoundSourceFilesFromStubFile(stubFileUri: Uri, stubToShadow?: Uri, originated?: Uri): SourceFile[] {
741-
const paths = this._getSourcePathsFromStub(stubFileUri, originated ?? this._fromFile?.uri);
767+
const paths = this.getSourcePathsFromStub(stubFileUri, originated ?? this._fromFile?.uri);
742768
return paths.map((fp) => this._fileBinder(stubToShadow ?? stubFileUri, fp)).filter(isDefined);
743769
}
744770

745-
private _getSourcePathsFromStub(stubFileUri: Uri, fromFile: Uri | undefined): Uri[] {
746-
// Attempt our stubFileUri to see if we can resolve it as a source file path
747-
let results = this._importResolver.getSourceFilesFromStub(stubFileUri, this._execEnv, this._mapCompiled);
748-
if (results.length > 0) {
749-
return results;
750-
}
751-
752-
// If that didn't work, try looking through the graph up to our fromFile.
753-
// One of them should be able to resolve to an actual file.
754-
const stubFileImportTree = this._getStubFileImportTree(stubFileUri, fromFile);
755-
756-
// Go through the items in this tree until we find at least one path.
757-
for (let i = 0; i < stubFileImportTree.length; i++) {
758-
results = this._importResolver.getSourceFilesFromStub(
759-
stubFileImportTree[i],
760-
this._execEnv,
761-
this._mapCompiled
762-
);
763-
if (results.length > 0) {
764-
return results;
765-
}
766-
}
767-
768-
return [];
769-
}
770-
771771
private _getStubFileImportTree(stubFileUri: Uri, fromFile: Uri | undefined): Uri[] {
772772
if (!fromFile || !this._isStubThatShouldBeMappedToImplementation(stubFileUri)) {
773773
// No path to search, just return the starting point.

packages/pyright-internal/src/common/logTracker.ts

Lines changed: 66 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,21 @@ export class LogTracker {
3737
return level ?? LogLevel.Error;
3838
}
3939

40-
log<T>(title: string, callback: (state: LogState) => T, minimalDuration = -1, logParsingPerf = false) {
40+
log<T>(title: string, callback: (state: LogState) => T): T;
41+
log<T>(title: string, callback: (state: LogState) => Promise<T>): Promise<T>;
42+
log<T>(title: string, callback: (state: LogState) => T, minimalDuration: number, logParsingPerf: boolean): T;
43+
log<T>(
44+
title: string,
45+
callback: (state: LogState) => Promise<T>,
46+
minimalDuration: number,
47+
logParsingPerf: boolean
48+
): Promise<T>;
49+
log<T>(
50+
title: string,
51+
callback: (state: LogState) => T | Promise<T>,
52+
minimalDuration = -1,
53+
logParsingPerf = false
54+
): T | Promise<T> {
4155
// If no console is given, don't do anything.
4256
if (this._console === undefined) {
4357
return callback(this._dummyState);
@@ -58,39 +72,57 @@ export class LogTracker {
5872
const state = new State();
5973

6074
try {
61-
return callback(state);
62-
} finally {
63-
const msDuration = state.duration;
64-
this._indentation = current;
65-
66-
// if we already printed our header (by nested calls), then it can't be skipped.
67-
if (this._previousTitles.length > 0 && (state.isSuppressed() || msDuration <= minimalDuration)) {
68-
// Get rid of myself so we don't even show header.
69-
this._previousTitles.pop();
70-
} else {
71-
this._printPreviousTitles();
72-
73-
let output = `[${this.prefix}] ${this._indentation}${title}${state.get()} (${msDuration}ms)`;
74-
75-
// Report parsing related perf info only if they occurred.
76-
if (
77-
logParsingPerf &&
78-
state.fileReadTotal +
79-
state.tokenizeTotal +
80-
state.parsingTotal +
81-
state.resolveImportsTotal +
82-
state.bindingTotal >
83-
0
84-
) {
85-
output += ` [f:${state.fileReadTotal}, t:${state.tokenizeTotal}, p:${state.parsingTotal}, i:${state.resolveImportsTotal}, b:${state.bindingTotal}]`;
86-
}
87-
88-
this._console.log(output);
89-
90-
// If the operation took really long, log it as "info" so it is more visible.
91-
if (msDuration >= durationThresholdForInfoInMs) {
92-
this._console.info(`[${this.prefix}] Long operation: ${title} (${msDuration}ms)`);
93-
}
75+
const maybePromise = callback(state);
76+
if (maybePromise instanceof Promise) {
77+
return maybePromise
78+
.then((result) => {
79+
this._onComplete(state, current, title, minimalDuration, logParsingPerf);
80+
return result;
81+
})
82+
.catch((err) => {
83+
this._onComplete(state, current, title, minimalDuration, logParsingPerf);
84+
throw err;
85+
});
86+
}
87+
this._onComplete(state, current, title, minimalDuration, logParsingPerf);
88+
return maybePromise;
89+
} catch (err) {
90+
this._onComplete(state, current, title, minimalDuration, logParsingPerf);
91+
throw err;
92+
}
93+
}
94+
95+
private _onComplete(state: State, current: string, title: string, minimalDuration = -1, logParsingPerf = false) {
96+
const msDuration = state.duration;
97+
this._indentation = current;
98+
99+
// if we already printed our header (by nested calls), then it can't be skipped.
100+
if (this._previousTitles.length > 0 && (state.isSuppressed() || msDuration <= minimalDuration)) {
101+
// Get rid of myself so we don't even show header.
102+
this._previousTitles.pop();
103+
} else {
104+
this._printPreviousTitles();
105+
106+
let output = `[${this.prefix}] ${this._indentation}${title}${state.get()} (${msDuration}ms)`;
107+
108+
// Report parsing related perf info only if they occurred.
109+
if (
110+
logParsingPerf &&
111+
state.fileReadTotal +
112+
state.tokenizeTotal +
113+
state.parsingTotal +
114+
state.resolveImportsTotal +
115+
state.bindingTotal >
116+
0
117+
) {
118+
output += ` [f:${state.fileReadTotal}, t:${state.tokenizeTotal}, p:${state.parsingTotal}, i:${state.resolveImportsTotal}, b:${state.bindingTotal}]`;
119+
}
120+
121+
this._console?.log(output);
122+
123+
// If the operation took really long, log it as "info" so it is more visible.
124+
if (msDuration >= durationThresholdForInfoInMs) {
125+
this._console?.info(`[${this.prefix}] Long operation: ${title} (${msDuration}ms)`);
94126
}
95127
}
96128
}

packages/pyright-internal/src/languageService/completionProvider.ts

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -637,9 +637,10 @@ export class CompletionProvider {
637637
? this.evaluator.resolveAliasDeclaration(primaryDecl, /* resolveLocalNames */ true) ?? primaryDecl
638638
: undefined;
639639

640-
const autoImportText = detail.autoImportSource
641-
? this.getAutoImportText(name, detail.autoImportSource, detail.autoImportAlias)
642-
: undefined;
640+
const autoImportText =
641+
detail.autoImportSource && this.program.configOptions.autoImportCompletions
642+
? this.getAutoImportText(name, detail.autoImportSource, detail.autoImportAlias)
643+
: undefined;
643644

644645
// Are we resolving a completion item? If so, see if this symbol
645646
// is the one that we're trying to match.
@@ -868,17 +869,23 @@ export class CompletionProvider {
868869
this.addNameToCompletions(
869870
result.alias ?? result.name,
870871
result.kind ?? CompletionItemKind.Module,
871-
priorWord,
872+
this.program.configOptions.autoImportCompletions ? priorWord : result.alias ?? result.name,
872873
completionMap,
873-
{
874-
extraCommitChars: true,
875-
autoImportText: this.getAutoImportText(result.name, result.source, result.alias),
876-
edits: {
877-
textEdit: this.createReplaceEdits(priorWord, /* node */ undefined, result.insertionText),
878-
additionalTextEdits: result.edits,
879-
},
880-
funcParensDisabled: parensDisabled,
881-
}
874+
this.program.configOptions.autoImportCompletions
875+
? {
876+
extraCommitChars: true,
877+
autoImportText: this.getAutoImportText(result.name, result.source, result.alias),
878+
edits: {
879+
textEdit: this.createReplaceEdits(
880+
priorWord,
881+
/* node */ undefined,
882+
result.insertionText
883+
),
884+
additionalTextEdits: result.edits,
885+
},
886+
funcParensDisabled: parensDisabled,
887+
}
888+
: undefined
882889
);
883890
}
884891
}

packages/pyright-internal/src/languageService/tooltipUtils.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -225,7 +225,7 @@ export function getOverloadedDocStringsFromType(
225225
);
226226
}
227227

228-
function getDocumentationPartForTypeAlias(
228+
export function getDocumentationPartForTypeAlias(
229229
sourceMapper: SourceMapper,
230230
resolvedDecl: Declaration | undefined,
231231
evaluator: TypeEvaluator,
@@ -263,7 +263,7 @@ function getDocumentationPartForTypeAlias(
263263
return undefined;
264264
}
265265

266-
function getDocumentationPartForType(
266+
export function getDocumentationPartForType(
267267
sourceMapper: SourceMapper,
268268
type: Type,
269269
resolvedDecl: Declaration | undefined,

packages/pyright-internal/src/tests/workspaceEditUtils.test.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -87,7 +87,7 @@ test('test edit mode for workspace', async () => {
8787

8888
program.analyzeFile(info.uri, CancellationToken.None);
8989
assert.strictEqual(info.contents, 'import sys');
90-
assert.strictEqual(info.imports.length, 2);
90+
assert.strictEqual(info.imports.length, 3);
9191

9292
// Add a new file.
9393
program.setFileOpened(addedFileUri, 0, '', {
@@ -148,15 +148,15 @@ test('test edit mode for workspace', async () => {
148148
program.analyzeFile(addedInfo.uri, CancellationToken.None);
149149

150150
assert.strictEqual(addedInfo.contents, 'import os');
151-
assert.strictEqual(addedInfo.imports.length, 2);
151+
assert.strictEqual(addedInfo.imports.length, 3);
152152
}, CancellationToken.None);
153153

154154
// After leaving edit mode, we should be back to where we were.
155155
const oldSourceFile = state.workspace.service.test_program.getSourceFile(range.fileUri);
156156
state.workspace.service.backgroundAnalysisProgram.analyzeFile(oldSourceFile!.getUri(), CancellationToken.None);
157157

158158
assert.strictEqual(oldSourceFile?.getFileContent(), '');
159-
assert.strictEqual(oldSourceFile.getImports().length, 1);
159+
assert.strictEqual(oldSourceFile.getImports().length, 2);
160160
assert.strictEqual(edits.length, 2);
161161

162162
assert.deepStrictEqual(edits[0].replacementText, 'import sys');

packages/vscode-pyright/package-lock.json

Lines changed: 5 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

packages/vscode-pyright/package.json

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"url": "https://github.com/Microsoft/pyright"
1515
},
1616
"engines": {
17-
"vscode": "^1.99.0"
17+
"vscode": "^1.100.0"
1818
},
1919
"keywords": [
2020
"python"
@@ -1589,7 +1589,7 @@
15891589
},
15901590
"devDependencies": {
15911591
"@types/node": "^22.10.5",
1592-
"@types/vscode": "^1.99.0",
1592+
"@types/vscode": "^1.100.0",
15931593
"@vscode/vsce": "^2.32.0",
15941594
"copy-webpack-plugin": "^11.0.0",
15951595
"esbuild-loader": "^3.2.0",

0 commit comments

Comments
 (0)