Example #1
0
 def test_misbalanced(self):
     """Make sure we cleanly excise a tag pair from a pair of interleaved
     tags."""
     # A  _________          (2, 6)
     # B        ____________ (5, 9)
     a = Ref('a')
     b = Ref('b')
     tags = [(2, True, a), (5, True, b), (6, False, a), (9, False, b)]
     with catch_warnings():
         warnings.simplefilter('ignore')
         remove_overlapping_refs(tags)
     eq_(tags, [(2, True, a), (6, False, a)])
Example #2
0
    def _refs_from_view(self, menu_maker, views, tooltip=constantly(None)):
        """Return an iterable of (start, end, (menu, tooltip)), running
        ``menu_maker`` across each item that comes of applying ``view`` to
        ``self.condensed`` and adding "Jump to definition" where applicable.

        :arg menu_maker: A function that takes a tree and an item from
            ``view()`` and returns a ref menu
        :arg views: An iterable of functions that take self.condensed and
            return an iterable of things to call ``menu_maker()`` on
        :arg tooltip: A function that takes one of those things from the
            iterable and emits a value to be shown in the mouseover of the ref

        """
        for prop in chain.from_iterable(v(self.condensed) for v in views):
            if 'span' in prop:  # TODO: This used to be unconditional. Should we still try to do it sometime if span isn't in prop? Both cases in test_direct are examples of this. [Marcell says no.]
                definition = prop.get('defloc')
                # If we can look up the target of this ref and it's not
                # outside the source tree (which results in an absolute path
                # starting with "/")...
                if definition and not definition[0].startswith('/'):
                    menu = definition_menu(self.tree,
                                           path=definition[0],
                                           row=definition[1].row)
                else:
                    menu = []

                menu.extend(menu_maker(self.tree, prop))
                start, end = prop['span']

                yield (self.char_offset(start.row, start.col),
                       self.char_offset(end.row, end.col),
                       Ref(menu, hover=tooltip(prop), qualname=prop.get('qualname')))
Example #3
0
def function_ref_menu(tree, datum, tree_config):
    fn_def = None
    fn_decl = None
    if 'refid' in datum and datum['refid'] and datum[
            'refid'] in tree.data.functions:
        fn_def = tree.data.functions[datum['refid']]
    elif 'refid' in datum and datum['refid'] and datum[
            'refid'] in tree.data.types:
        # enum variant ctors
        fn_def = tree.data.types[datum['refid']]
    if 'declid' in datum and datum['declid'] and datum[
            'declid'] in tree.data.functions:
        fn_decl = tree.data.functions[datum['declid']]

    menu = []
    name = None
    if fn_def:
        menu = function_menu_generic(tree, fn_def, tree_config)
        if fn_decl and (fn_def['file_name'] != fn_decl['file_name']
                        or fn_def['file_line'] != fn_decl['file_line']):
            add_jump_definition(tree, tree_config, menu, fn_decl,
                                "Jump to trait method")
        add_jump_definition(tree, tree_config, menu, fn_def)
        name = fn_def['qualname']
    elif fn_decl:
        menu = function_menu_generic(tree, fn_decl, tree_config)
        add_jump_definition(tree, tree_config, menu, fn_decl,
                            "Jump to trait method")
        name = fn_decl['qualname']

    # FIXME(#12) should have type, not name for title
    return Ref(menu, hover=name)
Example #4
0
def function_menu(tree, datum, tree_config):
    menu = function_menu_generic(tree, datum, tree_config)

    if 'declid' in datum and datum['declid'] in tree.data.functions:
        # it's an implementation, find the decl
        decl = tree.data.functions[datum['declid']]
        add_jump_definition(tree, tree_config, menu, decl,
                            "Jump to trait method")
    else:
        # it's a decl, find implementations
        impls = tree.data.index('functions', 'declid')
        count = len(impls[datum['id']]) if datum['id'] in impls else 0
        if count > 0:
            menu.append({
                'html':
                "Find implementations (%d)" % count,
                'title':
                "Find implementations of this trait method",
                'href':
                search_url(tree_config,
                           "+fn-impls:%s" % quote(datum['qualname'])),
                'icon':
                'method'
            })

    return Ref(menu)
Example #5
0
def variable_menu(tree, datum, tree_config):
    menu = variable_menu_generic(tree, datum, tree_config)
    typ = None
    if 'type' in datum:
        typ = datum['type']
    else:
        print "no type for variable", datum['qualname']
    return Ref(menu, hover=truncate_value("", typ))
Example #6
0
def type_ref_menu(tree, datum, tree_config):
    if datum['refid'] and datum['refid'] in tree.data.types:
        typ = tree.data.types[datum['refid']]
        menu = type_menu_generic(tree, typ, tree_config)
        add_jump_definition(tree, tree_config, menu, typ)
        title = None
        if 'value' in typ:
            title = typ['value']
        else:
            print "no value for", typ['kind'], typ['qualname']
        return Ref(menu, hover=truncate_value("", title))

    return None
Example #7
0
 def refs(self):
     for m in self.plugin_config.regex.finditer(self.contents):
         bug = m.group(1)
         yield m.start(0), m.end(0), Ref([{
             'html':
             cgi.escape("Bug %s" % bug),
             'title':
             "Find this bug in %s" % self.plugin_config.name,
             'href':
             self.plugin_config.url % bug,
             'icon':
             'buglink'
         }])
Example #8
0
    def test_horrors(self):
        """Try a fairly horrific scenario::

            A _______________            (0, 7)
            B     _________              (2, 6)
            C           ____________     (5, 9)
            D                    _______ (8, 11)
            E                         __ (10, 11)
              0   2     5 6 7    8 9

        A contains B. B closes while C's still going on. D and E end at the
        same time. There's even a Region in there.

        """
        a, b, c, d, e = Ref('a'), Region('b'), Ref('c'), Ref('d'), Ref('e')
        tags = [(0, True, a), (2, True, b), (5, True, c), (6, False, b),
                (7, False, a), (8, True, d), (9, False, c), (10, True, e),
                (11, False, e), (11, False, d)]

        eq_(
            spaced_tags(balanced_tags(tags)), '<L>\n'
            '<a>\n'
            '  <b>\n'
            '     <c>\n'
            '      </c>\n'
            '      </b>\n'
            '      <c>\n'
            '       </c>\n'
            '       </a>\n'
            '       <c>\n'
            '        <d>\n'
            '         </d>\n'
            '         </c>\n'
            '         <d>\n'
            '          <e>\n'
            '           </e>\n'
            '           </d>\n'
            '           </L>')
Example #9
0
    def test_overlapping_regions(self):
        """Regions (as opposed to refs) are allowed to overlap and shouldn't be
        disturbed::

            A           _________          (2, 6)
            B (region)        ____________ (5, 9)

        """
        a = Ref('a')
        b = Region('b')
        tags = [(2, True, a), (5, True, b), (6, False, a), (9, False, b)]
        original_tags = tags[:]
        remove_overlapping_refs(tags)
        eq_(tags, original_tags)
Example #10
0
def unknown_ref_menu(tree, datum, tree_config):
    if datum['refid'] and datum['refid'] in tree.data.unknowns:
        unknown = tree.data.unknowns[datum['refid']]
        menu = []
        add_find_references(tree_config, menu, str(datum['refid']),
                            "extern-ref", "item")
        if unknown['crate'] in tree.locations:
            urls = tree.locations[unknown['crate']]
            std_lib_links(tree_config, menu, urls)
        return Ref(menu)

    print "unknown unknown!"

    return None
Example #11
0
def variable_ref_menu(tree, datum, tree_config):
    if datum['refid'] and datum['refid'] in tree.data.variables:
        var = tree.data.variables[datum['refid']]
        menu = variable_menu_generic(tree, var, tree_config)
        add_jump_definition(tree, tree_config, menu, var)
        typ = None
        if 'type' in var:
            typ = var['type']
        else:
            print "no type for variable ref", var['qualname']
        return Ref(menu, hover=truncate_value(typ, var['value']))

    # TODO what is the culprit here?
    #print "variable ref missing def"
    return None
Example #12
0
 def test_split_anchor_avoidance(self):
     """Don't split anchor tags when we can avoid it."""
     eq_(
         text_to_html_lines('this that', [(0, 9, Ref({}))],
                            [(0, 4, Region('k'))]),
         [u'<a data-menu="{}"><span class="k">this</span> that</a>'])
Example #13
0
def module_alias_menu(tree, datum, tree_config):
    # Add straightforward aliases to modules
    if datum['refid'] and datum['refid'] in tree.data.modules:
        mod = tree.data.modules[datum['refid']]
        if mod['name'] != datum['name']:
            # Add module aliases. 'use' without an explicit alias and without any wildcards,
            # etc. introduces an implicit alias for the module. E.g, |use a::b::c|
            # introduces an alias |c|. In these cases, we make the alias transparent -
            # there is no link for the alias, but we add the alias menu stuff to the
            # module ref.
            menu = []
            add_find_references(tree_config, menu, datum['qualname'],
                                "module-alias-ref", "alias")
            add_jump_definition_to_line(tree, tree_config, menu,
                                        mod['def_file'], 1,
                                        "Jump to module defintion")
            return Ref(menu)

    # 'module' aliases to types
    if datum['refid'] and datum['refid'] in tree.data.types:
        typ = tree.data.types[datum['refid']]
        if typ['name'] != datum['name']:
            menu = []
            add_find_references(tree_config, menu, datum['qualname'],
                                "type-ref", "alias")
            add_jump_definition(tree, tree_config, menu, typ,
                                "Jump to type declaration")
            return Ref(menu)

    # 'module' aliases to variables
    if datum['refid'] and datum['refid'] in tree.data.variables:
        var = tree.data.variables[datum['refid']]
        if var['name'] != datum['name']:
            menu = []
            add_find_references(tree_config, menu, datum['qualname'],
                                "var-ref", "alias")
            add_jump_definition(tree, tree_config, menu, var,
                                "Jump to variable declaration")
            return Ref(menu)

    # 'module' aliases to functions
    if datum['refid'] and datum['refid'] in tree.data.functions:
        fn = tree.data.functions[datum['refid']]
        if fn['name'] != datum['name']:
            menu = []
            add_find_references(tree_config, menu, datum['qualname'],
                                "function-ref", "alias")
            add_jump_definition(tree, tree_config, menu, fn,
                                "Jump to function declaration")
            return Ref(menu)

    # extern crates to known local crates
    if 'location' in datum and datum['location'] and datum[
            'location'] in tree.crates_by_name:
        crate = tree.crates_by_name[datum['location']]
        menu = []
        add_find_references(tree_config, menu, datum['qualname'],
                            "module-alias-ref", "alias")
        add_jump_definition_to_line(tree, tree_config, menu,
                                    crate['file_name'], 1, "Jump to crate")
        return Ref(menu)

    # extern crates to standard library crates
    if 'location' in datum and datum['location'] and datum[
            'location'] in tree.locations:
        urls = tree.locations[datum['location']]
        menu = []
        add_find_references(tree_config, menu, datum['qualname'],
                            "module-alias-ref", "alias")
        std_lib_links(tree_config, menu, urls)
        return Ref(menu)

    # other references to standard library items
    if datum['refid'] in tree.data.unknowns:
        # FIXME We could probably do better and link to the precise type or static in docs etc., rather than just the crate
        urls = tree.locations[tree.data.unknowns[datum['refid']]['crate']]
        menu = []
        add_find_references(tree_config, menu, datum['qualname'],
                            "module-alias-ref", "alias")
        std_lib_links(tree_config, menu, urls)
        return Ref(menu)

    # extern mods to unknown local crates
    menu = []
    add_find_references(tree_config, menu, datum['qualname'],
                        "module-alias-ref", "alias")
    return Ref(menu)
Example #14
0
def module_ref_menu(tree, datum, tree_config):
    # Add straightforward aliases to modules
    if datum['refid']:
        mod = None
        if datum['refid'] in tree.data.modules:
            mod = tree.data.modules[datum['refid']]
        elif datum['refid'] in tree.data.extern_crate_mods:
            mod = tree.data.extern_crate_mods[datum['refid']]

        if mod:
            menu = module_menu_generic(tree, mod, tree_config)
            if datum['aliasid'] and datum[
                    'aliasid'] in tree.data.module_aliases:
                alias = tree.data.module_aliases[datum['aliasid']]
                if 'location' in alias and alias[
                        'location'] in tree.crates_by_name:
                    # Add references to extern mods via aliases (known local crates)
                    crate = tree.crates_by_name[alias['location']]
                    menu = []
                    add_find_references(tree_config, menu, alias['qualname'],
                                        "module-alias-ref", "alias")
                    add_jump_definition_to_line(tree, tree_config, menu,
                                                crate['file_name'], 1,
                                                "Jump to crate")
                elif 'location' in alias and alias[
                        'location'] in tree.locations:
                    # Add references to extern mods via aliases (standard library crates)
                    urls = tree.locations[alias['location']]
                    menu = []
                    add_find_references(tree_config, menu, alias['qualname'],
                                        "module-alias-ref", "alias")
                    std_lib_links(tree_config, menu, urls)
                elif 'location' in alias:
                    # Add references to extern mods via aliases (unknown local crates)
                    menu = []
                    add_find_references(tree_config, menu, alias['qualname'],
                                        "module-alias-ref", "alias")
                elif 'file_name' in mod:
                    add_jump_definition(tree, tree_config, menu, mod,
                                        "Jump to module defintion")
                if 'file_name' in mod:
                    add_jump_definition(tree, tree_config, menu, mod,
                                        "Jump to alias defintion")
            else:
                if 'file_name' in mod and 'def_file' in mod and mod[
                        'def_file'] == mod['file_name']:
                    add_jump_definition(tree, tree_config, menu, mod)
                else:
                    add_jump_definition_to_line(tree, tree_config, menu,
                                                mod['def_file'], 1,
                                                "Jump to module defintion")
                    add_jump_definition(tree, tree_config, menu, mod,
                                        "Jump to module declaration")
            return Ref(menu)

        # types masquerading as modules
        if datum['refid'] in tree.data.types:
            typ = tree.data.types[datum['refid']]
            menu = type_menu_generic(tree, typ, tree_config)
            add_jump_definition(tree, tree_config, menu, typ)
            title = None
            if 'value' in typ:
                title = typ['value']
            else:
                print "no value for", typ['kind'], typ['qualname']
            return Ref(menu, hover=truncate_value("", title))

    return None
Example #15
0
def module_menu(tree, datum, tree_config):
    menu = module_menu_generic(tree, datum, tree_config)
    if datum['def_file'] != datum['file_name']:
        add_jump_definition_to_line(tree, tree_config, menu, datum['def_file'],
                                    1, "Jump to module defintion")
    return Ref(menu)
Example #16
0
 def yield_ref(self, start, end, menus):
     self.refs.append((start, end, Ref(menus)))
Example #17
0
def type_menu(tree, datum, tree_config):
    return Ref(type_menu_generic(tree, datum, tree_config))
Example #18
0
 def yield_ref(self, start, end, menu):
     self.refs.append((
         self.file_to_index.char_offset(*start),
         self.file_to_index.char_offset(*end),
         Ref(menu),
     ))
Example #19
0
 def test_split_anchor_across_lines(self):
     """Support unavoidable splits of an anchor across lines."""
     # We must preserve the \n in the output so that text within refs/regions keeps line breaks.
     eq_(text_to_html_lines('this\nthat', refs=[(0, 9, Ref({}))]),
         [u'<a data-menu="{}">this\n</a>', u'<a data-menu="{}">that</a>'])