mirror of
https://github.com/flutter/flutter.git
synced 2025-06-03 00:51:18 +00:00
[flutter_tools] Separate style and data from AnalysisError (#60591)
This commit is contained in:
parent
c65f32f447
commit
72258eac5f
@ -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;
|
||||
|
||||
String get _separator => _platform.isWindows ? '-' : '•';
|
||||
|
||||
String get colorSeverity {
|
||||
switch (writtenError.severityLevel) {
|
||||
case _AnalysisSeverity.error:
|
||||
return _terminal.color(writtenError.severity, TerminalColor.red);
|
||||
case _AnalysisSeverity.warning:
|
||||
return _terminal.color(writtenError.severity, TerminalColor.yellow);
|
||||
case _AnalysisSeverity.info:
|
||||
case _AnalysisSeverity.none:
|
||||
return writtenError.severity;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
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 (writtenError.file != other.writtenError.file) {
|
||||
return writtenError.file.compareTo(other.writtenError.file);
|
||||
}
|
||||
|
||||
if (writtenError.offset != other.writtenError.offset) {
|
||||
return writtenError.offset - other.writtenError.offset;
|
||||
}
|
||||
|
||||
final int diff = other.writtenError.severityLevel.index -
|
||||
writtenError.severityLevel.index;
|
||||
if (diff != 0) {
|
||||
return diff;
|
||||
}
|
||||
|
||||
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 - writtenError.severity.length);
|
||||
return '$padding${colorSeverity.toLowerCase()} $_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,
|
||||
};
|
||||
|
||||
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) {
|
||||
case _AnalysisSeverity.error:
|
||||
return _terminal.color(severity, TerminalColor.red);
|
||||
case _AnalysisSeverity.warning:
|
||||
return _terminal.color(severity, TerminalColor.yellow);
|
||||
case _AnalysisSeverity.info:
|
||||
case _AnalysisSeverity.none:
|
||||
return 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;
|
||||
_AnalysisSeverity get severityLevel =>
|
||||
_severityMap[severity] ?? _AnalysisSeverity.none;
|
||||
|
||||
String get messageSentenceFragment {
|
||||
if (message.endsWith('.')) {
|
||||
return message.substring(0, message.length - 1);
|
||||
} else {
|
||||
return message;
|
||||
}
|
||||
}
|
||||
|
||||
@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 (offset != other.offset) {
|
||||
return offset - other.offset;
|
||||
}
|
||||
|
||||
final int diff = other._severityLevel.index - _severityLevel.index;
|
||||
if (diff != 0) {
|
||||
return diff;
|
||||
}
|
||||
|
||||
return message.compareTo(other.message);
|
||||
return 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);
|
||||
return '$padding${colorSeverity.toLowerCase()} $_separator '
|
||||
'$messageSentenceFragment $_separator '
|
||||
'${_fileSystem.path.relative(file)}:$startLine:$startColumn $_separator '
|
||||
'$code';
|
||||
}
|
||||
|
||||
String toLegacyString() {
|
||||
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) {
|
||||
|
Loading…
Reference in New Issue
Block a user