def test_attach_identifier_attributes_with_calling_func(self): ast = self.create_ast(Fixtures['CALLING_FUNC']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'FunctionCall': self.create_id_attr(is_declarative=False, is_function=True), 'autoload#AutoloadFunctionCall': self.create_id_attr(is_declarative=False, is_autoload=True, is_function=True), 'dot': self.create_id_attr(is_declarative=False), 'DotFunctionCall': self.create_id_attr(is_declarative=False, is_member=True, is_function=True), 'subscript': self.create_id_attr(is_declarative=False), "'SubscriptFunctionCall'": self.create_id_attr(is_declarative=False, is_member=True, is_function=True), 'FunctionCallInExpressionContext': self.create_id_attr(is_declarative=False, is_function=True), 'FunctionToBeDeleted': self.create_id_attr(is_declarative=False, is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_destructuring_assignment(self): ast = self.create_ast(Fixtures['DESTRUCTURING_ASSIGNMENT']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:for_var1': self.create_id_attr(is_declarative=True), 'g:for_var2': self.create_id_attr(is_declarative=True), 'g:let_var1': self.create_id_attr(is_declarative=True), 'g:let_var2': self.create_id_attr(is_declarative=True), 'g:let_var3': self.create_id_attr(is_declarative=True), 'g:rest': self.create_id_attr(is_declarative=True), 'g:list': self.create_id_attr(is_declarative=False), '1': self.create_id_attr(is_declarative=True, is_member=True), 'g:index_end': self.create_id_attr(is_declarative=False, is_dynamic=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_with_dict_key(self): ast = self.create_ast(Fixtures['DICT_KEY']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:dict': self.create_id_attr(is_declarative=False), 'Function1': self.create_id_attr(is_declarative=True, is_member=True, is_function=True), "'Function2'": self.create_id_attr(is_declarative=True, is_member=True, is_function=True), 'key1': self.create_id_attr(is_declarative=True, is_member=True, is_function=False), "'key2'": self.create_id_attr(is_declarative=True, is_member=True, is_function=False), "g:key3": self.create_id_attr(is_declarative=False, is_member=False, is_function=False), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def create_ast(self, file_path): parser = Parser() ast = parser.parse_file(file_path) id_classifier = IdentifierClassifier() attached_ast = id_classifier.attach_identifier_attributes(ast) return attached_ast
def create_ast(self, file_path): parser = Parser() ast = parser.parse(LintTargetFile(file_path)) id_classifier = IdentifierClassifier() attached_ast = id_classifier.attach_identifier_attributes(ast) return attached_ast
def test_attach_identifier_attributes_with_redir(self): ast = self.create_ast(Fixtures["REDIR"]) id_classifier = IdentifierClassifier() expected_id_attr_map = {"g:var": self.create_id_attr(is_declarative=True)} attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_arithmetic_assignment(self): ast = self.create_ast(Fixtures["ARITHMETIC_ASSIGNMENT"]) id_classifier = IdentifierClassifier() expected_id_attr_map = {"g:variable_defined": self.create_id_attr()} attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_redir(self): ast = self.create_ast(Fixtures['REDIR']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:var': self.create_id_attr(is_declarative=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_arithmetic_assignment(self): ast = self.create_ast(Fixtures['ARITHMETIC_ASSIGNMENT']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:variable_defined': self.create_id_attr(), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_loop_var(self): ast = self.create_ast(Fixtures["LOOP_VAR"]) id_classifier = IdentifierClassifier() expected_id_attr_map = { "implicit_global_loop_var": self.create_id_attr(is_declarative=True), "g:array": self.create_id_attr(is_declarative=False), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_func_in_func(self): ast = self.create_ast(Fixtures["DECLARING_FUNC_IN_FUNC"]) id_classifier = IdentifierClassifier() expected_id_attr_map = { "FuncContext": self.create_id_attr(is_declarative=True, is_function=True), "ImplicitGlobalFunc": self.create_id_attr(is_declarative=True, is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_issue_274_curlyname_complex(self): ast = self.create_ast(Fixtures['ISSUE_274_CURLYNAME_COMPLEX']) id_classifier = IdentifierClassifier() attached_ast = id_classifier.attach_identifier_attributes(ast) curlyname_node = attached_ast['body'][0]['body'][1]['right'] # For debugging. pprint(curlyname_node) self.assertTrue(curlyname_node[IDENTIFIER_ATTRIBUTE][IDENTIFIER_ATTRIBUTE_DYNAMIC_FLAG])
def test_issue_274_curlyname_complex(self): ast = self.create_ast(Fixtures['ISSUE_274_CURLYNAME_COMPLEX']) id_classifier = IdentifierClassifier() attached_ast = id_classifier.attach_identifier_attributes(ast) curlyname_node = attached_ast['body'][0]['body'][1]['right'] # For debugging. pprint(curlyname_node) self.assertTrue(curlyname_node[IDENTIFIER_ATTRIBUTE] [IDENTIFIER_ATTRIBUTE_DYNAMIC_FLAG])
def test_attach_identifier_attributes_with_loop_var(self): ast = self.create_ast(Fixtures['LOOP_VAR']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'implicit_global_loop_var': self.create_id_attr(is_declarative=True), 'g:array': self.create_id_attr(is_declarative=False), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_map_func(self): ast = self.create_ast(Fixtures['MAP_FUNC']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'v:val': self.create_id_attr(is_on_lambda_string=True), 'g:pattern': self.create_id_attr(is_on_lambda_string=True), 'map': self.create_id_attr(is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_var_in_func(self): ast = self.create_ast(Fixtures['DECLARING_VAR_IN_FUNC']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'FuncContext': self.create_id_attr(is_declarative=True, is_function=True), 'l:explicit_func_local_var': self.create_id_attr(is_declarative=True), 'implicit_func_local_var': self.create_id_attr(is_declarative=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_map_func(self): ast = self.create_ast(Fixtures["MAP_FUNC"]) id_classifier = IdentifierClassifier() expected_id_attr_map = { "v:val": self.create_id_attr(is_on_str_expr_context=True), "g:pattern": self.create_id_attr(is_on_str_expr_context=True), "map": self.create_id_attr(is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_map_func(self): ast = self.create_ast(Fixtures['MAP_FUNC']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'v:val': self.create_id_attr(is_on_str_expr_context=True), 'g:pattern': self.create_id_attr(is_on_str_expr_context=True), 'map': self.create_id_attr(is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_func(self): ast = self.create_ast(Fixtures['DECLARING_FUNC']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:ExplicitGlobalFunc': self.create_id_attr(is_declarative=True, is_function=True), 's:ScriptLocalFunc': self.create_id_attr(is_declarative=True, is_function=True), 'ImplicitGlobalFunc': self.create_id_attr(is_declarative=True, is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_lambda(self): ast = self.create_ast(Fixtures['LAMBDA']) id_classifier = IdentifierClassifier() attached_ast = id_classifier.attach_identifier_attributes(ast) expected_id_attr_map = { 'i': self.create_id_attr(is_declarative=True, is_lambda_argument=True), 'y': self.create_id_attr(is_on_lambda_body=True), 'map': self.create_id_attr(is_function=True), '...': self.create_id_attr(is_declarative=True, is_lambda_argument=True, is_variadic=True), } self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_func_in_func(self): ast = self.create_ast(Fixtures['DECLARING_FUNC_IN_FUNC']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'FuncContext': self.create_id_attr(is_declarative=True, is_function=True), 'ImplicitGlobalFunc': self.create_id_attr(is_declarative=True, is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def process(self, ast): # type: (Dict[str, Any]) -> None """ Build a scope tree and links between scopes and identifiers by the specified ast. You can access the built scope tree and the built links by .scope_tree and .link_registry. """ id_classifier = IdentifierClassifier() attached_ast = id_classifier.attach_identifier_attributes(ast) # We are already in script local scope. self._scope_tree_builder.enter_new_scope(ScopeVisibility.SCRIPT_LOCAL) traverse(attached_ast, on_enter=self._enter_handler, on_leave=self._leave_handler) self.scope_tree = self._scope_tree_builder.get_global_scope() self.link_registry = self._scope_tree_builder.link_registry
def test_attach_identifier_attributes_with_destructuring_assignment(self): ast = self.create_ast(Fixtures["DESTRUCTURING_ASSIGNMENT"]) id_classifier = IdentifierClassifier() expected_id_attr_map = { "g:for_var1": self.create_id_attr(is_declarative=True), "g:for_var2": self.create_id_attr(is_declarative=True), "g:let_var1": self.create_id_attr(is_declarative=True), "g:let_var2": self.create_id_attr(is_declarative=True), "g:let_var3": self.create_id_attr(is_declarative=True), "g:rest": self.create_id_attr(is_declarative=True), "g:list": self.create_id_attr(is_declarative=False), "1": self.create_id_attr(is_declarative=True, is_member=True), "g:index_end": self.create_id_attr(is_declarative=False, is_dynamic=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_var(self): ast = self.create_ast(Fixtures["DECLARING_VAR"]) id_classifier = IdentifierClassifier() expected_id_attr_map = { "g:explicit_global_var": self.create_id_attr(is_declarative=True), "b:buffer_local_var": self.create_id_attr(is_declarative=True), "w:window_local_var": self.create_id_attr(is_declarative=True), "t:tab_local_var": self.create_id_attr(is_declarative=True), "s:script_local_var": self.create_id_attr(is_declarative=True), "implicit_global_var": self.create_id_attr(is_declarative=True), "$ENV_VAR": self.create_id_attr(is_declarative=True), '@"': self.create_id_attr(is_declarative=True), "&opt_var": self.create_id_attr(is_declarative=True), "v:count": self.create_id_attr(is_declarative=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_declaring_var(self): ast = self.create_ast(Fixtures['DECLARING_VAR']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:explicit_global_var': self.create_id_attr(is_declarative=True), 'b:buffer_local_var': self.create_id_attr(is_declarative=True), 'w:window_local_var': self.create_id_attr(is_declarative=True), 't:tab_local_var': self.create_id_attr(is_declarative=True), 's:script_local_var': self.create_id_attr(is_declarative=True), 'implicit_global_var': self.create_id_attr(is_declarative=True), '$ENV_VAR': self.create_id_attr(is_declarative=True), '@"': self.create_id_attr(is_declarative=True), '&opt_var': self.create_id_attr(is_declarative=True), 'v:count': self.create_id_attr(is_declarative=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_func_param(self): ast = self.create_ast(Fixtures['FUNC_PARAM']) id_classifier = IdentifierClassifier() expected_id_attr_map = { 'g:FunctionWithNoParams': self.create_id_attr(is_declarative=True, is_function=True), 'g:FunctionWithOneParam': self.create_id_attr(is_declarative=True, is_function=True), 'param': self.create_id_attr(is_declarative=True, is_declarative_parameter=True), 'g:FunctionWithTwoParams': self.create_id_attr(is_declarative=True, is_function=True), 'param1': self.create_id_attr(is_declarative=True, is_declarative_parameter=True), 'param2': self.create_id_attr(is_declarative=True, is_declarative_parameter=True), 'g:FunctionWithVarParams': self.create_id_attr(is_declarative=True, is_function=True), 'g:FunctionWithParamsAndVarParams': self.create_id_attr(is_declarative=True, is_function=True), 'param_var1': self.create_id_attr(is_declarative=True, is_declarative_parameter=True), 'g:FunctionWithRange': self.create_id_attr(is_declarative=True, is_function=True), '...': self.create_id_attr(is_declarative=True, is_declarative_parameter=True, is_variadic=True), 'g:FunctionWithDict': self.create_id_attr(is_declarative=True, is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def test_attach_identifier_attributes_with_func_param(self): ast = self.create_ast(Fixtures["FUNC_PARAM"]) id_classifier = IdentifierClassifier() expected_id_attr_map = { "g:FunctionWithNoParams": self.create_id_attr(is_declarative=True, is_function=True), "g:FunctionWithOneParam": self.create_id_attr(is_declarative=True, is_function=True), "param": self.create_id_attr(is_declarative=True, is_declarative_parameter=True), "g:FunctionWithTwoParams": self.create_id_attr(is_declarative=True, is_function=True), "param1": self.create_id_attr(is_declarative=True, is_declarative_parameter=True), "param2": self.create_id_attr(is_declarative=True, is_declarative_parameter=True), "g:FunctionWithVarParams": self.create_id_attr(is_declarative=True, is_function=True), "g:FunctionWithParamsAndVarParams": self.create_id_attr(is_declarative=True, is_function=True), "param_var1": self.create_id_attr(is_declarative=True, is_declarative_parameter=True), "g:FunctionWithRange": self.create_id_attr(is_declarative=True, is_function=True), "...": self.create_id_attr(is_declarative=True, is_declarative_parameter=True), "g:FunctionWithDict": self.create_id_attr(is_declarative=True, is_function=True), } attached_ast = id_classifier.attach_identifier_attributes(ast) self.assertAttributesInIdentifiers(attached_ast, expected_id_attr_map)
def process(self, ast): self._scope_linker.process(ast) id_collector = IdentifierClassifier.IdentifierCollector() classified_id_group = id_collector.collect_identifiers(ast) dec_id_nodes = classified_id_group.statically_declared_identifiers ref_id_nodes = classified_id_group.statically_referencing_identifiers # Attach a parent_scope accessor to the scope tree ReferenceReachabilityTester.TwoWayScopeReferenceAttacher.attach( self._scope_linker.scope_tree) # Reset REFERENCED_FLAG to False for dec_id_node in dec_id_nodes: dec_id_node[REFERENCED_FLAG] = False for ref_id_node in ref_id_nodes: is_reachable = self.check_reachability(ref_id_node) ref_id_node[REACHABILITY_FLAG] = is_reachable
def test_bucket(self): ast = self.create_ast(Fixtures['LOOP_VAR']) collector = IdentifierClassifier.IdentifierCollector() bucket = collector.collect_identifiers(ast) declaring_id_values = [ id_node['value'] for id_node in bucket['static_declaring_identifiers'] ] referencing_id_values = [ id_node['value'] for id_node in bucket['static_referencing_identifiers'] ] expected_declaring_id_values = ['implicit_global_loop_var'] expected_referencing_id_values = ['g:array'] self.assertEqual(expected_declaring_id_values, declaring_id_values) self.assertEqual(expected_referencing_id_values, referencing_id_values)