644df9b9fb
This reverts commit c430a0ac0b.
Reason for revert: Will break flutter_frontend_server when rolled into google3
Original change's description:
> Reland: [kernel] Rename Name.name to Name.text
>
> Change-Id: I5240b0ff09faf35184998920202d7600dc97766d
> Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162746
> Reviewed-by: Johnni Winther <johnniwinther@google.com>
> Commit-Queue: Johnni Winther <johnniwinther@google.com>
TBR=jensj@google.com,johnniwinther@google.com
Change-Id: Ib6961f49dd416171c5d5935c490d79d6f7be779e
No-Presubmit: true
No-Tree-Checks: true
No-Try: true
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/162748
Reviewed-by: Johnni Winther <johnniwinther@google.com>
Commit-Queue: Johnni Winther <johnniwinther@google.com>
178 lines
5.2 KiB
Dart
178 lines
5.2 KiB
Dart
#!/usr/bin/env dart
|
|
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
|
|
// for details. All rights reserved. Use of this source code is governed by a
|
|
// BSD-style license that can be found in the LICENSE file.
|
|
|
|
import 'package:kernel/kernel.dart';
|
|
import 'package:kernel/naive_type_checker.dart';
|
|
import 'package:kernel/text/ast_to_text.dart';
|
|
|
|
class ErrorFormatter implements FailureListener {
|
|
List<String> failures = <String>[];
|
|
int get numberOfFailures => failures.length;
|
|
|
|
@override
|
|
void reportNotAssignable(TreeNode where, DartType from, DartType to) {
|
|
reportFailure(
|
|
where,
|
|
'${ansiBlue}${from}${ansiReset} ${ansiYellow}is not assignable to'
|
|
'${ansiReset} ${ansiBlue}${to}${ansiReset}');
|
|
}
|
|
|
|
@override
|
|
void reportInvalidOverride(
|
|
Member ownMember, Member superMember, String message) {
|
|
reportFailure(ownMember, '''
|
|
Incompatible override of ${superMember} with ${ownMember}:
|
|
|
|
${_realign(message, ' ')}''');
|
|
}
|
|
|
|
@override
|
|
void reportFailure(TreeNode where, String message) {
|
|
final dynamic context = where is Class || where is Library
|
|
? where
|
|
: _findEnclosingMember(where);
|
|
String sourceLocation = '<unknown source>';
|
|
String sourceLine = null;
|
|
|
|
// Try finding original source line.
|
|
final fileOffset = _findFileOffset(where);
|
|
if (fileOffset != TreeNode.noOffset) {
|
|
final fileUri = _fileUriOf(context);
|
|
|
|
final component = context.enclosingComponent;
|
|
final source = component.uriToSource[fileUri];
|
|
final location = component.getLocation(fileUri, fileOffset);
|
|
final lineStart = source.lineStarts[location.line - 1];
|
|
final lineEnd = (location.line < source.lineStarts.length)
|
|
? source.lineStarts[location.line]
|
|
: (source.source.length - 1);
|
|
if (lineStart < source.source.length &&
|
|
lineEnd < source.source.length &&
|
|
lineStart < lineEnd) {
|
|
sourceLocation = '${fileUri}:${location.line}';
|
|
sourceLine = new String.fromCharCodes(
|
|
source.source.getRange(lineStart, lineEnd));
|
|
}
|
|
}
|
|
|
|
// Find the name of the enclosing member.
|
|
var name = "", body = context;
|
|
if (context is Class || context is Library) {
|
|
name = context.name;
|
|
} else if (context is Procedure || context is Constructor) {
|
|
final parent = context.parent;
|
|
final parentName =
|
|
parent is Class ? parent.name : (parent as Library).name;
|
|
name = "${parentName}::${context.name.name}";
|
|
} else {
|
|
final field = context as Field;
|
|
if (where is Field) {
|
|
name = "${field.parent}.${field.name}";
|
|
} else {
|
|
name = "field initializer for ${field.parent}.${field.name}";
|
|
}
|
|
}
|
|
|
|
String failure = '''
|
|
-----------------------------------------------------------------------
|
|
In ${name} at ${sourceLocation}:
|
|
|
|
${message.replaceAll('\n', '\n ')}
|
|
|
|
Kernel:
|
|
|
|
|
| ${_realign(HighlightingPrinter.stringifyContainingLines(body, where))}
|
|
|
|
|
''';
|
|
|
|
if (sourceLine != null) {
|
|
failure = '''$failure
|
|
Source:
|
|
|
|
|
| ${_realign(sourceLine)}
|
|
|
|
|
''';
|
|
}
|
|
failures.add(failure);
|
|
}
|
|
|
|
static Uri _fileUriOf(FileUriNode node) {
|
|
return node.fileUri;
|
|
}
|
|
|
|
static String _realign(String str, [String prefix = '| ']) =>
|
|
str.trimRight().replaceAll('\n', '\n${prefix}');
|
|
|
|
static int _findFileOffset(TreeNode context) {
|
|
while (context != null && context.fileOffset == TreeNode.noOffset) {
|
|
context = context.parent;
|
|
}
|
|
|
|
return context?.fileOffset ?? TreeNode.noOffset;
|
|
}
|
|
|
|
static Member _findEnclosingMember(TreeNode n) {
|
|
var context = n;
|
|
while (context is! Member) {
|
|
context = context.parent;
|
|
}
|
|
return context;
|
|
}
|
|
}
|
|
|
|
/// Extension of a [Printer] that highlights the given node using ANSI
|
|
/// escape sequences.
|
|
class HighlightingPrinter extends Printer {
|
|
final highlight;
|
|
|
|
HighlightingPrinter(this.highlight)
|
|
: super(new StringBuffer(), syntheticNames: globalDebuggingNames);
|
|
|
|
@override
|
|
bool shouldHighlight(Node node) => highlight == node;
|
|
|
|
static const kHighlightStart = ansiRed;
|
|
static const kHighlightEnd = ansiReset;
|
|
|
|
@override
|
|
void startHighlight(Node node) {
|
|
sink.write(kHighlightStart);
|
|
}
|
|
|
|
@override
|
|
void endHighlight(Node node) {
|
|
sink.write(kHighlightEnd);
|
|
}
|
|
|
|
/// Stringify the given [node] but only return lines that contain string
|
|
/// representation of the [highlight] node.
|
|
static String stringifyContainingLines(Node node, Node highlight) {
|
|
if (node == highlight) {
|
|
final firstLine = debugNodeToString(node).split('\n').first;
|
|
return "${kHighlightStart}${firstLine}${kHighlightEnd}";
|
|
}
|
|
|
|
final HighlightingPrinter p = new HighlightingPrinter(highlight);
|
|
p.writeNode(node);
|
|
final String text = p.sink.toString();
|
|
return _onlyHighlightedLines(text).join('\n');
|
|
}
|
|
|
|
static Iterable<String> _onlyHighlightedLines(String text) sync* {
|
|
for (var line
|
|
in text.split('\n').skipWhile((l) => !l.contains(kHighlightStart))) {
|
|
yield line;
|
|
if (line.contains(kHighlightEnd)) {
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
const ansiBlue = "\u001b[1;34m";
|
|
const ansiYellow = "\u001b[1;33m";
|
|
const ansiRed = "\u001b[1;31m";
|
|
const ansiReset = "\u001b[0;0m";
|