/* * Copyright (c) 2013, the Dart project authors. * * Licensed under the Eclipse Public License v1.0 (the "License"); you may not use this file except * in compliance with the License. You may obtain a copy of the License at * * http://www.eclipse.org/legal/epl-v10.html * * Unless required by applicable law or agreed to in writing, software distributed under the License * is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express * or implied. See the License for the specific language governing permissions and limitations under * the License. */ package com.google.dart.engine.ast; import com.google.dart.engine.parser.ParserTestCase; import com.google.dart.engine.scanner.TokenType; import static com.google.dart.engine.ast.AstFactory.assignmentExpression; import static com.google.dart.engine.ast.AstFactory.binaryExpression; import static com.google.dart.engine.ast.AstFactory.catchClause; import static com.google.dart.engine.ast.AstFactory.classDeclaration; import static com.google.dart.engine.ast.AstFactory.classTypeAlias; import static com.google.dart.engine.ast.AstFactory.constructorDeclaration; import static com.google.dart.engine.ast.AstFactory.declaredIdentifier; import static com.google.dart.engine.ast.AstFactory.emptyStatement; import static com.google.dart.engine.ast.AstFactory.enumDeclaration; import static com.google.dart.engine.ast.AstFactory.fieldFormalParameter; import static com.google.dart.engine.ast.AstFactory.functionDeclaration; import static com.google.dart.engine.ast.AstFactory.identifier; import static com.google.dart.engine.ast.AstFactory.importDirective; import static com.google.dart.engine.ast.AstFactory.integer; import static com.google.dart.engine.ast.AstFactory.label; import static com.google.dart.engine.ast.AstFactory.labeledStatement; import static com.google.dart.engine.ast.AstFactory.list; import static com.google.dart.engine.ast.AstFactory.methodDeclaration; import static com.google.dart.engine.ast.AstFactory.methodInvocation; import static com.google.dart.engine.ast.AstFactory.namedExpression; import static com.google.dart.engine.ast.AstFactory.postfixExpression; import static com.google.dart.engine.ast.AstFactory.prefixExpression; import static com.google.dart.engine.ast.AstFactory.propertyAccess; import static com.google.dart.engine.ast.AstFactory.returnStatement; import static com.google.dart.engine.ast.AstFactory.simpleFormalParameter; import static com.google.dart.engine.ast.AstFactory.typeAlias; import static com.google.dart.engine.ast.AstFactory.typeName; import static com.google.dart.engine.ast.AstFactory.typeParameter; import static com.google.dart.engine.ast.AstFactory.variableDeclaration; public class SimpleIdentifierTest extends ParserTestCase { private enum AssignmentKind { BINARY, COMPOUND_LEFT, COMPOUND_RIGHT, POSTFIX_INC, PREFIX_DEC, PREFIX_INC, PREFIX_NOT, SIMPLE_LEFT, SIMPLE_RIGHT, NONE; } private enum WrapperKind { PREFIXED_LEFT, PREFIXED_RIGHT, PROPERTY_LEFT, PROPERTY_RIGHT, NONE; } public void test_inDeclarationContext_catch_exception() { SimpleIdentifier identifier = catchClause("e").getExceptionParameter(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_catch_stack() { SimpleIdentifier identifier = catchClause("e", "s").getStackTraceParameter(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_classDeclaration() { SimpleIdentifier identifier = classDeclaration(null, "C", null, null, null, null).getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_classTypeAlias() { SimpleIdentifier identifier = classTypeAlias("C", null, null, null, null, null).getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_constructorDeclaration() { SimpleIdentifier identifier = constructorDeclaration(identifier("C"), "c", null, null).getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_declaredIdentifier() { DeclaredIdentifier declaredIdentifier = declaredIdentifier("v"); SimpleIdentifier identifier = declaredIdentifier.getIdentifier(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_enumConstantDeclaration() { EnumDeclaration enumDeclaration = enumDeclaration("MyEnum", "CONST"); SimpleIdentifier identifier = enumDeclaration.getConstants().get(0).getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_enumDeclaration() { EnumDeclaration enumDeclaration = enumDeclaration("MyEnum", "A", "B", "C"); SimpleIdentifier identifier = enumDeclaration.getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_fieldFormalParameter() { SimpleIdentifier identifier = fieldFormalParameter("p").getIdentifier(); assertFalse(identifier.inDeclarationContext()); } public void test_inDeclarationContext_functionDeclaration() { SimpleIdentifier identifier = functionDeclaration(null, null, "f", null).getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_functionTypeAlias() { SimpleIdentifier identifier = typeAlias(null, "F", null, null).getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_label_false() { SimpleIdentifier identifier = namedExpression("l", integer(0)).getName().getLabel(); assertFalse(identifier.inDeclarationContext()); } public void test_inDeclarationContext_label_true() { Label label = label("l"); SimpleIdentifier identifier = label.getLabel(); labeledStatement(list(label), emptyStatement()); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_methodDeclaration() { SimpleIdentifier identifier = identifier("m"); methodDeclaration(null, null, null, null, identifier, null, null); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_prefix() { SimpleIdentifier identifier = importDirective("uri", "pref").getPrefix(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_simpleFormalParameter() { SimpleIdentifier identifier = simpleFormalParameter("p").getIdentifier(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_typeParameter_bound() { TypeName bound = typeName("A"); SimpleIdentifier identifier = (SimpleIdentifier) bound.getName(); typeParameter("E", bound); assertFalse(identifier.inDeclarationContext()); } public void test_inDeclarationContext_typeParameter_name() { SimpleIdentifier identifier = typeParameter("E").getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inDeclarationContext_variableDeclaration() { SimpleIdentifier identifier = variableDeclaration("v").getName(); assertTrue(identifier.inDeclarationContext()); } public void test_inGetterContext() throws Exception { for (WrapperKind wrapper : WrapperKind.values()) { for (AssignmentKind assignment : AssignmentKind.values()) { SimpleIdentifier identifier = createIdentifier(wrapper, assignment); if (assignment == AssignmentKind.SIMPLE_LEFT && wrapper != WrapperKind.PREFIXED_LEFT && wrapper != WrapperKind.PROPERTY_LEFT) { if (identifier.inGetterContext()) { fail("Expected " + topMostNode(identifier).toSource() + " to be false"); } } else { if (!identifier.inGetterContext()) { fail("Expected " + topMostNode(identifier).toSource() + " to be true"); } } } } } public void test_inReferenceContext() throws Exception { SimpleIdentifier identifier = identifier("id"); namedExpression(label(identifier), identifier("_")); assertFalse(identifier.inGetterContext()); assertFalse(identifier.inSetterContext()); } public void test_inSetterContext() throws Exception { for (WrapperKind wrapper : WrapperKind.values()) { for (AssignmentKind assignment : AssignmentKind.values()) { SimpleIdentifier identifier = createIdentifier(wrapper, assignment); if (wrapper == WrapperKind.PREFIXED_LEFT || wrapper == WrapperKind.PROPERTY_LEFT || assignment == AssignmentKind.BINARY || assignment == AssignmentKind.COMPOUND_RIGHT || assignment == AssignmentKind.PREFIX_NOT || assignment == AssignmentKind.SIMPLE_RIGHT || assignment == AssignmentKind.NONE) { if (identifier.inSetterContext()) { fail("Expected " + topMostNode(identifier).toSource() + " to be false"); } } else { if (!identifier.inSetterContext()) { fail("Expected " + topMostNode(identifier).toSource() + " to be true"); } } } } } public void test_isQualified_inMethodInvocation_noTarget() throws Exception { MethodInvocation invocation = methodInvocation("test", identifier("arg0")); SimpleIdentifier identifier = invocation.getMethodName(); assertFalse(identifier.isQualified()); } public void test_isQualified_inMethodInvocation_withTarget() throws Exception { MethodInvocation invocation = methodInvocation(identifier("target"), "test", identifier("arg0")); SimpleIdentifier identifier = invocation.getMethodName(); assertTrue(identifier.isQualified()); } public void test_isQualified_inPrefixedIdentifier_name() throws Exception { SimpleIdentifier identifier = identifier("test"); identifier("prefix", identifier); assertTrue(identifier.isQualified()); } public void test_isQualified_inPrefixedIdentifier_prefix() throws Exception { SimpleIdentifier identifier = identifier("test"); identifier(identifier, identifier("name")); assertFalse(identifier.isQualified()); } public void test_isQualified_inPropertyAccess_name() throws Exception { SimpleIdentifier identifier = identifier("test"); propertyAccess(identifier("target"), identifier); assertTrue(identifier.isQualified()); } public void test_isQualified_inPropertyAccess_target() throws Exception { SimpleIdentifier identifier = identifier("test"); propertyAccess(identifier, identifier("name")); assertFalse(identifier.isQualified()); } public void test_isQualified_inReturnStatement() throws Exception { SimpleIdentifier identifier = identifier("test"); returnStatement(identifier); assertFalse(identifier.isQualified()); } private SimpleIdentifier createIdentifier(WrapperKind wrapper, AssignmentKind assignment) { SimpleIdentifier identifier = identifier("a"); Expression expression = identifier; switch (wrapper) { case PREFIXED_LEFT: expression = identifier(identifier, identifier("_")); break; case PREFIXED_RIGHT: expression = identifier(identifier("_"), identifier); break; case PROPERTY_LEFT: expression = propertyAccess(expression, "_"); break; case PROPERTY_RIGHT: expression = propertyAccess(identifier("_"), identifier); break; case NONE: // Nothing to add. break; } switch (assignment) { case BINARY: binaryExpression(expression, TokenType.PLUS, identifier("_")); break; case COMPOUND_LEFT: assignmentExpression(expression, TokenType.PLUS_EQ, identifier("_")); break; case COMPOUND_RIGHT: assignmentExpression(identifier("_"), TokenType.PLUS_EQ, expression); break; case POSTFIX_INC: postfixExpression(expression, TokenType.PLUS_PLUS); break; case PREFIX_DEC: prefixExpression(TokenType.MINUS_MINUS, expression); break; case PREFIX_INC: prefixExpression(TokenType.PLUS_PLUS, expression); break; case PREFIX_NOT: prefixExpression(TokenType.BANG, expression); break; case SIMPLE_LEFT: assignmentExpression(expression, TokenType.EQ, identifier("_")); break; case SIMPLE_RIGHT: assignmentExpression(identifier("_"), TokenType.EQ, expression); break; case NONE: // Nothing to add. break; } return identifier; } /** * Return the top-most node in the AST structure containing the given identifier. * * @param identifier the identifier in the AST structure being traversed * @return the root of the AST structure containing the identifier */ private AstNode topMostNode(SimpleIdentifier identifier) { AstNode child = identifier; AstNode parent = identifier.getParent(); while (parent != null) { child = parent; parent = parent.getParent(); } return child; } }