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

Unified Diff: dart/pkg/dart2js_incremental/lib/library_updater.dart

Issue 705253002: Include reasons for failing in StateError. (Closed) Base URL: https://dart.googlecode.com/svn/branches/bleeding_edge
Patch Set: Have poi.dart recover when LibraryUpdater failed. Created 6 years, 1 month 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
« no previous file with comments | « no previous file | dart/site/try/poi/poi.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
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 1be2076d8923774e9c7b55debd734c439ccde498..b5b20fc728ae231f6ddc6e8a5c18df1c663c65b0 100644
--- a/dart/pkg/dart2js_incremental/lib/library_updater.dart
+++ b/dart/pkg/dart2js_incremental/lib/library_updater.dart
@@ -64,6 +64,19 @@ typedef bool Reuser(
PartialElement before,
PartialElement after);
+class FailedUpdate {
+ /// Either an [Element] or a [Difference].
+ final context;
+ final String message;
+
+ FailedUpdate(this.context, this.message);
+
+ String toString() {
+ if (context == null) return '$message';
+ return 'In $context:\n $message';
+ }
+}
+
// TODO(ahe): Generalize this class. For now only works for Compiler.mainApp,
// and only if that library has exactly one compilation unit.
class LibraryUpdater {
@@ -79,14 +92,10 @@ class LibraryUpdater {
// changed.
final Uri uri;
- // When [true], updates must be applied (using [applyUpdates]) before the
- // [compiler]'s state correctly reflects the updated program.
- bool hasPendingUpdates = false;
-
- bool onlySimpleUpdates = true;
-
final List<Update> updates = <Update>[];
+ final List<FailedUpdate> _failedUpdates = <FailedUpdate>[];
+
LibraryUpdater(
this.compiler,
this.inputProvider,
@@ -94,6 +103,12 @@ class LibraryUpdater {
this.logTime,
this.logVerbose);
+ /// When [true], updates must be applied (using [applyUpdates]) before the
+ /// [compiler]'s state correctly reflects the updated program.
+ bool get hasPendingUpdates => !updates.isEmpty;
+
+ bool get failed => !_failedUpdates.isEmpty;
+
JavaScriptBackend get backend => compiler.backend;
Namer get namer => backend.namer;
@@ -141,6 +156,12 @@ class LibraryUpdater {
return canReuseScopeContainerElement(library, newLibrary);
}
+ bool cannotReuse(context, String message) {
+ _failedUpdates.add(new FailedUpdate(context, message));
+ logVerbose(message);
+ return false;
+ }
+
bool canReuseScopeContainerElement(
ScopeContainerElement element,
ScopeContainerElement newElement) {
@@ -149,23 +170,18 @@ class LibraryUpdater {
for (Difference difference in differences) {
logTime('Looking at difference: $difference');
if (difference.before == null || difference.after == null) {
- logVerbose('Scope changed in $difference');
- // Scope changed, don't reuse library.
- onlySimpleUpdates = false;
- return false;
+ cannotReuse(difference, "Can't reuse; Scope changed.");
+ continue;
}
Token diffToken = difference.token;
if (diffToken == null) {
- logVerbose('No token stored in difference.');
- onlySimpleUpdates = false;
- return false;
+ cannotReuse(difference, "No difference token.");
+ continue;
}
if (difference.after is! PartialElement &&
difference.before is! PartialElement) {
- logVerbose('Not a PartialElement: $difference');
- // Don't know how to recompile element.
- onlySimpleUpdates = false;
- return false;
+ cannotReuse(difference, "Don't know how to recompile.");
+ continue;
}
PartialElement before = difference.before;
PartialElement after = difference.after;
@@ -178,16 +194,15 @@ class LibraryUpdater {
after is PartialClassElement) {
reuser = canReuseClass;
} else {
- reuser = cannotReuse;
+ reuser = unableToReuse;
}
if (!reuser(diffToken, before, after)) {
- onlySimpleUpdates = false;
- return false;
+ assert(!_failedUpdates.isEmpty);
+ continue;
}
}
- hasPendingUpdates = true;
- return true;
+ return _failedUpdates.isEmpty;
}
/// Returns true if function [before] can be reused to reflect the changes in
@@ -201,16 +216,14 @@ class LibraryUpdater {
FunctionExpression node =
after.parseNode(compiler).asFunctionExpression();
if (node == null) {
- logVerbose('Not a function expression.');
- return false;
+ return cannotReuse(after, "Not a function expression: '$node'");
}
Token last = after.endToken;
if (node.body != null) {
last = node.body.getBeginToken();
}
if (isTokenBetween(diffToken, after.beginToken, last)) {
- logVerbose('Signature changed.');
- return false;
+ return cannotReuse(after, 'Signature changed.');
}
logVerbose('Simple modification of ${after} detected');
updates.add(new FunctionUpdate(compiler, before, after));
@@ -223,17 +236,14 @@ class LibraryUpdater {
PartialClassElement after) {
ClassNode node = after.parseNode(compiler).asClassNode();
if (node == null) {
- logVerbose('Not a ClassNode.');
- return false;
+ return cannotReuse(after, "Not a ClassNode: '$node'");
}
NodeList body = node.body;
if (body == null) {
- logVerbose('Class has no body.');
- return false;
+ return cannotReuse(after, "Class has no body.");
}
if (isTokenBetween(diffToken, node.beginToken, body.beginToken)) {
- logVerbose('Class header changed.');
- return false;
+ return cannotReuse(after, "Class header changed.");
}
logVerbose('Simple modification of ${after} detected');
return canReuseScopeContainerElement(before, after);
@@ -250,19 +260,20 @@ class LibraryUpdater {
return false;
}
- bool cannotReuse(
+ bool unableToReuse(
Token diffToken,
PartialElement before,
PartialElement after) {
- logVerbose(
+ return cannotReuse(
+ after,
'Unhandled change:'
' ${before} (${before.runtimeType} -> ${after.runtimeType}).');
- return false;
}
List<Element> applyUpdates() {
- if (!onlySimpleUpdates) {
- throw new StateError("Can't compute update.");
+ if (!_failedUpdates.isEmpty) {
+ throw new StateError(
+ "Can't compute update.\n\n${_failedUpdates.join('\n\n')}");
}
return updates.map((Update update) => update.apply()).toList();
}
« no previous file with comments | « no previous file | dart/site/try/poi/poi.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698