Skip to content

Commit 735d459

Browse files
committed
Improvements
1 parent d32a278 commit 735d459

16 files changed

+528
-410
lines changed

LICENSE

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
MIT License
22

3-
Copyright (c) 2020 nj2534
3+
Copyright (c) 2020 nj-q
44

55
Permission is hereby granted, free of charge, to any person obtaining a copy
66
of this software and associated documentation files (the "Software"), to deal

README.md

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Python Type Hint
22

3-
Provides type hint auto-completion for Python.
3+
Provides type hint auto-completion for Python, with completion items for built-in types, classes and the typing module.
44

55
![](demo.gif)
66

@@ -12,14 +12,20 @@ Provides type hint auto-completion for Python.
1212

1313
* Can provide completion items for the typing module if it is imported.
1414

15+
## Settings
16+
17+
| Name | Description | Default
18+
|---|---|---|
19+
| workspace.search.limit | _(number)_ The maximum number of files searched when estimating types for a parameter.
20+
21+
If 0, only the current editor document is searched, which increases speed but can reduce estimation accuracy. | 20
22+
1523
## Installation
1624

17-
Get this extension from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=).
25+
Get this extension from the [Visual Studio Marketplace](https://marketplace.visualstudio.com/items?itemName=vscode-python-typehint).
1826

1927
## Known Issues
2028

2129
* The difference between function and class constructor calls when detecting types is determined by the first letter being upper case (unless the class or function is defined in the currently edited document).
2230

23-
* Up to 20 files within in the workspace are searched at a time. The limit is by design to keep the extension light weight, but there's probably a better solution.
24-
2531
-------------------------------------------------------------------------------------------

demo.gif

135 KB
Loading

images/icon.png

33.9 KB
Loading

package.json

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2,12 +2,12 @@
22
"name": "vscode-python-typehint",
33
"displayName": "Python Type Hint",
44
"version": "1.0.0",
5-
"publisher": "nj2532",
5+
"publisher": "nj-q",
66
"description": "Type hint completion for Python.",
77
"icon": "images/icon.png",
88
"repository": {
99
"type": "git",
10-
"url": "https://github.com/nj2532/vscode-python-typehint"
10+
"url": "https://github.com/nj-q/vscode-python-typehint"
1111
},
1212
"license": "MIT",
1313
"categories": [
@@ -43,10 +43,10 @@
4343
"configuration": {
4444
"title": "Python Type Hint",
4545
"properties": {
46-
"pyTypehint.search.limit": {
46+
"workspace.search.limit": {
4747
"type": "number",
48-
"default": 30,
49-
"description": "When providing type hint items, the number of files searched will be limited by this setting."
48+
"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."
5050
}
5151
}
5252
}

src/completionProvider.ts

Lines changed: 45 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,11 @@ import {
77
CompletionItemProvider,
88
Position,
99
TextLine,
10-
TextDocument
10+
TextDocument,
11+
Range
1112
} from "vscode";
1213
import { TypeHintProvider } from "./typeHintProvider";
13-
import { paramHintTrigger, returnHintTrigger, PythonType } from "./python";
14+
import { paramHintTrigger, returnHintTrigger, PythonType, anyClassOrFunctionName } from "./python";
1415
import { TypeHint, labelFor } from "./typeHint";
1516
import { TypeHintSettings } from "./settings";
1617

@@ -49,12 +50,13 @@ export class ParamHintCompletionProvider extends CompletionProvider implements C
4950
if (context.triggerCharacter === paramHintTrigger) {
5051
const items: CompletionItem[] = [];
5152
const line = doc.lineAt(pos);
52-
53-
if (this.shouldProvideItems(line, pos)) {
54-
const param = this.findParam(line, pos);
53+
const precedingText = line.text.substring(0, pos.character - 1).trim();
54+
55+
if (this.shouldProvideItems(precedingText, pos, doc)) {
56+
const param: string = this.findParam(precedingText, pos);
5557
const provider = new TypeHintProvider(doc, this.settings);
5658

57-
if (param && param.length > 0) {
59+
if (param.length > 0) {
5860
try {
5961
this.pushEstimationsToItems(await provider.getTypeHints(param), items);
6062
} catch (error) {
@@ -70,17 +72,21 @@ export class ParamHintCompletionProvider extends CompletionProvider implements C
7072
/**
7173
* Finds the parameter which is about to be type hinted.
7274
*
73-
* @param line The active line.
75+
* @param precedingText Text preceding the active position.
7476
* @param pos The active position.
77+
* @returns The parameter.
7578
*/
76-
private findParam(line: TextLine, pos: Position): string | null {
77-
let param = null;
78-
let split = line.text.substr(0, pos.character).split(new RegExp("[,(]"));
79-
if (split.length > 1) {
80-
param = split[split.length - 1].trim();
81-
param = param.substr(0, param.length - 1);
79+
private findParam(precedingText: string, pos: Position): string {
80+
let param = "";
81+
82+
let i = precedingText.length - 1;
83+
let last = precedingText[i];
84+
while (last !== "," && last !== "(" && i >= 0) {
85+
param = precedingText[i] + param;
86+
i--;
87+
last = precedingText[i];
8288
}
83-
return param;
89+
return param.trim();
8490
}
8591

8692
private pushEstimationsToItems(typeHints: TypeHint[], items: CompletionItem[]) {
@@ -100,17 +106,36 @@ export class ParamHintCompletionProvider extends CompletionProvider implements C
100106
item.insertText = typeHints[i].insertText;
101107
items.push(item);
102108
}
103-
104109
}
105110
}
106111

107-
private shouldProvideItems(line: TextLine, pos: Position): boolean {
112+
private shouldProvideItems(precedingText: string, activePos: Position, doc: TextDocument): boolean {
113+
114+
if (activePos.character > 0 && !this.isInvalid(precedingText)) {
115+
let provide = new RegExp("^[ \t]*def", "m").test(precedingText);
108116

109-
if (pos.character > 0) {
110-
return new RegExp("^[ \t]*def", "m").test(line.text);
117+
if (!provide) {
118+
const nLinesToCheck = activePos.character > 4 ? 4 : activePos.line;
119+
const range = new Range(doc.lineAt(activePos.line - nLinesToCheck).range.start, activePos);
120+
provide = new RegExp(
121+
`^[ \t]*def(?![\s\S]+(\\):|-> *${anyClassOrFunctionName}:))`,
122+
"m"
123+
).test(doc.getText(range));
124+
}
125+
return provide;
111126
}
112127
return false;
113128
}
129+
130+
/**
131+
* The text is invalid if it is a comment, dict or the end of the function definition.
132+
*/
133+
private isInvalid(precedingText: string): boolean {
134+
if (precedingText) {
135+
return new RegExp("#|\\)$|{ *[a-zA-Z0-9.+*/\\(\\)-]+$").test(precedingText);
136+
}
137+
return true;
138+
}
114139
}
115140

116141
/**
@@ -139,8 +164,8 @@ export class ReturnHintCompletionProvider extends CompletionProvider implements
139164
private shouldProvideItems(line: TextLine, pos: Position): boolean {
140165

141166
if (pos.character > 0 && line.text.substr(pos.character - 2, 2) === "->") {
142-
143-
return new RegExp("^[ \t]*def.*\\) *->[: ]*$", "m").test(line.text);
167+
168+
return new RegExp("\\) *->[: ]*$", "m").test(line.text);
144169
}
145170
return false;
146171
}

src/extension.ts

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,6 @@ import { TypeHintSettings } from './settings';
66
// Called when the extension is activated.
77
export function activate(context: vscode.ExtensionContext) {
88

9-
// Not used yet
10-
function registerCommand(commandId: string, func: (...args: any[]) => void): void {
11-
context.subscriptions.push(vscode.commands.registerCommand(commandId, func));
12-
}
13-
149
const settings = new TypeHintSettings();
1510

1611
context.subscriptions.push(

src/python.ts

Lines changed: 4 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,9 @@ export const anyClassOrFunctionName: string = "[a-zA-Z_][a-zA-Z0-9_.]*";
44
export const paramHintTrigger: string = ":";
55
export const returnHintTrigger: string = ">";
66

7+
/**
8+
* A built-in Python type.
9+
*/
710
export class DataType {
811
name: PythonType;
912
category: TypeCategory;
@@ -34,15 +37,7 @@ export const getDataTypeContainer = (): DataTypeContainer => {
3437
};
3538

3639
/**
37-
* Ways a variable can be initialized.
38-
*/
39-
export enum Initialization {
40-
WithValue,
41-
WithCall
42-
}
43-
44-
/**
45-
* Built-in Python types.
40+
* Names of built-in Python types.
4641
*/
4742
export enum PythonType {
4843
Bool = "bool",

src/settings.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import { workspace, Event, EventEmitter, window } from "vscode";
22

33
export class TypeHintSettings {
44

5-
private searchLimit = 50;
5+
private searchLimit = 20;
66

77
public get fileSearchLimit() {
88
return this.searchLimit;
@@ -24,9 +24,9 @@ export class TypeHintSettings {
2424
}
2525

2626
private initialize() {
27-
const searchLimit: number | undefined = workspace.getConfiguration('pyTypehint.search').get('limit');
27+
const searchLimit: number | undefined = workspace.getConfiguration('workspace.search').get('limit');
2828
if (searchLimit) {
29-
this.searchLimit = searchLimit;
29+
this.searchLimit = Number.isInteger(searchLimit) ? searchLimit : Math.round(searchLimit);
3030
}
3131
}
3232

0 commit comments

Comments
 (0)