Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/master'
Browse files Browse the repository at this point in the history
* upstream/master:
  Fetch tooltip details on-demand for auto-completions (#368)
  Fix interpreter display (#391)
  • Loading branch information
DonJayamanne committed Dec 11, 2017
2 parents bb0709e + 8d79301 commit 2c19004
Show file tree
Hide file tree
Showing 17 changed files with 844 additions and 1,672 deletions.
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
14 changes: 13 additions & 1 deletion src/client/interpreter/locators/services/condaEnvService.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ export class CondaEnvService implements IInterpreterLocatorService {
return;
}

const versionWithoutCompanyName = this.stripCompanyName(version);
const versionWithoutCompanyName = this.stripCondaDisplayName(this.stripCompanyName(version), condaDisplayName);
const displayName = `${condaDisplayName} ${versionWithoutCompanyName}`.trim();
// If it is an environment, hence suffix with env name.
const interpreterDisplayName = env === info.default_prefix ? displayName : `${displayName} (${envName})`;
Expand Down Expand Up @@ -86,6 +86,18 @@ export class CondaEnvService implements IInterpreterLocatorService {

return startOfCompanyName > 0 ? content.substring(0, startOfCompanyName).trim() : content;
}
private stripCondaDisplayName(content: string, condaDisplayName: string) {
// Strip company name from version.
if (content.endsWith(condaDisplayName)) {
let updatedContent = content.substr(0, content.indexOf(condaDisplayName)).trim();
if (updatedContent.endsWith('::')) {
updatedContent = updatedContent.substr(0, content.indexOf('::')).trim();
}
return updatedContent;
} else {
return content;
}
}
private async getSuggestionsFromConda(): Promise<PythonInterpreter[]> {
return this.condaLocator.getCondaFile()
.then(async condaFile => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import { Uri } from 'vscode';
import { Architecture, IRegistry, RegistryHive } from '../../../common/platform/types';
import { Is64Bit } from '../../../common/types';
import { IInterpreterLocatorService, InterpreterType, PythonInterpreter } from '../../contracts';
import { AnacondaCompanyName, AnacondaCompanyNames } from './conda';

// tslint:disable-next-line:variable-name
const DefaultPythonExecutable = 'python.exe';
Expand Down Expand Up @@ -100,10 +101,11 @@ export class WindowsRegistryService implements IInterpreterLocatorService {
this.registry.getValue(key, hive, arch, 'ExecutablePath'),
// tslint:disable-next-line:no-non-null-assertion
this.getInterpreterDisplayName(tagKey, companyKey, hive, arch),
this.registry.getValue(tagKey, hive, arch, 'Version'),
this.registry.getValue(tagKey, hive, arch, 'SysVersion'),
this.getCompanyDisplayName(companyKey, hive, arch)
])
.then(([installedPath, executablePath, displayName, version, companyDisplayName]) => {
companyDisplayName = AnacondaCompanyNames.indexOf(companyDisplayName) === -1 ? companyDisplayName : AnacondaCompanyName;
// tslint:disable-next-line:prefer-type-cast
return { installPath: installedPath, executablePath, displayName, version, companyDisplayName } as InterpreterInformation;
});
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

0 comments on commit 2c19004

Please sign in to comment.