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

Unified Diff: lib/src/report.dart

Issue 988483006: Add widget to display errors, and report dependency_graph errors correctly (Closed) Base URL: git@github.com:dart-lang/dev_compiler.git@master
Patch Set: Created 5 years, 9 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: lib/src/report.dart
diff --git a/lib/src/report.dart b/lib/src/report.dart
index d5ed23b6d0338ea9ac6db54359ec50c25c13f30f..5046c3b4ec6f39401fbfc888dd021bea79d424fd 100644
--- a/lib/src/report.dart
+++ b/lib/src/report.dart
@@ -7,30 +7,71 @@ library dev_compiler.src.report;
import 'dart:math' show max;
-import 'package:path/path.dart' as path;
-import 'package:source_span/source_span.dart';
-import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/source.dart' show Source;
import 'package:logging/logging.dart';
+import 'package:path/path.dart' as path;
+import 'package:source_span/source_span.dart';
import 'info.dart';
import 'utils.dart';
+import 'summary.dart';
+
+/// A message (error or warning) produced by the dev_compiler and it's location
+/// information.
+///
+/// Currently the location information includes only the offsets within a file
+/// where the error occurs. This is used in the context of a [CheckerReporter],
+/// where the current file is being tracked.
+abstract class Message {
+ // Message description.
+ final String message;
+
+ /// Log level. This is a placeholder for severity.
+ final Level level;
+
+ /// Offset where the error message begins in the tracked source file.
+ final int begin;
+
+ /// Offset where the error message ends in the tracked source file.
+ final int end;
+
+ const Message(this.message, this.level, this.begin, this.end);
+}
+
+/// Like [Message], but with a precomputed source span.
+abstract class MessageWithSpan implements Message {
+ final String message;
+
+ final Level level;
+
+ final SourceSpan span;
+
+ int get begin => span.start.offset;
+ int get end => span.end.offset;
+
+ const MessageWithSpan(this.message, this.level, this.span);
+}
// Interface used to report error messages from the checker.
abstract class CheckerReporter {
/// Called when starting to process a library.
- void enterLibrary(LibraryInfo info);
+ void enterLibrary(Uri uri);
void leaveLibrary();
+ /// Called when starting to process an HTML source file.
+ void enterHtml(Uri uri);
+ void leaveHtml();
+
/// Called when starting to process a source. All subsequent log entries must
/// belong to this source until the next call to enterSource.
void enterSource(Source source);
void leaveSource();
+ void log(Message message);
- void log(StaticInfo info);
-
- // TODO(sigmund): merge this and [log]
- void logAnalyzerError(String message, Level level, int begin, int end);
+ // Called in server-mode.
+ void clearLibrary(Uri uri);
+ void clearHtml(Uri uri);
+ void clearAll();
}
final _checkerLogger = new Logger('dev_compiler.checker');
@@ -43,9 +84,12 @@ class LogReporter implements CheckerReporter {
LogReporter([this.useColors = false]);
- void enterLibrary(LibraryInfo info) {}
+ void enterLibrary(Uri uri) {}
void leaveLibrary() {}
+ void enterHtml(Uri uri) {}
+ void leaveHtml() {}
+
void enterSource(Source source) {
_file = new SourceFile(source.contents.data, url: source.uri);
_current = source;
@@ -56,245 +100,92 @@ class LogReporter implements CheckerReporter {
_current = null;
}
- void log(StaticInfo info) {
- assert((info.node as dynamic).root.element.source == _current);
- final span = _spanForNode(_file, info.node);
- final color = useColors ? colorOf(info.level.name) : null;
- _checkerLogger.log(info.level, span.message(info.message, color: color));
- }
-
- void logAnalyzerError(String message, Level level, int begin, int end) {
- var span = _file.span(begin, end);
+ void log(Message message) {
+ if (message is StaticInfo) {
+ assert((message.node as dynamic).root.element.source == _current);
+ }
+ // TODO(sigmund): convert to use span information from AST (issue #73)
+ final span = message is MessageWithSpan
+ ? message.span
+ : _file.span(message.begin, message.end);
+ final level = message.level;
final color = useColors ? colorOf(level.name) : null;
- _checkerLogger.log(
- level, span.message('[from analyzer]: ${message}', color: color));
+ _checkerLogger.log(level, span.message(message.message, color: color));
}
+
+ void clearLibrary(Uri uri) {}
+ void clearHtml(Uri uri) {}
+ void clearAll() {}
}
/// A reporter that gathers all the information in a [GlobalSummary].
class SummaryReporter implements CheckerReporter {
GlobalSummary result = new GlobalSummary();
- LibrarySummary _currentLibrary;
+ IndividualSummary _current;
SourceFile _file;
- clear() {
- result = new GlobalSummary();
- }
-
- void enterLibrary(LibraryInfo lib) {
- var libKey = '${lib.library.source.uri}';
- var libSummary = _currentLibrary = new LibrarySummary(libKey);
-
- var uri = lib.library.source.uri;
+ void enterLibrary(Uri uri) {
+ var container;
if (uri.scheme == 'package') {
var pname = path.split(uri.path)[0];
result.packages.putIfAbsent(pname, () => new PackageSummary(pname));
- if (result.packages[pname].libraries[libKey] != null) {
- print('ERROR: duplicate ${libKey}');
- }
- result.packages[pname].libraries[libKey] = libSummary;
+ container = result.packages[pname].libraries;
} else if (uri.scheme == 'dart') {
- if (result.system[libKey] != null) {
- print('ERROR: duplicate ${libKey}');
- }
- result.system[libKey] = libSummary;
+ container = result.system;
} else {
- if (result.loose[libKey] != null) {
- print('ERROR: duplicate ${libKey}');
- }
- result.loose[libKey] = libSummary;
+ container = result.loose;
}
+ _current = container.putIfAbsent('$uri', () => new LibrarySummary('$uri'));
}
void leaveLibrary() {
- _currentLibrary = null;
- }
-
- void enterSource(Source source) {
- _file = new SourceFile(source.contents.data, url: source.uri);
- _currentLibrary.lines += _file.lines;
+ _current = null;
}
- void leaveSource() {
- _file = null;
+ void enterHtml(Uri uri) {
+ _current = result.loose.putIfAbsent('$uri', () => new HtmlSummary('$uri'));
}
- void log(StaticInfo info) {
- assert(_file != null);
- var span = _spanForNode(_file, info.node);
- _currentLibrary.messages.add(new MessageSummary('${info.runtimeType}',
- info.level.name.toLowerCase(), span, info.message));
+ void leaveHtml() {
+ _current = null;
}
- void logAnalyzerError(String message, Level level, int begin, int end) {
- var span = _file.span(begin, end);
- _currentLibrary.messages.add(new MessageSummary(
- 'AnalyzerError', level.name.toLowerCase(), span, message));
+ void enterSource(Source source) {
+ _file = new SourceFile(source.contents.data, url: source.uri);
+ if (_current is LibrarySummary) {
+ (_current as LibrarySummary).lines += _file.lines;
+ }
}
-}
-
-/// Summary information computed by the DDC checker.
Siggi Cherem (dart-lang) 2015/03/07 02:43:01 note: these deletions are actually code that moved
-abstract class Summary {
- Map toJsonMap();
- void accept(SummaryVisitor visitor);
-}
-
-/// Summary for the entire program.
-class GlobalSummary implements Summary {
- /// Summary from the system libaries.
- final Map<String, LibrarySummary> system = <String, LibrarySummary>{};
-
- /// Summary for libraries in packages.
- final Map<String, PackageSummary> packages = <String, PackageSummary>{};
-
- /// Summary for loose files
- // TODO(sigmund): consider inferring the package from the pubspec instead?
- final Map<String, LibrarySummary> loose = <String, LibrarySummary>{};
-
- GlobalSummary();
-
- Map toJsonMap() => {
- 'system': system.values.map((l) => l.toJsonMap()).toList(),
- 'packages': packages.values.map((p) => p.toJsonMap()).toList(),
- 'loose': loose.values.map((l) => l.toJsonMap()).toList(),
- };
-
- void accept(SummaryVisitor visitor) => visitor.visitGlobal(this);
-
- static GlobalSummary parse(Map json) {
- var res = new GlobalSummary();
- json['system'].map(LibrarySummary.parse).forEach((l) {
- res.system[l.name] = l;
- });
- json['packages'].map(PackageSummary.parse).forEach((p) {
- res.packages[p.name] = p;
- });
- json['loose'].map(LibrarySummary.parse).forEach((l) {
- res.loose[l.name] = l;
- });
- return res;
+ void leaveSource() {
+ _file = null;
}
-}
-
-/// A summary of a package.
-class PackageSummary implements Summary {
- final String name;
- final Map<String, LibrarySummary> libraries = <String, LibrarySummary>{};
-
- PackageSummary(this.name);
-
- Map toJsonMap() => {
- 'package_name': name,
- 'libraries': libraries.values.map((l) => l.toJsonMap()).toList(),
- };
- void accept(SummaryVisitor visitor) => visitor.visitPackage(this);
-
- static PackageSummary parse(Map json) {
- var res = new PackageSummary(json['package_name']);
- json['libraries'].map(LibrarySummary.parse).forEach((l) {
- res.libraries[l.name] = l;
- });
- return res;
+ void log(Message message) {
+ assert(message is MessageWithSpan || _file != null);
+ // TODO(sigmund): convert to use span information from AST (issue #73)
+ final span = message is MessageWithSpan
+ ? message.span
+ : _file.span(message.begin, message.end);
+ _current.messages.add(new MessageSummary('${message.runtimeType}',
+ message.level.name.toLowerCase(), span, message.message));
}
-}
-
-/// A summary at the level of a library.
-class LibrarySummary implements Summary {
- /// Name of the library.
- final String name;
-
- /// All messages collected for the library.
- final List<MessageSummary> messages;
-
- /// Total lines of code (including all parts of the library).
- int lines;
-
- LibrarySummary(this.name, [List<MessageSummary> messages, this.lines = 0])
- : messages = messages == null ? <MessageSummary>[] : messages;
-
- Map toJsonMap() => {
- 'library_name': name,
- 'messages': messages.map((m) => m.toJsonMap()).toList(),
- 'lines': lines,
- };
-
- void accept(SummaryVisitor visitor) => visitor.visitLibrary(this);
-
- static LibrarySummary parse(Map json) => new LibrarySummary(
- json['library_name'], json['messages'].map(MessageSummary.parse).toList(),
- json['lines']);
-}
-/// A single message produced by the checker.
-class MessageSummary implements Summary {
- /// The kind of message, currently the name of the StaticInfo type.
- final String kind;
-
- /// Level (error, warning, etc).
- final String level;
-
- /// Location where the error is reported.
- final SourceSpan span;
- final String message;
-
- MessageSummary(this.kind, this.level, this.span, this.message);
-
- Map toJsonMap() => {
- 'kind': kind,
- 'level': level,
- 'message': message,
- 'url': '${span.sourceUrl}',
- 'start': span.start.offset,
- 'end': span.end.offset,
- 'text': span.text,
- };
-
- void accept(SummaryVisitor visitor) => visitor.visitMessage(this);
-
- static MessageSummary parse(Map json) {
- var start = new SourceLocation(json['start'], sourceUrl: json['url']);
- var end = new SourceLocation(json['end'], sourceUrl: json['url']);
- var span = new SourceSpanBase(start, end, json['text']);
- return new MessageSummary(
- json['kind'], json['level'], span, json['message']);
+ void clearLibrary(Uri uri) {
+ enterLibrary(uri);
+ _current.messages.clear();
+ (_current as LibrarySummary).lines = 0;
+ leaveLibrary();
}
-}
-
-/// A visitor of the [Summary] hierarchy.
-abstract class SummaryVisitor {
- void visitGlobal(GlobalSummary global);
- void visitPackage(PackageSummary package);
- void visitLibrary(LibrarySummary lib);
- void visitMessage(MessageSummary message);
-}
-/// A recursive [SummaryVisitor] that visits summaries on a top-down fashion.
-class RecursiveSummaryVisitor implements SummaryVisitor {
- void visitGlobal(GlobalSummary global) {
- for (var lib in global.system.values) {
- lib.accept(this);
- }
- for (var package in global.packages.values) {
- package.accept(this);
- }
- for (var lib in global.loose.values) {
- lib.accept(this);
- }
+ void clearHtml(Uri uri) {
+ HtmlSummary htmlSummary = result.loose['$uri'];
+ if (htmlSummary != null) htmlSummary.messages.clear();
}
- void visitPackage(PackageSummary package) {
- for (var lib in package.libraries.values) {
- lib.accept(this);
- }
- }
- void visitLibrary(LibrarySummary lib) {
- for (var msg in lib.messages) {
- msg.accept(this);
- }
+ clearAll() {
+ result = new GlobalSummary();
}
- void visitMessage(MessageSummary message) {}
}
/// Produces a string representation of the summary.
@@ -491,12 +382,3 @@ class _Counter extends RecursiveSummaryVisitor {
totals[kind]++;
}
}
-
-/// Returns a [SourceSpan] in [file] for the offsets of [node].
-// TODO(sigmund): convert to use span information from AST (issue #73)
-SourceSpan _spanForNode(SourceFile file, AstNode node) {
- final begin = node is AnnotatedNode
- ? node.firstTokenAfterCommentAndMetadata.offset
- : node.offset;
- return file.span(begin, node.end);
-}

Powered by Google App Engine
This is Rietveld 408576698