Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(676)

Unified Diff: compiler/javatests/com/google/dart/compiler/end2end/inc/IncrementalCompilation2Test.java

Issue 9148026: Recompile unit with potential conflict/dependency on some top-level symbol. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge/dart
Patch Set: Rebase and merge Created 8 years, 11 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
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..3ea5e90495bfc30b687a1f1c4c50617cd4225628
--- /dev/null
+++ b/compiler/javatests/com/google/dart/compiler/end2end/inc/IncrementalCompilation2Test.java
@@ -0,0 +1,561 @@
+// 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",
+ "#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);
+ }
+
+ /**
+ * Test for "hole" feature. If we use unqualified invocation and add/remove top-level method, this
+ * should cause compilation of invocation unit.
+ */
+ public void test_isMethodHole_useUnqualifiedInvocation() {
+ appSource.setContent(
+ "B.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class A {",
+ " foo() {}",
+ "}",
+ ""));
+ appSource.setContent(
+ "C.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class B extends A {",
+ " int bar() {",
+ " foo();", // unqualified invocation
+ " }",
+ "}",
+ ""));
+ compile();
+ assertErrors(errors);
+ // Declare top-level foo(), now invocation of foo() in B should be bound to this top-level.
+ {
+ appSource.setContent(
+ "A.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "foo() {}",
+ ""));
+ compile();
+ // B should be compiled because it also declares foo(), so produces "shadow" conflict.
+ // C should be compiled because it has unqualified invocation which was declared in A.
+ didWrite("A.dart", EXTENSION_JS);
+ didWrite("B.dart", EXTENSION_JS);
+ didWrite("C.dart", EXTENSION_JS);
+ assertAppBuilt();
+ }
+ // Remove top-level foo(), so invocation of foo() in B should be bound to the super class.
+ {
+ appSource.setContent("A.dart", "");
+ compile();
+ // B should be compiled because it also declares foo(), so produces "shadow" conflict.
+ // C should be compiled because it has unqualified invocation which was declared in A.
+ didWrite("A.dart", EXTENSION_JS);
+ didWrite("B.dart", EXTENSION_JS);
+ didWrite("C.dart", EXTENSION_JS);
+ }
+ }
+
+ /**
+ * Test for "hole" feature. If we use qualified invocation and add/remove top-level method, this
+ * should not cause compilation of invocation unit.
+ */
+ public void test_notMethodHole_useQualifiedInvocation() {
+ appSource.setContent(
+ "B.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class A {",
+ " foo() {}",
+ "}",
+ ""));
+ appSource.setContent(
+ "C.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class B extends A {",
+ " int bar() {",
+ " super.foo();", // qualified invocation
+ " }",
+ "}",
+ ""));
+ compile();
+ assertErrors(errors);
+ // Declare top-level foo(), but it is ignored.
+ {
+ appSource.setContent(
+ "A.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "foo() {}",
+ ""));
+ compile();
+ // B should be compiled because it also declares foo(), so produces "shadow" conflict.
+ // C should not be compiled because.
+ didWrite("A.dart", EXTENSION_JS);
+ didWrite("B.dart", EXTENSION_JS);
+ didNotWrite("C.dart", EXTENSION_JS);
+ assertAppBuilt();
+ }
+ }
+
+ /**
+ * Test for "hole" feature. If we use unqualified access and add/remove top-level field, this
+ * should cause compilation of invocation unit.
+ */
+ public void test_fieldHole_useUnqualifiedAccess() {
+ appSource.setContent(
+ "B.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class A {",
+ " var foo;",
+ "}",
+ ""));
+ appSource.setContent(
+ "C.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class B extends A {",
+ " int bar() {",
+ " foo = 0;", // unqualified access
+ " }",
+ "}",
+ ""));
+ compile();
+ assertErrors(errors);
+ // Declare top-level "foo", now access to "foo" in B should be bound to this top-level.
+ {
+ appSource.setContent(
+ "A.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "var foo;",
+ ""));
+ compile();
+ // B should be compiled because it also declares "foo", so produces "shadow" conflict.
+ // C should be compiled because it has unqualified invocation which was declared in A.
+ didWrite("A.dart", EXTENSION_JS);
+ didWrite("B.dart", EXTENSION_JS);
+ didWrite("C.dart", EXTENSION_JS);
+ assertAppBuilt();
+ }
+ // Remove top-level "foo", so access to "foo" in B should be bound to the super class.
+ {
+ appSource.setContent("A.dart", "");
+ compile();
+ // B should be compiled because it also declares "foo", so produces "shadow" conflict.
+ // C should be compiled because it has unqualified access which was declared in A.
+ didWrite("A.dart", EXTENSION_JS);
+ didWrite("B.dart", EXTENSION_JS);
+ didWrite("C.dart", EXTENSION_JS);
+ }
+ }
+
+ /**
+ * Test for "hole" feature. If we use qualified access and add/remove top-level field, this should
+ * not cause compilation of invocation unit.
+ */
+ public void test_gieldHole_useQualifiedAccess() {
+ appSource.setContent(
+ "B.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class A {",
+ " var foo;",
+ "}",
+ ""));
+ appSource.setContent(
+ "C.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "class B extends A {",
+ " int bar() {",
+ " super.foo = 0;", // qualified access
+ " }",
+ "}",
+ ""));
+ compile();
+ assertErrors(errors);
+ // Declare top-level "foo", but it is ignored.
+ {
+ appSource.setContent(
+ "A.dart",
+ makeCode(
+ "// filler filler filler filler filler filler filler filler filler filler filler",
+ "var foo;",
+ ""));
+ compile();
+ // B should be compiled because it also declares "foo", so produces "shadow" conflict.
+ // C should not be compiled because it has qualified access to "foo".
+ didWrite("A.dart", EXTENSION_JS);
+ didWrite("B.dart", EXTENSION_JS);
+ didNotWrite("C.dart", EXTENSION_JS);
+ assertAppBuilt();
+ }
+ }
+
+ 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));
+ }
+}

Powered by Google App Engine
This is Rietveld 408576698