Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fetch tooltip details on-demand for auto-completions #368

Merged
merged 33 commits into from
Dec 11, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
33 commits
Select commit Hold shift + click to select a range
7675901
Basic tokenizer
Dec 1, 2017
eb42669
Fixed property names
Dec 1, 2017
2756974
Tests, round I
Dec 1, 2017
c2c1ced
Tests, round II
Dec 2, 2017
a108c96
merge master
Dec 3, 2017
14864a5
tokenizer test
Dec 4, 2017
0ed51d6
Remove temorary change
Dec 4, 2017
51b544c
Fix merge issue
Dec 4, 2017
3cd11e6
Merge conflict
Dec 4, 2017
82e0ad1
Merge conflict
Dec 4, 2017
9295c1a
Completion test
Dec 4, 2017
06eb1a5
Fix last line
Dec 4, 2017
e9db8e0
Fix javascript math
Dec 4, 2017
d12ca03
Merge master
Dec 5, 2017
d8ab041
Make test await for results
Dec 5, 2017
db75cd0
Add license headers
Dec 5, 2017
9ab2c47
Rename definitions to types
Dec 5, 2017
d9c95d0
Round I
Dec 5, 2017
d587485
License headers
Dec 5, 2017
1da5e0a
Merge branch 'master' of https://github.com/Microsoft/vscode-python
Dec 5, 2017
3ac66b6
Merge branch 'master' into 152
Dec 5, 2017
94a5a7e
Separate completion and doc fetching
Dec 6, 2017
df5af0e
Test fixes
Dec 7, 2017
af5c648
Merge master
Dec 7, 2017
fdb0e57
Undo temp change
Dec 7, 2017
c67ac49
Merge branch 'master' into 152
Dec 7, 2017
3f27b3b
Merge branch 'master' of https://github.com/Microsoft/vscode-python i…
Dec 7, 2017
7163a1e
Merge branch '152' of https://github.com/MikhailArkhipov/vscode-pytho…
Dec 7, 2017
2c8b179
CR feedback
Dec 8, 2017
3689667
Restore signature, make info colorized
Dec 9, 2017
e193805
Provide details string
Dec 11, 2017
ed48871
Merge branch 'master' of https://github.com/Microsoft/vscode-python i…
Dec 11, 2017
92655ec
Fix tests
Dec 11, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1,116 changes: 102 additions & 1,014 deletions package-lock.json

Large diffs are not rendered by default.

27 changes: 1 addition & 26 deletions pythonFiles/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -208,16 +208,6 @@ def _serialize_completions(self, script, identifier=None, prefix=''):
_completion['snippet'] = '%s=$1$0' % name
_completion['text'] = name
_completion['displayText'] = name
if self.show_doc_strings:
try:
_completion['description'] = signature.docstring()
_completion['raw_docstring'] = signature.docstring(raw=True)
except Exception:
_completion['description'] = ''
_completion['raw_docstring'] = ''
else:
_completion['description'] = self._generate_signature(
signature)
_completions.append(_completion)

try:
Expand All @@ -227,22 +217,11 @@ def _serialize_completions(self, script, identifier=None, prefix=''):
except :
completions = []
for completion in completions:
if self.show_doc_strings:
try:
description = completion.docstring()
except Exception:
description = ''
else:
description = self._generate_signature(completion)

try:
rawDocstring = completion.docstring(raw=True)
_completion = {
'text': completion.name,
'type': self._get_definition_type(completion),
'raw_type': completion.type,
'description': description,
'raw_docstring': rawDocstring,
'rightLabel': self._additional_info(completion)
}
except Exception:
Expand All @@ -252,11 +231,7 @@ def _serialize_completions(self, script, identifier=None, prefix=''):
if c['text'] == _completion['text']:
c['type'] = _completion['type']
c['raw_type'] = _completion['raw_type']
if len(c['description']) == 0 and len(c['raw_docstring']) == 0:
c['description'] = _completion['description']
c['raw_docstring'] = _completion['description']



if any([c['text'].split('=')[0] == _completion['text']
for c in _completions]):
# ignore function arguments we already have
Expand Down
2 changes: 1 addition & 1 deletion src/client/common/configSettings.ts
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ export interface ITerminalSettings {
launchArgs: string[];
}

function isTestExecution(): boolean {
export function isTestExecution(): boolean {
// tslint:disable-next-line:interface-name no-string-literal
return process.env['VSC_PYTHON_CI_TEST'] === '1';
}
Expand Down
27 changes: 0 additions & 27 deletions src/client/jedi/parsers/CompletionParser.ts

This file was deleted.

71 changes: 0 additions & 71 deletions src/client/jedi/parsers/HoverParser.ts

This file was deleted.

5 changes: 2 additions & 3 deletions src/client/languageServices/jediProxyFactory.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import { Disposable, Uri, workspace } from 'vscode';
import { JediProxy, JediProxyHandler, ICommandResult } from '../providers/jediProxy';
import { ICommandResult, JediProxy, JediProxyHandler } from '../providers/jediProxy';

export class JediFactory implements Disposable {
private disposables: Disposable[];
Expand All @@ -20,8 +20,7 @@ export class JediFactory implements Disposable {
if (!workspacePath) {
if (Array.isArray(workspace.workspaceFolders) && workspace.workspaceFolders.length > 0) {
workspacePath = workspace.workspaceFolders[0].uri.fsPath;
}
else {
} else {
workspacePath = __dirname;
}
}
Expand Down
83 changes: 23 additions & 60 deletions src/client/providers/completionProvider.ts
Original file line number Diff line number Diff line change
@@ -1,76 +1,39 @@
'use strict';

import * as vscode from 'vscode';
import { Position, ProviderResult, SnippetString, Uri } from 'vscode';
import { PythonSettings } from '../common/configSettings';
import { Tokenizer } from '../language/tokenizer';
import { TokenType } from '../language/types';
import { isTestExecution } from '../common/configSettings';
import { JediFactory } from '../languageServices/jediProxyFactory';
import { captureTelemetry } from '../telemetry';
import { COMPLETION } from '../telemetry/constants';
import { extractSignatureAndDocumentation } from './jediHelpers';
import * as proxy from './jediProxy';
import { CompletionSource } from './completionSource';

export class PythonCompletionItemProvider implements vscode.CompletionItemProvider {
private completionSource: CompletionSource;

public constructor(private jediFactory: JediFactory) { }
private static parseData(data: proxy.ICompletionResult, resource: Uri): vscode.CompletionItem[] {
if (data && data.items.length > 0) {
return data.items.map(item => {
const sigAndDocs = extractSignatureAndDocumentation(item);
const completionItem = new vscode.CompletionItem(item.text);
completionItem.kind = item.type;
completionItem.documentation = sigAndDocs[1].length === 0 ? item.description : sigAndDocs[1];
completionItem.detail = sigAndDocs[0].split(/\r?\n/).join('');
if (PythonSettings.getInstance(resource).autoComplete.addBrackets === true &&
(item.kind === vscode.SymbolKind.Function || item.kind === vscode.SymbolKind.Method)) {
completionItem.insertText = new SnippetString(item.text).appendText('(').appendTabstop().appendText(')');
}

// ensure the built in memebers are at the bottom
completionItem.sortText = (completionItem.label.startsWith('__') ? 'z' : (completionItem.label.startsWith('_') ? 'y' : '__')) + completionItem.label;
return completionItem;
});
}
return [];
constructor(jediFactory: JediFactory) {
this.completionSource = new CompletionSource(jediFactory);
}

@captureTelemetry(COMPLETION)
public provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): ProviderResult<vscode.CompletionItem[]> {
if (position.character <= 0) {
return Promise.resolve([]);
}
const filename = document.fileName;
const lineText = document.lineAt(position.line).text;
if (lineText.match(/^\s*\/\//)) {
return Promise.resolve([]);
public async provideCompletionItems(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken):
Promise<vscode.CompletionItem[]> {
const items = await this.completionSource.getVsCodeCompletionItems(document, position, token);
if (isTestExecution()) {
for (let i = 0; i < Math.min(3, items.length); i += 1) {
items[i] = await this.resolveCompletionItem(items[i], token);
}
}
// Suppress completion inside string and comments
if (this.isPositionInsideStringOrComment(document, position)) {
return Promise.resolve([]);
}
const type = proxy.CommandType.Completions;
const columnIndex = position.character;

const source = document.getText();
const cmd: proxy.ICommand<proxy.ICommandResult> = {
command: type,
fileName: filename,
columnIndex: columnIndex,
lineIndex: position.line,
source: source
};

return this.jediFactory.getJediProxyHandler<proxy.ICompletionResult>(document.uri).sendCommand(cmd, token).then(data => {
return PythonCompletionItemProvider.parseData(data, document.uri);
});
return items;
}

private isPositionInsideStringOrComment(document: vscode.TextDocument, position: vscode.Position): boolean {
const tokenizeTo = position.translate(1, 0);
const text = document.getText(new vscode.Range(new Position(0, 0), tokenizeTo));
const t = new Tokenizer();
const tokens = t.Tokenize(text);
const index = tokens.getItemContaining(document.offsetAt(position));
return index >= 0 && (tokens[index].TokenType === TokenType.String || tokens[index].TokenType === TokenType.Comment);
public async resolveCompletionItem(item: vscode.CompletionItem, token: vscode.CancellationToken): Promise<vscode.CompletionItem> {
if (!item.documentation) {
const itemInfos = await this.completionSource.getDocumentation(item, token);
if (itemInfos && itemInfos.length > 0) {
item.detail = itemInfos[0].detail;
item.documentation = itemInfos[0].documentation;
}
}
return item;
}
}
Loading