Chromium Code Reviews| OLD | NEW |
|---|---|
| (Empty) | |
| 1 // Copyright (c) 2011, the Dart project authors. Please see the AUTHORS file | |
| 2 // for details. All rights reserved. Use of this source code is governed by a | |
| 3 // BSD-style license that can be found in the LICENSE file. | |
| 4 package com.google.dart.compiler.end2end.inc; | |
| 5 | |
| 6 import static com.google.dart.compiler.DartCompiler.EXTENSION_DEPS; | |
| 7 import static com.google.dart.compiler.backend.js.AbstractJsBackend.EXTENSION_AP P_JS; | |
| 8 import static com.google.dart.compiler.backend.js.AbstractJsBackend.EXTENSION_JS ; | |
| 9 import static com.google.dart.compiler.common.ErrorExpectation.assertErrors; | |
| 10 import static com.google.dart.compiler.common.ErrorExpectation.errEx; | |
| 11 | |
| 12 import com.google.common.collect.Lists; | |
| 13 import com.google.dart.compiler.CompilerTestCase; | |
| 14 import com.google.dart.compiler.DartCompilationError; | |
| 15 import com.google.dart.compiler.DartCompiler; | |
| 16 import com.google.dart.compiler.DartCompilerListener; | |
| 17 import com.google.dart.compiler.DefaultCompilerConfiguration; | |
| 18 import com.google.dart.compiler.LibrarySource; | |
| 19 import com.google.dart.compiler.MockArtifactProvider; | |
| 20 import com.google.dart.compiler.Source; | |
| 21 import com.google.dart.compiler.backend.js.JavascriptBackend; | |
| 22 import com.google.dart.compiler.resolver.ResolverErrorCode; | |
| 23 import com.google.dart.compiler.resolver.TypeErrorCode; | |
| 24 | |
| 25 import junit.framework.AssertionFailedError; | |
| 26 | |
| 27 import java.io.IOException; | |
| 28 import java.io.Reader; | |
| 29 import java.io.StringReader; | |
| 30 import java.io.Writer; | |
| 31 import java.util.List; | |
| 32 import java.util.Set; | |
| 33 import java.util.concurrent.ConcurrentSkipListSet; | |
| 34 | |
| 35 public class IncrementalCompilation2Test extends CompilerTestCase { | |
| 36 private static final String APP = "Application.dart"; | |
| 37 | |
| 38 private static class IncMockArtifactProvider extends MockArtifactProvider { | |
| 39 Set<String> reads = new ConcurrentSkipListSet<String>(); | |
| 40 Set<String> writes = new ConcurrentSkipListSet<String>(); | |
| 41 | |
| 42 @Override | |
| 43 public Reader getArtifactReader(Source source, String part, String extension ) { | |
| 44 reads.add(source.getName() + "/" + extension); | |
| 45 return super.getArtifactReader(source, part, extension); | |
| 46 } | |
| 47 | |
| 48 @Override | |
| 49 public Writer getArtifactWriter(Source source, String part, String extension ) { | |
| 50 writes.add(source.getName() + "/" + extension); | |
| 51 return super.getArtifactWriter(source, part, extension); | |
| 52 } | |
| 53 | |
| 54 void resetReadsAndWrites() { | |
| 55 reads.clear(); | |
| 56 writes.clear(); | |
| 57 } | |
| 58 } | |
| 59 | |
| 60 private DefaultCompilerConfiguration config; | |
| 61 private IncMockArtifactProvider provider; | |
| 62 private MemoryLibrarySource appSource; | |
| 63 private long appSourceLastModified = 0; | |
| 64 private String appSourceContent = makeCode( | |
| 65 "// 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
| |
| 66 "#library('application');", | |
| 67 "#source('A.dart');", | |
| 68 "#source('B.dart');", | |
| 69 "#source('C.dart');", | |
| 70 ""); | |
| 71 private final List<DartCompilationError> errors = Lists.newArrayList(); | |
| 72 | |
| 73 @Override | |
| 74 protected void setUp() throws Exception { | |
| 75 config = new DefaultCompilerConfiguration(new JavascriptBackend()) { | |
| 76 @Override | |
| 77 public boolean incremental() { | |
| 78 return true; | |
| 79 } | |
| 80 }; | |
| 81 provider = new IncMockArtifactProvider(); | |
| 82 appSource = new MemoryLibrarySource(APP, "<not-used>") { | |
| 83 @Override | |
| 84 public long getLastModified() { | |
| 85 return appSourceLastModified; | |
| 86 } | |
| 87 | |
| 88 @Override | |
| 89 public Reader getSourceReader() throws IOException { | |
| 90 return new StringReader(appSourceContent); | |
| 91 } | |
| 92 }; | |
| 93 appSource.setContent("A.dart", ""); | |
| 94 appSource.setContent("B.dart", ""); | |
| 95 appSource.setContent("C.dart", ""); | |
| 96 } | |
| 97 | |
| 98 @Override | |
| 99 protected void tearDown() { | |
| 100 config = null; | |
| 101 provider = null; | |
| 102 appSource = null; | |
| 103 } | |
| 104 | |
| 105 /** | |
| 106 * "not_hole" is referenced using "super" qualifier, so is not affected by dec laring top-level | |
| 107 * field with same name. | |
| 108 */ | |
| 109 public void test_useQualifiedFieldReference_ignoreTopLevelDeclaration() { | |
| 110 appSource.setContent( | |
| 111 "B.dart", | |
| 112 makeCode( | |
| 113 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 114 "class A {", | |
| 115 " int not_hole;", | |
| 116 "}", | |
| 117 "")); | |
| 118 appSource.setContent( | |
| 119 "C.dart", | |
| 120 makeCode( | |
| 121 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 122 "class B extends A {", | |
| 123 " int bar() {", | |
| 124 " return super.not_hole;", // qualified reference | |
| 125 " }", | |
| 126 "}", | |
| 127 "")); | |
| 128 compile(); | |
| 129 assertErrors(errors); | |
| 130 // Update units and compile. | |
| 131 appSource.setContent( | |
| 132 "A.dart", | |
| 133 makeCode( | |
| 134 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 135 "int not_hole;", | |
| 136 "")); | |
| 137 compile(); | |
| 138 // TODO(scheglov) Fix this after 1159 | |
| 139 //assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARN ING, -1, 7, 20)); | |
| 140 // B should be compiled because it now conflicts with A. | |
| 141 // C should not be compiled, because it reference "not_hole" field, not top- level variable. | |
| 142 didWrite("A.dart", EXTENSION_JS); | |
| 143 didWrite("B.dart", EXTENSION_JS); | |
| 144 didNotWrite("C.dart", EXTENSION_JS); | |
| 145 assertAppBuilt(); | |
| 146 } | |
| 147 | |
| 148 /** | |
| 149 * Referenced "hole" identifier can not be resolved, but when we declare it in A, then B should be | |
| 150 * recompiled and error message disappear. | |
| 151 */ | |
| 152 public void test_useUnresolvedField_recompileOnTopLevelDeclaration() { | |
| 153 appSource.setContent( | |
| 154 "B.dart", | |
| 155 makeCode( | |
| 156 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 157 "class A {", | |
| 158 " int foo() {", | |
| 159 " return hole;", // no such field | |
| 160 " }", | |
| 161 "}", | |
| 162 "")); | |
| 163 compile(); | |
| 164 assertErrors(errors, errEx(TypeErrorCode.CANNOT_BE_RESOLVED, 4, 12, 4)); | |
| 165 // Update units and compile. | |
| 166 appSource.setContent( | |
| 167 "A.dart", | |
| 168 makeCode( | |
| 169 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 170 "int hole;", | |
| 171 "")); | |
| 172 compile(); | |
| 173 // A and B should be compiled. | |
| 174 didWrite("A.dart", EXTENSION_JS); | |
| 175 didWrite("B.dart", EXTENSION_JS); | |
| 176 assertAppBuilt(); | |
| 177 // "hole" was filled with top-level field. | |
| 178 assertErrors(errors); | |
| 179 } | |
| 180 | |
| 181 public void test_declareTopLevel_conflictWithLocalVariable() { | |
| 182 appSource.setContent( | |
| 183 "B.dart", | |
| 184 makeCode( | |
| 185 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 186 "methodB() {", | |
| 187 " var symbolDependency_foo;", | |
| 188 "}")); | |
| 189 compile(); | |
| 190 assertErrors(errors); | |
| 191 // Update units and compile. | |
| 192 appSource.setContent( | |
| 193 "A.dart", | |
| 194 makeCode( | |
| 195 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 196 "var symbolDependency_foo;")); | |
| 197 compile(); | |
| 198 // Now there is top-level declarations conflict between A and B. | |
| 199 // So, B should be compiled. | |
| 200 didWrite("B.dart", EXTENSION_JS); | |
| 201 // But application should be build. | |
| 202 assertAppBuilt(); | |
| 203 // Because B was compiled, it has warning. | |
| 204 assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNIN G, 3, 7, 20)); | |
| 205 } | |
| 206 | |
| 207 public void test_undeclareTopLevel_conflictWithLocalVariable() { | |
| 208 appSource.setContent( | |
| 209 "A.dart", | |
| 210 makeCode( | |
| 211 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 212 "var duplicate;")); | |
| 213 appSource.setContent( | |
| 214 "B.dart", | |
| 215 makeCode( | |
| 216 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 217 "bar() {", | |
| 218 " var duplicate;", | |
| 219 "}")); | |
| 220 compile(); | |
| 221 assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNIN G, 3, 7, 9)); | |
| 222 // Update units and compile. | |
| 223 appSource.setContent("A.dart", ""); | |
| 224 compile(); | |
| 225 // Top-level declaration in A was removed, so no conflict. | |
| 226 // So: | |
| 227 // ... B should be recompiled. | |
| 228 didWrite("B.dart", EXTENSION_JS); | |
| 229 // ... but application should be rebuild. | |
| 230 assertAppBuilt(); | |
| 231 // Because B was recompiled, it has no warning. | |
| 232 assertErrors(errors); | |
| 233 } | |
| 234 | |
| 235 /** | |
| 236 * Removes A, so changes set of top level units and forces compilation. | |
| 237 */ | |
| 238 public void test_removeOneSource() { | |
| 239 appSource.setContent( | |
| 240 "A.dart", | |
| 241 makeCode( | |
| 242 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 243 "var duplicate;")); | |
| 244 appSource.setContent( | |
| 245 "B.dart", | |
| 246 makeCode( | |
| 247 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 248 "bar() {", | |
| 249 " var duplicate;", | |
| 250 "}")); | |
| 251 compile(); | |
| 252 assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNIN G, 3, 7, 9)); | |
| 253 // Exclude A and compile. | |
| 254 appSourceLastModified++; | |
| 255 appSourceContent = | |
| 256 makeCode( | |
| 257 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 258 "#library('app');", | |
| 259 "#source('B.dart');", | |
| 260 ""); | |
| 261 compile(); | |
| 262 // Now there is top-level declarations conflict between A and B. | |
| 263 // So: | |
| 264 // ... B should be recompiled. | |
| 265 didWrite("B.dart", EXTENSION_JS); | |
| 266 // ... but application should be rebuild. | |
| 267 didWrite(APP, EXTENSION_DEPS); | |
| 268 didWrite(APP, EXTENSION_APP_JS); | |
| 269 // Because B was recompiled, it has no warning. | |
| 270 assertErrors(errors); | |
| 271 } | |
| 272 | |
| 273 public void test_declareField_conflictWithLocalVariable() { | |
| 274 appSource.setContent( | |
| 275 "A.dart", | |
| 276 makeCode( | |
| 277 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 278 "class A {", | |
| 279 "}", | |
| 280 "")); | |
| 281 appSource.setContent( | |
| 282 "B.dart", | |
| 283 makeCode( | |
| 284 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 285 "class B extends A {", | |
| 286 " foo() {", | |
| 287 " var bar;", | |
| 288 " }", | |
| 289 "}", | |
| 290 "")); | |
| 291 compile(); | |
| 292 assertErrors(errors); | |
| 293 // Update units and compile. | |
| 294 appSource.setContent( | |
| 295 "A.dart", | |
| 296 makeCode( | |
| 297 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 298 "class A {", | |
| 299 " var bar;", | |
| 300 "}", | |
| 301 "")); | |
| 302 compile(); | |
| 303 // B depends on A class, so compiled. | |
| 304 didWrite("B.dart", EXTENSION_JS); | |
| 305 assertAppBuilt(); | |
| 306 // Because B was compiled, it has warning. | |
| 307 assertErrors(errors, errEx(ResolverErrorCode.DUPLICATE_LOCAL_VARIABLE_WARNIN G, 4, 9, 3)); | |
| 308 } | |
| 309 | |
| 310 public void test_declareTopLevelVariable_conflictOtherTopLevelVariable() { | |
| 311 appSource.setContent( | |
| 312 "A.dart", | |
| 313 makeCode( | |
| 314 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 315 "var conflict;", | |
| 316 "")); | |
| 317 compile(); | |
| 318 assertErrors(errors); | |
| 319 // Update units and compile. | |
| 320 appSource.setContent( | |
| 321 "B.dart", | |
| 322 makeCode( | |
| 323 "// filler filler filler filler filler filler filler filler filler f iller filler", | |
| 324 "var conflict;", | |
| 325 "")); | |
| 326 compile(); | |
| 327 // A symbols intersect with new B symbols, so we compile A too. | |
| 328 // Both A and B have errors. | |
| 329 assertErrors( | |
| 330 errors, | |
| 331 errEx("A.dart", ResolverErrorCode.DUPLICATE_TOP_LEVEL_DEFINITION, 2, 5, 8), | |
| 332 errEx("B.dart", ResolverErrorCode.DUPLICATE_TOP_LEVEL_DEFINITION, 2, 5, 8)); | |
| 333 } | |
| 334 | |
| 335 private void assertAppBuilt() { | |
| 336 didWrite(APP, EXTENSION_DEPS); | |
| 337 didWrite(APP, EXTENSION_APP_JS); | |
| 338 } | |
| 339 | |
| 340 private void compile() { | |
| 341 compile(appSource); | |
| 342 } | |
| 343 | |
| 344 private void compile(LibrarySource lib) { | |
| 345 try { | |
| 346 provider.resetReadsAndWrites(); | |
| 347 errors.clear(); | |
| 348 DartCompilerListener listener = new DartCompilerListener.Empty() { | |
| 349 @Override | |
| 350 public void onError(DartCompilationError event) { | |
| 351 errors.add(event); | |
| 352 } | |
| 353 }; | |
| 354 DartCompiler.compileLib(lib, config, provider, listener); | |
| 355 } catch (IOException e) { | |
| 356 throw new AssertionFailedError("Unexpected IOException: " + e.getMessage() ); | |
| 357 } | |
| 358 } | |
| 359 | |
| 360 private void didWrite(String sourceName, String extension) { | |
| 361 String spec = sourceName + "/" + extension; | |
| 362 assertTrue("Expected write: " + spec, provider.writes.contains(spec)); | |
| 363 } | |
| 364 | |
| 365 private void didNotWrite(String sourceName, String extension) { | |
| 366 String spec = sourceName + "/" + extension; | |
| 367 assertFalse("Didn't expect write: " + spec, provider.writes.contains(spec)); | |
| 368 } | |
| 369 } | |
| OLD | NEW |