Example #1
0
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
Example #2
0
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
Example #3
0
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='}'),
                          ])
Example #4
0
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)
Example #5
0
    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
Example #6
0
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
Example #7
0
 def f(params: CompletionParams) -> CompletionList:
     return CompletionList(is_incomplete=False,
                           items=[
                               CompletionItem(
                                   label='test1',
                                   kind=CompletionItemKind.Method,
                                   preselect=True,
                               ),
                           ])
Example #8
0
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
Example #9
0
    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,
        )
Example #11
0
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,
    )
Example #12
0
    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
Example #13
0
    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
Example #14
0
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}",
    )
Example #15
0
    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
Example #16
0
    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)
Example #17
0
def project_to_completion_item(project: str) -> CompletionItem:
    return CompletionItem(label=project,
                          detail="intersphinx",
                          kind=CompletionItemKind.Module)
Example #18
0
    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