Chromium Code Reviews| Index: compiler/javatests/com/google/dart/compiler/end2end/inc/IncrementalCompilation2Test.java |
| diff --git a/compiler/javatests/com/google/dart/compiler/end2end/inc/IncrementalCompilation2Test.java b/compiler/javatests/com/google/dart/compiler/end2end/inc/IncrementalCompilation2Test.java |
| new file mode 100644 |
| index 0000000000000000000000000000000000000000..b2aad0bc1079a85e081909b0d3b8e90fb462fa4d |
| --- /dev/null |
| +++ b/compiler/javatests/com/google/dart/compiler/end2end/inc/IncrementalCompilation2Test.java |
| @@ -0,0 +1,369 @@ |
| +// Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file |
| +// for details. All rights reserved. Use of this source code is governed by a |
| +// BSD-style license that can be found in the LICENSE file. |
| +package com.google.dart.compiler.end2end.inc; |
| + |
| +import static com.google.dart.compiler.DartCompiler.EXTENSION_DEPS; |
| +import static com.google.dart.compiler.backend.js.AbstractJsBackend.EXTENSION_APP_JS; |
| +import static com.google.dart.compiler.backend.js.AbstractJsBackend.EXTENSION_JS; |
| +import static com.google.dart.compiler.common.ErrorExpectation.assertErrors; |
| +import static com.google.dart.compiler.common.ErrorExpectation.errEx; |
| + |
| +import com.google.common.collect.Lists; |
| +import com.google.dart.compiler.CompilerTestCase; |
| +import com.google.dart.compiler.DartCompilationError; |
| +import com.google.dart.compiler.DartCompiler; |
| +import com.google.dart.compiler.DartCompilerListener; |
| +import com.google.dart.compiler.DefaultCompilerConfiguration; |
| +import com.google.dart.compiler.LibrarySource; |
| +import com.google.dart.compiler.MockArtifactProvider; |
| +import com.google.dart.compiler.Source; |
| +import com.google.dart.compiler.backend.js.JavascriptBackend; |
| +import com.google.dart.compiler.resolver.ResolverErrorCode; |
| +import com.google.dart.compiler.resolver.TypeErrorCode; |
| + |
| +import junit.framework.AssertionFailedError; |
| + |
| +import java.io.IOException; |
| +import java.io.Reader; |
| +import java.io.StringReader; |
| +import java.io.Writer; |
| +import java.util.List; |
| +import java.util.Set; |
| +import java.util.concurrent.ConcurrentSkipListSet; |
| + |
| +public class IncrementalCompilation2Test extends CompilerTestCase { |
| + private static final String APP = "Application.dart"; |
| + |
| + private static class IncMockArtifactProvider extends MockArtifactProvider { |
| + Set<String> reads = new ConcurrentSkipListSet<String>(); |
| + Set<String> writes = new ConcurrentSkipListSet<String>(); |
| + |
| + @Override |
| + public Reader getArtifactReader(Source source, String part, String extension) { |
| + reads.add(source.getName() + "/" + extension); |
| + return super.getArtifactReader(source, part, extension); |
| + } |
| + |
| + @Override |
| + public Writer getArtifactWriter(Source source, String part, String extension) { |
| + writes.add(source.getName() + "/" + extension); |
| + return super.getArtifactWriter(source, part, extension); |
| + } |
| + |
| + void resetReadsAndWrites() { |
| + reads.clear(); |
| + writes.clear(); |
| + } |
| + } |
| + |
| + private DefaultCompilerConfiguration config; |
| + private IncMockArtifactProvider provider; |
| + private MemoryLibrarySource appSource; |
| + private long appSourceLastModified = 0; |
| + private String appSourceContent = makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
|
codefu
2012/01/19 21:48:54
I'm going to channel my inner-Mendez and ask what
scheglov
2012/01/20 15:59:24
"filler" line makes invocation long enough to forc
|
| + "#library('application');", |
| + "#source('A.dart');", |
| + "#source('B.dart');", |
| + "#source('C.dart');", |
| + ""); |
| + private final List<DartCompilationError> errors = Lists.newArrayList(); |
| + |
| + @Override |
| + protected void setUp() throws Exception { |
| + config = new DefaultCompilerConfiguration(new JavascriptBackend()) { |
| + @Override |
| + public boolean incremental() { |
| + return true; |
| + } |
| + }; |
| + provider = new IncMockArtifactProvider(); |
| + appSource = new MemoryLibrarySource(APP, "<not-used>") { |
| + @Override |
| + public long getLastModified() { |
| + return appSourceLastModified; |
| + } |
| + |
| + @Override |
| + public Reader getSourceReader() throws IOException { |
| + return new StringReader(appSourceContent); |
| + } |
| + }; |
| + appSource.setContent("A.dart", ""); |
| + appSource.setContent("B.dart", ""); |
| + appSource.setContent("C.dart", ""); |
| + } |
| + |
| + @Override |
| + protected void tearDown() { |
| + config = null; |
| + provider = null; |
| + appSource = null; |
| + } |
| + |
| + /** |
| + * "not_hole" is referenced using "super" qualifier, so is not affected by declaring top-level |
| + * field with same name. |
| + */ |
| + public void test_useQualifiedFieldReference_ignoreTopLevelDeclaration() { |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "class A {", |
| + " int not_hole;", |
| + "}", |
| + "")); |
| + appSource.setContent( |
| + "C.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "class B extends A {", |
| + " int bar() {", |
| + " return super.not_hole;", // qualified reference |
| + " }", |
| + "}", |
| + "")); |
| + compile(); |
| + assertErrors(errors); |
| + // Update units and compile. |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "int not_hole;", |
| + "")); |
| + compile(); |
| + // TODO(scheglov) Fix this after 1159 |
| + //assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNING, -1, 7, 20)); |
| + // B should be compiled because it now conflicts with A. |
| + // C should not be compiled, because it reference "not_hole" field, not top-level variable. |
| + didWrite("A.dart", EXTENSION_JS); |
| + didWrite("B.dart", EXTENSION_JS); |
| + didNotWrite("C.dart", EXTENSION_JS); |
| + assertAppBuilt(); |
| + } |
| + |
| + /** |
| + * Referenced "hole" identifier can not be resolved, but when we declare it in A, then B should be |
| + * recompiled and error message disappear. |
| + */ |
| + public void test_useUnresolvedField_recompileOnTopLevelDeclaration() { |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "class A {", |
| + " int foo() {", |
| + " return hole;", // no such field |
| + " }", |
| + "}", |
| + "")); |
| + compile(); |
| + assertErrors(errors, errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 4, 12, 4)); |
| + // Update units and compile. |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "int hole;", |
| + "")); |
| + compile(); |
| + // A and B should be compiled. |
| + didWrite("A.dart", EXTENSION_JS); |
| + didWrite("B.dart", EXTENSION_JS); |
| + assertAppBuilt(); |
| + // "hole" was filled with top-level field. |
| + assertErrors(errors); |
| + } |
| + |
| + public void test_declareTopLevel_conflictWithLocalVariable() { |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "methodB() {", |
| + " var symbolDependency_foo;", |
| + "}")); |
| + compile(); |
| + assertErrors(errors); |
| + // Update units and compile. |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "var symbolDependency_foo;")); |
| + compile(); |
| + // Now there is top-level declarations conflict between A and B. |
| + // So, B should be compiled. |
| + didWrite("B.dart", EXTENSION_JS); |
| + // But application should be build. |
| + assertAppBuilt(); |
| + // Because B was compiled, it has warning. |
| + assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNING, 3, 7, 20)); |
| + } |
| + |
| + public void test_undeclareTopLevel_conflictWithLocalVariable() { |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "var duplicate;")); |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "bar() {", |
| + " var duplicate;", |
| + "}")); |
| + compile(); |
| + assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNING, 3, 7, 9)); |
| + // Update units and compile. |
| + appSource.setContent("A.dart", ""); |
| + compile(); |
| + // Top-level declaration in A was removed, so no conflict. |
| + // So: |
| + // ... B should be recompiled. |
| + didWrite("B.dart", EXTENSION_JS); |
| + // ... but application should be rebuild. |
| + assertAppBuilt(); |
| + // Because B was recompiled, it has no warning. |
| + assertErrors(errors); |
| + } |
| + |
| + /** |
| + * Removes A, so changes set of top level units and forces compilation. |
| + */ |
| + public void test_removeOneSource() { |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "var duplicate;")); |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "bar() {", |
| + " var duplicate;", |
| + "}")); |
| + compile(); |
| + assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNING, 3, 7, 9)); |
| + // Exclude A and compile. |
| + appSourceLastModified++; |
| + appSourceContent = |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "#library('app');", |
| + "#source('B.dart');", |
| + ""); |
| + compile(); |
| + // Now there is top-level declarations conflict between A and B. |
| + // So: |
| + // ... B should be recompiled. |
| + didWrite("B.dart", EXTENSION_JS); |
| + // ... but application should be rebuild. |
| + didWrite(APP, EXTENSION_DEPS); |
| + didWrite(APP, EXTENSION_APP_JS); |
| + // Because B was recompiled, it has no warning. |
| + assertErrors(errors); |
| + } |
| + |
| + public void test_declareField_conflictWithLocalVariable() { |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "class A {", |
| + "}", |
| + "")); |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "class B extends A {", |
| + " foo() {", |
| + " var bar;", |
| + " }", |
| + "}", |
| + "")); |
| + compile(); |
| + assertErrors(errors); |
| + // Update units and compile. |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "class A {", |
| + " var bar;", |
| + "}", |
| + "")); |
| + compile(); |
| + // B depends on A class, so compiled. |
| + didWrite("B.dart", EXTENSION_JS); |
| + assertAppBuilt(); |
| + // Because B was compiled, it has warning. |
| + assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNING, 4, 9, 3)); |
| + } |
| + |
| + public void test_declareTopLevelVariable_conflictOtherTopLevelVariable() { |
| + appSource.setContent( |
| + "A.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "var conflict;", |
| + "")); |
| + compile(); |
| + assertErrors(errors); |
| + // Update units and compile. |
| + appSource.setContent( |
| + "B.dart", |
| + makeCode( |
| + "// filler filler filler filler filler filler filler filler filler filler filler", |
| + "var conflict;", |
| + "")); |
| + compile(); |
| + // A symbols intersect with new B symbols, so we compile A too. |
| + // Both A and B have errors. |
| + assertErrors( |
| + errors, |
| + errEx("A.dart", ResolverErrorCode.DUPLICATE_TOP_LEVEL_DEFINITION, 2, 5, 8), |
| + errEx("B.dart", ResolverErrorCode.DUPLICATE_TOP_LEVEL_DEFINITION, 2, 5, 8)); |
| + } |
| + |
| + private void assertAppBuilt() { |
| + didWrite(APP, EXTENSION_DEPS); |
| + didWrite(APP, EXTENSION_APP_JS); |
| + } |
| + |
| + private void compile() { |
| + compile(appSource); |
| + } |
| + |
| + private void compile(LibrarySource lib) { |
| + try { |
| + provider.resetReadsAndWrites(); |
| + errors.clear(); |
| + DartCompilerListener listener = new DartCompilerListener.Empty() { |
| + @Override |
| + public void onError(DartCompilationError event) { |
| + errors.add(event); |
| + } |
| + }; |
| + DartCompiler.compileLib(lib, config, provider, listener); |
| + } catch (IOException e) { |
| + throw new AssertionFailedError("Unexpected IOException: " + e.getMessage()); |
| + } |
| + } |
| + |
| + private void didWrite(String sourceName, String extension) { |
| + String spec = sourceName + "/" + extension; |
| + assertTrue("Expected write: " + spec, provider.writes.contains(spec)); |
| + } |
| + |
| + private void didNotWrite(String sourceName, String extension) { |
| + String spec = sourceName + "/" + extension; |
| + assertFalse("Didn't expect write: " + spec, provider.writes.contains(spec)); |
| + } |
| +} |