Example #1
0
def create_text_edit_from_diff(contents, new_contents):
    from difflib import SequenceMatcher
    from robocorp_ls_core.lsp import TextEdit
    from robocorp_ls_core.workspace import Document

    d = Document("", contents)

    s = SequenceMatcher(None, contents, new_contents)
    lst = []
    for tag, i1, i2, j1, j2 in s.get_opcodes():
        # print(
        #     "%7s a[%d:%d] (%s) b[%d:%d] (%s)"
        #     % (tag, i1, i2, contents[i1:i2], j1, j2, new_contents[j1:j2])
        # )

        if tag in ("replace", "insert"):
            lst.append(TextEdit(_create_range(d, i1, i2), new_contents[j1:j2]))

        elif tag == "delete":
            lst.append(TextEdit(_create_range(d, i1, i2), ""))

        elif tag == "equal":
            pass

        else:
            raise AssertionError("Unhandled: %s" % (tag, ))

    return lst
def _create_completion_item(
    label: str,
    new_text: str,
    selection: IDocumentSelection,
    col_start: int,
    col_end: int,
    documentation: str,
) -> dict:
    from robocorp_ls_core.lsp import (
        CompletionItem,
        InsertTextFormat,
        Position,
        Range,
        TextEdit,
    )
    from robocorp_ls_core.lsp import MarkupKind
    from robocorp_ls_core.lsp import CompletionItemKind

    text_edit = TextEdit(
        Range(
            start=Position(selection.line, col_start),
            end=Position(selection.line, col_end),
        ),
        new_text,
    )

    return CompletionItem(
        label,
        kind=CompletionItemKind.Field,
        text_edit=text_edit,
        insertText=label,
        documentation=documentation,
        insertTextFormat=InsertTextFormat.PlainText,
        documentationFormat=MarkupKind.PlainText,
    ).to_dict()
Example #3
0
def complete(completion_context):
    """
    :param CompletionContext completion_context:
    """
    from robocorp_ls_core.lsp import CompletionItemKind
    from robocorp_ls_core.lsp import CompletionItem
    from robocorp_ls_core.lsp import TextEdit
    from robocorp_ls_core.lsp import Range
    from robocorp_ls_core.lsp import Position
    from robotframework_ls.impl import text_utilities
    from robotframework_ls.impl.string_matcher import RobotStringMatcher
    from robotframework_ls.impl.robot_lsp_constants import (
        OPTION_ROBOT_COMPLETION_SECTION_HEADERS_FORM, )
    from robotframework_ls.impl.robot_lsp_constants import (
        OPTION_ROBOT_COMPLETION_SECTION_HEADERS_FORM_PLURAL, )

    selection = completion_context.sel  #: :type selection: DocumentSelection
    line_start = selection.line_to_column
    items = []

    if line_start:
        tu = text_utilities.TextUtilities(line_start)

        if tu.strip_leading_chars("*"):  # i.e.: the line must start with '*'
            tu.strip()

            words = completion_context.get_accepted_section_header_words()
            config = completion_context.config

            form = config.get_setting(
                OPTION_ROBOT_COMPLETION_SECTION_HEADERS_FORM,
                str,
                OPTION_ROBOT_COMPLETION_SECTION_HEADERS_FORM_PLURAL,
            )
            matcher = RobotStringMatcher(tu.text)
            for word in words:
                if form == "plural":
                    if not word.endswith("s"):
                        continue
                elif form == "singular":
                    if word.endswith("s"):
                        continue
                if matcher.accepts(word):
                    label = "*** %s ***" % (word, )
                    text_edit = TextEdit(
                        Range(
                            # i.e.: always replace from the start of the line.
                            start=Position(selection.line, 0),
                            end=Position(selection.line, selection.col),
                        ),
                        label,
                    )
                    # text_edit = None
                    items.append(
                        CompletionItem(label,
                                       kind=CompletionItemKind.Class,
                                       text_edit=text_edit,
                                       insertText=text_edit.newText))

    return [item.to_dict() for item in items]
Example #4
0
    def _create_completion_item_from_keyword(self,
                                             keyword_found: IKeywordFound,
                                             selection,
                                             token,
                                             col_delta=0):
        from robocorp_ls_core.lsp import (
            CompletionItem,
            InsertTextFormat,
            Position,
            Range,
            TextEdit,
        )
        from robocorp_ls_core.lsp import MarkupKind
        from robotframework_ls.impl.protocols import IKeywordArg

        label = keyword_found.keyword_name

        if keyword_found.library_name:
            # If we found the keyword in a library, convert its format depending on
            # the user configuration.
            label = self._convert_keyword_format(label)

        text = label
        arg: IKeywordArg
        for i, arg in enumerate(keyword_found.keyword_args):
            if arg.is_keyword_arg or arg.is_star_arg or arg.default_value is not None:
                continue

            arg_name = arg.arg_name
            arg_name = arg_name.replace("$",
                                        "\\$").replace("{",
                                                       "").replace("}", "")

            text += "    ${%s:%s}" % (i + 1, arg_name)

        text_edit = TextEdit(
            Range(
                start=Position(selection.line, token.col_offset + col_delta),
                end=Position(selection.line, token.end_col_offset),
            ),
            text,
        )

        # text_edit = None
        return CompletionItem(
            label,
            kind=keyword_found.completion_item_kind,
            text_edit=text_edit,
            insertText=text_edit.newText,
            documentation=keyword_found.docs,
            insertTextFormat=InsertTextFormat.Snippet,
            documentationFormat=(MarkupKind.Markdown
                                 if keyword_found.docs_format == "markdown"
                                 else MarkupKind.PlainText),
        ).to_dict()
    def _create_completion_item_from_keyword(self,
                                             keyword_found: IKeywordFound,
                                             selection,
                                             token,
                                             col_delta=0):
        from robocorp_ls_core.lsp import (
            CompletionItem,
            InsertTextFormat,
            Position,
            Range,
            TextEdit,
        )
        from robocorp_ls_core.lsp import MarkupKind
        from robotframework_ls.impl.robot_specbuilder import KeywordArg

        label = keyword_found.keyword_name
        text = label

        arg: KeywordArg
        for i, arg in enumerate(keyword_found.keyword_args):
            if arg.is_keyword_arg or arg.is_star_arg or arg.default_value is not None:
                continue

            arg_name = arg.arg_name
            arg_name = arg_name.replace("$",
                                        "\\$").replace("{",
                                                       "").replace("}", "")

            text += "    ${%s:%s}" % (i + 1, arg_name)

        text_edit = TextEdit(
            Range(
                start=Position(
                    selection.line, token.col_offset +
                    col_delta if token is not None else selection.col),
                end=Position(
                    selection.line, token.end_col_offset
                    if token is not None else selection.col),
            ),
            text,
        )

        # text_edit = None
        return CompletionItem(
            keyword_found.keyword_name,
            kind=keyword_found.completion_item_kind,
            text_edit=text_edit,
            insertText=text_edit.newText,
            documentation=keyword_found.docs,
            insertTextFormat=InsertTextFormat.Snippet,
            documentationFormat=(MarkupKind.Markdown
                                 if keyword_found.docs_format == "markdown"
                                 else MarkupKind.PlainText),
        )
Example #6
0
    def _create_completion_item_from_variable(self, variable_found, selection,
                                              token):
        """
        :param IVariableFound variable_found:
        :param selection:
        :param token:
        """
        from robocorp_ls_core.lsp import (
            CompletionItem,
            InsertTextFormat,
            Position,
            Range,
            TextEdit,
        )
        from robocorp_ls_core.lsp import MarkupKind
        from robocorp_ls_core.lsp import CompletionItemKind

        label = variable_found.variable_name
        text = label
        text = text.replace("$", "\\$")

        text_edit = TextEdit(
            Range(
                start=Position(selection.line, token.col_offset),
                end=Position(selection.line, token.end_col_offset),
            ),
            text,
        )

        # text_edit = None
        return CompletionItem(
            variable_found.variable_name,
            kind=CompletionItemKind.Variable,
            text_edit=text_edit,
            insertText=label,
            documentation=variable_found.variable_value,
            insertTextFormat=InsertTextFormat.Snippet,
            documentationFormat=MarkupKind.PlainText,
        ).to_dict()
def _create_completion_item_from_snippet(label, snippet, selection,
                                         line_to_col):
    """
    :param selection: DocumentSelection
    """
    from robocorp_ls_core.lsp import (
        CompletionItem,
        InsertTextFormat,
        Position,
        Range,
        TextEdit,
    )
    from robocorp_ls_core.lsp import MarkupKind
    from robocorp_ls_core.lsp import CompletionItemKind

    current_col = selection.col

    text = "\n".join(snippet["body"])

    text_edit = TextEdit(
        Range(
            start=Position(selection.line, current_col - len(line_to_col)),
            end=Position(selection.line, current_col),
        ),
        text,
    )

    return CompletionItem(
        label,
        kind=CompletionItemKind.Snippet,
        text_edit=text_edit,
        insertText=text_edit.newText,
        documentation=snippet["description"] +
        "\n".join(["", ""] + snippet["body"]),
        insertTextFormat=InsertTextFormat.Snippet,
        documentationFormat=MarkupKind.Markdown,
    ).to_dict()
def _create_completion_item(library_name,
                            selection,
                            token,
                            start_col_offset=None):
    from robocorp_ls_core.lsp import (
        CompletionItem,
        InsertTextFormat,
        Position,
        Range,
        TextEdit,
    )
    from robocorp_ls_core.lsp import MarkupKind
    from robocorp_ls_core.lsp import CompletionItemKind

    text_edit = TextEdit(
        Range(
            start=Position(
                selection.line,
                start_col_offset
                if start_col_offset is not None else token.col_offset,
            ),
            end=Position(selection.line, token.end_col_offset),
        ),
        library_name,
    )

    # text_edit = None
    return CompletionItem(
        library_name,
        kind=CompletionItemKind.Module,
        text_edit=text_edit,
        insertText=text_edit.newText,
        documentation="",
        insertTextFormat=InsertTextFormat.Snippet,
        documentationFormat=MarkupKind.PlainText,
    ).to_dict()
Example #9
0
    def create_completion_item(
        self,
        completion_context: ICompletionContext,
        keyword_name,
        selection,
        token,
        col_delta: int,
        memo: Set[str],
        lib_import: Optional[str] = None,
        resource_path: Optional[str] = None,
        data: Optional[Any] = None,
    ) -> None:
        """
        Note: the lib_import and resource_path are the strings to be added
        so that the given library/resource is loaded.
        
        i.e.: It's the name concatenated to the `Library    {lib_import}` or
        `Resource    {resource_path}`.
        """
        from robocorp_ls_core.lsp import (
            CompletionItem,
            InsertTextFormat,
            Position,
            Range,
            TextEdit,
        )
        from robocorp_ls_core.lsp import MarkupKind
        from robotframework_ls.impl.protocols import CompletionType

        label = f"{keyword_name} ({lib_import or resource_path})"
        if label in memo:
            return
        memo.add(label)

        prefix = ""
        import_line = -1
        if completion_context.type != CompletionType.shell:
            if lib_import is not None:
                import_line = self.import_location_info.get_library_import_line(
                )
            elif resource_path is not None:
                import_line = self.import_location_info.get_resource_import_line(
                )

        if import_line == -1:
            # There's no existing import, so, let's see if we have a *** Settings *** section.
            # If we don't we have to create the whole settings, otherwise, we'll add the statement
            # as the first thing in the existing *** Settings *** section.
            if completion_context.type == CompletionType.shell:
                import_line = 0
                prefix = "*** Settings ***\n"
            elif self.import_location_info.setting_section_node_info is None:
                import_line = 0
                prefix = "*** Settings ***\n"
            else:
                import_line = (self.import_location_info.
                               setting_section_node_info.node.end_lineno - 1)

        text = keyword_name

        if keyword_name in self.imported_keyword_name_to_keyword:
            check = lib_import or resource_path
            if check:
                basename = os.path.basename(check)
                if basename.endswith((".txt", ".py", ".robot", ".resource")):
                    basename = os.path.splitext(basename)[0]
                text = f"{basename}.{keyword_name}"

        text_edit = TextEdit(
            Range(
                start=Position(selection.line, token.col_offset + col_delta),
                end=Position(selection.line, token.end_col_offset),
            ),
            text,
        )

        additional_text_edits: List[TextEdit] = []

        if lib_import is not None:
            additional_text_edits.append(
                TextEdit(
                    Range(start=Position(import_line, 0),
                          end=Position(import_line, 0)),
                    f"{prefix}Library    {lib_import}\n",
                ))
        elif resource_path is not None:
            additional_text_edits.append(
                TextEdit(
                    Range(start=Position(import_line, 0),
                          end=Position(import_line, 0)),
                    f"{prefix}Resource    {resource_path}\n",
                ))

        # text_edit = None
        self.completion_items.append(
            CompletionItem(
                label,
                kind=CompletionItemKind.Reference,
                text_edit=text_edit,
                insertText=text_edit.newText,
                documentation="",
                insertTextFormat=InsertTextFormat.Snippet,
                documentationFormat=MarkupKind.PlainText,
                additionalTextEdits=additional_text_edits,
                data=data,
            ).to_dict())
Example #10
0
def complete(completion_context):
    """
    :param CompletionContext completion_context:
    """
    import itertools
    from robocorp_ls_core.lsp import (
        TextEdit,
        Range,
        Position,
        CompletionItem,
        CompletionItemKind,
    )

    section_name = completion_context.get_current_section_name()
    if section_name:
        from robotframework_ls.impl.string_matcher import RobotStringMatcher

        section = completion_context.get_section(section_name)
        if section is not None:
            selection = completion_context.sel  #: :type selection: DocumentSelection
            line_to_col = selection.line_to_column
            if line_to_col.endswith("  "):
                return []
            replace_to_col = selection.col
            if section.names_in_brackets:
                for i, c in enumerate(line_to_col):
                    if c.isspace():
                        continue
                    elif c == "[":
                        line_to_col = line_to_col[i + 1:]
                        replace_from_col = i
                        break
                    else:
                        return []
                else:
                    return []

                matcher = RobotStringMatcher(line_to_col)

            else:
                # i.e.: Needs to be the first char
                matcher = RobotStringMatcher(line_to_col)
                replace_from_col = 0

            ret = []
            for word in sorted(itertools.chain(section.names,
                                               section.aliases)):
                if matcher.accepts(word):
                    if section.names_in_brackets:
                        label = "[%s]" % (word, )
                        line = selection.current_line
                        replacement = "[%s]" % (word, )
                        if line[selection.col:].startswith("]"):
                            replace_to_col += 1

                    else:
                        label = word
                        replacement = word

                    text_edit = TextEdit(
                        Range(
                            start=Position(selection.line, replace_from_col),
                            end=Position(selection.line, replace_to_col),
                        ),
                        replacement,
                    )
                    # text_edit = None
                    ret.append(
                        CompletionItem(label,
                                       kind=CompletionItemKind.Keyword,
                                       text_edit=text_edit).to_dict())

            return ret

    return []