def lsp_completion_item_resolve( item: CompletionItem, markup_kind: MarkupKind, ) -> CompletionItem: """Resolve completion item using cached jedi completion data.""" completion = _MOST_RECENT_COMPLETIONS[item.label] item.detail = next(get_full_signatures(completion), completion.name) docstring = convert_docstring(completion.docstring(raw=True), markup_kind) item.documentation = MarkupContent(kind=markup_kind, value=docstring) return item
def lsp_completion_item_resolve( item: CompletionItem, markup_kind: MarkupKind, ) -> CompletionItem: """Resolve completion item using cached jedi completion data.""" completion = _MOST_RECENT_COMPLETIONS[item.label] item.detail = completion.description docstring = convert_docstring(completion.docstring(), markup_kind) item.documentation = MarkupContent(kind=markup_kind, value=docstring) return item
def completions(params: Optional[CompletionParams] = None) -> CompletionList: """Returns completion items.""" return CompletionList(is_incomplete=False, items=[ CompletionItem(label='"'), CompletionItem(label='['), CompletionItem(label=']'), CompletionItem(label='{'), CompletionItem(label='}'), ])
def object_to_completion_item(object_: tuple) -> CompletionItem: # _, _, _, docname, anchor, priority name, display_name, type_, _, _, _ = object_ insert_text = name key = type_.split(":")[1] if ":" in type_ else type_ kind = TARGET_KINDS.get(key, CompletionItemKind.Reference) # ensure :doc: targets are inserted as an absolute path - that way the reference # will always work regardless of the file's location. if type_ == "doc": insert_text = f"/{name}" # :option: targets need to be inserted as `<progname> <option>` in order to resolve # correctly. However, this only seems to be the case "locally" as # `<progname>.<option>` seems to resolve fine when using intersphinx... if type_ == "cmdoption": name = " ".join(name.split(".")) display_name = name insert_text = name return CompletionItem(label=name, kind=kind, detail=str(display_name), insert_text=insert_text)
def completion_resolve_option(self, item: CompletionItem) -> CompletionItem: # We need the detail field set to the implementation's fully qualified name. if not item.detail or not item.data: return item directive, option = item.detail.split(":") name = typing.cast(Dict, item.data).get("for_directive", "") documentation = self.get_documentation(name, directive) if not documentation: return item description = documentation.get("options", {}).get(option, None) if not description: return item source = documentation.get("source", "") license = documentation.get("license", "") if source: description += f"\n\n[Source]({source})" if license: description += f"\n\n[License]({license})" kind = MarkupKind.PlainText if documentation.get("is_markdown", False): kind = MarkupKind.Markdown item.documentation = MarkupContent(kind=kind, value=description) return item
async def lsp_completion( ls: LanguageServer, params: CompletionParams, ) -> Optional[List[CompletionItem]]: await asyncio.sleep(DEBOUNCE_DELAY) items: List[CompletionItem] = [] ast = await buildout.parse(ls, params.text_document.uri, True) for line in ast.lines: pos = params.position (var_name, var_type, value) = line ci = CompletionItem(label=var_name, text_edit=TextEdit( range=Range( start=Position(line=pos.line, character=pos.character), end=Position(line=pos.line, character=pos.character + len(var_name))), new_text=var_name, ), kind=CompletionItemKind.Variable, documentation=MarkupContent( kind=MarkupKind.Markdown, value=f"{var_name} : {var_type} = {value}", )) items.append(ci) return items
def f(params: CompletionParams) -> CompletionList: return CompletionList(is_incomplete=False, items=[ CompletionItem( label='test1', kind=CompletionItemKind.Method, preselect=True, ), ])
def lsp_completion_item( completion: Completion, char_before_cursor: str, enable_snippets: bool, resolve_eagerly: bool, markup_kind: MarkupKind, ) -> CompletionItem: """Using a Jedi completion, obtain a jedi completion item.""" completion_name = completion.name name_clean = clean_completion_name(completion_name, char_before_cursor) lsp_type = get_lsp_completion_type(completion.type) completion_item = CompletionItem( label=completion_name, filter_text=completion_name, kind=lsp_type, sort_text=complete_sort_name(completion), insert_text=name_clean, insert_text_format=InsertTextFormat.PlainText, ) _MOST_RECENT_COMPLETIONS[completion_name] = completion if resolve_eagerly: completion_item = lsp_completion_item_resolve( completion_item, markup_kind=markup_kind ) if not enable_snippets: return completion_item if lsp_type not in _LSP_TYPE_FOR_SNIPPET: return completion_item signatures = completion.get_signatures() if not signatures: return completion_item try: snippet_signature = get_snippet_signature(signatures[0]) except Exception: # pylint: disable=broad-except return completion_item new_text = completion_name + snippet_signature completion_item.insert_text = new_text completion_item.insert_text_format = InsertTextFormat.Snippet return completion_item
def _index_methods(self): self.items = [] for name, meth in M.__dict__.items(): if not isinstance(meth, str) or not name.isupper(): continue item = CompletionItem(label=meth, kind=CompletionItemKind.Constant) self.items.append(item)
def generate_list( bibliographies: Biblio, search_key: str ) -> Generator[CompletionItem, None, None]: """Given a bibliography and a search string, find all completion items that might match the entry.""" key_regex = re.compile("^{}.*".format(search_key)) for key in list(filter(key_regex.match, bibliographies.keys())): entry = bibliographies[key] yield CompletionItem( label="{}".format(key), kind=CompletionItemKind.Text, documentation=info(entry), insert_text=key, )
def path_to_completion_item(context: CompletionContext, path: pathlib.Path) -> CompletionItem: """Create the ``CompletionItem`` for the given path. In the case where there are multiple filepath components, this function needs to provide an appropriate ``TextEdit`` so that the most recent entry in the path can be easily edited - without clobbering the existing path. Also bear in mind that this function must play nice with both role target and directive argument completions. """ new_text = f"{path.name}" kind = CompletionItemKind.Folder if path.is_dir( ) else CompletionItemKind.File # If we can't find the '/' we may as well not bother with a `TextEdit` and let the # `Roles` feature provide the default handling. start = _find_start_char(context) if start == -1: insert_text = new_text filter_text = None text_edit = None else: start += 1 _, end = context.match.span() prefix = context.match.group(0)[start:] insert_text = None filter_text = ( f"{prefix}{new_text}" # Needed so VSCode will actually show the results. ) text_edit = TextEdit( range=Range( start=Position(line=context.position.line, character=start), end=Position(line=context.position.line, character=end), ), new_text=new_text, ) return CompletionItem( label=new_text, kind=kind, insert_text=insert_text, filter_text=filter_text, text_edit=text_edit, )
def complete_options(self, context: CompletionContext) -> List[CompletionItem]: surrounding_directive = self.get_surrounding_directive(context) if not surrounding_directive: return [] domain = "" if surrounding_directive.group("domain"): domain = f'{surrounding_directive.group("domain")}:' name = f"{domain}{surrounding_directive.group('name')}" directive = self.rst.get_directives().get(name, None) if not directive: return [] items = [] match = context.match groups = match.groupdict() option = groups["option"] start = match.span()[0] + match.group(0).find(option) end = start + len(option) range_ = Range( start=Position(line=context.position.line, character=start), end=Position(line=context.position.line, character=end), ) for option in self.rst.get_directive_options(name): insert_text = f":{option}:" items.append( CompletionItem( label=option, detail= f"{directive.__module__}.{directive.__name__}:{option}", kind=CompletionItemKind.Field, filter_text=insert_text, text_edit=TextEdit(range=range_, new_text=insert_text), data={ "completion_type": "directive_option", "for_directive": name }, )) return items
def completion_resolve_role(self, item: CompletionItem) -> CompletionItem: # We need the detail field set to the role implementation's fully qualified name if not item.detail: return item documentation = self.get_documentation(item.label, item.detail) if not documentation: return item description = documentation.get("description", "") is_markdown = documentation.get("is_markdown", False) kind = MarkupKind.Markdown if is_markdown else MarkupKind.PlainText item.documentation = MarkupContent(kind=kind, value=description) return item
def intersphinx_target_to_completion_item(project: str, label: str, target: tuple, type_: str) -> CompletionItem: # _. _. url, _ source, version, _, display = target display_name = label if display == "-" else display completion_kind = ":".join(type_.split(":")[1:]) if ":" in type_ else type_ if version: version = f" v{version}" return CompletionItem( label=label, detail=f"{display_name} - {source}{version}", kind=TARGET_KINDS.get(completion_kind, CompletionItemKind.Reference), insert_text=f"{project}:{label}", )
def complete_roles(self, context: CompletionContext) -> List[CompletionItem]: match = context.match groups = match.groupdict() domain = groups["domain"] or "" items = [] # Insert text starting from the starting ':' character of the role. start = match.span()[0] + match.group(0).find(":") end = start + len(groups["role"]) range_ = Range( start=Position(line=context.position.line, character=start), end=Position(line=context.position.line, character=end), ) for name, role in self.rst.get_roles().items(): if not name.startswith(domain): continue try: dotted_name = f"{role.__module__}.{role.__name__}" except AttributeError: dotted_name = f"{role.__module__}.{role.__class__.__name__}" insert_text = f":{name}:" item = CompletionItem( label=name, kind=CompletionItemKind.Function, detail=f"{dotted_name}", filter_text=insert_text, text_edit=TextEdit(range=range_, new_text=insert_text), data={"completion_type": "role"}, ) items.append(item) return items
def _index_lexers(self): self._lexers = [] for (name, labels, files, mimes) in get_all_lexers(): for label in labels: documentation = f"""\ ### {name} Filenames: {', '.join(files)} MIME Types: {', '.join(mimes)} """ item = CompletionItem( label=label, kind=CompletionItemKind.Constant, documentation=MarkupContent( kind=MarkupKind.Markdown, value=textwrap.dedent(documentation)), ) self._lexers.append(item)
def project_to_completion_item(project: str) -> CompletionItem: return CompletionItem(label=project, detail="intersphinx", kind=CompletionItemKind.Module)
def complete_directives( self, context: CompletionContext) -> List[CompletionItem]: self.logger.debug("Completing directives") items = [] match = context.match groups = match.groupdict() domain = "" if groups["domain"]: domain = f'{groups["domain"]}:' # Calculate the range of text the CompletionItems should edit. # If there is an existing argument to the directive, we should leave it untouched # otherwise, edit the whole line to insert any required arguments. start = match.span()[0] + match.group(0).find(".") include_argument = context.snippet_support end = match.span()[1] if groups["argument"]: include_argument = False end = match.span()[0] + match.group(0).find("::") + 2 range_ = Range( start=Position(line=context.position.line, character=start), end=Position(line=context.position.line, character=end), ) for name, directive in self.rst.get_directives().items(): if not name.startswith(domain): continue # TODO: Give better names to arguments based on what they represent. if include_argument: insert_format = InsertTextFormat.Snippet args = " " + " ".join( "${{{0}:arg{0}}}".format(i) for i in range(1, directive.required_arguments + 1)) else: args = "" insert_format = InsertTextFormat.PlainText try: dotted_name = f"{directive.__module__}.{directive.__name__}" except AttributeError: dotted_name = f"{directive.__module__}.{directive.__class__.__name__}" insert_text = f".. {name}::{args}" items.append( CompletionItem( label=name, kind=CompletionItemKind.Class, detail=dotted_name, filter_text=insert_text, text_edit=TextEdit(range=range_, new_text=insert_text), insert_text_format=insert_format, data={"completion_type": "directive"}, )) return items