/* * 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.internal.constant; import com.google.dart.engine.AnalysisEngine; import com.google.dart.engine.ast.AstNode; import com.google.dart.engine.ast.CompilationUnit; import com.google.dart.engine.ast.CompilationUnitMember; import com.google.dart.engine.ast.ConstructorDeclaration; import com.google.dart.engine.ast.Expression; import com.google.dart.engine.ast.FormalParameter; import com.google.dart.engine.ast.InstanceCreationExpression; import com.google.dart.engine.ast.NodeList; import com.google.dart.engine.ast.TopLevelVariableDeclaration; import com.google.dart.engine.ast.VariableDeclaration; import com.google.dart.engine.ast.VariableDeclarationList; import com.google.dart.engine.constant.DeclaredVariables; import com.google.dart.engine.context.AnalysisException; import com.google.dart.engine.element.ConstructorElement; import com.google.dart.engine.element.LibraryElement; import com.google.dart.engine.element.ParameterElement; import com.google.dart.engine.error.CompileTimeErrorCode; import com.google.dart.engine.error.ErrorCode; import com.google.dart.engine.internal.element.VariableElementImpl; import com.google.dart.engine.internal.error.ErrorReporter; import com.google.dart.engine.internal.object.DartObjectImpl; import com.google.dart.engine.internal.object.GenericState; import com.google.dart.engine.internal.resolver.TypeProvider; import com.google.dart.engine.resolver.ResolverTestCase; import com.google.dart.engine.source.Source; import com.google.dart.engine.utilities.collection.DirectedGraph; import com.google.dart.engine.utilities.logging.TestLogger; import java.util.HashMap; public class ConstantValueComputerTest extends ResolverTestCase { class ValidatingConstantVisitor extends ConstantVisitor { private DirectedGraph<AstNode> referenceGraph; private AstNode nodeBeingEvaluated; public ValidatingConstantVisitor(TypeProvider typeProvider, DirectedGraph<AstNode> referenceGraph, AstNode nodeBeingEvaluated, ErrorReporter errorReporter) { super(typeProvider, errorReporter); this.referenceGraph = referenceGraph; this.nodeBeingEvaluated = nodeBeingEvaluated; } @Override protected void beforeGetEvaluationResult(AstNode node) { super.beforeGetEvaluationResult(node); // If we are getting the evaluation result for a node in the graph, make sure we properly // recorded the dependency. if (referenceGraph.getNodes().contains(node)) { assertTrue(referenceGraph.containsPath(nodeBeingEvaluated, node)); } } } private class ValidatingConstantValueComputer extends ConstantValueComputer { private AstNode nodeBeingEvaluated; public ValidatingConstantValueComputer(TypeProvider typeProvider, DeclaredVariables declaredVariables) { super(typeProvider, declaredVariables); } @Override protected void beforeComputeValue(AstNode constNode) { super.beforeComputeValue(constNode); nodeBeingEvaluated = constNode; } @Override protected void beforeGetConstantInitializers(ConstructorElement constructor) { super.beforeGetConstantInitializers(constructor); // If we are getting the constant initializers for a node in the graph, make sure we properly // recorded the dependency. ConstructorDeclaration node = findConstructorDeclaration(constructor); if (node != null && referenceGraph.getNodes().contains(node)) { assertTrue(referenceGraph.containsPath(nodeBeingEvaluated, node)); } } @Override protected void beforeGetParameterDefault(ParameterElement parameter) { super.beforeGetParameterDefault(parameter); // Find the ConstructorElement and figure out which parameter we're talking about. ConstructorElement constructor = parameter.getAncestor(ConstructorElement.class); int parameterIndex; ParameterElement[] parameters = constructor.getParameters(); int numParameters = parameters.length; for (parameterIndex = 0; parameterIndex < numParameters; parameterIndex++) { if (parameters[parameterIndex] == parameter) { break; } } assertTrue(parameterIndex < numParameters); // If we are getting the default parameter for a constructor in the graph, make sure we properly // recorded the dependency on the parameter. ConstructorDeclaration constructorNode = constructorDeclarationMap.get(constructor); if (constructorNode != null) { FormalParameter parameterNode = constructorNode.getParameters().getParameters().get( parameterIndex); assertTrue(referenceGraph.getNodes().contains(parameterNode)); assertTrue(referenceGraph.containsPath(nodeBeingEvaluated, parameterNode)); } } @Override protected ConstantVisitor createConstantVisitor(ErrorReporter errorReporter) { return new ValidatingConstantVisitor( typeProvider, referenceGraph, nodeBeingEvaluated, errorReporter); } } public void test_computeValues_cycle() throws Exception { TestLogger logger = new TestLogger(); AnalysisEngine.getInstance().setLogger(logger); Source librarySource = addSource(createSource(// "const int a = c;", "const int b = a;", "const int c = b;")); LibraryElement libraryElement = resolve(librarySource); CompilationUnit unit = getAnalysisContext().resolveCompilationUnit( librarySource, libraryElement); getAnalysisContext().computeErrors(librarySource); assertNotNull(unit); ConstantValueComputer computer = makeConstantValueComputer(); computer.add(unit); computer.computeValues(); NodeList<CompilationUnitMember> members = unit.getDeclarations(); assertSizeOfList(3, members); validate(false, ((TopLevelVariableDeclaration) members.get(0)).getVariables()); validate(false, ((TopLevelVariableDeclaration) members.get(1)).getVariables()); validate(false, ((TopLevelVariableDeclaration) members.get(2)).getVariables()); } public void test_computeValues_dependentVariables() throws Exception { Source librarySource = addSource(createSource(// "const int b = a;", "const int a = 0;")); LibraryElement libraryElement = resolve(librarySource); CompilationUnit unit = getAnalysisContext().resolveCompilationUnit( librarySource, libraryElement); assertNotNull(unit); ConstantValueComputer computer = makeConstantValueComputer(); computer.add(unit); computer.computeValues(); NodeList<CompilationUnitMember> members = unit.getDeclarations(); assertSizeOfList(2, members); validate(true, ((TopLevelVariableDeclaration) members.get(0)).getVariables()); validate(true, ((TopLevelVariableDeclaration) members.get(1)).getVariables()); } public void test_computeValues_empty() throws Exception { ConstantValueComputer computer = makeConstantValueComputer(); computer.computeValues(); } public void test_computeValues_multipleSources() throws Exception { Source librarySource = addNamedSource("/lib.dart", createSource(// "library lib;", "part 'part.dart';", "const int c = b;", "const int a = 0;")); Source partSource = addNamedSource("/part.dart", createSource(// "part of lib;", "const int b = a;", "const int d = c;")); LibraryElement libraryElement = resolve(librarySource); CompilationUnit libraryUnit = getAnalysisContext().resolveCompilationUnit( librarySource, libraryElement); assertNotNull(libraryUnit); CompilationUnit partUnit = getAnalysisContext().resolveCompilationUnit( partSource, libraryElement); assertNotNull(partUnit); ConstantValueComputer computer = makeConstantValueComputer(); computer.add(libraryUnit); computer.add(partUnit); computer.computeValues(); NodeList<CompilationUnitMember> libraryMembers = libraryUnit.getDeclarations(); assertSizeOfList(2, libraryMembers); validate(true, ((TopLevelVariableDeclaration) libraryMembers.get(0)).getVariables()); validate(true, ((TopLevelVariableDeclaration) libraryMembers.get(1)).getVariables()); NodeList<CompilationUnitMember> partMembers = libraryUnit.getDeclarations(); assertSizeOfList(2, partMembers); validate(true, ((TopLevelVariableDeclaration) partMembers.get(0)).getVariables()); validate(true, ((TopLevelVariableDeclaration) partMembers.get(1)).getVariables()); } public void test_computeValues_singleVariable() throws Exception { Source librarySource = addSource("const int a = 0;"); LibraryElement libraryElement = resolve(librarySource); CompilationUnit unit = getAnalysisContext().resolveCompilationUnit( librarySource, libraryElement); assertNotNull(unit); ConstantValueComputer computer = makeConstantValueComputer(); computer.add(unit); computer.computeValues(); NodeList<CompilationUnitMember> members = unit.getDeclarations(); assertSizeOfList(1, members); validate(true, ((TopLevelVariableDeclaration) members.get(0)).getVariables()); } public void test_dependencyOnConstructor() throws Exception { // x depends on "const A()" assertProperDependencies(createSource(// "class A {", " const A();", "}", "const x = const A();")); } public void test_dependencyOnConstructorArgument() throws Exception { // "const A(x)" depends on x assertProperDependencies(createSource(// "class A {", " const A(this.next);", " final A next;", "}", "const A x = const A(null);", "const A y = const A(x);")); } public void test_dependencyOnConstructorArgument_unresolvedConstructor() throws Exception { // "const A.a(x)" depends on x even if the constructor A.a can't be found. assertProperDependencies(createSource(// "class A {", "}", "const int x = 1;", "const A y = const A.a(x);"), CompileTimeErrorCode.CONST_WITH_UNDEFINED_CONSTRUCTOR); } public void test_dependencyOnConstructorInitializer() throws Exception { // "const A()" depends on x assertProperDependencies(createSource(// "const int x = 1;", "class A {", " const A() : v = x;", " final int v;", "}")); } public void test_dependencyOnExplicitSuperConstructor() throws Exception { // b depends on B() depends on A() assertProperDependencies(createSource(// "class A {", " const A(this.x);", " final int x;", "}", "class B extends A {", " const B() : super(5);", "}", "const B b = const B();")); } public void test_dependencyOnExplicitSuperConstructorParameters() throws Exception { // b depends on B() depends on i assertProperDependencies(createSource(// "class A {", " const A(this.x);", " final int x;", "}", "class B extends A {", " const B() : super(i);", "}", "const B b = const B();", "const int i = 5;")); } public void test_dependencyOnFactoryRedirect() throws Exception { // a depends on A.foo() depends on A.bar() assertProperDependencies(createSource(// "const A a = const A.foo();", "class A {", " factory const A.foo() = A.bar;", " const A.bar();", "}")); } public void test_dependencyOnFactoryRedirectWithTypeParams() throws Exception { assertProperDependencies(createSource(// "class A {", " const factory A(var a) = B<int>;", "}", "", "class B<T> implements A {", " final T x;", " const B(this.x);", "}", "", "const A a = const A(10);")); } public void test_dependencyOnImplicitSuperConstructor() throws Exception { // b depends on B() depends on A() assertProperDependencies(createSource(// "class A {", " const A() : x = 5;", " final int x;", "}", "class B extends A {", " const B();", "}", "const B b = const B();")); } public void test_dependencyOnOptionalParameterDefault() throws Exception { // a depends on A() depends on B() assertProperDependencies(createSource(// "class A {", " const A([x = const B()]) : b = x;", " final B b;", "}", "class B {", " const B();", "}", "const A a = const A();")); } public void test_dependencyOnVariable() throws Exception { // x depends on y assertProperDependencies(createSource(// "const x = y + 1;", "const y = 2;")); } public void test_fromEnvironment_bool_default_false() throws Exception { assertEquals(false, assertValidBool(check_fromEnvironment_bool(null, "false"))); } public void test_fromEnvironment_bool_default_overridden() throws Exception { assertEquals(false, assertValidBool(check_fromEnvironment_bool("false", "true"))); } public void test_fromEnvironment_bool_default_parseError() throws Exception { assertEquals(true, assertValidBool(check_fromEnvironment_bool("parseError", "true"))); } public void test_fromEnvironment_bool_default_true() throws Exception { assertEquals(true, assertValidBool(check_fromEnvironment_bool(null, "true"))); } public void test_fromEnvironment_bool_false() throws Exception { assertEquals(false, assertValidBool(check_fromEnvironment_bool("false", null))); } public void test_fromEnvironment_bool_parseError() throws Exception { assertEquals(false, assertValidBool(check_fromEnvironment_bool("parseError", null))); } public void test_fromEnvironment_bool_true() throws Exception { assertEquals(true, assertValidBool(check_fromEnvironment_bool("true", null))); } public void test_fromEnvironment_bool_undeclared() throws Exception { assertValidUnknown(check_fromEnvironment_bool(null, null)); } public void test_fromEnvironment_int_default_overridden() throws Exception { assertEquals(234, assertValidInt(check_fromEnvironment_int("234", "123"))); } public void test_fromEnvironment_int_default_parseError() throws Exception { assertEquals(123, assertValidInt(check_fromEnvironment_int("parseError", "123"))); } public void test_fromEnvironment_int_default_undeclared() throws Exception { assertEquals(123, assertValidInt(check_fromEnvironment_int(null, "123"))); } public void test_fromEnvironment_int_ok() throws Exception { assertEquals(234, assertValidInt(check_fromEnvironment_int("234", null))); } public void test_fromEnvironment_int_parseError() throws Exception { assertValidNull(check_fromEnvironment_int("parseError", null)); } public void test_fromEnvironment_int_parseError_nullDefault() throws Exception { assertValidNull(check_fromEnvironment_int("parseError", "null")); } public void test_fromEnvironment_int_undeclared() throws Exception { assertValidUnknown(check_fromEnvironment_int(null, null)); } public void test_fromEnvironment_int_undeclared_nullDefault() throws Exception { assertValidNull(check_fromEnvironment_int(null, "null")); } public void test_fromEnvironment_string_default_overridden() throws Exception { assertEquals("abc", assertValidString(check_fromEnvironment_string("abc", "'def'"))); } public void test_fromEnvironment_string_default_undeclared() throws Exception { assertEquals("def", assertValidString(check_fromEnvironment_string(null, "'def'"))); } public void test_fromEnvironment_string_empty() throws Exception { assertEquals("", assertValidString(check_fromEnvironment_string("", null))); } public void test_fromEnvironment_string_ok() throws Exception { assertEquals("abc", assertValidString(check_fromEnvironment_string("abc", null))); } public void test_fromEnvironment_string_undeclared() throws Exception { assertValidUnknown(check_fromEnvironment_string(null, null)); } public void test_fromEnvironment_string_undeclared_nullDefault() throws Exception { assertValidNull(check_fromEnvironment_string(null, "null")); } public void test_instanceCreationExpression_computedField() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A(4, 5);", "class A {", " const A(int i, int j) : k = 2 * i + j;", " final int k;", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fields = assertType(result, "A"); assertSizeOfMap(1, fields); assertIntField(fields, "k", 13L); } public void test_instanceCreationExpression_computedField_namedOptionalWithDefault() throws Exception { checkInstanceCreationOptionalParams(false, true, true); } public void test_instanceCreationExpression_computedField_namedOptionalWithoutDefault() throws Exception { checkInstanceCreationOptionalParams(false, true, false); } public void test_instanceCreationExpression_computedField_unnamedOptionalWithDefault() throws Exception { checkInstanceCreationOptionalParams(false, false, true); } public void test_instanceCreationExpression_computedField_unnamedOptionalWithoutDefault() throws Exception { checkInstanceCreationOptionalParams(false, false, false); } public void test_instanceCreationExpression_computedField_usesConstConstructor() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A(3);", "class A {", " const A(int i) : b = const B(4);", " final int b;", "}", "class B {", " const B(this.k);", " final int k;", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fieldsOfA = assertType(result, "A"); assertSizeOfMap(1, fieldsOfA); HashMap<String, DartObjectImpl> fieldsOfB = assertFieldType(fieldsOfA, "b", "B"); assertSizeOfMap(1, fieldsOfB); assertIntField(fieldsOfB, "k", 4L); } public void test_instanceCreationExpression_computedField_usesStaticConst() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A(3);", "class A {", " const A(int i) : k = i + B.bar;", " final int k;", "}", "class B {", " static const bar = 4;", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fields = assertType(result, "A"); assertSizeOfMap(1, fields); assertIntField(fields, "k", 7L); } public void test_instanceCreationExpression_computedField_usesToplevelConst() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A(3);", "const bar = 4;", "class A {", " const A(int i) : k = i + bar;", " final int k;", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fields = assertType(result, "A"); assertSizeOfMap(1, fields); assertIntField(fields, "k", 7L); } public void test_instanceCreationExpression_explicitSuper() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const B(4, 5);", "class A {", " const A(this.x);", " final int x;", "}", "class B extends A {", " const B(int x, this.y) : super(x * 2);", " final int y;", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fields = assertType(result, "B"); assertSizeOfMap(2, fields); assertIntField(fields, "y", 5L); HashMap<String, DartObjectImpl> superclassFields = assertFieldType( fields, GenericState.SUPERCLASS_FIELD, "A"); assertSizeOfMap(1, superclassFields); assertIntField(superclassFields, "x", 8L); } public void test_instanceCreationExpression_fieldFormalParameter() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A(42);", "class A {", " int x;", " const A(this.x)", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fields = assertType(result, "A"); assertSizeOfMap(1, fields); assertIntField(fields, "x", 42L); } public void test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithDefault() throws Exception { checkInstanceCreationOptionalParams(true, true, true); } public void test_instanceCreationExpression_fieldFormalParameter_namedOptionalWithoutDefault() throws Exception { checkInstanceCreationOptionalParams(true, true, false); } public void test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithDefault() throws Exception { checkInstanceCreationOptionalParams(true, false, true); } public void test_instanceCreationExpression_fieldFormalParameter_unnamedOptionalWithoutDefault() throws Exception { checkInstanceCreationOptionalParams(true, false, false); } public void test_instanceCreationExpression_implicitSuper() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const B(4);", "class A {", " const A() : x(3);", " final int x;", "}", "class B extends A {", " const B(this.y);", " final int y;", "}")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "foo"); HashMap<String, DartObjectImpl> fields = assertType(result, "B"); assertSizeOfMap(2, fields); assertIntField(fields, "y", 4L); HashMap<String, DartObjectImpl> superclassFields = assertFieldType( fields, GenericState.SUPERCLASS_FIELD, "A"); assertSizeOfMap(1, superclassFields); assertIntField(superclassFields, "x", 3L); } public void test_instanceCreationExpression_redirect() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A();", "class A {", " const factory A() = B;", "}", "class B implements A {", " const B();", "}")); assertType(evaluateInstanceCreationExpression(compilationUnit, "foo"), "B"); } public void test_instanceCreationExpression_redirect_cycle() throws Exception { // It is an error to have a cycle in factory redirects; however, we need // to make sure that even if the error occurs, attempting to evaluate the // constant will terminate. CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A();", "class A {", " const factory A() = A.b;", " const factory A.b() = A;", "}")); assertValidUnknown(evaluateInstanceCreationExpression(compilationUnit, "foo")); } public void test_instanceCreationExpression_redirect_extern() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A();", "class A {", " external const factory A();", "}")); assertValidUnknown(evaluateInstanceCreationExpression(compilationUnit, "foo")); } public void test_instanceCreationExpression_redirect_nonConst() throws Exception { // It is an error for a const factory constructor redirect to a non-const // constructor; however, we need to make sure that even if the error // attempting to evaluate the constant won't cause a crash. CompilationUnit compilationUnit = resolveSource(createSource(// "const foo = const A();", "class A {", " const factory A() = A.b;", " A.b();", "}")); assertValidUnknown(evaluateInstanceCreationExpression(compilationUnit, "foo")); } public void test_instanceCreationExpression_redirectWithTypeParams() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "class A {", " const factory A(var a) = B<int>;", "}", "", "class B<T> implements A {", " final T x;", " const B(this.x);", "}", "", "const A a = const A(10);")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "a"); HashMap<String, DartObjectImpl> fields = assertType(result, "B<int>"); assertSizeOfMap(1, fields); assertIntField(fields, "x", 10L); } public void test_instanceCreationExpression_redirectWithTypeSubstitution() throws Exception { // To evaluate the redirection of A<int>, A's template argument (T=int) must be substituted // into B's template argument (B<U> where U=T) to get B<int>. CompilationUnit compilationUnit = resolveSource(createSource(// "class A<T> {", " const factory A(var a) = B<T>;", "}", "", "class B<U> implements A {", " final U x;", " const B(this.x);", "}", "", "const A<int> a = const A<int>(10);")); EvaluationResultImpl result = evaluateInstanceCreationExpression(compilationUnit, "a"); HashMap<String, DartObjectImpl> fields = assertType(result, "B<int>"); assertSizeOfMap(1, fields); assertIntField(fields, "x", 10L); } public void test_instanceCreationExpression_symbol() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource("const foo = const Symbol('a');")); EvaluationResultImpl evaluationResult = evaluateInstanceCreationExpression( compilationUnit, "foo"); assertNotNull(evaluationResult.getValue()); DartObjectImpl value = evaluationResult.getValue(); assertEquals(getTypeProvider().getSymbolType(), value.getType()); assertEquals("a", value.getValue()); } public void test_instanceCreationExpression_withSupertypeParams_explicit() throws Exception { checkInstanceCreation_withSupertypeParams(true); } public void test_instanceCreationExpression_withSupertypeParams_implicit() throws Exception { checkInstanceCreation_withSupertypeParams(false); } public void test_instanceCreationExpression_withTypeParams() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "class C<E> {", " const C();", "}", "const c_int = const C<int>();", "const c_num = const C<num>();")); EvaluationResultImpl c_int = evaluateInstanceCreationExpression(compilationUnit, "c_int"); assertType(c_int, "C<int>"); DartObjectImpl c_int_value = c_int.getValue(); EvaluationResultImpl c_num = evaluateInstanceCreationExpression(compilationUnit, "c_num"); assertType(c_num, "C<num>"); DartObjectImpl c_num_value = c_num.getValue(); assertFalse(c_int_value.equals(c_num_value)); } public void test_isValidSymbol() { assertTrue(ConstantValueComputer.isValidPublicSymbol("")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo.bar")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo$")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo$bar")); assertTrue(ConstantValueComputer.isValidPublicSymbol("iff")); assertTrue(ConstantValueComputer.isValidPublicSymbol("gif")); assertTrue(ConstantValueComputer.isValidPublicSymbol("if$")); assertTrue(ConstantValueComputer.isValidPublicSymbol("$if")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo=")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo.bar=")); assertTrue(ConstantValueComputer.isValidPublicSymbol("foo.+")); assertTrue(ConstantValueComputer.isValidPublicSymbol("void")); assertFalse(ConstantValueComputer.isValidPublicSymbol("_foo")); assertFalse(ConstantValueComputer.isValidPublicSymbol("_foo.bar")); assertFalse(ConstantValueComputer.isValidPublicSymbol("foo._bar")); assertFalse(ConstantValueComputer.isValidPublicSymbol("if")); assertFalse(ConstantValueComputer.isValidPublicSymbol("if.foo")); assertFalse(ConstantValueComputer.isValidPublicSymbol("foo.if")); assertFalse(ConstantValueComputer.isValidPublicSymbol("foo=.bar")); assertFalse(ConstantValueComputer.isValidPublicSymbol("foo.")); assertFalse(ConstantValueComputer.isValidPublicSymbol("+.foo")); assertFalse(ConstantValueComputer.isValidPublicSymbol("void.foo")); assertFalse(ConstantValueComputer.isValidPublicSymbol("foo.void")); } public void test_symbolLiteral_void() throws Exception { CompilationUnit compilationUnit = resolveSource(createSource(// "const voidSymbol = #void;")); VariableDeclaration voidSymbol = findTopLevelDeclaration(compilationUnit, "voidSymbol"); EvaluationResultImpl voidSymbolResult = ((VariableElementImpl) voidSymbol.getElement()).getEvaluationResult(); DartObjectImpl value = voidSymbolResult.getValue(); assertEquals(getTypeProvider().getSymbolType(), value.getType()); assertEquals("void", value.getValue()); } private HashMap<String, DartObjectImpl> assertFieldType(HashMap<String, DartObjectImpl> fields, String fieldName, String expectedType) { DartObjectImpl field = fields.get(fieldName); assertEquals(expectedType, field.getType().getDisplayName()); return field.getFields(); } private void assertIntField(HashMap<String, DartObjectImpl> fields, String fieldName, long expectedValue) { DartObjectImpl field = fields.get(fieldName); assertEquals("int", field.getType().getName()); assertEquals(expectedValue, field.getIntValue().longValue()); } private void assertNullField(HashMap<String, DartObjectImpl> fields, String fieldName) { DartObjectImpl field = fields.get(fieldName); assertTrue(field.isNull()); } private void assertProperDependencies(String sourceText, ErrorCode... expectedErrorCodes) throws AnalysisException { Source source = addSource(sourceText); LibraryElement element = resolve(source); CompilationUnit unit = getAnalysisContext().resolveCompilationUnit(source, element); assertNotNull(unit); ConstantValueComputer computer = makeConstantValueComputer(); computer.add(unit); computer.computeValues(); assertErrors(source, expectedErrorCodes); } private HashMap<String, DartObjectImpl> assertType(EvaluationResultImpl result, String typeName) { assertNotNull(result.getValue()); DartObjectImpl value = result.getValue(); assertEquals(typeName, value.getType().getDisplayName()); return value.getFields(); } private boolean assertValidBool(EvaluationResultImpl result) throws AnalysisException { assertNotNull(result.getValue()); DartObjectImpl value = result.getValue(); assertEquals(getTypeProvider().getBoolType(), value.getType()); Boolean boolValue = value.getBoolValue(); assertNotNull(boolValue); return boolValue; } private int assertValidInt(EvaluationResultImpl result) throws AnalysisException { assertNotNull(result.getValue()); DartObjectImpl value = result.getValue(); assertEquals(getTypeProvider().getIntType(), value.getType()); return value.getIntValue().intValue(); } private void assertValidNull(EvaluationResultImpl result) throws AnalysisException { assertNotNull(result.getValue()); DartObjectImpl value = result.getValue(); assertEquals(getTypeProvider().getNullType(), value.getType()); } private String assertValidString(EvaluationResultImpl result) throws AnalysisException { assertNotNull(result.getValue()); DartObjectImpl value = result.getValue(); assertEquals(getTypeProvider().getStringType(), value.getType()); return value.getStringValue(); } private void assertValidUnknown(EvaluationResultImpl result) { assertNotNull(result.getValue()); DartObjectImpl value = result.getValue(); assertTrue(value.isUnknown()); } private EvaluationResultImpl check_fromEnvironment_bool(String valueInEnvironment, String defaultExpr) throws AnalysisException { String envVarName = "x"; String varName = "foo"; if (valueInEnvironment != null) { analysisContext.getDeclaredVariables().define(envVarName, valueInEnvironment); } String defaultArg = defaultExpr == null ? "" : ", defaultValue: " + defaultExpr; CompilationUnit compilationUnit = resolveSource(createSource(// "const " + varName + " = const bool.fromEnvironment('" + envVarName + "'" + defaultArg + ");")); return evaluateInstanceCreationExpression(compilationUnit, varName); } private EvaluationResultImpl check_fromEnvironment_int(String valueInEnvironment, String defaultExpr) throws AnalysisException { String envVarName = "x"; String varName = "foo"; if (valueInEnvironment != null) { analysisContext.getDeclaredVariables().define(envVarName, valueInEnvironment); } String defaultArg = defaultExpr == null ? "" : ", defaultValue: " + defaultExpr; CompilationUnit compilationUnit = resolveSource(createSource(// "const " + varName + " = const int.fromEnvironment('" + envVarName + "'" + defaultArg + ");")); return evaluateInstanceCreationExpression(compilationUnit, varName); } private EvaluationResultImpl check_fromEnvironment_string(String valueInEnvironment, String defaultExpr) throws AnalysisException { String envVarName = "x"; String varName = "foo"; if (valueInEnvironment != null) { analysisContext.getDeclaredVariables().define(envVarName, valueInEnvironment); } String defaultArg = defaultExpr == null ? "" : ", defaultValue: " + defaultExpr; CompilationUnit compilationUnit = resolveSource(createSource(// "const " + varName + " = const String.fromEnvironment('" + envVarName + "'" + defaultArg + ");")); return evaluateInstanceCreationExpression(compilationUnit, varName); } private void checkInstanceCreation_withSupertypeParams(boolean isExplicit) throws AnalysisException { String superCall = isExplicit ? " : super()" : ""; CompilationUnit compilationUnit = resolveSource(createSource(// "class A<T> {", " const A();", "}", "class B<T, U> extends A<T> {", " const B()" + superCall + ";", "}", "class C<T, U> extends A<U> {", " const C()" + superCall + ";", "}", "const b_int_num = const B<int, num>();", "const c_int_num = const C<int, num>();")); EvaluationResultImpl b_int_num = evaluateInstanceCreationExpression( compilationUnit, "b_int_num"); HashMap<String, DartObjectImpl> b_int_num_fields = assertType(b_int_num, "B<int, num>"); assertFieldType(b_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<int>"); EvaluationResultImpl c_int_num = evaluateInstanceCreationExpression( compilationUnit, "c_int_num"); HashMap<String, DartObjectImpl> c_int_num_fields = assertType(c_int_num, "C<int, num>"); assertFieldType(c_int_num_fields, GenericState.SUPERCLASS_FIELD, "A<num>"); } private void checkInstanceCreationOptionalParams(boolean isFieldFormal, boolean isNamed, boolean hasDefault) throws AnalysisException { String fieldName = "j"; String paramName = isFieldFormal ? fieldName : "i"; String formalParam = (isFieldFormal ? "this." : "int ") + paramName + (hasDefault ? " = 3" : ""); CompilationUnit compilationUnit = resolveSource(createSource(// "const x = const A();", "const y = const A(" + (isNamed ? paramName + ": " : "") + "10);", "class A {", " const A(" + (isNamed ? "{" + formalParam + "}" : "[" + formalParam + "]") + ")" + (isFieldFormal ? "" : " : " + fieldName + " = " + paramName) + ";", " final int " + fieldName + ";", "}")); EvaluationResultImpl x = evaluateInstanceCreationExpression(compilationUnit, "x"); HashMap<String, DartObjectImpl> fieldsOfX = assertType(x, "A"); assertSizeOfMap(1, fieldsOfX); if (hasDefault) { assertIntField(fieldsOfX, fieldName, 3L); } else { assertNullField(fieldsOfX, fieldName); } EvaluationResultImpl y = evaluateInstanceCreationExpression(compilationUnit, "y"); HashMap<String, DartObjectImpl> fieldsOfY = assertType(y, "A"); assertSizeOfMap(1, fieldsOfY); assertIntField(fieldsOfY, fieldName, 10L); } private EvaluationResultImpl evaluateInstanceCreationExpression(CompilationUnit compilationUnit, String name) throws AnalysisException { Expression expression = findTopLevelConstantExpression(compilationUnit, name); return ((InstanceCreationExpression) expression).getEvaluationResult(); } private ConstantValueComputer makeConstantValueComputer() throws AnalysisException { return new ValidatingConstantValueComputer( analysisContext.getTypeProvider(), analysisContext.getDeclaredVariables()); } private void validate(boolean shouldBeValid, VariableDeclarationList declarationList) { for (VariableDeclaration declaration : declarationList.getVariables()) { VariableElementImpl element = (VariableElementImpl) declaration.getElement(); assertNotNull(element); EvaluationResultImpl result = element.getEvaluationResult(); if (shouldBeValid) { assertNotNull(result.getValue()); } else { assertNull(result.getValue()); } } } }