Skip to content

Commit

Permalink
improvements to hover provider
Browse files Browse the repository at this point in the history
  • Loading branch information
DonJayamanne committed Feb 12, 2017
1 parent 612478a commit 6a7a3f3
Show file tree
Hide file tree
Showing 3 changed files with 95 additions and 34 deletions.
76 changes: 50 additions & 26 deletions pythonFiles/completion.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import traceback

WORD_RE = re.compile(r'\w')
jediPreview = False


class JediCompletion(object):
Expand Down Expand Up @@ -314,7 +315,7 @@ def _extract_range(self, definition):
'end_line': definition.line - 1,
'end_column': definition.column
}
def _get_definitions(self, definitions, identifier=None):
def _get_definitionsx(self, definitions, identifier=None, ignoreNoModulePath=False):
"""Serialize response to be read from VSCode.
Args:
Expand All @@ -327,25 +328,39 @@ def _get_definitions(self, definitions, identifier=None):
_definitions = []
for definition in definitions:
try:
if definition.module_path:
if definition.type == 'import':
definition = self._top_definition(definition)
if not definition.module_path:
if definition.type == 'import':
definition = self._top_definition(definition)
definitionRange = {
'start_line': 0,
'start_column': 0,
'end_line': 0,
'end_column': 0
}
module_path = ''
if hasattr(definition, 'module_path') and definition.module_path:
module_path = definition.module_path
definitionRange = self._extract_range(definition)
else:
if not ignoreNoModulePath:
continue
try:
parent = definition.parent()
container = parent.name if parent.type != 'module' else ''
except Exception:
container = ''
_definition = {
'text': definition.name,
'type': self._get_definition_type(definition),
'raw_type': definition.type,
'fileName': definition.module_path,
'container': container,
'range': self._extract_range(definition)
}
_definitions.append(_definition)
try:
parent = definition.parent()
container = parent.name if parent.type != 'module' else ''
except Exception:
container = ''
_definition = {
'text': definition.name,
'type': self._get_definition_type(definition),
'raw_type': definition.type,
'fileName': module_path,
'container': container,
'range': definitionRange,
'description': definition.description,
'docstring': definition.docstring(),
'raw_docstring': definition.docstring(raw=True),
'signature': self._generate_signature(definition)
}
_definitions.append(_definition)
except Exception as e:
pass
return _definitions
Expand Down Expand Up @@ -379,7 +394,10 @@ def _serialize_definitions(self, definitions, identifier=None):
'raw_type': definition.type,
'fileName': definition.module_path,
'container': container,
'range': self._extract_range(definition)
'range': self._extract_range(definition),
'description': definition.description,
'docstring': definition.docstring(),
'raw_docstring': definition.docstring(raw=True)
}
_definitions.append(_definition)
except Exception as e:
Expand All @@ -405,7 +423,9 @@ def _serialize_tooltip(self, definitions, identifier=None):
description = definition.docstring().strip()
_definition = {
'type': self._get_definition_type(definition),
'text': definition.name,
'description': description,
'docstring': description,
'signature': signature
}
_definitions.append(_definition)
Expand Down Expand Up @@ -477,15 +497,20 @@ def _process_request(self, request):
script = jedi.api.Script(
source=request.get('source', None), line=request['line'] + 1,
column=request['column'], path=request.get('path', ''))

if lookup == 'definitions':
defs = self._get_definitions(script.goto_definitions(), request['id'])
defs = self._get_definitionsx(script.goto_definitions(), request['id'])
if len(defs) == 0:
defs = self._get_definitions(script.goto_assignments(), request['id'])
defs = self._get_definitionsx(script.goto_assignments(), request['id'])
return self._write_response(json.dumps({'id': request['id'], 'results': defs}))
if lookup == 'tooltip':
return self._write_response(self._serialize_tooltip(
script.goto_definitions(), request['id']))
if jediPreview:
defs = self._get_definitionsx(script.goto_definitions(), request['id'], True)
if len(defs) == 0:
defs = self._get_definitionsx(script.goto_assignments(), request['id'], True)
return self._write_response(json.dumps({'id': request['id'], 'results': defs}))
else:
return self._write_response(self._serialize_tooltip(script.goto_definitions(), request['id']))
elif lookup == 'arguments':
return self._write_response(self._serialize_arguments(
script, request['id']))
Expand Down Expand Up @@ -514,7 +539,6 @@ def watch(self):
sys.stderr.flush()

if __name__ == '__main__':
jediPreview = False
cachePrefix = 'v'
if len(sys.argv) > 0 and sys.argv[1] == 'preview':
jediPath = os.path.join(os.path.dirname(__file__), 'preview')
Expand Down
45 changes: 39 additions & 6 deletions src/client/providers/hoverProvider.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,15 +4,17 @@ import * as vscode from 'vscode';
import * as proxy from './jediProxy';
import * as telemetryContracts from "../common/telemetryContracts";
import { highlightCode } from './jediHelpers';
import { EOL } from 'os';

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

public constructor(context: vscode.ExtensionContext, jediProxy: proxy.JediProxy = null) {
this.jediProxyHandler = new proxy.JediProxyHandler(context, jediProxy);
}
private static parseData(data: proxy.IHoverResult): vscode.Hover {
private static parseData(data: proxy.IHoverResult, currentWord: string): vscode.Hover {
let results = [];
let capturedInfo: string[] = [];
data.items.forEach(item => {
let { description, signature } = item;
switch (item.kind) {
Expand All @@ -26,11 +28,42 @@ export class PythonHoverProvider implements vscode.HoverProvider {
signature = 'class ' + signature;
break;
}
default: {
signature = typeof item.text === 'string' && item.text.length > 0 ? item.text : currentWord;
}
}
if (item.docstring) {
let lines = item.docstring.split(EOL);
if (lines.length > 0 && lines[0] === item.signature) {
lines.shift();
}
if (lines.length > 0 && item.signature.startsWith(currentWord) && lines[0].startsWith(currentWord) && lines[0].endsWith(')')) {
lines.shift();
}
let descriptionWithHighlightedCode = highlightCode(lines.join(EOL));
let hoverInfo = '```python' + EOL + signature + EOL + '```' + EOL + descriptionWithHighlightedCode;
let key = signature + lines.join('');
// Sometimes we have duplicate documentation, one with a period at the end
if (capturedInfo.indexOf(key) >= 0 || capturedInfo.indexOf(key + '.') >= 0) {
return;
}
capturedInfo.push(key);
capturedInfo.push(key + '.');
results.push(hoverInfo);
return;
}
results.push({ language: 'python', value: signature });
if (item.description) {
var descriptionWithHighlightedCode = highlightCode(item.description);
results.push(descriptionWithHighlightedCode);
let descriptionWithHighlightedCode = highlightCode(item.description);
let hoverInfo = '```python' + EOL + signature + EOL + '```' + EOL + descriptionWithHighlightedCode;
let lines = item.description.split(EOL);
let key = signature + lines.join('');
// Sometimes we have duplicate documentation, one with a period at the end
if (capturedInfo.indexOf(key) >= 0 || capturedInfo.indexOf(key + '.') >= 0) {
return;
}
capturedInfo.push(key);
capturedInfo.push(key + '.');
results.push(hoverInfo);
}
});
return new vscode.Hover(results);
Expand All @@ -48,7 +81,7 @@ export class PythonHoverProvider implements vscode.HoverProvider {
if (!range || range.isEmpty) {
return null;
}

let word = document.getText(range);
var cmd: proxy.ICommand<proxy.IDefinitionResult> = {
command: proxy.CommandType.Hover,
fileName: filename,
Expand All @@ -64,6 +97,6 @@ export class PythonHoverProvider implements vscode.HoverProvider {
return;
}

return PythonHoverProvider.parseData(data);
return PythonHoverProvider.parseData(data, word);
}
}
8 changes: 6 additions & 2 deletions src/client/providers/jediProxy.ts
Original file line number Diff line number Diff line change
Expand Up @@ -342,8 +342,10 @@ function spawnProcess(dir: string) {
return {
kind: getMappedVSCodeSymbol(def.type),
description: def.description,
signature: def.signature
}
signature: def.signature,
docstring: def.docstring,
text: def.text
};
})
};

Expand Down Expand Up @@ -651,7 +653,9 @@ export interface IDefinition {

export interface IHoverItem {
kind: vscode.SymbolKind;
text: string;
description: string;
docstring: string;
signature: string;
}

Expand Down

0 comments on commit 6a7a3f3

Please sign in to comment.