<commit_before>from functools import partial

import os
from warnings import warn
from flask import url_for

from dxr.utils import BROWSE, search_url


def quote(qualname):
    """ Wrap qualname in quotes if it contains spaces """
    if ' ' in qualname:
        qualname = '"' + qualname + '"'
    return qualname


def truncate_value(value, typ=""):
    result = ""
    if value:
        eol = value.find('\n')
        if eol < 0:
            result = value.strip()
        else:
            value = value[0:eol]
            value = value.strip()
            result = value + " ..."

    if typ:
        if result:
            result = typ + ": " + result
        else:
            result = typ

    if not result:
        return None

    return result


def find_references_menu(tree_config, qualname, filter_name, kind):
    """A sort of compound menu that handles finding various sorts of
    references

    Should be broken into several.

    """
    return {'html':   "Find references",
            'title':  "Find references to this " + kind,
            'href':   search_url(tree_config, "+" + filter_name + ":%s" % quote(qualname)),
            'icon':   'reference'}


def std_lib_links((doc_url, src_url, dxr_url), extra_text=""):
    # TODO: Stop storing entire URLs in ES.
    def get_domain(url):
        start = url.find('//') + 2
        return url[start:url.find('/', start)]

    def add_link_to_menu(url, html, title):
        if url:
            menu.append({'html': html,
                         'title': title,
                         'href': url,
                         'icon': 'jump'})

    menu = []
    add_link_to_menu(doc_url,
                     'Go to docs' + extra_text,
                     'Go to documentation for this crate on ' + get_domain(doc_url))
    add_link_to_menu(src_url,
                     'Go to source' + extra_text,
                     'Go to source code for this crate on ' + get_domain(doc_url))
    add_link_to_menu(dxr_url,
                     'Go to DXR index' + extra_text,
                     'Go to DXR index of this crate on ' + get_domain(doc_url))
    return menu


def call_menu(qualname, tree):
    return [{'html': "Find callers",
             'title': "Find functions that call this function",
             'href': search_url(tree, "+callers:%s" % quote(qualname)),
             'icon': 'method'},
            {'html': "Find callees",  # TODO: Probably useless. Remove.
             'title': "Find functions that are called by this function",
             'href': search_url(tree, "+called-by:%s" % quote(qualname)),
             'icon': 'method'}]


def function_menu_generic(datum, tree_config):
    """Return menu makers shared by function def/decls and function refs."""
    return [call_menu(datum['qualname'], tree_config),
            find_references_menu(tree_config, datum['qualname'], "function-ref", "function")]


def jump_to_target_menu(target_name, tree_config, path, row):
    """Make a menu that jumps straight to a specific line of a file."""

    return {'html': 'Jump to %s' % target_name,
            'title': "Jump to %s in '%s'" % (target_name,
                                             os.path.basename(path)),
            'href': url_for(BROWSE, tree=tree_config.name, path=path, _anchor=row),
            'icon': 'jump'}

def jump_to_target_from_decl(menu_maker, tree, decl):
    """Return an jump menu from a declaration mapping.

    If the incoming declaration doesn't warrant the creation of a menu,
    return None.
    """

    path = decl['file_name']
    if path:
        return menu_maker(tree, path, decl['file_line'])
    else:
        warn("Can't add jump to empty path.")  # Can this happen?

jump_to_trait_method_menu = partial(jump_to_target_menu, target_name='trait method')
jump_to_definition_menu = partial(jump_to_target_menu, target_name='definition')
jump_to_module_definition_menu = partial(jump_to_target_menu, target_name='module definition')
jump_to_module_declaration_menu = partial(jump_to_target_menu, target_name='module declaration')
jump_to_alias_definition_menu = partial(jump_to_target_menu, target_name='alias definition')
jump_to_crate_menu = partial(jump_to_target_menu, target_name='crate')
jump_to_type_declaration_menu = partial(jump_to_target_menu, target_name='type declaration')
jump_to_variable_declaration_menu = partial(jump_to_target_menu, target_name='variable declaration')
jump_to_function_declaration_menu = partial(jump_to_target_menu, target_name='function declaration')

def trait_impl_menu(tree_config, qualname, count):
    return {'html': "Find implementations (%d)" % count,
            'title': "Find implementations of this trait method",
            'href': search_url(tree_config, "+fn-impls:%s" % quote(qualname)),
            'icon': 'method'}


def variable_menu_generic(datum, tree_config):
    yield find_references_menu(tree_config, datum['qualname'], "var-ref", "variable")


def type_menu(tree_config, kind, qualname):
    if kind == 'trait':
        yield {'html': "Find sub-traits",
               'title': "Find sub-traits of this trait",
               'href': search_url(tree_config, "+derived:%s" % quote(qualname)),
               'icon': 'type'}
        yield {'html': "Find super-traits",
               'title': "Find super-traits of this trait",
               'href': search_url(tree_config, "+bases:%s" % quote(qualname)),
               'icon': 'type'}
    if kind == 'struct' or kind == 'enum' or kind == 'trait':
        yield {'html': "Find impls",
               'title': "Find impls which involve this " + kind,
               'href': search_url(tree_config, "+impl:%s" % quote(qualname)),
               'icon': 'reference'}


def type_menu_generic(datum, tree_config):
    kind = datum['kind']
    qualname = datum['qualname']
    menu = [type_menu(tree_config, kind, qualname),
            find_references_menu(tree_config, qualname, "type-ref", kind)]
    return menu


def use_items_menu(tree_config, qualname):
    return {'html': "Find use items",
            'title': "Find instances of this module in 'use' items",
            'href': search_url(tree_config, "+module-use:%s" % quote(qualname)),
            'icon': 'reference'}


def module_menu_generic(tree, datum, tree_config):
    return [use_items_menu(tree_config, datum['qualname']),
            find_references_menu(tree_config, datum['qualname'], "module-ref", "module")]

<commit_msg>Be more careful about which are iterable.<commit_after>import os
from functools import partial
from warnings import warn

from flask import url_for

from dxr.utils import BROWSE, search_url


def quote(qualname):
    """ Wrap qualname in quotes if it contains spaces """
    if ' ' in qualname:
        qualname = '"' + qualname + '"'
    return qualname


def truncate_value(value, typ=""):
    result = ""
    if value:
        eol = value.find('\n')
        if eol < 0:
            result = value.strip()
        else:
            value = value[0:eol]
            value = value.strip()
            result = value + " ..."

    if typ:
        if result:
            result = typ + ": " + result
        else:
            result = typ

    if not result:
        return None

    return result


def find_references_menu(tree_config, qualname, filter_name, kind):
    """A sort of compound menu that handles finding various sorts of
    references

    Should be broken into several.

    """
    return {'html':   "Find references",
            'title':  "Find references to this " + kind,
            'href':   search_url(tree_config, "+" + filter_name + ":%s" % quote(qualname)),
            'icon':   'reference'}


def std_lib_links((doc_url, src_url, dxr_url), extra_text=""):
    # TODO: Stop storing entire URLs in ES.
    def get_domain(url):
        start = url.find('//') + 2
        return url[start:url.find('/', start)]

    def add_link_to_menu(url, html, title):
        if url:
            menu.append({'html': html,
                         'title': title,
                         'href': url,
                         'icon': 'jump'})

    menu = []
    add_link_to_menu(doc_url,
                     'Go to docs' + extra_text,
                     'Go to documentation for this crate on ' + get_domain(doc_url))
    add_link_to_menu(src_url,
                     'Go to source' + extra_text,
                     'Go to source code for this crate on ' + get_domain(doc_url))
    add_link_to_menu(dxr_url,
                     'Go to DXR index' + extra_text,
                     'Go to DXR index of this crate on ' + get_domain(doc_url))
    return menu


def call_menu(qualname, tree):
    return [{'html': "Find callers",
             'title': "Find functions that call this function",
             'href': search_url(tree, "+callers:%s" % quote(qualname)),
             'icon': 'method'},
            {'html': "Find callees",  # TODO: Probably useless. Remove.
             'title': "Find functions that are called by this function",
             'href': search_url(tree, "+called-by:%s" % quote(qualname)),
             'icon': 'method'}]


def function_menu_generic(datum, tree_config):
    """Return menu makers shared by function def/decls and function refs."""
    menus = call_menu(datum['qualname'], tree_config)
    menus.append(find_references_menu(tree_config, datum['qualname'], "function-ref", "function"))
    return menus


def jump_to_target_menu(target_name, tree_config, path, row):
    """Make a menu that jumps straight to a specific line of a file."""

    return {'html': 'Jump to %s' % target_name,
            'title': "Jump to %s in '%s'" % (target_name,
                                             os.path.basename(path)),
            'href': url_for(BROWSE, tree=tree_config.name, path=path, _anchor=row),
            'icon': 'jump'}

def jump_to_target_from_decl(menu_maker, tree, decl):
    """Return an jump menu from a declaration mapping.

    If the incoming declaration doesn't warrant the creation of a menu,
    return None.
    """

    path = decl['file_name']
    if path:
        return menu_maker(tree, path, decl['file_line'])
    else:
        warn("Can't add jump to empty path.")  # Can this happen?

jump_to_trait_method_menu = partial(jump_to_target_menu, target_name='trait method')
jump_to_definition_menu = partial(jump_to_target_menu, target_name='definition')
jump_to_module_definition_menu = partial(jump_to_target_menu, target_name='module definition')
jump_to_module_declaration_menu = partial(jump_to_target_menu, target_name='module declaration')
jump_to_alias_definition_menu = partial(jump_to_target_menu, target_name='alias definition')
jump_to_crate_menu = partial(jump_to_target_menu, target_name='crate')
jump_to_type_declaration_menu = partial(jump_to_target_menu, target_name='type declaration')
jump_to_variable_declaration_menu = partial(jump_to_target_menu, target_name='variable declaration')
jump_to_function_declaration_menu = partial(jump_to_target_menu, target_name='function declaration')


def trait_impl_menu(tree_config, qualname, count):
    return {'html': "Find implementations (%d)" % count,
            'title': "Find implementations of this trait method",
            'href': search_url(tree_config, "+fn-impls:%s" % quote(qualname)),
            'icon': 'method'}


def variable_menu_generic(datum, tree_config):
    return [find_references_menu(tree_config, datum['qualname'], "var-ref", "variable")]


def type_menu(tree_config, kind, qualname):
    if kind == 'trait':
        yield {'html': "Find sub-traits",
               'title': "Find sub-traits of this trait",
               'href': search_url(tree_config, "+derived:%s" % quote(qualname)),
               'icon': 'type'}
        yield {'html': "Find super-traits",
               'title': "Find super-traits of this trait",
               'href': search_url(tree_config, "+bases:%s" % quote(qualname)),
               'icon': 'type'}
    if kind == 'struct' or kind == 'enum' or kind == 'trait':
        yield {'html': "Find impls",
               'title': "Find impls which involve this " + kind,
               'href': search_url(tree_config, "+impl:%s" % quote(qualname)),
               'icon': 'reference'}


def type_menu_generic(datum, tree_config):
    kind = datum['kind']
    qualname = datum['qualname']
    menu = list(type_menu(tree_config, kind, qualname))
    menu.append(find_references_menu(tree_config, qualname, "type-ref", kind))
    return menu


def use_items_menu(tree_config, qualname):
    return {'html': "Find use items",
            'title': "Find instances of this module in 'use' items",
            'href': search_url(tree_config, "+module-use:%s" % quote(qualname)),
            'icon': 'reference'}


def module_menu_generic(datum, tree_config):
    return [use_items_menu(tree_config, datum['qualname']),
            find_references_menu(tree_config, datum['qualname'], "module-ref", "module")]
{'fraction_non_alphanumeric': 0.12396694214876033, 'fraction_numerical': 0.00046342782111686106, 'mean_word_length': 2.7892888498683055, 'pattern_counts': {'":': 4, '<': 5, '<?xml version=': 0, '>': 3, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '4502159', 'n_tokens_mistral': 3946, 'n_tokens_neox': 3821, 'n_words': 1039}