Skip to content

Commit 0b52166

Browse files
committed
Release 1.1.0
- Add a new setting for disabling workspace searching. - Refactoring to improve hinting speed. - Fix setting workspace search limit to 0 not working.
1 parent 0329b91 commit 0b52166

File tree

7 files changed

+134
-89
lines changed

7 files changed

+134
-89
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Change Log
22

3+
## [1.1.0] - 2020-04-19
4+
5+
### Improvements:
6+
7+
* Added a new setting for disabling workspace searching.
8+
* More default hints are provided for the typing module.
9+
* Overall speed improvements.
10+
11+
### Fixes:
12+
13+
* Setting the workspace search limit to 0 not working.
14+
315
## [1.0.2] - 2020-04-16
416

517
* Fixed type hints being provided for non-parameters.

package.json

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
{
22
"name": "vscode-python-typehint",
33
"displayName": "Python Type Hint",
4-
"version": "1.0.2",
4+
"version": "1.1.0",
55
"publisher": "njqdev",
66
"description": "Type hint completion for Python.",
77
"icon": "images/icon.png",
@@ -43,10 +43,15 @@
4343
"configuration": {
4444
"title": "Python Type Hint",
4545
"properties": {
46-
"workspace.search.limit": {
46+
"workspace.searchEnabled": {
47+
"type": "boolean",
48+
"default": true,
49+
"description": "Search other files in the workspace when estimating types for a parameter. Disabling this will increase type hinting speed."
50+
},
51+
"workspace.searchLimit": {
4752
"type": "number",
4853
"default": 20,
49-
"description": "The maximum number of files searched when estimating types for a parameter. If 0, only the current editor document is searched, which increases speed but can reduce estimation accuracy."
54+
"description": "The maximum number of files searched in a workspace search."
5055
}
5156
}
5257
}

src/completionProvider.ts

Lines changed: 39 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -11,14 +11,18 @@ import {
1111
Range
1212
} from "vscode";
1313
import { TypeHintProvider } from "./typeHintProvider";
14-
import { paramHintTrigger, returnHintTrigger, PythonType, simpleIdentifier } from "./python";
14+
import { paramHintTrigger, returnHintTrigger, PythonType, simpleIdentifier, getDataTypeContainer } from "./python";
1515
import { TypeHintSettings } from "./settings";
16+
import { WorkspaceSearcher } from "./workspaceSearcher";
1617

1718

1819
export abstract class CompletionProvider {
1920

2021
protected bottomOfListSortPrefix: number = 999;
2122

23+
/**
24+
* Push type hints to the bottom of an array of completion items.
25+
*/
2226
protected pushHintsToItems(typeHints: string[], completionItems: CompletionItem[]) {
2327
const sortTextPrefix = this.bottomOfListSortPrefix.toString();
2428
for (const hint of typeHints) {
@@ -65,11 +69,21 @@ export class ParamHintCompletionProvider extends CompletionProvider implements C
6569

6670
if (this.shouldProvideItems(precedingText, pos, doc)) {
6771
const param = this.getParam(precedingText);
68-
const provider = new TypeHintProvider(doc, this.settings);
69-
72+
const documentText = doc.getText();
73+
const typeContainer = getDataTypeContainer();
74+
const provider = new TypeHintProvider(typeContainer);
75+
const wsSearcher = new WorkspaceSearcher(doc.uri, this.settings, typeContainer);
76+
7077
if (param) {
78+
const workspaceHintSearch = this.settings.workspaceSearchEnabled
79+
? this.workspaceHintSearch(param, wsSearcher, documentText)
80+
: null;
7181
try {
72-
this.pushEstimationsToItems(await provider.getTypeHints(param), items);
82+
const estimations = await provider.estimateTypeHints(param, documentText);
83+
if (estimations.length > 0) {
84+
this.pushEstimationsToItems(estimations, items);
85+
wsSearcher.cancel();
86+
}
7387
} catch {
7488
}
7589

@@ -83,14 +97,25 @@ export class ParamHintCompletionProvider extends CompletionProvider implements C
8397
if (provider.typingImported) {
8498
this.pushHintsToItems(provider.remainingTypingHints(), items);
8599
}
86-
100+
const hint = await workspaceHintSearch;
101+
if (hint && provider.hintNotProvided(hint)) {
102+
items.unshift(this.toSelectedCompletionItem(hint));
103+
}
87104
return Promise.resolve(new CompletionList(items, false));
88105
}
89106
}
90107
}
91108
return Promise.resolve(null);
92109
}
93110

111+
private async workspaceHintSearch(param: string, ws: WorkspaceSearcher, docText: string): Promise<string | null> {
112+
try {
113+
return ws.findHintOfSimilarParam(param, docText);
114+
} catch {
115+
return null;
116+
}
117+
}
118+
94119
/**
95120
* Returns the parameter which is about to be type hinted.
96121
*
@@ -105,19 +130,23 @@ export class ParamHintCompletionProvider extends CompletionProvider implements C
105130
private pushEstimationsToItems(typeHints: string[], items: CompletionItem[]) {
106131

107132
if (typeHints.length > 0) {
108-
let item = new CompletionItem(this.labelFor(typeHints[0]), CompletionItemKind.TypeParameter);
109-
item.sortText = `0${typeHints[0]}`;
110-
item.preselect = true;
111-
items.push(item);
133+
items.push(this.toSelectedCompletionItem(typeHints[0]));
112134

113135
for (let i = 1; i < typeHints.length; i++) {
114-
item = new CompletionItem(this.labelFor(typeHints[i]), CompletionItemKind.TypeParameter);
136+
let item = new CompletionItem(this.labelFor(typeHints[i]), CompletionItemKind.TypeParameter);
115137
item.sortText = `${i}${typeHints[i]}`;
116138
items.push(item);
117139
}
118140
}
119141
}
120142

143+
private toSelectedCompletionItem(typeHint: string): CompletionItem {
144+
let item = new CompletionItem(this.labelFor(typeHint), CompletionItemKind.TypeParameter);
145+
item.sortText = `0${typeHint}`;
146+
item.preselect = true;
147+
return item;
148+
}
149+
121150
private shouldProvideItems(precedingText: string, activePos: Position, doc: TextDocument): boolean {
122151

123152
if (activePos.character > 0 && !/#/.test(precedingText)) {

src/settings.ts

Lines changed: 16 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,8 @@ import { workspace, Event, EventEmitter } from "vscode";
55
*/
66
export class TypeHintSettings {
77

8-
private searchLimit = 20;
9-
10-
public get fileSearchLimit() {
11-
return this.searchLimit;
12-
}
8+
private _workspaceSearchEnabled = true;
9+
private _workspaceSearchLimit = 20;
1310

1411
constructor() {
1512
workspace.onDidChangeConfiguration(() => {
@@ -18,7 +15,13 @@ export class TypeHintSettings {
1815
});
1916
this.initialize();
2017
}
21-
18+
19+
public get workspaceSearchLimit() {
20+
return this._workspaceSearchLimit;
21+
}
22+
public get workspaceSearchEnabled() {
23+
return this._workspaceSearchEnabled;
24+
}
2225

2326
public readonly settingsUpdated = new EventEmitter<void>();
2427

@@ -27,9 +30,13 @@ export class TypeHintSettings {
2730
}
2831

2932
private initialize() {
30-
const searchLimit: number | undefined = workspace.getConfiguration('workspace.search').get('limit');
31-
if (searchLimit) {
32-
this.searchLimit = Number.isInteger(searchLimit) ? searchLimit : Math.round(searchLimit);
33+
const wsEnable: boolean | undefined = workspace.getConfiguration('workspace').get('searchEnabled');
34+
const searchLimit: number | undefined = workspace.getConfiguration('workspace').get('searchLimit');
35+
if (wsEnable !== undefined) {
36+
this._workspaceSearchEnabled = wsEnable;
37+
}
38+
if (searchLimit || searchLimit === 0) {
39+
this._workspaceSearchLimit = Number.isInteger(searchLimit) ? searchLimit : Math.round(searchLimit);
3340
}
3441
}
3542

src/typeHintProvider.ts

Lines changed: 38 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,15 @@ import { TextDocument } from "vscode";
22
import { PythonType as PythonType, DataTypeContainer, getDataTypeContainer } from "./python";
33
import { TypeSearch, VariableSearchResult } from "./typeSearch";
44
import { TypingHintProvider } from "./typingHintProvider";
5-
import { WorkspaceSearcher } from "./workspaceSearcher";
65
import { TypeHintSettings } from "./settings";
76

87
/**
98
* Provides type hints.
109
*/
1110
export class TypeHintProvider {
1211

13-
private doc: TextDocument;
14-
private settings: TypeHintSettings;
15-
private typingHintProvider: TypingHintProvider;
12+
private _typingHintProvider: TypingHintProvider;
13+
1614
private likelyTypes: PythonType[] = [
1715
PythonType.String,
1816
PythonType.List,
@@ -22,20 +20,13 @@ export class TypeHintProvider {
2220
PythonType.Tuple,
2321
PythonType.Float
2422
];
25-
private providedTypeHints: string[] = [];
26-
private typeContainer: DataTypeContainer = getDataTypeContainer();
23+
private _providedTypeHints: string[] = [];
24+
private _typeContainer: DataTypeContainer;
2725
private _typingImported = false;
2826

29-
/**
30-
* Constructs a new TypeHintProvider.
31-
*
32-
* @param doc The active document.
33-
* @param settings User settings.
34-
*/
35-
constructor(doc: TextDocument, settings: TypeHintSettings) {
36-
this.doc = doc;
37-
this.settings = settings;
38-
this.typingHintProvider = new TypingHintProvider(this.typeContainer);
27+
constructor(typeContainer: DataTypeContainer) {
28+
this._typeContainer = typeContainer;
29+
this._typingHintProvider = new TypingHintProvider(typeContainer);
3930
}
4031

4132
public get typingImported() {
@@ -47,47 +38,44 @@ export class TypeHintProvider {
4738
* The returned hints are ordered with the most likely type being first.
4839
*
4940
* @param param The parameter name.
41+
* @param documentText The text to search in order to estimate types.
5042
*/
51-
public async getTypeHints(param: string): Promise<string[]> {
43+
public async estimateTypeHints(param: string, documentText: string): Promise<string[]> {
5244
const typeHints: string[] = [];
53-
const documentText = this.doc.getText();
54-
55-
const typingSearch = this.typingHintProvider.detectTypingImport(documentText);
5645

46+
const typingSearch = this._typingHintProvider.detectTypingImport(documentText);
5747
const variableSearch = TypeSearch.variableWithSameName(param, documentText);
5848

59-
const wsSearcher = new WorkspaceSearcher(this.doc.uri, this.settings);
60-
const workspaceSearch = wsSearcher.findHintOfSimilarParam(param, documentText);
61-
62-
this.tryAdd(TypeSearch.classWithSameName(param, documentText), typeHints);
63-
this.tryAdd(TypeSearch.hintOfSimilarParam(param, documentText), typeHints);
64-
6549
let typeName = this.getTypeParamEndsWith(param, "_");
50+
this._typingImported = await typingSearch;
6651
if (typeName) {
6752
this.add(typeName, typeHints);
68-
this.tryAddTypingHint(await typingSearch, typeName, typeHints);
69-
wsSearcher.cancel();
70-
await workspaceSearch;
53+
this.tryAddTypingHint(typeName, typeHints);
54+
}
55+
56+
if (
57+
typeHints.length > 0
58+
|| this.tryAdd(TypeSearch.hintOfSimilarParam(param, documentText), typeHints)
59+
|| this.tryAdd(TypeSearch.classWithSameName(param, documentText), typeHints)
60+
) {
7161
return typeHints;
7262
}
7363

7464
const searchResult = await variableSearch;
7565

7666
if (searchResult !== null && !TypeSearch.invalidTernaryOperator(searchResult)) {
7767
this.add(searchResult.typeName, typeHints);
78-
this.tryAddTypingHints(await typingSearch, searchResult, typeHints);
68+
this.tryAddTypingHints(searchResult, typeHints);
7969
this.tryAdd(this.typeGuessFor(param, typeHints), typeHints);
8070
} else {
8171
typeName = this.getTypeParamEndsWith(param, "");
8272
if (typeName) {
8373
this.add(typeName, typeHints);
84-
this.tryAddTypingHint(await typingSearch, typeName, typeHints);
74+
this.tryAddTypingHint(typeName, typeHints);
8575
} else {
8676
this.tryAdd(this.typeGuessFor(param, typeHints), typeHints);
8777
}
88-
}
89-
90-
this.tryAdd(await workspaceSearch, typeHints);
78+
}
9179
return typeHints;
9280
}
9381

@@ -97,7 +85,7 @@ export class TypeHintProvider {
9785
public remainingTypeHints(): PythonType[] {
9886
const result: PythonType[] = [];
9987

100-
for (const type of Object.values(this.typeContainer)) {
88+
for (const type of Object.values(this._typeContainer)) {
10189
if (this.hintNotProvided(type.name)) {
10290
result.push(type.name);
10391
}
@@ -110,7 +98,11 @@ export class TypeHintProvider {
11098
* Returns hints for the typing module that have not been provided yet.
11199
*/
112100
public remainingTypingHints(): string[] {
113-
return this.typingHintProvider.getRemainingHints();
101+
return this._typingHintProvider.getRemainingHints();
102+
}
103+
104+
public hintNotProvided(typeHint: string): boolean {
105+
return !this._providedTypeHints.includes(typeHint);
114106
}
115107

116108
/**
@@ -153,27 +145,21 @@ export class TypeHintProvider {
153145
type = type.trim();
154146
if (this.hintNotProvided(type)) {
155147
typeHints.push(type);
156-
this.providedTypeHints.push(type);
148+
this._providedTypeHints.push(type);
157149
}
158150
}
159-
160-
private hintNotProvided(type: string): boolean {
161-
return !this.providedTypeHints.includes(type);
162-
}
163151

164-
private tryAdd(type: string | null, typeHints: string[]) {
152+
private tryAdd(type: string | null, typeHints: string[]): boolean {
165153
if (type) {
166154
this.add(type, typeHints);
155+
return true;
167156
}
157+
return false;
168158
}
169159

170-
private tryAddTypingHints(
171-
typingFound: boolean,
172-
searchResult: VariableSearchResult | null,
173-
typeHints: string[]
174-
) {
175-
if (typingFound) {
176-
const hints: string[] | null = this.typingHintProvider.getHints(searchResult);
160+
private tryAddTypingHints(searchResult: VariableSearchResult | null, typeHints: string[]) {
161+
if (this._typingImported) {
162+
const hints: string[] | null = this._typingHintProvider.getHints(searchResult);
177163
if (hints) {
178164
for (const hint of hints) {
179165
this.add(hint, typeHints);
@@ -182,10 +168,9 @@ export class TypeHintProvider {
182168
}
183169
}
184170

185-
private tryAddTypingHint(typingImported: boolean, typeName: string, typeHints: string[]) {
186-
this._typingImported = typingImported;
187-
if (typingImported) {
188-
const typingHint = this.typingHintProvider.getHint(typeName);
171+
private tryAddTypingHint(typeName: string, typeHints: string[]) {
172+
if (this._typingImported) {
173+
const typingHint = this._typingHintProvider.getHint(typeName);
189174
if (typingHint) {
190175
this.add(typingHint, typeHints);
191176
}

src/typeSearch.ts

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -152,7 +152,10 @@ export class TypeSearch {
152152
* @returns The type hint of the found parameter or null.
153153
*/
154154
public static hintOfSimilarParam(param: string, src: string): string | null {
155-
const m = new RegExp(`^[ \t]*def ${simpleIdentifier}\\([^)]*\\b${param}\\b: *([^),\\s]+)`, "m").exec(src);
155+
const m = new RegExp(
156+
`^[ \t]*def ${simpleIdentifier}\\([^)]*\\b${param}\\b: *([a-zA-Z_][^),\\s]+)`,
157+
"m"
158+
).exec(src);
156159
if (m) {
157160
let hint = m[1].trim();
158161
return hint ? hint : null;

0 commit comments

Comments
 (0)