Exemplo n.º 1
0
def _get_explicit_scope_visibility(id_node):  # type: (Dict[str, Any]) -> Optional[ScopeVisibility]
    # See :help internal-variables
    scope_prefix = id_node['value'][0:2]

    if is_function_identifier(id_node) and is_declarative_identifier(id_node):
        return FunctionDeclarationIdentifierScopePrefixToScopeVisibility.get(scope_prefix)
    else:
        return VariableIdentifierScopePrefixToScopeVisibility.get(scope_prefix)
Exemplo n.º 2
0
def _get_explicit_scope_visibility(
        id_node):  # type: (Dict[str, Any]) -> Optional[ScopeVisibility]
    # See :help internal-variables
    scope_prefix = id_node['value'][0:2]

    if is_function_identifier(id_node) and is_declarative_identifier(id_node):
        return FunctionDeclarationIdentifierScopePrefixToScopeVisibility.get(
            scope_prefix)
    else:
        return VariableIdentifierScopePrefixToScopeVisibility.get(scope_prefix)
    def get_referenced_variable_declarations(self, ref_id_node):
        # type: (Dict[str, Any]) -> Union[List[VariableDeclaration], GlobalVariableDeclaration]

        scope = self._scope_linker.link_registry.get_context_scope_by_identifier(
            ref_id_node)
        var_name = remove_optional_scope_prefix(ref_id_node['value'])
        is_func_id = is_function_identifier(ref_id_node)

        while scope is not None:
            if is_func_id:
                functions_list = scope.functions
                if var_name in functions_list:
                    # The function is found in the symbol table for functions.
                    funcs = functions_list[var_name]

                    for func in funcs:
                        declaring_id_node = self._scope_linker.link_registry \
                            .get_declarative_identifier_by_variable(func)
                        declaring_id_node[REFERENCED_FLAG] = True

                    return funcs
                else:
                    # We can access the function via a variable function
                    # reference if the function not found from the symbol table
                    # for functions. So we should check the symbol table for
                    # variables to search the function reference.
                    pass

            variables_list = scope.variables
            if var_name in variables_list:
                # The variable or function reference found in the symbol table
                # for variables.
                variables = variables_list[var_name]

                for variable in variables:
                    declaring_id_node = self._scope_linker.link_registry \
                        .get_declarative_identifier_by_variable(variable)
                    declaring_id_node[REFERENCED_FLAG] = True

                return variables

            scope = scope.parent

        # If it is builtin, it will be used by Vim.
        if is_builtin_variable(ref_id_node):
            return GLOBAL_VARIABLE_DECLARATION

        return []
Exemplo n.º 4
0
    def get_referenced_variable_declarations(self, ref_id_node):
        # type: (Dict[str, Any]) -> Union[List[VariableDeclaration], GlobalVariableDeclaration]

        scope = self._scope_linker.link_registry.get_context_scope_by_identifier(ref_id_node)
        var_name = remove_optional_scope_prefix(ref_id_node['value'])
        is_func_id = is_function_identifier(ref_id_node)

        while scope is not None:
            if is_func_id:
                functions_list = scope.functions
                if var_name in functions_list:
                    # The function is found in the symbol table for functions.
                    funcs = functions_list[var_name]

                    for func in funcs:
                        declaring_id_node = self._scope_linker.link_registry \
                            .get_declarative_identifier_by_variable(func)
                        declaring_id_node[REFERENCED_FLAG] = True

                    return funcs
                else:
                    # We can access the function via a variable function
                    # reference if the function not found from the symbol table
                    # for functions. So we should check the symbol table for
                    # variables to search the function reference.
                    pass

            variables_list = scope.variables
            if var_name in variables_list:
                # The variable or function reference found in the symbol table
                # for variables.
                variables = variables_list[var_name]

                for variable in variables:
                    declaring_id_node = self._scope_linker.link_registry \
                        .get_declarative_identifier_by_variable(variable)
                    declaring_id_node[REFERENCED_FLAG] = True

                return variables

            scope = scope.parent

        # If it is builtin, it will be used by Vim.
        if is_builtin_variable(ref_id_node):
            return GLOBAL_VARIABLE_DECLARATION

        return []
Exemplo n.º 5
0
def is_builtin_function(id_node):  # type: (Dict[str, Any]) -> bool
    """ Whether the specified node is a builtin function name identifier.
    The given identifier should be a child node of NodeType.CALL.
    """
    # Builtin functions are always IDENTIFIER.
    if NodeType(id_node['type']) is not NodeType.IDENTIFIER:
        return False

    id_value = id_node['value']

    if not is_function_identifier(id_node):
        return False

    # There are difference between a function identifier and variable
    # identifier:
    #
    #   let localtime = 0
    #   echo localtime " => 0
    #   echo localtime() " => 1420011455
    return id_value in BuiltinFunctions
Exemplo n.º 6
0
def is_builtin_function(id_node):  # type: (Dict[str, Any]) -> bool
    """ Whether the specified node is a builtin function name identifier.
    The given identifier should be a child node of NodeType.CALL.
    """
    # Builtin functions are always IDENTIFIER.
    if NodeType(id_node['type']) is not NodeType.IDENTIFIER:
        return False

    id_value = id_node['value']

    if not is_function_identifier(id_node):
        return False

    # There are difference between a function identifier and variable
    # identifier:
    #
    #   let localtime = 0
    #   echo localtime " => 0
    #   echo localtime() " => 1420011455
    return id_value in BuiltinFunctions
Exemplo n.º 7
0
def _detect_possible_identifier_scope_visibility(id_node, context_scope):
    # type: (Dict[str, Any], Scope) -> ScopeVisibilityHint
    explicit_scope_visibility = _get_explicit_scope_visibility(id_node)
    if explicit_scope_visibility is not None:
        # Vim allow `g:` as a function name prefix but it is not recommended.
        # SEE: https://github.com/Kuniwak/vint/pull/136
        is_unrecommended_explicit = is_function_identifier(id_node) and _is_just_global(id_node)
        if is_unrecommended_explicit:
            return ScopeVisibilityHint(
                explicit_scope_visibility,
                ExplicityOfScopeVisibility.UNRECOMMENDED_EXPLICIT
            )

        return ScopeVisibilityHint(
            explicit_scope_visibility,
            ExplicityOfScopeVisibility.EXPLICIT
        )

    if is_function_argument(id_node):
        # Function arguments can not have any explicit scope prefix.
        return ScopeVisibilityHint(
            ScopeVisibility.FUNCTION_LOCAL,
            ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED
        )

    if is_builtin_function(id_node):
        # Builtin functions can not have any scope prefix.
        return ScopeVisibilityHint(
            ScopeVisibility.BUILTIN,
            ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED
        )

    if is_builtin_variable(id_node):
        # Implicit scope variable will be resolved as a builtin variable if it
        # has a same name to Vim builtin variables.
        return ScopeVisibilityHint(
            ScopeVisibility.BUILTIN,
            ExplicityOfScopeVisibility.IMPLICIT
        )

    if is_function_identifier(id_node):
        # Functions can have the scope visibility only explicit global or
        # implicit global or explicit script local. So a function have implicit
        # scope visibility is always a global function.
        #
        # And the explicity should be implicit. Vim allow `g:` but it is not recommended.
        # SEE: https://github.com/Kuniwak/vint/pull/136
        return ScopeVisibilityHint(
            ScopeVisibility.GLOBAL_LIKE,
            ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED
        )

    if not context_scope:
        # We can not detect implicit scope visibility if context scope is not
        # specified.
        return ScopeVisibilityHint(
            ScopeVisibility.UNANALYZABLE,
            ExplicityOfScopeVisibility.UNANALYZABLE
        )

    current_scope_visibility = context_scope.scope_visibility

    # A lambda argument declaration or the references can not have any explicit scope prefix.
    if current_scope_visibility is ScopeVisibility.LAMBDA:
        if is_lambda_argument_identifier(id_node):
            # It can not have any explicit scope prefix.
            explicity = ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED
        else:
            # We can not detect the scope of an implicit variable until
            # we know whether the variable can reach to a lambda argument or not.
            # If it can reach to a lambda argument, then it is IMPLICIT_BUT_CONSTRAINED otherwise IMPLICIT.
            explicity = ExplicityOfScopeVisibility.IMPLICIT_OR_LAMBDA
    else:
        explicity = ExplicityOfScopeVisibility.IMPLICIT

    if current_scope_visibility is ScopeVisibility.SCRIPT_LOCAL:
        # Implicit scope variable will be resolved as a global variable when
        # current scope is script local.
        return ScopeVisibilityHint(
            ScopeVisibility.GLOBAL_LIKE,
            explicity
        )

    # Otherwise be a function local variable.
    return ScopeVisibilityHint(
        ScopeVisibility.FUNCTION_LOCAL,
        explicity
    )
Exemplo n.º 8
0
def _detect_possible_identifier_scope_visibility(id_node, context_scope):
    # type: (Dict[str, Any], Scope) -> ScopeVisibilityHint
    explicit_scope_visibility = _get_explicit_scope_visibility(id_node)
    if explicit_scope_visibility is not None:
        # Vim allow `g:` as a function name prefix but it is not recommended.
        # SEE: https://github.com/Kuniwak/vint/pull/136
        is_unrecommended_explicit = is_function_identifier(
            id_node) and _is_just_global(id_node)
        if is_unrecommended_explicit:
            return ScopeVisibilityHint(
                explicit_scope_visibility,
                ExplicityOfScopeVisibility.UNRECOMMENDED_EXPLICIT)

        return ScopeVisibilityHint(explicit_scope_visibility,
                                   ExplicityOfScopeVisibility.EXPLICIT)

    if is_function_argument(id_node):
        # Function arguments can not have any explicit scope prefix.
        return ScopeVisibilityHint(
            ScopeVisibility.FUNCTION_LOCAL,
            ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED)

    if is_builtin_function(id_node):
        # Builtin functions can not have any scope prefix.
        return ScopeVisibilityHint(
            ScopeVisibility.BUILTIN,
            ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED)

    if is_builtin_variable(id_node):
        # Implicit scope variable will be resolved as a builtin variable if it
        # has a same name to Vim builtin variables.
        return ScopeVisibilityHint(ScopeVisibility.BUILTIN,
                                   ExplicityOfScopeVisibility.IMPLICIT)

    if is_function_identifier(id_node):
        # Functions can have the scope visibility only explicit global or
        # implicit global or explicit script local. So a function have implicit
        # scope visibility is always a global function.
        #
        # And the explicity should be implicit. Vim allow `g:` but it is not recommended.
        # SEE: https://github.com/Kuniwak/vint/pull/136
        return ScopeVisibilityHint(
            ScopeVisibility.GLOBAL_LIKE,
            ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED)

    if not context_scope:
        # We can not detect implicit scope visibility if context scope is not
        # specified.
        return ScopeVisibilityHint(ScopeVisibility.UNANALYZABLE,
                                   ExplicityOfScopeVisibility.UNANALYZABLE)

    current_scope_visibility = context_scope.scope_visibility

    # A lambda argument declaration or the references can not have any explicit scope prefix.
    if current_scope_visibility is ScopeVisibility.LAMBDA:
        if is_lambda_argument_identifier(id_node):
            # It can not have any explicit scope prefix.
            explicity = ExplicityOfScopeVisibility.IMPLICIT_BUT_CONSTRAINED
        else:
            # We can not detect the scope of an implicit variable until
            # we know whether the variable can reach to a lambda argument or not.
            # If it can reach to a lambda argument, then it is IMPLICIT_BUT_CONSTRAINED otherwise IMPLICIT.
            explicity = ExplicityOfScopeVisibility.IMPLICIT_OR_LAMBDA
    else:
        explicity = ExplicityOfScopeVisibility.IMPLICIT

    if current_scope_visibility is ScopeVisibility.SCRIPT_LOCAL:
        # Implicit scope variable will be resolved as a global variable when
        # current scope is script local.
        return ScopeVisibilityHint(ScopeVisibility.GLOBAL_LIKE, explicity)

    # Otherwise be a function local variable.
    return ScopeVisibilityHint(ScopeVisibility.FUNCTION_LOCAL, explicity)