Example #1
0
    def _get_enclosing_entity(self, curloc):
        """
        Return the entity that encloses the current cursor
        """

        buf = GPS.EditorBuffer.get(curloc.file(), open=False)
        if buf is not None:
            edloc = buf.at(curloc.line(), curloc.column())
            (start_loc, end_loc) = self._get_enclosing_block(edloc)
        else:
            return None, None, None

        if not start_loc:
            return None, None, None
        name = edloc.subprogram_name()  # FIXME: not right.

        # [entity_bounds] returns the beginning of the col/line of the
        # definition/declaration. To be able to call GPS.Entity, we need to be
        # closer to the actual subprogram name. We get closer by skipping the
        # keyword that introduces the subprogram (procedure/function/entry etc.)

        id_loc = start_loc
        id_loc = id_loc.forward_word(1)
        try:
            return GPS.Entity(name,
                              id_loc.buffer().file(), id_loc.line(),
                              id_loc.column()), start_loc, end_loc
        except:
            return None, None, None
Example #2
0
def compute_subp_sloc(self):
    """Return the location of the declaration of the subprogram that we are
       currently in"""

    try:
        curloc = self.location()
        buf = GPS.EditorBuffer.get(curloc.file(), open=False)
        if buf is not None:
            edloc = buf.at(curloc.line(), curloc.column())
            start_loc = subprogram_start(edloc)
        else:
            return None
    except Exception:
        return None

    if not start_loc:
        return None
    name = edloc.subprogram_name()

    # [subprogram_start] returns the beginning of the line of the
    # definition/declaration. To be able to call GPS.Entity, we need to be
    # closer to the actual subprogram name. We get closer by skipping the
    # keyword that introduces the subprogram (procedure/function/entry etc.)

    start_loc = start_loc.forward_word(1)
    try:
        entity = GPS.Entity(name,
                            start_loc.buffer().file(), start_loc.line(),
                            start_loc.column())
    except Exception:
        return None
    if entity is not None:
        return entity.declaration()
    else:
        return None
Example #3
0
    def entity(self):
        """
        Returns a :class:`GPS.Entity` instance at the given location.

        If there is no entity that can be resolved at this location,
        returns None

        :rtype: :class:`GPS.Entity`
        """
        try:
            word, start_loc, end_loc = self.get_word()
            return GPS.Entity(word, self.buffer().file(),
                              start_loc.line(), start_loc.column())
        except Exception:
            return None
Example #4
0
def inside_generic_unit_context(self):
    """Return True if the context is inside a generic unit"""

    try:
        curloc = self.location()
        buf = GPS.EditorBuffer.get(curloc.file(), open=False)
        if buf is not None:
            start_loc = buf.at(1, 1)
            unit_loc, _ = start_loc.search('package|function|procedure',
                                           regexp=True,
                                           whole_word=True,
                                           dialog_on_failure=False)
            if unit_loc is None:
                return False
            # reach the start of the next word. We need to forward 2 words and
            # backward 1 in order to get the cursor at the start of the next
            # word instead of the end of the current word with forward 1.
            unit_loc = unit_loc.forward_word(2)
            unit_loc = unit_loc.forward_word(-1)
            tok, _, _ = unit_loc.get_word()
            if tok == 'body':
                # reach the start of the next word
                unit_loc = unit_loc.forward_word(2)
                unit_loc = unit_loc.forward_word(-1)
            name, _, _ = unit_loc.get_word()
            try:
                entity = GPS.Entity(name,
                                    unit_loc.buffer().file(), unit_loc.line(),
                                    unit_loc.column())
            except Exception:
                return False
            return entity.is_generic()
        else:
            return False
    except Exception:
        return False
Example #5
0
def mc_all_entity_references():
    def get_word_bounds(loc):
        loc_id_start = goto_word_start(loc)
        loc_id_end = goto_word_end(loc)
        # Check the case when we are at the end of a word
        if not id_pattern.match(loc.get_char()):
            ploc = loc.forward_char(-1)
            # If we are really not in an identifier, exit
            if not id_pattern.match(ploc.get_char()):
                return None, None
            else:
                loc_id_end = ploc

        return loc_id_start, loc_id_end

    editor = GPS.EditorBuffer.get()
    marks = []
    loc = editor.current_view().cursor()

    loc_id_start, loc_id_end = get_word_bounds(loc)
    if not loc_id_start or not loc_id_end:
        return

    identifier = editor.get_chars(loc_id_start, loc_id_end)

    try:
        entity = GPS.Entity(identifier, editor.file(), loc_id_start.line(),
                            loc_id_start.column())
    except GPS.Exception:
        return

    overlay = editor.create_overlay("entityrefs_overlay")
    overlay.set_property("background", mc_on_entity_color.get())

    def loc_tuple(loc):
        return loc.line(), loc.column()

    mark_start = loc_id_start.create_mark()
    mark_end = loc_id_end.forward_char().create_mark(left_gravity=False)

    def apply_overlay(editor, mark_start, mark_end, overlay):
        """
        Apply overlay overlay between mark_start and mark end
        if mark_start - mark_end >= 1 char
        """
        lstart = mark_start.location()
        lend = mark_end.location().forward_char(-1)
        if lend >= lstart:
            editor.apply_overlay(overlay, lstart, lend)

    # noinspection PyUnusedLocal
    def on_edit(hook_name, file_name):
        """
        Event handler on insert/delete. Mainly ensures that the current field
        in alias expansion is highlighted (via the aliases overlay)
        """
        if editor == GPS.EditorBuffer.get(file_name):
            editor.remove_overlay(overlay, editor.beginning_of_buffer(),
                                  editor.end_of_buffer())
            for mark_start, mark_end in marks:
                apply_overlay(editor, mark_start, mark_end, overlay)

    # noinspection PyUnusedLocal
    def on_move(hook_name, file_name, line, column):
        """
        Event handler on cursor move. Gets out of alias expansion mode
        when the cursor gets out of the zone.
        """
        start_loc = mark_start.location()
        end_loc = mark_end.location()
        cursor_loc = editor.current_view().cursor()
        if not (start_loc <= cursor_loc <= end_loc):
            exit_alias_expansion()

    def exit_alias_expansion():
        editor.remove_overlay(overlay, editor.beginning_of_buffer(),
                              editor.end_of_buffer())
        editor.remove_all_slave_cursors()
        GPS.Hook("character_added").remove(on_edit)
        GPS.Hook("location_changed").remove(on_move)

    marks.append((mark_start, mark_end))
    apply_overlay(editor, mark_start, mark_end, overlay)
    cursor_loc_t = loc_tuple(loc)
    word_offset = loc.column() - loc_id_start.column()

    locs = [
        editor.at(floc.line(), floc.column()) for floc in entity.references()
        if floc.file() == editor.file()
    ]

    locs_set = set()
    for s_loc in locs:
        loc = s_loc.forward_char(word_offset)
        loc_t = loc_tuple(loc)
        if not (loc_t in locs_set or loc_t == cursor_loc_t):
            locs_set.add(loc_t)
            s, e = get_word_bounds(loc)
            ms = s.create_mark()
            me = e.forward_char().create_mark(left_gravity=False)
            marks.append((ms, me))
            apply_overlay(editor, ms, me, overlay)
            editor.add_cursor(loc)

    GPS.Hook("character_added").add(on_edit)
    GPS.Hook("location_changed").add(on_move)
Example #6
0
def mc_all_entity_references():

    def get_word_bounds(loc):
        loc_id_start = goto_word_start(loc)
        loc_id_end = goto_word_end(loc)
        # Check the case when we are at the end of a word
        if not id_pattern.match(loc.get_char()):
            ploc = loc.forward_char(-1)
            # If we are really not in an identifier, exit
            if not id_pattern.match(ploc.get_char()):
                return None, None
            else:
                loc_id_end = ploc

        return loc_id_start, loc_id_end

    editor = GPS.EditorBuffer.get()
    marks = []
    loc = editor.current_view().cursor()

    loc_id_start, loc_id_end = get_word_bounds(loc)
    if not loc_id_start or not loc_id_end:
        return

    identifier = editor.get_chars(loc_id_start, loc_id_end)

    # Get the references for the current entity using the ALS
    # in priority. Fallback to the old xref engine when the
    # the request gets rejected.

    als = GPS.LanguageServer.get_by_language_name("Ada")

    params = {"textDocument": {"uri": editor.file().uri},
              "position": {"line": loc_id_start.line() - 1,
                           "character": loc_id_start.column() - 1},
              "context": {"includeDeclaration": True}}

    result = yield als.request_promise("textDocument/references", params)
    yield hook('language_server_response_processed')

    if result.is_valid:
        locs = [editor.at(lsp_loc['range']['end']['line'] + 1,
                          lsp_loc['range']['end']['character'])
                for lsp_loc in result.data
                if lsp_loc['uri'] == editor.file().uri]

    elif result.is_reject:
        try:
            entity = GPS.Entity(
                identifier, editor.file(),
                loc_id_start.line(), loc_id_start.column())
            locs = [editor.at(floc.line(), floc.column())
                    for floc in entity.references()
                    if floc.file() == editor.file()]
        except GPS.Exception:
            return
    else:
        return

    overlay = editor.create_overlay("entityrefs_overlay")
    overlay.set_property(
        "background", mc_on_entity_color.get()
    )

    def loc_tuple(loc):
        return loc.line(), loc.column()

    mark_start = loc_id_start.create_mark()
    mark_end = loc_id_end.forward_char().create_mark(left_gravity=False)

    def apply_overlay(editor, mark_start, mark_end, overlay):
        """
        Apply overlay overlay between mark_start and mark end
        if mark_start - mark_end >= 1 char
        """
        lstart = mark_start.location()
        lend = mark_end.location().forward_char(-1)
        if lend >= lstart:
            editor.apply_overlay(overlay, lstart, lend)

    # noinspection PyUnusedLocal
    def on_edit(hook_name, file_name):
        """
        Event handler on insert/delete. Mainly ensures that the current field
        in alias expansion is highlighted (via the aliases overlay)
        """
        if editor == GPS.EditorBuffer.get(file_name):
            editor.remove_overlay(
                overlay,
                editor.beginning_of_buffer(),
                editor.end_of_buffer()
            )
            for mark_start, mark_end in marks:
                apply_overlay(editor, mark_start, mark_end, overlay)

    # noinspection PyUnusedLocal
    def on_move(hook_name, file_name, line, column):
        """
        Event handler on cursor move. Gets out of alias expansion mode
        when the cursor gets out of the zone.
        """
        start_loc = mark_start.location()
        end_loc = mark_end.location()
        cursor_loc = editor.current_view().cursor()
        if not (start_loc <= cursor_loc <= end_loc):
            exit_alias_expansion()

    def exit_alias_expansion():
        editor.remove_overlay(
            overlay,
            editor.beginning_of_buffer(),
            editor.end_of_buffer()
        )
        editor.remove_all_slave_cursors()
        GPS.Hook("character_added").remove(on_edit)
        GPS.Hook("location_changed").remove(on_move)

    marks.append((mark_start, mark_end))
    apply_overlay(editor, mark_start, mark_end, overlay)
    cursor_loc_t = loc_tuple(loc)
    word_offset = loc.column() - loc_id_start.column()

    locs_set = set()
    for s_loc in locs:
        loc = s_loc.forward_char(word_offset)
        loc_t = loc_tuple(loc)
        if not (loc_t in locs_set or loc_t == cursor_loc_t):
            locs_set.add(loc_t)
            s, e = get_word_bounds(loc)
            ms = s.create_mark()
            me = e.forward_char().create_mark(left_gravity=False)
            marks.append((ms, me))
            apply_overlay(editor, ms, me, overlay)
            editor.add_cursor(loc)

    GPS.Hook("character_added").add(on_edit)
    GPS.Hook("location_changed").add(on_move)