def pyls_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().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 pyls_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: raise Exception('No support for renaming in Python 2/3.5 with Jedi. ' 'Consider using the rope_rename plugin instead') log.debug('Finished rename: %s', refactoring.get_diff()) return { 'documentChanges': [ { 'textDocument': { 'uri': uris.uri_with(document.uri, path=file_path), 'version': workspace.get_document(document.uri).version, }, 'edits': [ { 'range': { 'start': {'line': 0, 'character': 0}, 'end': { 'line': _num_lines(changed_file.get_new_code()), 'character': 0, }, }, 'newText': changed_file.get_new_code(), } ], } for file_path, changed_file in refactoring.get_changed_files().items() ], }
def pyls_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 pyls_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 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 pyls_definitions(config, document, position): settings = config.plugin_settings('jedi_definition') code_position = _utils.position_to_jedi_linecolumn(document, position) definitions = document.jedi_script().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=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 pyls_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 pyls_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()]