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

Unified Diff: lib/src/dependency_graph.dart

Issue 1141013002: Fixes #179 -- compile error if editing files during server mode (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 7 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
« no previous file with comments | « lib/src/codegen/reify_coercions.dart ('k') | lib/src/info.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/src/dependency_graph.dart
diff --git a/lib/src/dependency_graph.dart b/lib/src/dependency_graph.dart
index dcded66942caf4a90baf757f77e1483f85cf5e30..dcf876d41257013d6f2d8589f5abb24f691d682e 100644
--- a/lib/src/dependency_graph.dart
+++ b/lib/src/dependency_graph.dart
@@ -25,12 +25,10 @@ import 'package:html/dom.dart' show Document, Node;
import 'package:html/parser.dart' as html;
import 'package:logging/logging.dart' show Logger, Level;
import 'package:path/path.dart' as path;
-import 'package:source_span/source_span.dart' show SourceSpan;
import 'info.dart';
import 'options.dart';
import 'report.dart';
-import 'utils.dart';
/// Holds references to all source nodes in the import graph. This is mainly
/// used as a level of indirection to ensure that each source has a canonical
@@ -70,11 +68,11 @@ class SourceGraph {
var source = _context.sourceFactory.forUri(uriString);
var extension = path.extension(uriString);
if (extension == '.html') {
- return new HtmlSourceNode(uri, source, this);
+ return new HtmlSourceNode(this, uri, source);
} else if (extension == '.dart' || uriString.startsWith('dart:')) {
- return new DartSourceNode(uri, source);
+ return new DartSourceNode(this, uri, source);
} else {
- return new ResourceSourceNode(uri, source);
+ return new ResourceSourceNode(this, uri, source);
}
});
}
@@ -82,6 +80,8 @@ class SourceGraph {
/// A node in the import graph representing a source file.
abstract class SourceNode {
+ final SourceGraph graph;
+
/// Resolved URI for this node.
final Uri uri;
@@ -90,6 +90,8 @@ abstract class SourceNode {
Source _source;
Source get source => _source;
+ String get contents => graph._context.getContents(source).data;
+
/// Last stamp read from `source.modificationStamp`.
int _lastStamp = 0;
@@ -113,22 +115,27 @@ abstract class SourceNode {
/// parts are excluded from this list.
Iterable<SourceNode> get depsWithoutParts => const [];
- SourceNode(this.uri, this._source);
+ SourceNode(this.graph, this.uri, this._source);
/// Check for whether the file has changed and, if so, mark [needsRebuild] and
/// [structureChanged] as necessary.
- void update(SourceGraph graph) {
+ void update() {
if (_source == null) {
_source = graph._context.sourceFactory.forUri(Uri.encodeFull('$uri'));
if (_source == null) return;
}
int newStamp = _source.modificationStamp;
if (newStamp > _lastStamp) {
+ // If the timestamp changed, read the file from disk and cache it.
+ // We don't want the source text to change during compilation.
+ saveUpdatedContents();
_lastStamp = newStamp;
needsRebuild = true;
}
}
+ void saveUpdatedContents() {}
+
String toString() {
var simpleUri = uri.scheme == 'file' ? path.relative(uri.path) : "$uri";
return '[$runtimeType: $simpleUri]';
@@ -156,15 +163,16 @@ class HtmlSourceNode extends SourceNode {
/// Parsed document, updated whenever [update] is invoked.
Document document;
- HtmlSourceNode(Uri uri, Source source, SourceGraph graph)
+ HtmlSourceNode(SourceGraph graph, Uri uri, Source source)
: runtimeDeps = graph.runtimeDeps,
- super(uri, source);
+ super(graph, uri, source);
- void update(SourceGraph graph) {
- super.update(graph);
+ @override
+ void update() {
+ super.update();
if (needsRebuild) {
graph._reporter.clearHtml(uri);
- document = html.parse(source.contents.data, generateSpans: true);
+ document = html.parse(contents, generateSpans: true);
var newScripts = new Set<DartSourceNode>();
var tags = document.querySelectorAll('script[type="application/dart"]');
for (var script in tags) {
@@ -204,7 +212,9 @@ class HtmlSourceNode extends SourceNode {
void _reportError(SourceGraph graph, String message, Node node) {
graph._reporter.enterHtml(source.uri);
- graph._reporter.log(new DependencyGraphError(message, node.sourceSpan));
+ var span = node.sourceSpan;
+ graph._reporter.log(
+ new Message(message, Level.SEVERE, span.start.offset, span.end.offset));
graph._reporter.leaveHtml();
}
}
@@ -223,7 +233,7 @@ class DartSourceNode extends SourceNode {
/// How many times this file is included as a part.
int includedAsPart = 0;
- DartSourceNode(uri, source) : super(uri, source);
+ DartSourceNode(graph, uri, source) : super(graph, uri, source);
@override
Iterable<SourceNode> get allDeps =>
@@ -235,14 +245,25 @@ class DartSourceNode extends SourceNode {
LibraryInfo info;
- void update(SourceGraph graph) {
- super.update(graph);
+ // TODO(jmesserly): it would be nice to not keep all sources in memory at
+ // once, but how else can we ensure a consistent view across a given
+ // compile? One different from dev_compiler vs analyzer is that our
+ // messages later in the compiler need the original source text to print
+ // spans. We also read source text ourselves to parse directives.
+ // But we could discard it after that point.
+ void saveUpdatedContents() {
+ graph._context.setContents(source, source.contents.data);
+ }
- if (needsRebuild && source.contents.data != null) {
+ @override
+ void update() {
+ super.update();
+
+ if (needsRebuild && contents != null) {
graph._reporter.clearLibrary(uri);
// If the defining compilation-unit changed, the structure might have
// changed.
- var unit = parseDirectives(source.contents.data, name: source.fullName);
+ var unit = parseDirectives(contents, name: source.fullName);
var newImports = new Set<DartSourceNode>();
var newExports = new Set<DartSourceNode>();
var newParts = new Set<DartSourceNode>();
@@ -262,7 +283,7 @@ class DartSourceNode extends SourceNode {
if (targetUri != target.uri) print(">> ${target.uri} $targetUri");
}
var node = graph.nodes.putIfAbsent(
- targetUri, () => new DartSourceNode(targetUri, target));
+ targetUri, () => new DartSourceNode(graph, targetUri, target));
//var node = graph.nodeFromUri(targetUri);
if (node.source == null || !node.source.exists()) {
_reportError(graph, 'File $targetUri not found', unit, d);
@@ -314,24 +335,26 @@ class DartSourceNode extends SourceNode {
// contain imports, exports, or parts, we'll ignore them in our crawling.
// However we do a full update to make it easier to adjust when users
// switch a file from a part to a library.
- p.update(graph);
+ p.update();
if (p.needsRebuild) needsRebuild = true;
}
}
void _reportError(
SourceGraph graph, String message, CompilationUnit unit, AstNode node) {
- graph._reporter.enterLibrary(source.uri);
- graph._reporter.log(
- new DependencyGraphError(message, spanForNode(unit, source, node)));
- graph._reporter.leaveLibrary();
+ graph._reporter
+ ..enterLibrary(source.uri)
+ ..enterCompilationUnit(unit, source)
+ ..log(new Message(message, Level.SEVERE, node.offset, node.end))
+ ..leaveCompilationUnit()
+ ..leaveLibrary();
}
}
/// Represents a runtime resource from our compiler that is needed to run an
/// application.
class ResourceSourceNode extends SourceNode {
- ResourceSourceNode(uri, source) : super(uri, source);
+ ResourceSourceNode(graph, uri, source) : super(graph, uri, source);
}
/// Updates the structure and `needsRebuild` marks in nodes of [graph] reachable
@@ -345,8 +368,8 @@ class ResourceSourceNode extends SourceNode {
/// contained local changes. Rebuild decisions that derive from transitive
/// changes (e.g. when the API of a dependency changed) are handled later in
/// [rebuild].
-void refreshStructureAndMarks(SourceNode start, SourceGraph graph) {
- visitInPreOrder(start, (n) => n.update(graph), includeParts: false);
+void refreshStructureAndMarks(SourceNode start) {
+ visitInPreOrder(start, (n) => n.update(), includeParts: false);
}
/// Clears all the `needsRebuild` and `structureChanged` marks in nodes
@@ -382,8 +405,8 @@ void clearMarks(SourceNode start) {
/// whether other nodes need to be rebuilt. The function [build] is expected
/// to return `true` on a node `n` if it detemines other nodes that import
/// `n` may need to be rebuilt as well.
-rebuild(SourceNode start, SourceGraph graph, bool build(SourceNode node)) {
- refreshStructureAndMarks(start, graph);
+rebuild(SourceNode start, bool build(SourceNode node)) {
+ refreshStructureAndMarks(start);
// Hold which source nodes may have changed their public API, this includes
// libraries that were modified or libraries that export other modified APIs.
// TODO(sigmund): consider removing this special support for exports? Many
@@ -454,12 +477,6 @@ visitInPostOrder(SourceNode start, void action(SourceNode node),
bool _same(Set a, Set b) => a.length == b.length && a.containsAll(b);
-/// An error message discovered while parsing the dependencies between files.
-class DependencyGraphError extends MessageWithSpan {
- const DependencyGraphError(String message, SourceSpan span)
- : super(message, Level.SEVERE, span);
-}
-
/// Runtime files added to all applications when running the compiler in the
/// command line.
final defaultRuntimeFiles = () {
« no previous file with comments | « lib/src/codegen/reify_coercions.dart ('k') | lib/src/info.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698