def pylsp_signature_help(document, position): code_position = _utils.position_to_jedi_linecolumn(document, position) signatures = document.jedi_script().get_signatures(**code_position) if not signatures: return {'signatures': []} s = signatures[0] # Docstring contains one or more lines of signature, followed by empty line, followed by docstring function_sig_lines = (s.docstring().split('\n\n') or [''])[0].splitlines() function_sig = ' '.join([line.strip() for line in function_sig_lines]) sig = { 'label': function_sig, 'documentation': _utils.format_docstring(s.docstring(raw=True)) } # If there are params, add those if s.params: sig['parameters'] = [{ 'label': p.name, 'documentation': _param_docs(s.docstring(), p.name) } for p in s.params] # We only return a single signature because Python doesn't allow overloading sig_info = {'signatures': [sig], 'activeSignature': 0} if s.index is not None and s.params: # Then we know which parameter we're looking at sig_info['activeParameter'] = s.index return sig_info
def pylsp_completions(config, document, position): """Get formatted completions for current code position""" settings = config.plugin_settings('jedi_completion', document_path=document.path) code_position = _utils.position_to_jedi_linecolumn(document, position) code_position["fuzzy"] = settings.get("fuzzy", False) completions = document.jedi_script(use_document_path=True).complete(**code_position) if not completions: return None completion_capabilities = config.capabilities.get('textDocument', {}).get('completion', {}) snippet_support = completion_capabilities.get('completionItem', {}).get('snippetSupport') should_include_params = settings.get('include_params') should_include_class_objects = settings.get('include_class_objects', True) include_params = snippet_support and should_include_params and use_snippets(document, position) include_class_objects = snippet_support and should_include_class_objects and use_snippets(document, position) ready_completions = [ _format_completion(c, include_params) for c in completions ] if include_class_objects: for c in completions: if c.type == 'class': completion_dict = _format_completion(c, False) completion_dict['kind'] = lsp.CompletionItemKind.TypeParameter completion_dict['label'] += ' object' ready_completions.append(completion_dict) return ready_completions or None
def pylsp_rename(config, workspace, document, position, new_name): # pylint: disable=unused-argument log.debug('Executing rename of %s to %s', document.word_at_position(position), new_name) kwargs = _utils.position_to_jedi_linecolumn(document, position) kwargs['new_name'] = new_name try: refactoring = document.jedi_script().rename(**kwargs) except NotImplementedError as exc: raise Exception('No support for renaming in Python 2/3.5 with Jedi. ' 'Consider using the rope_rename plugin instead') from exc log.debug('Finished rename: %s', refactoring.get_diff()) changes = [] for file_path, changed_file in refactoring.get_changed_files().items(): uri = uris.from_fs_path(str(file_path)) doc = workspace.get_maybe_document(uri) changes.append({ 'textDocument': { 'uri': uri, 'version': doc.version if doc else None }, 'edits': [ { 'range': { 'start': {'line': 0, 'character': 0}, 'end': { 'line': _num_lines(changed_file.get_new_code()), 'character': 0, }, }, 'newText': changed_file.get_new_code(), } ], }) return {'documentChanges': changes}
def pylsp_references(document, position, exclude_declaration=False): code_position = _utils.position_to_jedi_linecolumn(document, position) usages = document.jedi_script().get_references(**code_position) if exclude_declaration: # Filter out if the usage is the actual declaration of the thing usages = [d for d in usages if not d.is_definition()] # Filter out builtin modules return [{ 'uri': uris.uri_with(document.uri, path=str(d.module_path)) if d.module_path else document.uri, 'range': { 'start': {'line': d.line - 1, 'character': d.column}, 'end': {'line': d.line - 1, 'character': d.column + len(d.name)} } } for d in usages if not d.in_builtin_module()]
def pylsp_document_highlight(document, position): code_position = _utils.position_to_jedi_linecolumn(document, position) usages = document.jedi_script().get_references(**code_position) def is_valid(definition): return definition.line is not None and definition.column is not None def local_to_document(definition): return not definition.module_path or str(definition.module_path) == document.path return [{ 'range': { 'start': {'line': d.line - 1, 'character': d.column}, 'end': {'line': d.line - 1, 'character': d.column + len(d.name)} }, 'kind': lsp.DocumentHighlightKind.Write if d.is_definition() else lsp.DocumentHighlightKind.Read } for d in usages if is_valid(d) and local_to_document(d)]
def pylsp_definitions(config, document, position): settings = config.plugin_settings('jedi_definition') code_position = _utils.position_to_jedi_linecolumn(document, position) definitions = document.jedi_script(use_document_path=True).goto( follow_imports=settings.get('follow_imports', True), follow_builtin_imports=settings.get('follow_builtin_imports', True), **code_position) return [ { 'uri': uris.uri_with(document.uri, path=str(d.module_path)), 'range': { 'start': {'line': d.line - 1, 'character': d.column}, 'end': {'line': d.line - 1, 'character': d.column + len(d.name)}, } } for d in definitions if d.is_definition() and _not_internal_definition(d) ]
def pylsp_hover(document, position): code_position = _utils.position_to_jedi_linecolumn(document, position) definitions = document.jedi_script().infer(**code_position) word = document.word_at_position(position) # Find first exact matching definition definition = next((x for x in definitions if x.name == word), None) # Ensure a definition is used if only one is available # even if the word doesn't match. An example of this case is 'np' # where 'numpy' doesn't match with 'np'. Same for NumPy ufuncs if len(definitions) == 1: definition = definitions[0] if not definition: return {'contents': ''} # raw docstring returns only doc, without signature doc = _utils.format_docstring(definition.docstring(raw=True)) # Find first exact matching signature signature = next( (x.to_string() for x in definition.get_signatures() if x.name == word), '') contents = [] if signature: contents.append({ 'language': 'python', 'value': signature, }) if doc: contents.append(doc) if not contents: return {'contents': ''} return {'contents': contents}
def pylsp_completions(config, document, position): """Get formatted completions for current code position""" # pylint: disable=too-many-locals settings = config.plugin_settings('jedi_completion', document_path=document.path) resolve_eagerly = settings.get('eager', False) code_position = _utils.position_to_jedi_linecolumn(document, position) code_position['fuzzy'] = settings.get('fuzzy', False) completions = document.jedi_script(use_document_path=True).complete( **code_position) if not completions: return None completion_capabilities = config.capabilities.get('textDocument', {}).get( 'completion', {}) snippet_support = completion_capabilities.get('completionItem', {}).get('snippetSupport') should_include_params = settings.get('include_params') should_include_class_objects = settings.get('include_class_objects', True) max_to_resolve = settings.get('resolve_at_most', 25) modules_to_cache_for = settings.get('cache_for', None) if modules_to_cache_for is not None: LABEL_RESOLVER.cached_modules = modules_to_cache_for SNIPPET_RESOLVER.cached_modules = modules_to_cache_for include_params = snippet_support and should_include_params and use_snippets( document, position) include_class_objects = snippet_support and should_include_class_objects and use_snippets( document, position) ready_completions = [ _format_completion(c, include_params, resolve=resolve_eagerly, resolve_label_or_snippet=(i < max_to_resolve)) for i, c in enumerate(completions) ] # TODO split up once other improvements are merged if include_class_objects: for i, c in enumerate(completions): if c.type == 'class': completion_dict = _format_completion( c, False, resolve=resolve_eagerly, resolve_label_or_snippet=(i < max_to_resolve)) completion_dict['kind'] = lsp.CompletionItemKind.TypeParameter completion_dict['label'] += ' object' ready_completions.append(completion_dict) for completion_dict in ready_completions: completion_dict['data'] = {'doc_uri': document.uri} # most recently retrieved completion items, used for resolution document.shared_data['LAST_JEDI_COMPLETIONS'] = { # label is the only required property; here it is assumed to be unique completion['label']: (completion, data) for completion, data in zip(ready_completions, completions) } return ready_completions or None