def _detect_identifier_scope_visibility(id_node, context_scope): explicit_scope_visibility = _get_explicit_scope_visibility(id_node) if explicit_scope_visibility is not None: return _create_identifier_visibility_hint(explicit_scope_visibility) is_implicit = get_explicity_of_scope_visibility(id_node) \ is ExplicityOfScopeVisibility.IMPLICIT # Implicit scope variable will be resolved as a builtin variable if it # has a same name to Vim builtin variables. if is_builtin_variable(id_node): return _create_identifier_visibility_hint(ScopeVisibility.BUILTIN, is_implicit=is_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 global function. return _create_identifier_visibility_hint(ScopeVisibility.GLOBAL_LIKE, is_implicit=is_implicit) if not context_scope: # We cannot detect implicit scope visibility if context scope is not # specified. return _create_identifier_visibility_hint(ScopeVisibility.UNANALYZABLE) # Implicit scope variable will be resolved as a global variable when # current scope is script local. Otherwise be a function local variable. current_scope_visibility = context_scope['scope_visibility'] if current_scope_visibility is ScopeVisibility.SCRIPT_LOCAL: return _create_identifier_visibility_hint(ScopeVisibility.GLOBAL_LIKE, is_implicit=is_implicit) return _create_identifier_visibility_hint(ScopeVisibility.FUNCTION_LOCAL, is_implicit=is_implicit)
def _detect_identifier_scope_visibility(id_node, context_scope): explicit_scope_visibility = _get_explicit_scope_visibility(id_node) if explicit_scope_visibility is not None: return _create_identifier_visibility_hint(explicit_scope_visibility) is_implicit = get_explicity_of_scope_visibility(id_node) \ is ExplicityOfScopeVisibility.IMPLICIT # Implicit scope variable will be resolved as a builtin variable if it # has a same name to Vim builtin variables. if is_builtin_variable(id_node): return _create_identifier_visibility_hint(ScopeVisibility.BUILTIN, is_implicit=is_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 global function. return _create_identifier_visibility_hint(ScopeVisibility.GLOBAL_LIKE, is_implicit=is_implicit) if not context_scope: # We cannot detect implicit scope visibility if context scope is not # specified. return _create_identifier_visibility_hint(ScopeVisibility.UNANALYZABLE) # Implicit scope variable will be resolved as a global variable when # current scope is script local. Otherwise be a function local variable. current_scope_visibility = context_scope['scope_visibility'] if current_scope_visibility is ScopeVisibility.SCRIPT_LOCAL: return _create_identifier_visibility_hint(ScopeVisibility.GLOBAL_LIKE, is_implicit=is_implicit) return _create_identifier_visibility_hint(ScopeVisibility.FUNCTION_LOCAL, is_implicit=is_implicit)
def _get_explicit_scope_visibility(id_node): # 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_explicit_scope_visibility(id_node): # 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 _normalize_identifier_value(id_node, context_scope): scope_visibility_hint = detect_scope_visibility(id_node, context_scope) if not scope_visibility_hint['is_implicit']: return id_node['value'] scope_visibility = scope_visibility_hint['scope_visibility'] if scope_visibility is ScopeVisibility.BUILTIN and is_function_identifier(id_node): # Builtin functions can not have explicit scope visibility. return id_node['value'] scope_prefix = ImplicitScopeVisibilityToIdentifierScopePrefix[scope_visibility] return scope_prefix + id_node['value']
def _normalize_identifier_value(id_node, context_scope): scope_visibility_hint = detect_scope_visibility(id_node, context_scope) if not scope_visibility_hint['is_implicit']: return id_node['value'] scope_visibility = scope_visibility_hint['scope_visibility'] if scope_visibility is ScopeVisibility.BUILTIN and is_function_identifier( id_node): # Builtin functions can not have explicit scope visibility. return id_node['value'] scope_prefix = ImplicitScopeVisibilityToIdentifierScopePrefix[ scope_visibility] return scope_prefix + id_node['value']
def is_builtin_function(id_node): """ 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 defference between a function identifier and variable # identifier: # # let localtime = 0 # echo localtime " => 0 # echo localtime() " => 1420011455 return id_value in BuiltinFunctions
def is_builtin_function(id_node): """ 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 defference between a function identifier and variable # identifier: # # let localtime = 0 # echo localtime " => 0 # echo localtime() " => 1420011455 return id_value in BuiltinFunctions
def check_reachability(self, ref_id_node): scope = self._link_registry.get_context_scope_by_identifier( ref_id_node) var_name = normalize_variable_name(ref_id_node, scope) 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. for variable in functions_list[var_name]: declaring_id_node = self._link_registry\ .get_declarative_identifier_by_variable(variable) declaring_id_node[REFERECED_FLAG] = True return True 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. for variable in variables_list[var_name]: declaring_id_node = self._link_registry\ .get_declarative_identifier_by_variable(variable) declaring_id_node[REFERECED_FLAG] = True return True scope = scope['parent_scope'] # If it is builtin, it will be used by Vim. return is_builtin_variable(ref_id_node)
def handle_new_variable_found(self, node): current_scope = self.get_current_scope() scope_visibility_hint = detect_scope_visibility( node, current_scope) if scope_visibility_hint is None: # We cannot do anything return is_implicit = scope_visibility_hint['is_implicit'] is_function = is_function_identifier(node) if is_builtin_variable(node): self._add_builtin_variable(node, is_function=is_function, is_implicit=is_implicit) return objective_scope = self._get_objective_scope(node) self._add_variable(objective_scope, node, is_function=is_function, is_implicit=is_implicit)