Unverified Commit 72258eac authored by includecmath's avatar includecmath Committed by GitHub

[flutter_tools] Separate style and data from AnalysisError (#60591)

parent c65f32f4
......@@ -19,7 +19,9 @@ import '../convert.dart';
/// An interface to the Dart analysis server.
class AnalysisServer {
AnalysisServer(this.sdkPath, this.directories, {
AnalysisServer(
this.sdkPath,
this.directories, {
@required FileSystem fileSystem,
@required ProcessManager processManager,
@required Logger logger,
......@@ -78,12 +80,14 @@ class AnalysisServer {
// This callback hookup can't throw.
unawaited(_process.exitCode.whenComplete(() => _process = null));
final Stream<String> errorStream =
_process.stderr.transform<String>(utf8.decoder).transform<String>(const LineSplitter());
final Stream<String> errorStream = _process.stderr
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter());
errorStream.listen(_logger.printError);
final Stream<String> inStream =
_process.stdout.transform<String>(utf8.decoder).transform<String>(const LineSplitter());
final Stream<String> inStream = _process.stdout
.transform<String>(utf8.decoder)
.transform<String>(const LineSplitter());
inStream.listen(_handleServerResponse);
_sendCommand('server.setSubscriptions', <String, dynamic>{
......@@ -95,7 +99,9 @@ class AnalysisServer {
}
bool get didServerErrorOccur => _didServerErrorOccur;
Stream<bool> get onAnalyzing => _analyzingController.stream;
Stream<FileAnalysisErrors> get onErrors => _errorsController.stream;
Future<int> get onExit => _process.exitCode;
......@@ -165,7 +171,7 @@ class AnalysisServer {
final List<AnalysisError> errors = errorsList
.map<Map<String, dynamic>>(castStringKeyedMap)
.map<AnalysisError>((Map<String, dynamic> json) {
return AnalysisError(json,
return AnalysisError(WrittenError.fromJson(json),
fileSystem: _fileSystem,
platform: _platform,
terminal: _terminal,
......@@ -191,8 +197,10 @@ enum _AnalysisSeverity {
none,
}
/// [AnalysisError] with command line style.
class AnalysisError implements Comparable<AnalysisError> {
AnalysisError(this.json, {
AnalysisError(
this.writtenError, {
@required Platform platform,
@required Terminal terminal,
@required FileSystem fileSystem,
......@@ -200,85 +208,132 @@ class AnalysisError implements Comparable<AnalysisError> {
_terminal = terminal,
_fileSystem = fileSystem;
final WrittenError writtenError;
final Platform _platform;
final Terminal _terminal;
final FileSystem _fileSystem;
static final Map<String, _AnalysisSeverity> _severityMap = <String, _AnalysisSeverity>{
'INFO': _AnalysisSeverity.info,
'WARNING': _AnalysisSeverity.warning,
'ERROR': _AnalysisSeverity.error,
};
String get _separator => _platform.isWindows ? '-' : '•';
String get _separator => _platform.isWindows ? '-' : '•';
// "severity":"INFO","type":"TODO","location":{
// "file":"/Users/.../lib/test.dart","offset":362,"length":72,"startLine":15,"startColumn":4
// },"message":"...","hasFix":false}
Map<String, dynamic> json;
String get severity => json['severity'] as String;
String get colorSeverity {
switch(_severityLevel) {
switch (writtenError.severityLevel) {
case _AnalysisSeverity.error:
return _terminal.color(severity, TerminalColor.red);
return _terminal.color(writtenError.severity, TerminalColor.red);
case _AnalysisSeverity.warning:
return _terminal.color(severity, TerminalColor.yellow);
return _terminal.color(writtenError.severity, TerminalColor.yellow);
case _AnalysisSeverity.info:
case _AnalysisSeverity.none:
return severity;
return writtenError.severity;
}
return null;
}
_AnalysisSeverity get _severityLevel => _severityMap[severity] ?? _AnalysisSeverity.none;
String get type => json['type'] as String;
String get message => json['message'] as String;
String get code => json['code'] as String;
String get file => json['location']['file'] as String;
int get startLine => json['location']['startLine'] as int;
int get startColumn => json['location']['startColumn'] as int;
int get offset => json['location']['offset'] as int;
String get messageSentenceFragment {
if (message.endsWith('.')) {
return message.substring(0, message.length - 1);
} else {
return message;
}
}
String get type => writtenError.type;
String get code => writtenError.code;
@override
int compareTo(AnalysisError other) {
// Sort in order of file path, error location, severity, and message.
if (file != other.file) {
return file.compareTo(other.file);
if (writtenError.file != other.writtenError.file) {
return writtenError.file.compareTo(other.writtenError.file);
}
if (offset != other.offset) {
return offset - other.offset;
if (writtenError.offset != other.writtenError.offset) {
return writtenError.offset - other.writtenError.offset;
}
final int diff = other._severityLevel.index - _severityLevel.index;
final int diff = other.writtenError.severityLevel.index -
writtenError.severityLevel.index;
if (diff != 0) {
return diff;
}
return message.compareTo(other.message);
return writtenError.message.compareTo(other.writtenError.message);
}
@override
String toString() {
// Can't use "padLeft" because of ANSI color sequences in the colorized
// severity.
final String padding = ' ' * math.max(0, 7 - severity.length);
final String padding = ' ' * math.max(0, 7 - writtenError.severity.length);
return '$padding${colorSeverity.toLowerCase()} $_separator '
'$messageSentenceFragment $_separator '
'${_fileSystem.path.relative(file)}:$startLine:$startColumn $_separator '
'${writtenError.messageSentenceFragment} $_separator '
'${_fileSystem.path.relative(writtenError.file)}:${writtenError.startLine}:${writtenError.startColumn} $_separator '
'$code';
}
String toLegacyString() {
return writtenError.toString();
}
}
/// [AnalysisError] in plain text content.
class WrittenError {
WrittenError._({
@required this.severity,
@required this.type,
@required this.message,
@required this.code,
@required this.file,
@required this.startLine,
@required this.startColumn,
@required this.offset,
});
/// {
/// "severity":"INFO",
/// "type":"TODO",
/// "location":{
/// "file":"/Users/.../lib/test.dart",
/// "offset":362,
/// "length":72,
/// "startLine":15,
/// "startColumn":4
/// },
/// "message":"...",
/// "hasFix":false
/// }
static WrittenError fromJson(Map<String, dynamic> json) {
return WrittenError._(
severity: json['severity'] as String,
type: json['type'] as String,
message: json['message'] as String,
code: json['code'] as String,
file: json['location']['file'] as String,
startLine: json['location']['startLine'] as int,
startColumn: json['location']['startColumn'] as int,
offset: json['location']['offset'] as int,
);
}
final String severity;
final String type;
final String message;
final String code;
final String file;
final int startLine;
final int startColumn;
final int offset;
static final Map<String, _AnalysisSeverity> _severityMap = <String, _AnalysisSeverity>{
'INFO': _AnalysisSeverity.info,
'WARNING': _AnalysisSeverity.warning,
'ERROR': _AnalysisSeverity.error,
};
_AnalysisSeverity get severityLevel =>
_severityMap[severity] ?? _AnalysisSeverity.none;
String get messageSentenceFragment {
if (message.endsWith('.')) {
return message.substring(0, message.length - 1);
}
return message;
}
@override
String toString() {
return '[${severity.toLowerCase()}] $messageSentenceFragment ($file:$startLine:$startColumn)';
}
}
......
......@@ -6,6 +6,7 @@ import 'package:file/file.dart';
import 'package:file/memory.dart';
import 'package:flutter_tools/src/cache.dart';
import 'package:flutter_tools/src/commands/analyze_base.dart';
import 'package:flutter_tools/src/dart/analysis.dart';
import '../../src/common.dart';
......@@ -43,6 +44,24 @@ void main() {
inRepo(null, fileSystem);
inRepo(<String>[], fileSystem);
});
testWithoutContext('AnalysisError from json write correct', () {
final Map<String, dynamic> json = <String, dynamic>{
'severity': 'INFO',
'type': 'TODO',
'location': <String, dynamic>{
'file': '/Users/.../lib/test.dart',
'offset': 362,
'length': 72,
'startLine': 15,
'startColumn': 4
},
'message': 'Prefer final for variable declarations if they are not reassigned.',
'hasFix': false
};
expect(WrittenError.fromJson(json).toString(),
'[info] Prefer final for variable declarations if they are not reassigned (/Users/.../lib/test.dart:15:4)');
});
}
bool inRepo(List<String> fileList, FileSystem fileSystem) {
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment