Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
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
49 changes: 24 additions & 25 deletions pythonFiles/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -266,14 +266,14 @@ def _extract_range(self, definition):
from jedi import common
from jedi.parser.utils import load_parser
# get the scope range
if definition.type in ['class', 'function', 'method']:
scope = definition._name.get_parent_scope()
if definition.type in ['class', 'function']:
scope = definition._definition
start_line = scope.start_pos[0] - 1
start_column = scope.start_pos[1]
end_line = scope.end_pos[0] - 1
end_column = scope.end_pos[1]
# get the lines
path = definition._name.get_parent_until().path
path = definition._definition.get_parent_until().path
parser = load_parser(path)
lines = common.splitlines(parser.source)
lines[end_line] = lines[end_line][:end_column]
Expand Down Expand Up @@ -334,27 +334,26 @@ def _serialize_definitions(self, definitions, identifier=None):
def _serialize_tooltip(self, definitions, identifier=None):
_definitions = []
for definition in definitions:
if definition.module_path:
if definition.type == 'import':
definition = self._top_definition(definition)
if not definition.module_path:
continue

description = definition.docstring()
if description is not None:
description = description.strip()
if not description:
description = self._additional_info(definition)
_definition = {
'text': definition.name,
'type': self._get_definition_type(definition),
'fileName': definition.module_path,
'description': description,
'line': definition.line - 1,
'column': definition.column
}
_definitions.append(_definition)
break
signature = definition.name
description = None
if definition.type in ['class', 'function']:
signature = self._generate_signature(definition)
description = definition.docstring(raw=True).strip()
if not description and not definition.get_line_code():
# jedi returns an empty string for compiled objects
description = definition.docstring().strip()
if definition.type == 'module':
signature = definition.full_name
description = definition.docstring(raw=True).strip()
if not description and not definition.get_line_code():
# jedi returns an empty string for compiled objects
description = definition.docstring().strip()
_definition = {
'type': self._get_definition_type(definition),
'description': description,
'signature': signature
}
_definitions.append(_definition)
return json.dumps({'id': identifier, 'results': _definitions})

def _serialize_usages(self, usages, identifier=None):
Expand Down Expand Up @@ -429,7 +428,7 @@ def _process_request(self, request):
script.goto_assignments(), request['id']))
if lookup == 'tooltip':
return self._write_response(self._serialize_tooltip(
script.goto_assignments(), request['id']))
script.goto_definitions(), request['id']))
elif lookup == 'arguments':
return self._write_response(self._serialize_arguments(
script, request['id']))
Expand Down
2 changes: 1 addition & 1 deletion src/client/providers/completionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ import { PythonSettings } from '../common/configSettings';
const pythonSettings = PythonSettings.getInstance();

export class PythonCompletionItemProvider implements vscode.CompletionItemProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.ICompletionResult, vscode.CompletionItem[]>;
private jediProxyHandler: proxy.JediProxyHandler<proxy.ICompletionResult>;

public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, jediProxy);
Expand Down
2 changes: 1 addition & 1 deletion src/client/providers/definitionProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as proxy from './jediProxy';
import * as telemetryContracts from "../common/telemetryContracts";

export class PythonDefinitionProvider implements vscode.DefinitionProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.IDefinitionResult, vscode.Definition>;
private jediProxyHandler: proxy.JediProxyHandler<proxy.IDefinitionResult>;
public get JediProxy(): proxy.JediProxy {
return this.jediProxyHandler.JediProxy;
}
Expand Down
67 changes: 37 additions & 30 deletions src/client/providers/hoverProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,58 +3,65 @@
import * as vscode from 'vscode';
import * as proxy from './jediProxy';
import * as telemetryContracts from "../common/telemetryContracts";
import { extractHoverInfo} from './jediHelpers';

export class PythonHoverProvider implements vscode.HoverProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.ICompletionResult, vscode.Hover>;
private jediProxyHandler: proxy.JediProxyHandler<proxy.IHoverResult>;

public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, jediProxy);
}
public provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Thenable<vscode.Hover> {
private static parseData(data: proxy.IHoverResult): vscode.Hover {
let results = [];
data.items.forEach(item => {
let { description, signature } = item;
switch (item.kind) {
case vscode.SymbolKind.Constructor:
case vscode.SymbolKind.Function:
case vscode.SymbolKind.Method: {
signature = 'def ' + signature;
break;
}
case vscode.SymbolKind.Class: {
signature = 'class ' + signature;
break;
}
}
results.push({language: 'python', value: signature});
if (item.description) {
results.push(description);
}
});
return new vscode.Hover(results);
}
public async provideHover(document: vscode.TextDocument, position: vscode.Position, token: vscode.CancellationToken): Promise<vscode.Hover> {
var filename = document.fileName;
if (document.lineAt(position.line).text.match(/^\s*\/\//)) {
return Promise.resolve(null);
return null;
}
if (position.character <= 0) {
return Promise.resolve(null);
return null;
}

var range = document.getWordRangeAtPosition(position);
if (!range || range.isEmpty) {
return Promise.resolve(null);
return null;
}
var columnIndex = range.start.character < range.end.character ? range.start.character + 2 : range.end.character;
var cmd: proxy.ICommand<proxy.ICompletionResult> = {
command: proxy.CommandType.Completions,

var cmd: proxy.ICommand<proxy.IDefinitionResult> = {
command: proxy.CommandType.Hover,
fileName: filename,
columnIndex: columnIndex,
columnIndex: range.end.character,
lineIndex: position.line
};
if (document.isDirty) {
cmd.source = document.getText();
}

return this.jediProxyHandler.sendCommand(cmd, token).then(data => {
if (!data || !Array.isArray(data.items) || data.items.length === 0) {
return;
}
// Find the right items
const wordUnderCursor = document.getText(range);
const completionItem = data.items.filter(item => item.text === wordUnderCursor);
if (completionItem.length === 0) {
return;
}
var definition = completionItem[0];
var txt = definition.description || definition.text;
if (typeof txt !== 'string' || txt.length === 0) {
return;
}
if (wordUnderCursor === txt) {
return;
}
const data = await this.jediProxyHandler.sendCommand(cmd, token);
if (!data || !data.items.length) {
return;
}

return extractHoverInfo(definition);
});
return PythonHoverProvider.parseData(data);
}
}
9 changes: 0 additions & 9 deletions src/client/providers/jediHelpers.ts
Original file line number Diff line number Diff line change
Expand Up @@ -47,12 +47,3 @@ export function extractSignatureAndDocumentation(definition: proxy.IAutoComplete
}
return [signature, lines.join(EOL).trim().replace(/^\s+|\s+$/g, '').trim()];
}

export function extractHoverInfo(definition: proxy.IAutoCompleteItem): vscode.Hover {
const parts = extractSignatureAndDocumentation(definition, true);
const hoverInfo: vscode.MarkedString[] = parts[0].length === 0 ? [] : [{ language: 'python', value: parts[0] }];
if (parts[1].length > 0) {
hoverInfo.push(parts[1]);
}
return new vscode.Hover(hoverInfo);
}
36 changes: 33 additions & 3 deletions src/client/providers/jediProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,7 @@ function getMappedVSCodeSymbol(pythonType: string): vscode.SymbolKind {
export enum CommandType {
Arguments,
Completions,
Hover,
Usages,
Definitions,
Symbols
Expand All @@ -115,6 +116,7 @@ var commandNames = new Map<CommandType, string>();
commandNames.set(CommandType.Arguments, "arguments");
commandNames.set(CommandType.Completions, "completions");
commandNames.set(CommandType.Definitions, "definitions");
commandNames.set(CommandType.Hover, "tooltip");
commandNames.set(CommandType.Usages, "usages");
commandNames.set(CommandType.Symbols, "names");

Expand Down Expand Up @@ -291,7 +293,7 @@ function spawnProcess(dir: string) {
const originalType = <string><any>item.type;
item.type = getMappedVSCodeType(originalType);
item.kind = getMappedVSCodeSymbol(originalType);
item.raw_type = getMappedVSCodeType(originalType);
item.rawType = getMappedVSCodeType(originalType);
});

let completionResult: ICompletionResult = {
Expand All @@ -313,6 +315,7 @@ function spawnProcess(dir: string) {
defResult.definition = {
fileName: def.fileName,
text: def.text,
rawType: originalType,
type: getMappedVSCodeType(originalType),
kind: getMappedVSCodeSymbol(originalType),
container: def.container,
Expand All @@ -328,6 +331,22 @@ function spawnProcess(dir: string) {
cmd.deferred.resolve(defResult);
break;
}
case CommandType.Hover: {
var defs = <any[]>response['results'];
var defResult: IHoverResult = {
requestId: cmd.id,
items: defs.map(def => {
return {
kind: getMappedVSCodeSymbol(def.type),
description: def.description,
signature: def.signature
}
})
};

cmd.deferred.resolve(defResult);
break;
}
case CommandType.Symbols: {
var defs = <any[]>response['results'];
defs = Array.isArray(defs) ? defs : [];
Expand All @@ -340,6 +359,7 @@ function spawnProcess(dir: string) {
return {
fileName: def.fileName,
text: def.text,
rawType: originalType,
type: getMappedVSCodeType(originalType),
kind: getMappedVSCodeSymbol(originalType),
container: def.container,
Expand Down Expand Up @@ -563,6 +583,9 @@ export interface ICommandResult {
export interface ICompletionResult extends ICommandResult {
items: IAutoCompleteItem[];
}
export interface IHoverResult extends ICommandResult {
items: IHoverItem[];
}
export interface IDefinitionResult extends ICommandResult {
definition: IDefinition;
}
Expand Down Expand Up @@ -600,7 +623,7 @@ export interface IReference {

export interface IAutoCompleteItem {
type: vscode.CompletionItemKind;
raw_type: vscode.CompletionItemKind;
rawType: vscode.CompletionItemKind;
kind: vscode.SymbolKind;
text: string;
description: string;
Expand All @@ -614,6 +637,7 @@ interface IDefinitionRange {
endColumn: number;
}
export interface IDefinition {
rawType: string;
type: vscode.CompletionItemKind;
kind: vscode.SymbolKind;
text: string;
Expand All @@ -622,7 +646,13 @@ export interface IDefinition {
range: IDefinitionRange;
}

export class JediProxyHandler<R extends ICommandResult, T> {
export interface IHoverItem {
kind: vscode.SymbolKind;
description: string;
signature: string;
}

export class JediProxyHandler<R extends ICommandResult> {
private jediProxy: JediProxy;
private lastToken: vscode.CancellationToken;
private lastCommandId: number;
Expand Down
2 changes: 1 addition & 1 deletion src/client/providers/referenceProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import * as telemetryContracts from "../common/telemetryContracts";


export class PythonReferenceProvider implements vscode.ReferenceProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.IReferenceResult, vscode.Location[]>;
private jediProxyHandler: proxy.JediProxyHandler<proxy.IReferenceResult>;

public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, jediProxy);
Expand Down
2 changes: 1 addition & 1 deletion src/client/providers/signatureProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ function extractParamDocString(paramName: string, docString: string): string {
return paramDocString.trim();
}
export class PythonSignatureProvider implements vscode.SignatureHelpProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.IArgumentsResult, vscode.SignatureHelp>;
private jediProxyHandler: proxy.JediProxyHandler<proxy.IArgumentsResult>;

public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, jediProxy);
Expand Down
2 changes: 1 addition & 1 deletion src/client/providers/symbolProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ import * as proxy from './jediProxy';
import * as telemetryContracts from "../common/telemetryContracts";

export class PythonSymbolProvider implements vscode.DocumentSymbolProvider {
private jediProxyHandler: proxy.JediProxyHandler<proxy.ISymbolResult, vscode.SymbolInformation[]>;
private jediProxyHandler: proxy.JediProxyHandler<proxy.ISymbolResult>;

public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, jediProxy);
Expand Down
Loading