Ejemplo n.º 1
0
    def init_ghcmod_completions(self):
        # Init LANGUAGE completions
        self.language_completions = call_ghcmod_and_wait(['lang']).split('\n')
        log("Reading LANGUAGE completions from ghc-mod")

        # Init import module completion
        self.module_completions = call_ghcmod_and_wait(['list']).split('\n')
Ejemplo n.º 2
0
    def init_ghcmod_completions(self):

        if not get_setting('enable_ghc_mod'):
            return

        sublime.status_message('SublimeHaskell: Updating ghc_mod completions...')

        # Init LANGUAGE completions
        autocompletion.language_completions = call_ghcmod_and_wait(['lang']).splitlines()

        # Init import module completion
        autocompletion.module_completions = set(call_ghcmod_and_wait(['list']).splitlines())

        sublime.status_message('SublimeHaskell: Updating ghc_mod completions ' + u" \u2714")
Ejemplo n.º 3
0
def wait_ghcmod_and_parse(view, file_dir, msg, cmds_with_args, alter_messages_cb):
    sublime.set_timeout(lambda: hide_output(view), 0)

    exit_success = True

    parsed_messages = []

    for (cmd, args) in cmds_with_args:
        stdout = call_ghcmod_and_wait(args, file_dir)

        # stdout contains NULL as line endings within one message
        # error_output_regex using indents to determine one message scope
        # Replace NULLs to indents
        out = stdout.replace('\0', '\n  ').decode('utf-8')

        exit_success = exit_success and len(out) == 0

        parsed = parse_output_messages(file_dir, out)
        for p in parsed:
            parsed_messages.append((cmd, p))

    exit_code = 0 if exit_success else 1

    if alter_messages_cb:
        alter_messages_cb(parsed_messages)

    concated_messages = map(lambda m: m[1], parsed_messages)
    output_text = format_output_messages(concated_messages)

    show_output_result_text(view, msg, output_text, exit_code, file_dir)
    sublime.set_timeout(lambda: mark_messages_in_views(concated_messages), 0)
Ejemplo n.º 4
0
    def ghcmod_get_type_of_cursor(self):
        view = self.view

        filename = str(view.file_name())
        row, col = view.rowcol(view.sel()[0].a)
        row1, col1 = row + 1, col + 1  # ghc-mod uses rows/cols starting with 1
        module_region = view.find(MODULE_RE_STR, 0)

        if module_region is None:
            sublime.status_message(
                "SublimeHaskell: Could not determine module name!")
            return None

        # RE must match; there is only one group in the RE.
        module = MODULE_RE.match(view.substr(module_region)).group(1)

        ghcmod_args = ['type', filename, module, str(row1), str(col1)]
        out = call_ghcmod_and_wait(ghcmod_args)

        if not out:
            sublime.status_message("ghc-mod %s returned nothing" %
                                   ' '.join(ghcmod_args))
            return None

        # ghc-mod type returns the type of the expression at at the given row/col.
        # It can return multiple lines, extending the expression scope by one level each.
        # The last line belongs to the toplevel expression.
        types = map(parse_ghc_mod_type_line, out.strip().split('\n'))
        result_type = types[0]['type']  # innermost expression's type

        if not result_type:
            sublime.error_message("ghc-mod type returned unexpected output")
            return None

        return result_type
Ejemplo n.º 5
0
    def ghcmod_get_type_of_cursor(self):
        view = self.view

        filename = str(view.file_name())
        row, col = view.rowcol(view.sel()[0].a)
        row1, col1 = row + 1, col + 1  # ghc-mod uses rows/cols starting with 1
        module_region = view.find(MODULE_RE_STR, 0)

        if module_region is None:
            sublime.status_message("SublimeHaskell: Could not determine module name!")
            return None

        # RE must match; there is only one group in the RE.
        module = MODULE_RE.match(view.substr(module_region)).group(1)

        ghcmod_args = ['type', filename, module, str(row1), str(col1)]
        out = call_ghcmod_and_wait(ghcmod_args)

        if not out:
            sublime.status_message("ghc-mod %s returned nothing" % ' '.join(ghcmod_args))
            return None

        # ghc-mod type returns the type of the expression at at the given row/col.
        # It can return multiple lines, extending the expression scope by one level each.
        # The last line belongs to the toplevel expression.
        types = map(parse_ghc_mod_type_line, out.strip().split('\n'))
        result_type = types[0]['type']  # innermost expression's type

        if not result_type:
            sublime.error_message("ghc-mod type returned unexpected output")
            return None

        return result_type
Ejemplo n.º 6
0
def ghcmod_browse_module(module_name, cabal = None, use_ghc_package = False):
    """
    Returns symbols.Module with all declarations
    """
    contents = None
    if use_ghc_package:
        contents = call_ghcmod_and_wait(['-g', '-package ghc','browse', '-d', module_name], cabal = cabal).splitlines()
    else:
        contents = call_ghcmod_and_wait(['browse', '-d', module_name], cabal = cabal).splitlines()
    
    # Adding empty modules into cache greatly speeds up loading standard modules cache
    # if not contents:
    #    return None

    m = symbols.Module(module_name, cabal = cabal)

    functionRegex = r'(?P<name>\w+)\s+::\s+(?P<type>.*)'
    typeRegex = r'(?P<what>(class|type|data|newtype))\s+(?P<name>\w+)(\s+(?P<args>\w+(\s+\w+)*))?'

    def toDecl(line):
        matched = re.search(functionRegex, line)
        if matched:
            return symbols.Function(matched.group('name'), matched.group('type'))
        else:
            matched = re.search(typeRegex, line)
            if matched:
                decl_type = matched.group('what')
                decl_name = matched.group('name')
                decl_args = matched.group('args')
                decl_args = decl_args.split() if decl_args else []

                if decl_type == 'class':
                    return symbols.Class(decl_name, None, decl_args)
                elif decl_type == 'data':
                    return symbols.Data(decl_name, None, decl_args)
                elif decl_type == 'type':
                    return symbols.Type(decl_name, None, decl_args)
                elif decl_type == 'newtype':
                    return symbols.Newtype(decl_name, None, decl_args)
            else:
                return symbols.Declaration(line)

    decls = map(toDecl, contents)
    for decl in decls:
        m.add_declaration(decl)

    return m
Ejemplo n.º 7
0
def ghcmod_info(filename, module_name, symbol_name, cabal = None):
    """
    Uses ghc-mod info filename module_name symbol_name to get symbol info
    """
    contents = call_ghcmod_and_wait(['info', filename, module_name, symbol_name], filename = filename, cabal = cabal)
    # TODO: Returned symbol doesn't contain location
    # But in fact we use ghcmod_info only to retrieve type of symbol
    return parse_info(symbol_name, contents)
Ejemplo n.º 8
0
def ghcmod_info(filename, module_name, symbol_name, cabal = None):
    """
    Uses ghc-mod info filename module_name symbol_name to get symbol info
    """
    contents = call_ghcmod_and_wait(['info', filename, module_name, symbol_name], filename = filename, cabal = cabal)
    # TODO: Returned symbol doesn't contain location
    # But in fact we use ghcmod_info only to retrieve type of symbol
    return parse_info(symbol_name, contents)
Ejemplo n.º 9
0
def ghcmod_type(filename, module_name, line, column, cabal=None):
    """
    Uses ghc-mod type to infer type
    """
    return call_ghcmod_and_wait(
        ['type', filename, module_name,
         str(line), str(column)],
        filename=filename,
        cabal=cabal)
Ejemplo n.º 10
0
def wait_ghcmod_and_parse(view, filename, msg, cmds_with_args, alter_messages_cb):
    sublime.set_timeout(lambda: hide_output(view), 0)

    parsed_messages = []

    file_dir = os.path.dirname(filename)

    all_cmds_successful = True
    all_cmds_outputs = []

    for (cmd, args) in cmds_with_args:
        stdout = call_ghcmod_and_wait(args, filename)

        # stdout contains NULL as line endings within one message
        # error_output_regex using indents to determine one message scope
        # Replace NULLs to indents
        out1 = stdout.replace('\0', '\n  ')
        
        # Hlint outputs Error instead Warning for tips
        # so lets replace them
        out = out1.replace('Error', 'Warning')

        success = len(out.strip()) == 0

        if not success:
            all_cmds_outputs.append(out)
            log(u"ghc-mod %s didn't exit with success on '%s'" % (u' '.join(cmd), filename))

        all_cmds_successful &= success

        parsed = parse_output_messages(file_dir, out)
        for p in parsed:
            parsed_messages.append((cmd, p))

    if alter_messages_cb:
        alter_messages_cb(parsed_messages)

    concated_messages = [m[1] for m in parsed_messages]

    # Set global error list
    set_global_error_messages(concated_messages)

    sublime.set_timeout(lambda: mark_messages_in_views(concated_messages), 0)

    output_text = (format_output_messages(concated_messages) if parsed_messages
                   else '\n'.join(all_cmds_outputs))

    exit_code = 0 if all_cmds_successful else 1

    show_output_result_text(view, msg, output_text, exit_code, file_dir)
Ejemplo n.º 11
0
def wait_ghcmod_and_parse(view, filename, msg, cmds_with_args, alter_messages_cb):
    sublime.set_timeout(lambda: hide_output(view), 0)

    parsed_messages = []

    file_dir = os.path.dirname(filename)

    all_cmds_successful = True
    all_cmds_outputs = []

    for (cmd, args) in cmds_with_args:
        stdout = call_ghcmod_and_wait(args, filename)

        # stdout contains NULL as line endings within one message
        # error_output_regex using indents to determine one message scope
        # Replace NULLs to indents
        out = stdout.replace('\0', '\n  ')

        success = len(out.strip()) == 0

        if not success:
            all_cmds_outputs.append(out)
            log(u"ghc-mod %s didn't exit with success on '%s'" % (u' '.join(cmd), filename))

        all_cmds_successful &= success

        parsed = parse_output_messages(file_dir, out)
        for p in parsed:
            parsed_messages.append((cmd, p))

    if alter_messages_cb:
        alter_messages_cb(parsed_messages)

    concated_messages = [m[1] for m in parsed_messages]

    # Set global error list
    set_global_error_messages(concated_messages)

    sublime.set_timeout(lambda: mark_messages_in_views(concated_messages), 0)

    output_text = (format_output_messages(concated_messages) if parsed_messages
                   else '\n'.join(all_cmds_outputs))

    exit_code = 0 if all_cmds_successful else 1

    show_output_result_text(view, msg, output_text, exit_code, file_dir)
Ejemplo n.º 12
0
def ghcmod_browse_module(module_name, cabal = None):
    """
    Returns symbols.Module with all declarations
    """
    contents = call_ghcmod_and_wait(['browse', '-d', module_name], cabal = cabal).splitlines()

    if not contents:
        return None

    m = symbols.Module(module_name, cabal = cabal)

    functionRegex = r'(?P<name>\w+)\s+::\s+(?P<type>.*)'
    typeRegex = r'(?P<what>(class|type|data|newtype))\s+(?P<name>\w+)(\s+(?P<args>\w+(\s+\w+)*))?'

    def toDecl(line):
        matched = re.search(functionRegex, line)
        if matched:
            return symbols.Function(matched.group('name'), matched.group('type'))
        else:
            matched = re.search(typeRegex, line)
            if matched:
                decl_type = matched.group('what')
                decl_name = matched.group('name')
                decl_args = matched.group('args')
                decl_args = decl_args.split() if decl_args else []

                if decl_type == 'class':
                    return symbols.Class(decl_name, None, decl_args)
                elif decl_type == 'data':
                    return symbols.Data(decl_name, None, decl_args)
                elif decl_type == 'type':
                    return symbols.Type(decl_name, None, decl_args)
                elif decl_type == 'newtype':
                    return symbols.Newtype(decl_name, None, decl_args)
            else:
                return symbols.Declaration(line)

    decls = map(toDecl, contents)
    for decl in decls:
        m.add_declaration(decl)

    return m
Ejemplo n.º 13
0
def ghcmod_browse_module(module_name, cabal=None):
    """
    Returns symbols.Module with all declarations
    """
    contents = call_ghcmod_and_wait(["browse", "-d", module_name], cabal=cabal).splitlines()

    if not contents:
        return None

    m = symbols.Module(module_name, cabal=cabal)

    functionRegex = r"(?P<name>\w+)\s+::\s+(?P<type>.*)"
    typeRegex = r"(?P<what>(class|type|data|newtype))\s+(?P<name>\w+)(\s+(?P<args>\w+(\s+\w+)*))?"

    def toDecl(line):
        matched = re.search(functionRegex, line)
        if matched:
            return symbols.Function(matched.group("name"), matched.group("type"))
        else:
            matched = re.search(typeRegex, line)
            if matched:
                decl_type = matched.group("what")
                decl_name = matched.group("name")
                decl_args = matched.group("args")
                decl_args = decl_args.split() if decl_args else []

                if decl_type == "class":
                    return symbols.Class(decl_name, None, decl_args)
                elif decl_type == "data":
                    return symbols.Data(decl_name, None, decl_args)
                elif decl_type == "type":
                    return symbols.Type(decl_name, None, decl_args)
                elif decl_type == "newtype":
                    return symbols.Newtype(decl_name, None, decl_args)
            else:
                return symbols.Declaration(line)

    decls = map(toDecl, contents)
    for decl in decls:
        m.add_declaration(decl)

    return m
Ejemplo n.º 14
0
 def _load_standard_module(self, module_name):
     if module_name not in autocompletion.std_info:
         module_contents = call_ghcmod_and_wait(['browse', module_name]).splitlines()
         with autocompletion.std_info_lock:
             autocompletion.std_info[module_name] = module_contents
Ejemplo n.º 15
0
def ghcmod_type(filename, module_name, line, column, cabal = None):
    """
    Uses ghc-mod type to infer type
    """
    return call_ghcmod_and_wait(['type', filename, module_name, str(line), str(column)], filename = filename, cabal = cabal)