Chromium Code Reviews| Index: compiler/javatests/com/google/dart/compiler/resolver/ResolverTestCase.java |
| diff --git a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTestCase.java b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTestCase.java |
| index 799d13c0774c9df6d95d34f2dcbb8df85626d39b..02d25709f4d0058ff6d56271f9064f189411e761 100644 |
| --- a/compiler/javatests/com/google/dart/compiler/resolver/ResolverTestCase.java |
| +++ b/compiler/javatests/com/google/dart/compiler/resolver/ResolverTestCase.java |
| @@ -4,17 +4,27 @@ |
| package com.google.dart.compiler.resolver; |
| +import com.google.common.base.Joiner; |
| +import com.google.common.base.Splitter; |
| +import com.google.common.collect.Lists; |
| +import com.google.dart.compiler.DartCompilationError; |
| +import com.google.dart.compiler.DartCompilerErrorCode; |
| +import com.google.dart.compiler.DartCompilerListener; |
| +import com.google.dart.compiler.ErrorCode; |
| import com.google.dart.compiler.ast.DartClass; |
| import com.google.dart.compiler.ast.DartIdentifier; |
| import com.google.dart.compiler.ast.DartNode; |
| import com.google.dart.compiler.ast.DartTypeNode; |
| import com.google.dart.compiler.ast.DartTypeParameter; |
| import com.google.dart.compiler.ast.DartUnit; |
| +import com.google.dart.compiler.parser.DartParser; |
| +import com.google.dart.compiler.parser.DartScannerParserContext; |
| import com.google.dart.compiler.testing.TestCompilerContext; |
| import com.google.dart.compiler.type.DynamicType; |
| import com.google.dart.compiler.type.InterfaceType; |
| import com.google.dart.compiler.type.Type; |
| import com.google.dart.compiler.type.Types; |
| +import com.google.dart.compiler.util.DartSourceString; |
| import junit.framework.TestCase; |
| @@ -28,6 +38,18 @@ import java.util.List; |
| */ |
| abstract class ResolverTestCase extends TestCase { |
| + private List<DartCompilationError> encounteredErrors = Lists.newArrayList(); |
| + |
| + @Override |
| + public void setUp() { |
| + resetExpectedErrors(); |
| + } |
| + |
| + @Override |
| + public void tearDown() { |
| + resetExpectedErrors(); |
| + } |
| + |
| static Scope resolve(DartUnit unit, TestCompilerContext context) { |
| Scope scope = new Scope("library"); |
| new TopLevelElementBuilder().exec(unit, context); |
| @@ -73,26 +95,38 @@ abstract class ResolverTestCase extends TestCase { |
| static class MockCoreTypeProvider implements CoreTypeProvider { |
| + private final InterfaceType boolType; |
| private final InterfaceType intType; |
| + private final InterfaceType doubleType; |
| + private final InterfaceType numType; |
| private final InterfaceType stringType; |
| private final InterfaceType functionType; |
| - private final InterfaceType mapType; |
| - private final InterfaceType arrayType; |
| + private final InterfaceType dynamicType; |
| + private final InterfaceType defaultMapType; |
| + private final InterfaceType defaultArrayType; |
| private final ClassElement objectElement; |
| { |
| + ClassElement boolElement = Elements.classNamed("bool"); |
|
zundel
2011/10/12 21:25:28
these extra settings are used by Compile time cons
|
| + boolType = Types.interfaceType(boolElement, Collections.<Type>emptyList()); |
| ClassElement intElement = Elements.classNamed("int"); |
| intType = Types.interfaceType(intElement, Collections.<Type>emptyList()); |
| + ClassElement doubleElement = Elements.classNamed("double"); |
| + doubleType = Types.interfaceType(doubleElement, Collections.<Type>emptyList()); |
| + ClassElement numElement = Elements.classNamed("num"); |
| + numType = Types.interfaceType(numElement, Collections.<Type>emptyList()); |
| ClassElement stringElement = Elements.classNamed("String"); |
| stringType = Types.interfaceType(stringElement, Collections.<Type>emptyList()); |
| intElement.setType(intType); |
| ClassElement functionElement = Elements.classNamed("Function"); |
| functionType = Types.interfaceType(functionElement, Collections.<Type>emptyList()); |
| + ClassElement dynamicElement = Elements.classNamed("Dynamic"); |
| + dynamicType = Types.interfaceType(dynamicElement, Collections.<Type>emptyList()); |
| ClassElement mapElement = Elements.classNamed("Map"); |
| - mapType = Types.interfaceType(mapElement, Collections.<Type>emptyList()); |
| - ClassElement arrayElement = Elements.classNamed("Array"); |
| - arrayType = Types.interfaceType(arrayElement, Collections.<Type>emptyList()); |
| + defaultMapType = Types.interfaceType(mapElement, Lists.newArrayList(stringType, dynamicType)); |
| + ClassElement listElement = Elements.classNamed("List"); |
| + defaultArrayType = Types.interfaceType(listElement, Lists.newArrayList(dynamicType)); |
| functionElement.setType(functionType); |
| } |
| @@ -107,12 +141,17 @@ abstract class ResolverTestCase extends TestCase { |
| @Override |
| public InterfaceType getDoubleType() { |
| - throw new AssertionError(); |
| + return doubleType; |
| + } |
| + |
| + @Override |
| + public InterfaceType getNumType() { |
| + return numType; |
| } |
| @Override |
| public InterfaceType getBoolType() { |
| - throw new AssertionError(); |
| + return boolType; |
| } |
| @Override |
| @@ -127,7 +166,7 @@ abstract class ResolverTestCase extends TestCase { |
| @Override |
| public InterfaceType getArrayType(Type elementType) { |
| - return arrayType; |
| + return defaultArrayType; |
| } |
| @Override |
| @@ -152,7 +191,7 @@ abstract class ResolverTestCase extends TestCase { |
| @Override |
| public InterfaceType getMapType(Type key, Type value) { |
| - return mapType; |
| + return defaultMapType; |
| } |
| @Override |
| @@ -166,18 +205,13 @@ abstract class ResolverTestCase extends TestCase { |
| } |
| @Override |
| - public InterfaceType getNumType() { |
|
jbrosenberg
2011/10/12 21:43:38
Did you mean to remove this one?
zundel
2011/10/13 00:45:38
Its still hanging around. I replaced the body wit
|
| - throw new AssertionError(); |
| - } |
| - |
| - @Override |
| public InterfaceType getArrayLiteralType(Type value) { |
| - throw new AssertionError(); |
| + return defaultArrayType; |
| } |
| @Override |
| public InterfaceType getMapLiteralType(Type key, Type value) { |
| - throw new AssertionError(); |
| + return defaultMapType; |
| } |
| @Override |
| @@ -190,4 +224,161 @@ abstract class ResolverTestCase extends TestCase { |
| throw new AssertionError(); |
| } |
| } |
| + |
| + protected static DartTypeNode makeType(String name, String... arguments) { |
| + List<DartTypeNode> argumentNodes = makeTypes(arguments); |
| + return new DartTypeNode(new DartIdentifier(name), argumentNodes); |
| + } |
| + |
| + static List<DartTypeNode> makeTypes(String... typeNames) { |
| + List<DartTypeNode> types = new ArrayList<DartTypeNode>(); |
| + for (String typeName : typeNames) { |
| + types.add(makeType(typeName)); |
| + } |
| + return types; |
| + } |
| + |
| + |
| + protected static DartUnit makeUnit(DartNode... topLevelElements) { |
| + DartUnit unit = new DartUnit(null); |
| + for (DartNode topLevelElement : topLevelElements) { |
| + unit.addTopLevelNode(topLevelElement); |
| + } |
| + return unit; |
| + } |
| + |
| + protected DartUnit parseUnit(String firstLine, String secondLine, String... rest) { |
| + return parseUnit(Joiner.on('\n').join(firstLine, secondLine, (Object[]) rest).toString()); |
| + } |
| + |
| + protected DartUnit parseUnit(String string) { |
| + DartSourceString source = new DartSourceString("<source string>", string); |
| + return getParser(string).parseUnit(source); |
| + } |
| + |
| + private DartParser getParser(String string) { |
| + return new DartParser(new DartScannerParserContext(null, string, getListener())); |
| + } |
| + |
| + private DartCompilerListener getListener() { |
| + return new DartCompilerListener() { |
| + @Override |
| + public void compilationError(DartCompilationError event) { |
| + encounteredErrors.add(event); |
| + } |
| + |
| + @Override |
| + public void compilationWarning(DartCompilationError event) { |
| + compilationError(event); |
| + } |
| + |
| + @Override |
| + public void typeError(DartCompilationError event) { |
| + compilationError(event); |
| + } |
| + }; |
| + } |
| + |
| + protected void checkExpectedErrors(ErrorCode[] errorCodes) { |
| + checkExpectedErrors(encounteredErrors, errorCodes, null); |
| + } |
| + |
| + /** |
| + * Given a list of errors encountered during parse/resolve, compare them to |
| + * a list of expected error codes. |
| + * |
| + * @param encountered errors actually encountered |
| + * @param errorCodes expected errors. |
| + */ |
| + protected void checkExpectedErrors(List<DartCompilationError> encountered, |
| + ErrorCode[] errorCodes, |
| + String source) { |
| + if (errorCodes.length != encountered.size()) { |
| + printSource(source); |
| + printEncountered(encountered); |
| + assertEquals(errorCodes.length, encountered.size()); |
| + } |
| + int index = 0; |
| + for (ErrorCode errorCode : errorCodes) { |
| + ErrorCode found = encountered.get(index).getErrorCode(); |
| + if (!found.equals(errorCode)) { |
| + printSource(source); |
| + printEncountered(encountered); |
| + assertEquals("Unexpected Error Code: ", errorCode, found); |
| + } |
| + index++; |
| + } |
| + } |
| + |
| + /** |
| + * Returns a context with a listener that remembers all DartCompilationErrors and records |
| + * them. |
| + * @return |
| + */ |
| + protected TestCompilerContext getContext() { |
| + return new TestCompilerContext() { |
| + @Override |
| + public void compilationError(DartCompilationError event) { |
| + recordError(event); |
| + } |
| + }; |
| + } |
| + |
| + /** |
| + * Resets the global list of encountered errors. Call this before evaluating a new test. |
| + */ |
| + protected void resetExpectedErrors() { |
| + encounteredErrors = Lists.newArrayList(); |
| + } |
| + |
| + /** |
| + * Save an error event in the global list of encountered errors. For use by |
| + * custom {@link DartCompilerListener} implementations. |
| + */ |
| + protected void recordError(DartCompilationError event) { |
| + encounteredErrors.add(event); |
| + } |
| + |
| + protected void printSource(String source) { |
| + if (source != null) { |
| + int count = 1; |
| + for (String line : Splitter.on("\n").split(source)) { |
| + System.out.println(String.format(" %02d: %s", count++, line)); |
| + } |
| + } |
| + } |
| + /** |
| + * For debugging. |
| + */ |
| + protected void printEncountered(List<DartCompilationError> encountered) { |
| + for (DartCompilationError error : encountered) { |
| + DartCompilerErrorCode errorCode = (DartCompilerErrorCode) error |
| + .getErrorCode(); |
| + String msg = String.format("%s > %s (%d:%d)", errorCode.name(), error |
| + .getMessage(), error.getLineNumber(), error.getColumnNumber()); |
| + System.out.println(msg); |
| + } |
| + } |
| + |
| + /** |
| + * Convenience method to parse and resolve a code snippet, then test for error codes. |
| + */ |
| + protected void resolveAndTest(String source, ErrorCode... errorCodes) { |
| + resetExpectedErrors(); |
| + final List<DartCompilationError> encountered = Lists.newArrayList(); |
| + TestCompilerContext ctx = new TestCompilerContext() { |
| + @Override |
| + public void compilationError(DartCompilationError event) { |
| + encountered.add(event); |
| + } |
| + }; |
| + DartUnit unit = parseUnit(source); |
| + if (encounteredErrors.size() != 0) { |
| + printSource(source); |
| + printEncountered(encounteredErrors); |
| + assertEquals("Expected no errors in parse step:", 0, encountered.size()); |
| + } |
| + resolve(unit, ctx); |
| + checkExpectedErrors(encountered, errorCodes, source); |
| + } |
| } |