Index: dart/pkg/dart2js_incremental/lib/library_updater.dart |
diff --git a/dart/pkg/dart2js_incremental/lib/library_updater.dart b/dart/pkg/dart2js_incremental/lib/library_updater.dart |
index 14034c6ddfe50679935c8651c0ed0e6255226a61..7478f76f7a5d4a45a57e6c637c8b8f50231cfcbe 100644 |
--- a/dart/pkg/dart2js_incremental/lib/library_updater.dart |
+++ b/dart/pkg/dart2js_incremental/lib/library_updater.dart |
@@ -19,6 +19,7 @@ import 'package:compiler/src/dart2jslib.dart' show |
import 'package:compiler/src/elements/elements.dart' show |
ClassElement, |
+ CompilationUnitElement, |
Element, |
FunctionElement, |
LibraryElement, |
@@ -89,6 +90,9 @@ import 'package:compiler/src/universe/universe.dart' show |
import 'package:compiler/src/constants/values.dart' show |
ConstantValue; |
+import 'package:compiler/src/library_loader.dart' show |
+ TagState; |
+ |
import 'diff.dart' show |
Difference, |
computeDifference; |
@@ -185,6 +189,10 @@ class LibraryUpdater extends JsFeatures { |
bool _hasCapturedCompilerState = false; |
+ Token _entryUnitTokens; |
+ |
+ SourceFile _entrySourceFile; |
Johnni Winther
2014/12/19 12:17:33
What is the semantics of this?
ahe
2014/12/19 13:35:45
Done.
|
+ |
LibraryUpdater( |
this.compiler, |
this.inputProvider, |
@@ -233,43 +241,57 @@ class LibraryUpdater extends JsFeatures { |
" supported."); |
return true; |
} |
+ |
+ bool isChanged = false; |
+ List<Future<Script>> futureScripts = <Future<Script>>[]; |
+ |
for (CompilationUnitElementX unit in library.compilationUnits) { |
Uri uri = unit.script.resourceUri; |
if (_context._uriHasUpdate(uri)) { |
- if (!library.compilationUnits.tail.isEmpty) { |
- // TODO(ahe): Remove this restriction. |
- cannotReuse( |
- library, |
- "Multiple compilation units not supported" |
- " (${library.compilationUnits})."); |
- return true; |
- } |
- return _readUri(uri).then((bytes) { |
- return canReuseLibrary(library, bytes); |
- }); |
+ isChanged = true; |
+ futureScripts.add(_updatedScript(unit.script, library)); |
+ } else { |
+ futureScripts.add(new Future.value(unit.script)); |
} |
} |
- logTime("Reusing $library, source didn't change."); |
- // Source code of [library] wasn't changed. |
- return true; |
+ if (!isChanged) { |
+ logTime("Reusing $library, source didn't change."); |
+ return true; |
+ } |
+ |
+ return Future.wait(futureScripts).then( |
+ (List<Script> scripts) => canReuseLibrary(library, scripts)); |
+ }); |
+ } |
+ |
+ Future<Script> _updatedScript(Script before, LibraryElementX library) { |
+ if (before == library.entryCompilationUnit.script && |
+ _entrySourceFile != null) { |
+ return new Future.value(before.copyWithFile(_entrySourceFile)); |
+ } |
+ |
+ return _readUri(before.resourceUri).then((bytes) { |
+ String filename = before.file.filename; |
+ SourceFile sourceFile = bytes is String |
+ ? new StringSourceFile(filename, bytes) |
+ : new CachingUtf8BytesSourceFile(filename, bytes); |
+ return before.copyWithFile(sourceFile); |
}); |
} |
Future<bool> _haveTagsChanged(LibraryElement library) { |
- Uri uri = library.entryCompilationUnit.script.resourceUri; |
- if (!_context._uriHasUpdate(uri)) { |
+ Script before = library.entryCompilationUnit.script; |
+ if (!_context._uriHasUpdate(before.resourceUri)) { |
// The entry compilation unit hasn't been updated. So the tags aren't |
// changed. |
return new Future<bool>.value(false); |
} |
- return _readUri(uri).then((bytes) { |
- String filename = '$uri'; |
- SourceFile sourceFile = bytes is String |
- ? new StringSourceFile(filename, bytes) |
- : new CachingUtf8BytesSourceFile(filename, bytes); |
- Token token = new Scanner(sourceFile).tokenize(); |
+ return _updatedScript(before, library).then((Script script) { |
+ _entrySourceFile = script.file; |
+ Token token = new Scanner(_entrySourceFile).tokenize(); |
+ _entryUnitTokens = token; |
// Using two parsers to only create the nodes we want ([LibraryTag]). |
Parser parser = new Parser(new Listener()); |
NodeListener listener = new NodeListener( |
@@ -313,18 +335,59 @@ class LibraryUpdater extends JsFeatures { |
/// Returns true if [library] can be reused. |
/// |
/// This methods also computes the [updates] (patches) needed to have |
- /// [library] reflect the modifications in [bytes]. |
- bool canReuseLibrary(LibraryElement library, bytes) { |
+ /// [library] reflect the modifications in [scripts]. |
+ bool canReuseLibrary(LibraryElement library, List<Script> scripts) { |
logTime('Attempting to reuse ${library}.'); |
- String newSource = bytes is String ? bytes : UTF8.decode(bytes); |
- logTime('Decoded UTF8'); |
- |
- Uri uri = library.entryCompilationUnit.script.resourceUri; |
- Script sourceScript = new Script( |
- uri, uri, new StringSourceFile('$uri', newSource)); |
- var dartPrivacyIsBroken = compiler.libraryLoader; |
- LibraryElement newLibrary = dartPrivacyIsBroken.createLibrarySync( |
- null, sourceScript, uri); |
+ |
+ Uri entryUri = library.entryCompilationUnit.script.resourceUri; |
+ Script entryScript = |
+ scripts.singleWhere((Script script) => script.resourceUri == entryUri); |
+ LibraryElement newLibrary = |
+ new LibraryElementX(entryScript, library.canonicalUri); |
+ if (_entryUnitTokens != null) { |
+ compiler.dietParser.dietParse( |
+ newLibrary.entryCompilationUnit, _entryUnitTokens); |
+ } else { |
+ compiler.scanner.scanLibrary(newLibrary); |
+ } |
+ |
+ TagState tagState = new TagState(); |
+ for (LibraryTag tag in newLibrary.tags) { |
+ if (tag.isImport) { |
+ tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler); |
+ } else if (tag.isExport) { |
+ tagState.checkTag(TagState.IMPORT_OR_EXPORT, tag, compiler); |
+ } else if (tag.isLibraryName) { |
+ tagState.checkTag(TagState.LIBRARY, tag, compiler); |
+ if (newLibrary.libraryTag == null) { |
+ // Use the first if there are multiple (which is reported as an |
+ // error in [TagState.checkTag]). |
+ newLibrary.libraryTag = tag; |
+ } |
+ } else if (tag.isPart) { |
+ tagState.checkTag(TagState.PART, tag, compiler); |
+ } |
+ } |
+ |
+ // TODO(ahe): Process tags using TagState, not |
+ // LibraryLoaderTask.processLibraryTags. |
+ Link<CompilationUnitElement> units = library.compilationUnits; |
+ for (Script script in scripts) { |
+ CompilationUnitElementX unit = units.head; |
+ units = units.tail; |
+ if (script != entryScript) { |
+ // TODO(ahe): Copied form library_loader. |
Johnni Winther
2014/12/19 12:17:33
'form' -> 'from'
ahe
2014/12/19 13:35:45
Done.
|
+ CompilationUnitElement newUnit = |
+ new CompilationUnitElementX(script, newLibrary); |
+ compiler.withCurrentElement(newUnit, () { |
+ compiler.scanner.scan(newUnit); |
+ if (unit.partTag == null) { |
+ compiler.reportError(unit, MessageKind.MISSING_PART_OF_TAG); |
+ } |
+ }); |
+ } |
+ } |
+ |
logTime('New library synthesized.'); |
return canReuseScopeContainerElement(library, newLibrary); |
} |