mirror of
https://github.com/microsoft/pyright.git
synced 2024-09-11 16:06:39 +03:00
[PylanceBot] Pull Pylance with Pyright 1.1.265 (#3783)
Co-authored-by: HeeJae Chang <hechang@microsoft.com>
This commit is contained in:
parent
cdba65d4c8
commit
e4a0f2088c
5854
package-lock.json
generated
5854
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
10
package.json
10
package.json
@ -23,16 +23,16 @@
|
|||||||
"@types/glob": "^7.2.0",
|
"@types/glob": "^7.2.0",
|
||||||
"@types/node": "^17.0.45",
|
"@types/node": "^17.0.45",
|
||||||
"@types/yargs": "^16.0.4",
|
"@types/yargs": "^16.0.4",
|
||||||
"@typescript-eslint/eslint-plugin": "^5.31.0",
|
"@typescript-eslint/eslint-plugin": "^5.32.0",
|
||||||
"@typescript-eslint/parser": "^5.31.0",
|
"@typescript-eslint/parser": "^5.32.0",
|
||||||
"detect-indent": "^6.1.0",
|
"detect-indent": "^6.1.0",
|
||||||
"eslint": "^8.20.0",
|
"eslint": "^8.21.0",
|
||||||
"eslint-config-prettier": "^8.5.0",
|
"eslint-config-prettier": "^8.5.0",
|
||||||
"eslint-plugin-simple-import-sort": "^7.0.0",
|
"eslint-plugin-simple-import-sort": "^7.0.0",
|
||||||
"glob": "^7.2.3",
|
"glob": "^7.2.3",
|
||||||
"jsonc-parser": "^3.1.0",
|
"jsonc-parser": "^3.1.0",
|
||||||
"lerna": "^5.2.0",
|
"lerna": "^5.3.0",
|
||||||
"npm-check-updates": "^12.5.12",
|
"npm-check-updates": "^16.0.5",
|
||||||
"p-queue": "^6.6.2",
|
"p-queue": "^6.6.2",
|
||||||
"prettier": "2.7.1",
|
"prettier": "2.7.1",
|
||||||
"syncpack": "^5.8.15",
|
"syncpack": "^5.8.15",
|
||||||
|
@ -38,7 +38,6 @@ import { ParseResults } from '../parser/parser';
|
|||||||
import * as AnalyzerNodeInfo from './analyzerNodeInfo';
|
import * as AnalyzerNodeInfo from './analyzerNodeInfo';
|
||||||
import { ModuleNameAndType } from './importResolver';
|
import { ModuleNameAndType } from './importResolver';
|
||||||
import { ImportResult, ImportType } from './importResult';
|
import { ImportResult, ImportType } from './importResult';
|
||||||
import { ParseTreeWalker } from './parseTreeWalker';
|
|
||||||
import * as SymbolNameUtils from './symbolNameUtils';
|
import * as SymbolNameUtils from './symbolNameUtils';
|
||||||
|
|
||||||
export interface ImportStatement {
|
export interface ImportStatement {
|
||||||
@ -72,6 +71,12 @@ export interface ImportNameInfo {
|
|||||||
|
|
||||||
export interface ImportNameWithModuleInfo extends ImportNameInfo {
|
export interface ImportNameWithModuleInfo extends ImportNameInfo {
|
||||||
module: ModuleNameAndType;
|
module: ModuleNameAndType;
|
||||||
|
nameForImportFrom?: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface ModuleNameInfo {
|
||||||
|
name: string;
|
||||||
|
nameForImportFrom?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Determines which import grouping should be used when sorting imports.
|
// Determines which import grouping should be used when sorting imports.
|
||||||
@ -110,10 +115,6 @@ export function compareImportStatements(a: ImportStatement, b: ImportStatement)
|
|||||||
return a.moduleName < b.moduleName ? -1 : 1;
|
return a.moduleName < b.moduleName ? -1 : 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function getAllImports(root: ModuleNode, token: CancellationToken) {
|
|
||||||
return ImportCollector.collect(root, token);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Looks for top-level 'import' and 'import from' statements and provides
|
// Looks for top-level 'import' and 'import from' statements and provides
|
||||||
// an ordered list and a map (by file path).
|
// an ordered list and a map (by file path).
|
||||||
export function getTopLevelImports(parseTree: ModuleNode, includeImplicitImports = false): ImportStatements {
|
export function getTopLevelImports(parseTree: ModuleNode, includeImplicitImports = false): ImportStatements {
|
||||||
@ -338,13 +339,13 @@ export function getTextEditsForAutoImportInsertions(
|
|||||||
return [];
|
return [];
|
||||||
}
|
}
|
||||||
|
|
||||||
const map = createMapFromItems(importNameInfo, (i) => i.module.moduleName);
|
const map = createMapFromItems(importNameInfo, (i) => `${i.module.moduleName}-${i.nameForImportFrom ?? ''}`);
|
||||||
for (const importInfo of map.values()) {
|
for (const importInfo of map.values()) {
|
||||||
insertionEdits.push(
|
insertionEdits.push(
|
||||||
..._getInsertionEditsForAutoImportInsertion(
|
..._getInsertionEditsForAutoImportInsertion(
|
||||||
importInfo,
|
importInfo,
|
||||||
|
{ name: importInfo[0].module.moduleName, nameForImportFrom: importInfo[0].nameForImportFrom },
|
||||||
importStatements,
|
importStatements,
|
||||||
importInfo[0].module.moduleName,
|
|
||||||
getImportGroupFromModuleNameAndType(importInfo[0].module),
|
getImportGroupFromModuleNameAndType(importInfo[0].module),
|
||||||
parseResults,
|
parseResults,
|
||||||
invocationPosition
|
invocationPosition
|
||||||
@ -357,16 +358,16 @@ export function getTextEditsForAutoImportInsertions(
|
|||||||
|
|
||||||
export function getTextEditsForAutoImportInsertion(
|
export function getTextEditsForAutoImportInsertion(
|
||||||
importNameInfo: ImportNameInfo[] | ImportNameInfo,
|
importNameInfo: ImportNameInfo[] | ImportNameInfo,
|
||||||
|
moduleNameInfo: ModuleNameInfo,
|
||||||
importStatements: ImportStatements,
|
importStatements: ImportStatements,
|
||||||
moduleName: string,
|
|
||||||
importGroup: ImportGroup,
|
importGroup: ImportGroup,
|
||||||
parseResults: ParseResults,
|
parseResults: ParseResults,
|
||||||
invocationPosition: Position
|
invocationPosition: Position
|
||||||
): TextEditAction[] {
|
): TextEditAction[] {
|
||||||
const insertionEdits = _getInsertionEditsForAutoImportInsertion(
|
const insertionEdits = _getInsertionEditsForAutoImportInsertion(
|
||||||
importNameInfo,
|
importNameInfo,
|
||||||
|
moduleNameInfo,
|
||||||
importStatements,
|
importStatements,
|
||||||
moduleName,
|
|
||||||
importGroup,
|
importGroup,
|
||||||
parseResults,
|
parseResults,
|
||||||
invocationPosition
|
invocationPosition
|
||||||
@ -423,8 +424,8 @@ function _convertInsertionEditsToTextEdits(parseResults: ParseResults, insertion
|
|||||||
|
|
||||||
function _getInsertionEditsForAutoImportInsertion(
|
function _getInsertionEditsForAutoImportInsertion(
|
||||||
importNameInfo: ImportNameInfo[] | ImportNameInfo,
|
importNameInfo: ImportNameInfo[] | ImportNameInfo,
|
||||||
|
moduleNameInfo: ModuleNameInfo,
|
||||||
importStatements: ImportStatements,
|
importStatements: ImportStatements,
|
||||||
moduleName: string,
|
|
||||||
importGroup: ImportGroup,
|
importGroup: ImportGroup,
|
||||||
parseResults: ParseResults,
|
parseResults: ParseResults,
|
||||||
invocationPosition: Position
|
invocationPosition: Position
|
||||||
@ -449,7 +450,10 @@ function _getInsertionEditsForAutoImportInsertion(
|
|||||||
// Add from import statements next.
|
// Add from import statements next.
|
||||||
const fromImports = map.get('from');
|
const fromImports = map.get('from');
|
||||||
if (fromImports) {
|
if (fromImports) {
|
||||||
appendToEdits(fromImports, (names) => `from ${moduleName} import ${names.join(', ')}`);
|
appendToEdits(
|
||||||
|
fromImports,
|
||||||
|
(names) => `from ${moduleNameInfo.nameForImportFrom ?? moduleNameInfo.name} import ${names.join(', ')}`
|
||||||
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
return insertionEdits;
|
return insertionEdits;
|
||||||
@ -464,7 +468,7 @@ function _getInsertionEditsForAutoImportInsertion(
|
|||||||
|
|
||||||
function appendToEdits(importNameInfo: ImportNameInfo[], importStatementGetter: (n: string[]) => string) {
|
function appendToEdits(importNameInfo: ImportNameInfo[], importStatementGetter: (n: string[]) => string) {
|
||||||
const importNames = importNameInfo
|
const importNames = importNameInfo
|
||||||
.map((i) => getImportAsText(i, moduleName))
|
.map((i) => getImportAsText(i, moduleNameInfo.name))
|
||||||
.sort((a, b) => _compareImportNames(a.sortText, b.sortText))
|
.sort((a, b) => _compareImportNames(a.sortText, b.sortText))
|
||||||
.reduce((set, v) => addIfUnique(set, v.text), [] as string[]);
|
.reduce((set, v) => addIfUnique(set, v.text), [] as string[]);
|
||||||
|
|
||||||
@ -472,7 +476,7 @@ function _getInsertionEditsForAutoImportInsertion(
|
|||||||
_getInsertionEditForAutoImportInsertion(
|
_getInsertionEditForAutoImportInsertion(
|
||||||
importStatementGetter(importNames),
|
importStatementGetter(importNames),
|
||||||
importStatements,
|
importStatements,
|
||||||
moduleName,
|
moduleNameInfo.name,
|
||||||
importGroup,
|
importGroup,
|
||||||
parseResults,
|
parseResults,
|
||||||
invocationPosition
|
invocationPosition
|
||||||
@ -897,34 +901,3 @@ export function getResolvedFilePath(importResult: ImportResult | undefined) {
|
|||||||
// Regular case.
|
// Regular case.
|
||||||
return importResult.resolvedPaths[importResult.resolvedPaths.length - 1];
|
return importResult.resolvedPaths[importResult.resolvedPaths.length - 1];
|
||||||
}
|
}
|
||||||
|
|
||||||
class ImportCollector extends ParseTreeWalker {
|
|
||||||
private readonly _imports: (ImportNode | ImportFromNode)[] = [];
|
|
||||||
|
|
||||||
private constructor(private _token: CancellationToken) {
|
|
||||||
super();
|
|
||||||
}
|
|
||||||
|
|
||||||
public static collect(root: ModuleNode, token: CancellationToken) {
|
|
||||||
const collector = new ImportCollector(token);
|
|
||||||
collector.walk(root);
|
|
||||||
|
|
||||||
return collector._imports;
|
|
||||||
}
|
|
||||||
|
|
||||||
override walk(node: ParseNode): void {
|
|
||||||
throwIfCancellationRequested(this._token);
|
|
||||||
|
|
||||||
super.walk(node);
|
|
||||||
}
|
|
||||||
|
|
||||||
override visitImport(node: ImportNode) {
|
|
||||||
this._imports.push(node);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
override visitImportFrom(node: ImportFromNode) {
|
|
||||||
this._imports.push(node);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -47,6 +47,7 @@ import { DocumentRange, doesRangeContain, doRangesIntersect, Position, Range } f
|
|||||||
import { Duration, timingStats } from '../common/timing';
|
import { Duration, timingStats } from '../common/timing';
|
||||||
import {
|
import {
|
||||||
AutoImporter,
|
AutoImporter,
|
||||||
|
AutoImportOptions,
|
||||||
AutoImportResult,
|
AutoImportResult,
|
||||||
buildModuleSymbolsMap,
|
buildModuleSymbolsMap,
|
||||||
ModuleSymbolMap,
|
ModuleSymbolMap,
|
||||||
@ -1254,9 +1255,7 @@ export class Program {
|
|||||||
range: Range,
|
range: Range,
|
||||||
similarityLimit: number,
|
similarityLimit: number,
|
||||||
nameMap: AbbreviationMap | undefined,
|
nameMap: AbbreviationMap | undefined,
|
||||||
libraryMap: Map<string, IndexResults> | undefined,
|
options: AutoImportOptions,
|
||||||
lazyEdit: boolean,
|
|
||||||
allowVariableInAll: boolean,
|
|
||||||
token: CancellationToken
|
token: CancellationToken
|
||||||
): AutoImportResult[] {
|
): AutoImportResult[] {
|
||||||
const sourceFileInfo = this._getSourceFileInfoFromPath(filePath);
|
const sourceFileInfo = this._getSourceFileInfoFromPath(filePath);
|
||||||
@ -1288,10 +1287,14 @@ export class Program {
|
|||||||
const writtenWord = fileContents.substr(textRange.start, textRange.length);
|
const writtenWord = fileContents.substr(textRange.start, textRange.length);
|
||||||
const map = this._buildModuleSymbolsMap(
|
const map = this._buildModuleSymbolsMap(
|
||||||
sourceFileInfo,
|
sourceFileInfo,
|
||||||
!!libraryMap,
|
!!options.libraryMap,
|
||||||
/* includeIndexUserSymbols */ true,
|
/* includeIndexUserSymbols */ true,
|
||||||
token
|
token
|
||||||
);
|
);
|
||||||
|
|
||||||
|
options.patternMatcher =
|
||||||
|
options.patternMatcher ?? ((p, t) => computeCompletionSimilarity(p, t) > similarityLimit);
|
||||||
|
|
||||||
const autoImporter = new AutoImporter(
|
const autoImporter = new AutoImporter(
|
||||||
this._configOptions.findExecEnvironment(filePath),
|
this._configOptions.findExecEnvironment(filePath),
|
||||||
this._importResolver,
|
this._importResolver,
|
||||||
@ -1299,12 +1302,7 @@ export class Program {
|
|||||||
range.start,
|
range.start,
|
||||||
new CompletionMap(),
|
new CompletionMap(),
|
||||||
map,
|
map,
|
||||||
{
|
options
|
||||||
lazyEdit,
|
|
||||||
allowVariableInAll,
|
|
||||||
libraryMap,
|
|
||||||
patternMatcher: (p, t) => computeCompletionSimilarity(p, t) > similarityLimit,
|
|
||||||
}
|
|
||||||
);
|
);
|
||||||
|
|
||||||
// Filter out any name that is already defined in the current scope.
|
// Filter out any name that is already defined in the current scope.
|
||||||
|
@ -55,6 +55,7 @@ import {
|
|||||||
} from '../common/pathUtils';
|
} from '../common/pathUtils';
|
||||||
import { DocumentRange, Position, Range } from '../common/textRange';
|
import { DocumentRange, Position, Range } from '../common/textRange';
|
||||||
import { timingStats } from '../common/timing';
|
import { timingStats } from '../common/timing';
|
||||||
|
import { AutoImportOptions } from '../languageService/autoImporter';
|
||||||
import { AbbreviationMap, CompletionOptions, CompletionResultsList } from '../languageService/completionProvider';
|
import { AbbreviationMap, CompletionOptions, CompletionResultsList } from '../languageService/completionProvider';
|
||||||
import { DefinitionFilter } from '../languageService/definitionProvider';
|
import { DefinitionFilter } from '../languageService/definitionProvider';
|
||||||
import { IndexResults, WorkspaceSymbolCallback } from '../languageService/documentSymbolProvider';
|
import { IndexResults, WorkspaceSymbolCallback } from '../languageService/documentSymbolProvider';
|
||||||
@ -316,20 +317,11 @@ export class AnalyzerService {
|
|||||||
range: Range,
|
range: Range,
|
||||||
similarityLimit: number,
|
similarityLimit: number,
|
||||||
nameMap: AbbreviationMap | undefined,
|
nameMap: AbbreviationMap | undefined,
|
||||||
lazyEdit: boolean,
|
options: AutoImportOptions,
|
||||||
allowVariableInAll: boolean,
|
|
||||||
token: CancellationToken
|
token: CancellationToken
|
||||||
) {
|
) {
|
||||||
return this._program.getAutoImports(
|
options.libraryMap = options.libraryMap ?? this._backgroundAnalysisProgram.getIndexing(filePath);
|
||||||
filePath,
|
return this._program.getAutoImports(filePath, range, similarityLimit, nameMap, options, token);
|
||||||
range,
|
|
||||||
similarityLimit,
|
|
||||||
nameMap,
|
|
||||||
this._backgroundAnalysisProgram.getIndexing(filePath),
|
|
||||||
lazyEdit,
|
|
||||||
allowVariableInAll,
|
|
||||||
token
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
getDefinitionForPosition(
|
getDefinitionForPosition(
|
||||||
|
@ -107,6 +107,7 @@ import { DocumentRange, Position, Range } from './common/textRange';
|
|||||||
import { UriParser } from './common/uriParser';
|
import { UriParser } from './common/uriParser';
|
||||||
import { convertWorkspaceDocumentEdits } from './common/workspaceEditUtils';
|
import { convertWorkspaceDocumentEdits } from './common/workspaceEditUtils';
|
||||||
import { AnalyzerServiceExecutor } from './languageService/analyzerServiceExecutor';
|
import { AnalyzerServiceExecutor } from './languageService/analyzerServiceExecutor';
|
||||||
|
import { ImportFormat } from './languageService/autoImporter';
|
||||||
import { CompletionItemData, CompletionOptions, CompletionResultsList } from './languageService/completionProvider';
|
import { CompletionItemData, CompletionOptions, CompletionResultsList } from './languageService/completionProvider';
|
||||||
import { DefinitionFilter } from './languageService/definitionProvider';
|
import { DefinitionFilter } from './languageService/definitionProvider';
|
||||||
import { convertToFlatSymbols, WorkspaceSymbolCallback } from './languageService/documentSymbolProvider';
|
import { convertToFlatSymbols, WorkspaceSymbolCallback } from './languageService/documentSymbolProvider';
|
||||||
@ -1317,6 +1318,7 @@ export abstract class LanguageServerBase implements LanguageServerInterface {
|
|||||||
lazyEdit: this.client.completionItemResolveSupportsAdditionalTextEdits,
|
lazyEdit: this.client.completionItemResolveSupportsAdditionalTextEdits,
|
||||||
autoImport: true,
|
autoImport: true,
|
||||||
extraCommitChars: false,
|
extraCommitChars: false,
|
||||||
|
importFormat: ImportFormat.Absolute,
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -7,17 +7,21 @@
|
|||||||
|
|
||||||
import { CancellationToken, CompletionItemKind, SymbolKind } from 'vscode-languageserver';
|
import { CancellationToken, CompletionItemKind, SymbolKind } from 'vscode-languageserver';
|
||||||
|
|
||||||
|
import { getFileInfo } from '../analyzer/analyzerNodeInfo';
|
||||||
import { DeclarationType } from '../analyzer/declaration';
|
import { DeclarationType } from '../analyzer/declaration';
|
||||||
import { ImportResolver, ModuleNameAndType } from '../analyzer/importResolver';
|
import { ImportResolver, ModuleNameAndType } from '../analyzer/importResolver';
|
||||||
import { ImportType } from '../analyzer/importResult';
|
import { ImportType } from '../analyzer/importResult';
|
||||||
import {
|
import {
|
||||||
getImportGroup,
|
getImportGroup,
|
||||||
getImportGroupFromModuleNameAndType,
|
getImportGroupFromModuleNameAndType,
|
||||||
|
getRelativeModuleName,
|
||||||
getTextEditsForAutoImportInsertion,
|
getTextEditsForAutoImportInsertion,
|
||||||
getTextEditsForAutoImportSymbolAddition,
|
getTextEditsForAutoImportSymbolAddition,
|
||||||
getTopLevelImports,
|
getTopLevelImports,
|
||||||
ImportGroup,
|
ImportGroup,
|
||||||
|
ImportNameInfo,
|
||||||
ImportStatements,
|
ImportStatements,
|
||||||
|
ModuleNameInfo,
|
||||||
} from '../analyzer/importStatementUtils';
|
} from '../analyzer/importStatementUtils';
|
||||||
import { SourceFileInfo } from '../analyzer/program';
|
import { SourceFileInfo } from '../analyzer/program';
|
||||||
import { isUserCode } from '../analyzer/sourceFileInfoUtils';
|
import { isUserCode } from '../analyzer/sourceFileInfoUtils';
|
||||||
@ -36,11 +40,16 @@ import { ParseResults } from '../parser/parser';
|
|||||||
import { CompletionMap } from './completionProvider';
|
import { CompletionMap } from './completionProvider';
|
||||||
import { IndexAliasData, IndexResults } from './documentSymbolProvider';
|
import { IndexAliasData, IndexResults } from './documentSymbolProvider';
|
||||||
|
|
||||||
|
export const enum ImportFormat {
|
||||||
|
Absolute = 'absolute',
|
||||||
|
Relative = 'relative',
|
||||||
|
}
|
||||||
|
|
||||||
export interface AutoImportSymbol {
|
export interface AutoImportSymbol {
|
||||||
readonly importAlias?: IndexAliasData | undefined;
|
readonly importAlias?: IndexAliasData;
|
||||||
readonly symbol?: Symbol | undefined;
|
readonly symbol?: Symbol;
|
||||||
readonly kind?: SymbolKind | undefined;
|
readonly kind?: SymbolKind;
|
||||||
readonly itemKind?: CompletionItemKind | undefined;
|
readonly itemKind?: CompletionItemKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface ModuleSymbolTable {
|
export interface ModuleSymbolTable {
|
||||||
@ -50,31 +59,32 @@ export interface ModuleSymbolTable {
|
|||||||
export type ModuleSymbolMap = Map<string, ModuleSymbolTable>;
|
export type ModuleSymbolMap = Map<string, ModuleSymbolTable>;
|
||||||
|
|
||||||
export interface AbbreviationInfo {
|
export interface AbbreviationInfo {
|
||||||
importFrom?: string | undefined;
|
importFrom?: string;
|
||||||
importName: string;
|
importName: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutoImportResult {
|
export interface AutoImportResult {
|
||||||
name: string;
|
name: string;
|
||||||
symbol?: Symbol | undefined;
|
symbol?: Symbol;
|
||||||
source?: string | undefined;
|
source?: string;
|
||||||
insertionText: string;
|
insertionText: string;
|
||||||
edits?: TextEditAction[] | undefined;
|
edits?: TextEditAction[];
|
||||||
alias?: string | undefined;
|
alias?: string;
|
||||||
kind?: CompletionItemKind | undefined;
|
kind?: CompletionItemKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface AutoImportOptions {
|
export interface AutoImportOptions {
|
||||||
libraryMap?: Map<string, IndexResults> | undefined;
|
libraryMap?: Map<string, IndexResults>;
|
||||||
patternMatcher?: ((pattern: string, name: string) => boolean) | undefined;
|
patternMatcher?: (pattern: string, name: string) => boolean;
|
||||||
allowVariableInAll?: boolean | undefined;
|
allowVariableInAll?: boolean;
|
||||||
lazyEdit?: boolean | undefined;
|
lazyEdit?: boolean;
|
||||||
|
importFormat?: ImportFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
interface ImportParts {
|
interface ImportParts {
|
||||||
importName: string;
|
importName: string;
|
||||||
symbolName?: string | undefined;
|
symbolName?: string;
|
||||||
importFrom?: string | undefined;
|
importFrom?: string;
|
||||||
filePath: string;
|
filePath: string;
|
||||||
dotCount: number;
|
dotCount: number;
|
||||||
moduleNameAndType: ModuleNameAndType;
|
moduleNameAndType: ModuleNameAndType;
|
||||||
@ -83,9 +93,9 @@ interface ImportParts {
|
|||||||
interface ImportAliasData {
|
interface ImportAliasData {
|
||||||
importParts: ImportParts;
|
importParts: ImportParts;
|
||||||
importGroup: ImportGroup;
|
importGroup: ImportGroup;
|
||||||
symbol?: Symbol | undefined;
|
symbol?: Symbol;
|
||||||
kind?: SymbolKind | undefined;
|
kind?: SymbolKind;
|
||||||
itemKind?: CompletionItemKind | undefined;
|
itemKind?: CompletionItemKind;
|
||||||
}
|
}
|
||||||
|
|
||||||
type AutoImportResultMap = Map<string, AutoImportResult[]>;
|
type AutoImportResultMap = Map<string, AutoImportResult[]>;
|
||||||
@ -148,7 +158,7 @@ export function buildModuleSymbolsMap(
|
|||||||
!declaration.isFinal
|
!declaration.isFinal
|
||||||
? SymbolKind.Variable
|
? SymbolKind.Variable
|
||||||
: undefined;
|
: undefined;
|
||||||
callbackfn({ symbol, kind: variableKind }, name, /* library */ false);
|
callbackfn({ symbol, kind: variableKind }, name, /* library */ !isUserCode(file));
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
});
|
});
|
||||||
@ -167,11 +177,12 @@ export function buildModuleSymbolsMap(
|
|||||||
}
|
}
|
||||||
|
|
||||||
export class AutoImporter {
|
export class AutoImporter {
|
||||||
private _importStatements: ImportStatements;
|
private readonly _filePath: string;
|
||||||
|
private readonly _importStatements: ImportStatements;
|
||||||
|
|
||||||
// Track some auto import internal perf numbers.
|
// Track some auto import internal perf numbers.
|
||||||
private _stopWatch = new Duration();
|
private readonly _stopWatch = new Duration();
|
||||||
private _perfInfo = {
|
private readonly _perfInfo = {
|
||||||
indexUsed: false,
|
indexUsed: false,
|
||||||
totalInMs: 0,
|
totalInMs: 0,
|
||||||
|
|
||||||
@ -193,6 +204,7 @@ export class AutoImporter {
|
|||||||
private _moduleSymbolMap: ModuleSymbolMap,
|
private _moduleSymbolMap: ModuleSymbolMap,
|
||||||
private _options: AutoImportOptions
|
private _options: AutoImportOptions
|
||||||
) {
|
) {
|
||||||
|
this._filePath = getFileInfo(_parseResults.parseTree).filePath;
|
||||||
this._importStatements = getTopLevelImports(this._parseResults.parseTree, /* includeImplicitImports */ true);
|
this._importStatements = getTopLevelImports(this._parseResults.parseTree, /* includeImplicitImports */ true);
|
||||||
|
|
||||||
this._perfInfo.indexUsed = !!this._options.libraryMap;
|
this._perfInfo.indexUsed = !!this._options.libraryMap;
|
||||||
@ -321,7 +333,7 @@ export class AutoImporter {
|
|||||||
|
|
||||||
private _processModuleSymbolTable(
|
private _processModuleSymbolTable(
|
||||||
topLevelSymbols: ModuleSymbolTable,
|
topLevelSymbols: ModuleSymbolTable,
|
||||||
filePath: string,
|
moduleFilePath: string,
|
||||||
word: string,
|
word: string,
|
||||||
similarityLimit: number,
|
similarityLimit: number,
|
||||||
isStubOrHasInit: { isStub: boolean; hasInit: boolean },
|
isStubOrHasInit: { isStub: boolean; hasInit: boolean },
|
||||||
@ -332,7 +344,7 @@ export class AutoImporter {
|
|||||||
) {
|
) {
|
||||||
throwIfCancellationRequested(token);
|
throwIfCancellationRequested(token);
|
||||||
|
|
||||||
const [importSource, importGroup, moduleNameAndType] = this._getImportPartsForSymbols(filePath);
|
const [importSource, importGroup, moduleNameAndType] = this._getImportPartsForSymbols(moduleFilePath);
|
||||||
if (!importSource) {
|
if (!importSource) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -367,7 +379,7 @@ export class AutoImporter {
|
|||||||
symbolName: name,
|
symbolName: name,
|
||||||
importName: name,
|
importName: name,
|
||||||
importFrom: importSource,
|
importFrom: importSource,
|
||||||
filePath,
|
filePath: moduleFilePath,
|
||||||
dotCount,
|
dotCount,
|
||||||
moduleNameAndType,
|
moduleNameAndType,
|
||||||
},
|
},
|
||||||
@ -381,13 +393,17 @@ export class AutoImporter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const nameForImportFrom =
|
||||||
|
this._options.importFormat === ImportFormat.Relative && !library
|
||||||
|
? getRelativeModuleName(this._importResolver.fileSystem, this._filePath, moduleFilePath)
|
||||||
|
: undefined;
|
||||||
|
|
||||||
const autoImportTextEdits = this._getTextEditsForAutoImportByFilePath(
|
const autoImportTextEdits = this._getTextEditsForAutoImportByFilePath(
|
||||||
importSource,
|
{ name, alias: abbrFromUsers },
|
||||||
name,
|
{ name: importSource, nameForImportFrom },
|
||||||
abbrFromUsers,
|
|
||||||
name,
|
name,
|
||||||
importGroup,
|
importGroup,
|
||||||
filePath
|
moduleFilePath
|
||||||
);
|
);
|
||||||
|
|
||||||
this._addResult(results, {
|
this._addResult(results, {
|
||||||
@ -408,7 +424,7 @@ export class AutoImporter {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
const importParts = this._getImportParts(filePath);
|
const importParts = this._getImportParts(moduleFilePath);
|
||||||
if (!importParts) {
|
if (!importParts) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -425,7 +441,7 @@ export class AutoImporter {
|
|||||||
|
|
||||||
this._addToImportAliasMap(
|
this._addToImportAliasMap(
|
||||||
{
|
{
|
||||||
modulePath: filePath,
|
modulePath: moduleFilePath,
|
||||||
originalName: importParts.importName,
|
originalName: importParts.importName,
|
||||||
kind: SymbolKind.Module,
|
kind: SymbolKind.Module,
|
||||||
itemKind: CompletionItemKind.Module,
|
itemKind: CompletionItemKind.Module,
|
||||||
@ -510,9 +526,10 @@ export class AutoImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
const autoImportTextEdits = this._getTextEditsForAutoImportByFilePath(
|
const autoImportTextEdits = this._getTextEditsForAutoImportByFilePath(
|
||||||
importAliasData.importParts.importFrom ?? importAliasData.importParts.importName,
|
{ name: importAliasData.importParts.symbolName, alias: abbrFromUsers },
|
||||||
importAliasData.importParts.symbolName,
|
{
|
||||||
abbrFromUsers,
|
name: importAliasData.importParts.importFrom ?? importAliasData.importParts.importName,
|
||||||
|
},
|
||||||
importAliasData.importParts.importName,
|
importAliasData.importParts.importName,
|
||||||
importAliasData.importGroup,
|
importAliasData.importGroup,
|
||||||
importAliasData.importParts.filePath
|
importAliasData.importParts.filePath
|
||||||
@ -685,9 +702,8 @@ export class AutoImporter {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private _getTextEditsForAutoImportByFilePath(
|
private _getTextEditsForAutoImportByFilePath(
|
||||||
moduleName: string,
|
importNameInfo: ImportNameInfo,
|
||||||
importName: string | undefined,
|
moduleNameInfo: ModuleNameInfo,
|
||||||
abbrFromUsers: string | undefined,
|
|
||||||
insertionText: string,
|
insertionText: string,
|
||||||
importGroup: ImportGroup,
|
importGroup: ImportGroup,
|
||||||
filePath: string
|
filePath: string
|
||||||
@ -700,11 +716,11 @@ export class AutoImporter {
|
|||||||
// For now, we don't check whether alias or moduleName got overwritten at
|
// For now, we don't check whether alias or moduleName got overwritten at
|
||||||
// given position
|
// given position
|
||||||
const importAlias = importStatement.subnode?.alias?.value;
|
const importAlias = importStatement.subnode?.alias?.value;
|
||||||
if (importName) {
|
if (importNameInfo.name) {
|
||||||
// ex) import module
|
// ex) import module
|
||||||
// method | <= auto-import
|
// method | <= auto-import
|
||||||
return {
|
return {
|
||||||
insertionText: `${importAlias ?? importStatement.moduleName}.${importName}`,
|
insertionText: `${importAlias ?? importStatement.moduleName}.${importNameInfo.name}`,
|
||||||
edits: [],
|
edits: [],
|
||||||
};
|
};
|
||||||
} else if (importAlias) {
|
} else if (importAlias) {
|
||||||
@ -719,18 +735,18 @@ export class AutoImporter {
|
|||||||
|
|
||||||
// Does an 'import from' statement already exist?
|
// Does an 'import from' statement already exist?
|
||||||
if (
|
if (
|
||||||
importName &&
|
importNameInfo.name &&
|
||||||
importStatement.node.nodeType === ParseNodeType.ImportFrom &&
|
importStatement.node.nodeType === ParseNodeType.ImportFrom &&
|
||||||
!importStatement.node.isWildcardImport
|
!importStatement.node.isWildcardImport
|
||||||
) {
|
) {
|
||||||
// If so, see whether what we want already exist.
|
// If so, see whether what we want already exist.
|
||||||
const importNode = importStatement.node.imports.find((i) => i.name.value === importName);
|
const importNode = importStatement.node.imports.find((i) => i.name.value === importNameInfo.name);
|
||||||
if (importNode) {
|
if (importNode) {
|
||||||
// For now, we don't check whether alias or moduleName got overwritten at
|
// For now, we don't check whether alias or moduleName got overwritten at
|
||||||
// given position
|
// given position
|
||||||
const importAlias = importNode.alias?.value;
|
const importAlias = importNode.alias?.value;
|
||||||
return {
|
return {
|
||||||
insertionText: `${importAlias ?? importName}`,
|
insertionText: `${importAlias ?? importNameInfo.name}`,
|
||||||
edits: [],
|
edits: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@ -738,25 +754,25 @@ export class AutoImporter {
|
|||||||
// If not, add what we want at the existing 'import from' statement as long as
|
// If not, add what we want at the existing 'import from' statement as long as
|
||||||
// what is imported is not module itself.
|
// what is imported is not module itself.
|
||||||
// ex) don't add "path" to existing "from os.path import dirname" statement.
|
// ex) don't add "path" to existing "from os.path import dirname" statement.
|
||||||
if (moduleName === importStatement.moduleName) {
|
if (moduleNameInfo.name === importStatement.moduleName) {
|
||||||
return {
|
return {
|
||||||
insertionText: abbrFromUsers ?? insertionText,
|
insertionText: importNameInfo.alias ?? insertionText,
|
||||||
edits: this._options.lazyEdit
|
edits: this._options.lazyEdit
|
||||||
? undefined
|
? undefined
|
||||||
: getTextEditsForAutoImportSymbolAddition(
|
: getTextEditsForAutoImportSymbolAddition(
|
||||||
{ name: importName, alias: abbrFromUsers },
|
importNameInfo,
|
||||||
importStatement,
|
importStatement,
|
||||||
this._parseResults
|
this._parseResults
|
||||||
),
|
),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (importName) {
|
} else if (importNameInfo.name) {
|
||||||
// If it is the module itself that got imported, make sure we don't import it again.
|
// If it is the module itself that got imported, make sure we don't import it again.
|
||||||
// ex) from module import submodule
|
// ex) from module import submodule
|
||||||
const imported = this._importStatements.orderedImports.find((i) => i.moduleName === moduleName);
|
const imported = this._importStatements.orderedImports.find((i) => i.moduleName === moduleNameInfo.name);
|
||||||
if (imported && imported.node.nodeType === ParseNodeType.ImportFrom && !imported.node.isWildcardImport) {
|
if (imported && imported.node.nodeType === ParseNodeType.ImportFrom && !imported.node.isWildcardImport) {
|
||||||
const importFrom = imported.node.imports.find((i) => i.name.value === importName);
|
const importFrom = imported.node.imports.find((i) => i.name.value === importNameInfo.name);
|
||||||
if (importFrom) {
|
if (importFrom) {
|
||||||
// For now, we don't check whether alias or moduleName got overwritten at
|
// For now, we don't check whether alias or moduleName got overwritten at
|
||||||
// given position. only move to alias, but not the other way around
|
// given position. only move to alias, but not the other way around
|
||||||
@ -770,14 +786,10 @@ export class AutoImporter {
|
|||||||
} else {
|
} else {
|
||||||
// If not, add what we want at the existing import from statement.
|
// If not, add what we want at the existing import from statement.
|
||||||
return {
|
return {
|
||||||
insertionText: abbrFromUsers ?? insertionText,
|
insertionText: importNameInfo.alias ?? insertionText,
|
||||||
edits: this._options.lazyEdit
|
edits: this._options.lazyEdit
|
||||||
? undefined
|
? undefined
|
||||||
: getTextEditsForAutoImportSymbolAddition(
|
: getTextEditsForAutoImportSymbolAddition(importNameInfo, imported, this._parseResults),
|
||||||
{ name: importName, alias: abbrFromUsers },
|
|
||||||
imported,
|
|
||||||
this._parseResults
|
|
||||||
),
|
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -789,20 +801,20 @@ export class AutoImporter {
|
|||||||
// given position
|
// given position
|
||||||
const importAlias = importFrom.alias?.value;
|
const importAlias = importFrom.alias?.value;
|
||||||
return {
|
return {
|
||||||
insertionText: `${importAlias ?? importFrom.name.value}.${importName}`,
|
insertionText: `${importAlias ?? importFrom.name.value}.${importNameInfo.name}`,
|
||||||
edits: [],
|
edits: [],
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return {
|
return {
|
||||||
insertionText: abbrFromUsers ?? insertionText,
|
insertionText: importNameInfo.alias ?? insertionText,
|
||||||
edits: this._options.lazyEdit
|
edits: this._options.lazyEdit
|
||||||
? undefined
|
? undefined
|
||||||
: getTextEditsForAutoImportInsertion(
|
: getTextEditsForAutoImportInsertion(
|
||||||
{ name: importName, alias: abbrFromUsers },
|
importNameInfo,
|
||||||
|
moduleNameInfo,
|
||||||
this._importStatements,
|
this._importStatements,
|
||||||
moduleName,
|
|
||||||
importGroup,
|
importGroup,
|
||||||
this._parseResults,
|
this._parseResults,
|
||||||
this._invocationPosition
|
this._invocationPosition
|
||||||
|
@ -112,7 +112,7 @@ import {
|
|||||||
} from '../parser/parseNodes';
|
} from '../parser/parseNodes';
|
||||||
import { ParseResults } from '../parser/parser';
|
import { ParseResults } from '../parser/parser';
|
||||||
import { StringToken, StringTokenFlags, Token, TokenType } from '../parser/tokenizerTypes';
|
import { StringToken, StringTokenFlags, Token, TokenType } from '../parser/tokenizerTypes';
|
||||||
import { AbbreviationInfo, AutoImporter, AutoImportResult, ModuleSymbolMap } from './autoImporter';
|
import { AbbreviationInfo, AutoImporter, AutoImportResult, ImportFormat, ModuleSymbolMap } from './autoImporter';
|
||||||
import { DocumentSymbolCollector } from './documentSymbolCollector';
|
import { DocumentSymbolCollector } from './documentSymbolCollector';
|
||||||
import { IndexResults } from './documentSymbolProvider';
|
import { IndexResults } from './documentSymbolProvider';
|
||||||
import {
|
import {
|
||||||
@ -282,6 +282,7 @@ export interface CompletionOptions {
|
|||||||
lazyEdit: boolean;
|
lazyEdit: boolean;
|
||||||
autoImport: boolean;
|
autoImport: boolean;
|
||||||
extraCommitChars: boolean;
|
extraCommitChars: boolean;
|
||||||
|
importFormat: ImportFormat;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type AbbreviationMap = Map<string, AbbreviationInfo>;
|
export type AbbreviationMap = Map<string, AbbreviationInfo>;
|
||||||
@ -2241,7 +2242,11 @@ export class CompletionProvider {
|
|||||||
this._position,
|
this._position,
|
||||||
completionResults.completionMap,
|
completionResults.completionMap,
|
||||||
moduleSymbolMap,
|
moduleSymbolMap,
|
||||||
{ libraryMap: this._autoImportMaps.libraryMap, lazyEdit }
|
{
|
||||||
|
libraryMap: this._autoImportMaps.libraryMap,
|
||||||
|
lazyEdit,
|
||||||
|
importFormat: this._options.importFormat,
|
||||||
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
const results: AutoImportResult[] = [];
|
const results: AutoImportResult[] = [];
|
||||||
|
@ -52,6 +52,7 @@ import { convertOffsetToPosition } from '../common/positionUtils';
|
|||||||
import { TextRange } from '../common/textRange';
|
import { TextRange } from '../common/textRange';
|
||||||
import { ModuleNameNode, NameNode, ParseNode, ParseNodeType } from '../parser/parseNodes';
|
import { ModuleNameNode, NameNode, ParseNode, ParseNodeType } from '../parser/parseNodes';
|
||||||
import { ParseResults } from '../parser/parser';
|
import { ParseResults } from '../parser/parser';
|
||||||
|
import { ImportFormat } from './autoImporter';
|
||||||
|
|
||||||
export interface ImportData {
|
export interface ImportData {
|
||||||
containsUnreferenceableSymbols: boolean;
|
containsUnreferenceableSymbols: boolean;
|
||||||
@ -79,6 +80,7 @@ export class ImportAdder {
|
|||||||
result: ImportData,
|
result: ImportData,
|
||||||
parseResults: ParseResults,
|
parseResults: ParseResults,
|
||||||
insertionPosition: number,
|
insertionPosition: number,
|
||||||
|
importFormat: ImportFormat,
|
||||||
token: CancellationToken
|
token: CancellationToken
|
||||||
): TextEditAction[] {
|
): TextEditAction[] {
|
||||||
throwIfCancellationRequested(token);
|
throwIfCancellationRequested(token);
|
||||||
@ -94,6 +96,7 @@ export class ImportAdder {
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const relativePath = getRelativeModuleName(this._importResolver.fileSystem, filePath, importInfo.filePath);
|
||||||
const moduleAndType = this._importResolver.getModuleNameForImport(importInfo.filePath, execEnv);
|
const moduleAndType = this._importResolver.getModuleNameForImport(importInfo.filePath, execEnv);
|
||||||
if (!moduleAndType.moduleName) {
|
if (!moduleAndType.moduleName) {
|
||||||
if (!importInfo.nameInfo.name) {
|
if (!importInfo.nameInfo.name) {
|
||||||
@ -103,16 +106,17 @@ export class ImportAdder {
|
|||||||
// module can't be addressed by absolute path in "from import" statement.
|
// module can't be addressed by absolute path in "from import" statement.
|
||||||
// ex) namespace package at [workspace root] or [workspace root]\__init__.py(i)
|
// ex) namespace package at [workspace root] or [workspace root]\__init__.py(i)
|
||||||
// use relative path
|
// use relative path
|
||||||
moduleAndType.moduleName = getRelativeModuleName(
|
importFormat = ImportFormat.Relative;
|
||||||
this._importResolver.fileSystem,
|
|
||||||
filePath,
|
|
||||||
importInfo.filePath
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
addIfUnique(
|
addIfUnique(
|
||||||
importNameInfo,
|
importNameInfo,
|
||||||
{ module: moduleAndType, name: importInfo.nameInfo.name, alias: importInfo.nameInfo.alias },
|
{
|
||||||
|
name: importInfo.nameInfo.name,
|
||||||
|
alias: importInfo.nameInfo.alias,
|
||||||
|
module: moduleAndType,
|
||||||
|
nameForImportFrom: importFormat === ImportFormat.Relative ? relativePath : undefined,
|
||||||
|
},
|
||||||
(a, b) => this._areSame(a, b)
|
(a, b) => this._areSame(a, b)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
@ -100,8 +100,8 @@ function _addMissingOptionalToParam(
|
|||||||
} else {
|
} else {
|
||||||
const additionalEditActions = getTextEditsForAutoImportInsertion(
|
const additionalEditActions = getTextEditsForAutoImportInsertion(
|
||||||
{ name: 'Optional' },
|
{ name: 'Optional' },
|
||||||
|
{ name: 'typing' },
|
||||||
importStatements,
|
importStatements,
|
||||||
'typing',
|
|
||||||
ImportGroup.BuiltIn,
|
ImportGroup.BuiltIn,
|
||||||
parseResults,
|
parseResults,
|
||||||
startPos
|
startPos
|
||||||
|
@ -486,8 +486,8 @@ export class RenameModuleProvider {
|
|||||||
this._addResultEdits(
|
this._addResultEdits(
|
||||||
getTextEditsForAutoImportInsertion(
|
getTextEditsForAutoImportInsertion(
|
||||||
[],
|
[],
|
||||||
|
{ name: this._newModuleName },
|
||||||
importStatements,
|
importStatements,
|
||||||
this._newModuleName,
|
|
||||||
getImportGroupFromModuleNameAndType(this._newModuleNameAndType),
|
getImportGroupFromModuleNameAndType(this._newModuleNameAndType),
|
||||||
parseResults,
|
parseResults,
|
||||||
convertOffsetToPosition(parseResults.parseTree.length, parseResults.tokenizerOutput.lines)
|
convertOffsetToPosition(parseResults.parseTree.length, parseResults.tokenizerOutput.lines)
|
||||||
@ -1324,8 +1324,8 @@ export class RenameModuleProvider {
|
|||||||
|
|
||||||
return getTextEditsForAutoImportInsertion(
|
return getTextEditsForAutoImportInsertion(
|
||||||
importNameInfo,
|
importNameInfo,
|
||||||
|
{ name: moduleName },
|
||||||
importStatements,
|
importStatements,
|
||||||
moduleName,
|
|
||||||
getImportGroupFromModuleNameAndType(this._newModuleNameAndType),
|
getImportGroupFromModuleNameAndType(this._newModuleNameAndType),
|
||||||
parseResults,
|
parseResults,
|
||||||
convertOffsetToPosition(parseResults.parseTree.length, parseResults.tokenizerOutput.lines)
|
convertOffsetToPosition(parseResults.parseTree.length, parseResults.tokenizerOutput.lines)
|
||||||
|
@ -17,6 +17,7 @@ import { ConfigOptions } from '../common/configOptions';
|
|||||||
import { NullConsole } from '../common/console';
|
import { NullConsole } from '../common/console';
|
||||||
import { normalizeSlashes } from '../common/pathUtils';
|
import { normalizeSlashes } from '../common/pathUtils';
|
||||||
import { convertOffsetsToRange, convertOffsetToPosition } from '../common/positionUtils';
|
import { convertOffsetsToRange, convertOffsetToPosition } from '../common/positionUtils';
|
||||||
|
import { ImportFormat } from '../languageService/autoImporter';
|
||||||
import { parseTestData } from './harness/fourslash/fourSlashParser';
|
import { parseTestData } from './harness/fourslash/fourSlashParser';
|
||||||
import { TestAccessHost } from './harness/testAccessHost';
|
import { TestAccessHost } from './harness/testAccessHost';
|
||||||
import * as host from './harness/testHost';
|
import * as host from './harness/testHost';
|
||||||
@ -54,6 +55,7 @@ test('check chained files', async () => {
|
|||||||
snippet: false,
|
snippet: false,
|
||||||
autoImport: false,
|
autoImport: false,
|
||||||
extraCommitChars: false,
|
extraCommitChars: false,
|
||||||
|
importFormat: ImportFormat.Absolute,
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
CancellationToken.None
|
CancellationToken.None
|
||||||
@ -100,6 +102,7 @@ test('modify chained files', async () => {
|
|||||||
snippet: false,
|
snippet: false,
|
||||||
autoImport: false,
|
autoImport: false,
|
||||||
extraCommitChars: false,
|
extraCommitChars: false,
|
||||||
|
importFormat: ImportFormat.Absolute,
|
||||||
},
|
},
|
||||||
undefined,
|
undefined,
|
||||||
CancellationToken.None
|
CancellationToken.None
|
||||||
|
@ -65,7 +65,7 @@ import {
|
|||||||
WellKnownWorkspaceKinds,
|
WellKnownWorkspaceKinds,
|
||||||
WorkspaceServiceInstance,
|
WorkspaceServiceInstance,
|
||||||
} from '../../../languageServerBase';
|
} from '../../../languageServerBase';
|
||||||
import { AbbreviationInfo } from '../../../languageService/autoImporter';
|
import { AbbreviationInfo, ImportFormat } from '../../../languageService/autoImporter';
|
||||||
import { CompletionOptions } from '../../../languageService/completionProvider';
|
import { CompletionOptions } from '../../../languageService/completionProvider';
|
||||||
import { DefinitionFilter } from '../../../languageService/definitionProvider';
|
import { DefinitionFilter } from '../../../languageService/definitionProvider';
|
||||||
import { convertHoverResults } from '../../../languageService/hoverProvider';
|
import { convertHoverResults } from '../../../languageService/hoverProvider';
|
||||||
@ -1099,6 +1099,7 @@ export class TestState {
|
|||||||
lazyEdit: true,
|
lazyEdit: true,
|
||||||
autoImport: true,
|
autoImport: true,
|
||||||
extraCommitChars: true,
|
extraCommitChars: true,
|
||||||
|
importFormat: ImportFormat.Absolute,
|
||||||
};
|
};
|
||||||
const nameMap = abbrMap ? new Map<string, AbbreviationInfo>(Object.entries(abbrMap)) : undefined;
|
const nameMap = abbrMap ? new Map<string, AbbreviationInfo>(Object.entries(abbrMap)) : undefined;
|
||||||
const result = await this.workspace.serviceInstance.getCompletionsForPosition(
|
const result = await this.workspace.serviceInstance.getCompletionsForPosition(
|
||||||
|
@ -10,6 +10,7 @@ import assert from 'assert';
|
|||||||
import { CancellationToken } from 'vscode-languageserver';
|
import { CancellationToken } from 'vscode-languageserver';
|
||||||
|
|
||||||
import { rangesAreEqual, TextRange } from '../common/textRange';
|
import { rangesAreEqual, TextRange } from '../common/textRange';
|
||||||
|
import { ImportFormat } from '../languageService/autoImporter';
|
||||||
import { ImportAdder } from '../languageService/importAdder';
|
import { ImportAdder } from '../languageService/importAdder';
|
||||||
import { parseAndGetTestState } from './harness/fourslash/testState';
|
import { parseAndGetTestState } from './harness/fourslash/testState';
|
||||||
|
|
||||||
@ -1319,7 +1320,23 @@ test('move into the same file from import statement for submodule', () => {
|
|||||||
testImportMove(code);
|
testImportMove(code);
|
||||||
});
|
});
|
||||||
|
|
||||||
function testImportMove(code: string) {
|
test('use relative import format', () => {
|
||||||
|
const code = `
|
||||||
|
// @filename: test1.py
|
||||||
|
//// from nested import module
|
||||||
|
////
|
||||||
|
//// [|/*src*/module.foo()|]
|
||||||
|
|
||||||
|
// @filename: nested/__init__.py
|
||||||
|
//// [|{|"r":"from . import module!n!!n!!n!"|}|][|/*dest*/|]
|
||||||
|
|
||||||
|
// @filename: nested/module.py
|
||||||
|
//// def foo(): pass
|
||||||
|
`;
|
||||||
|
testImportMove(code, ImportFormat.Relative);
|
||||||
|
});
|
||||||
|
|
||||||
|
function testImportMove(code: string, importFormat = ImportFormat.Absolute) {
|
||||||
const state = parseAndGetTestState(code).state;
|
const state = parseAndGetTestState(code).state;
|
||||||
|
|
||||||
const src = state.getRangeByMarkerName('src')!;
|
const src = state.getRangeByMarkerName('src')!;
|
||||||
@ -1336,6 +1353,7 @@ function testImportMove(code: string) {
|
|||||||
importData,
|
importData,
|
||||||
state.program.getBoundSourceFile(dest.fileName)!.getParseResults()!,
|
state.program.getBoundSourceFile(dest.fileName)!.getParseResults()!,
|
||||||
dest.position,
|
dest.position,
|
||||||
|
importFormat,
|
||||||
CancellationToken.None
|
CancellationToken.None
|
||||||
);
|
);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user