Fix analysis throwing string (#91435)
This commit is contained in:
parent
5883a6628d
commit
b0810bc939
@ -125,7 +125,12 @@ class AnalyzeOnce extends AnalyzeBase {
|
|||||||
// Completing the future in the callback can't fail.
|
// Completing the future in the callback can't fail.
|
||||||
unawaited(server.onExit.then<void>((int exitCode) {
|
unawaited(server.onExit.then<void>((int exitCode) {
|
||||||
if (!analysisCompleter.isCompleted) {
|
if (!analysisCompleter.isCompleted) {
|
||||||
analysisCompleter.completeError('analysis server exited: $exitCode');
|
analysisCompleter.completeError(
|
||||||
|
// Include the last 20 lines of server output in exception message
|
||||||
|
Exception(
|
||||||
|
'analysis server exited with code $exitCode and output:\n${server.getLogs(20)}',
|
||||||
|
),
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ class AnalysisServer {
|
|||||||
final Stream<String> errorStream = _process!.stderr
|
final Stream<String> errorStream = _process!.stderr
|
||||||
.transform<String>(utf8.decoder)
|
.transform<String>(utf8.decoder)
|
||||||
.transform<String>(const LineSplitter());
|
.transform<String>(const LineSplitter());
|
||||||
errorStream.listen(_logger.printError);
|
errorStream.listen(_handleError);
|
||||||
|
|
||||||
final Stream<String> inStream = _process!.stdout
|
final Stream<String> inStream = _process!.stdout
|
||||||
.transform<String>(utf8.decoder)
|
.transform<String>(utf8.decoder)
|
||||||
@ -94,6 +94,28 @@ class AnalysisServer {
|
|||||||
<String, dynamic>{'included': directories, 'excluded': <String>[]});
|
<String, dynamic>{'included': directories, 'excluded': <String>[]});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
final List<String> _logs = <String>[];
|
||||||
|
|
||||||
|
/// Aggregated STDOUT and STDERR logs from the server.
|
||||||
|
///
|
||||||
|
/// This can be surfaced to the user if the server crashes. If [tail] is null,
|
||||||
|
/// returns all logs, else only the last [tail] lines.
|
||||||
|
String getLogs([int? tail]) {
|
||||||
|
if (tail == null) {
|
||||||
|
return _logs.join('\n');
|
||||||
|
}
|
||||||
|
// Since List doesn't implement a .tail() method, we reverse it then use
|
||||||
|
// .take()
|
||||||
|
final Iterable<String> reversedLogs = _logs.reversed;
|
||||||
|
final List<String> firstTailLogs = reversedLogs.take(tail).toList();
|
||||||
|
return firstTailLogs.reversed.join('\n');
|
||||||
|
}
|
||||||
|
|
||||||
|
void _handleError(String message) {
|
||||||
|
_logs.add('[stderr] $message');
|
||||||
|
_logger.printError(message);
|
||||||
|
}
|
||||||
|
|
||||||
bool get didServerErrorOccur => _didServerErrorOccur;
|
bool get didServerErrorOccur => _didServerErrorOccur;
|
||||||
|
|
||||||
Stream<bool> get onAnalyzing => _analyzingController.stream;
|
Stream<bool> get onAnalyzing => _analyzingController.stream;
|
||||||
@ -113,6 +135,7 @@ class AnalysisServer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void _handleServerResponse(String line) {
|
void _handleServerResponse(String line) {
|
||||||
|
_logs.add('[stdout] $line');
|
||||||
_logger.printTrace('<== $line');
|
_logger.printTrace('<== $line');
|
||||||
|
|
||||||
final dynamic response = json.decode(line);
|
final dynamic response = json.decode(line);
|
||||||
|
@ -312,7 +312,6 @@ class FlutterCommandRunner extends CommandRunner<void> {
|
|||||||
return <String>[];
|
return <String>[];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
final List<String> projectPaths = globals.fs.directory(rootPath)
|
final List<String> projectPaths = globals.fs.directory(rootPath)
|
||||||
.listSync(followLinks: false)
|
.listSync(followLinks: false)
|
||||||
.expand((FileSystemEntity entity) {
|
.expand((FileSystemEntity entity) {
|
||||||
|
@ -4,15 +4,25 @@
|
|||||||
|
|
||||||
// @dart = 2.8
|
// @dart = 2.8
|
||||||
|
|
||||||
|
import 'package:args/command_runner.dart';
|
||||||
import 'package:file/file.dart';
|
import 'package:file/file.dart';
|
||||||
import 'package:file/memory.dart';
|
import 'package:file/memory.dart';
|
||||||
|
import 'package:flutter_tools/src/artifacts.dart';
|
||||||
|
import 'package:flutter_tools/src/base/logger.dart';
|
||||||
|
import 'package:flutter_tools/src/base/platform.dart';
|
||||||
|
import 'package:flutter_tools/src/base/terminal.dart';
|
||||||
import 'package:flutter_tools/src/cache.dart';
|
import 'package:flutter_tools/src/cache.dart';
|
||||||
|
import 'package:flutter_tools/src/commands/analyze.dart';
|
||||||
import 'package:flutter_tools/src/commands/analyze_base.dart';
|
import 'package:flutter_tools/src/commands/analyze_base.dart';
|
||||||
import 'package:flutter_tools/src/dart/analysis.dart';
|
import 'package:flutter_tools/src/dart/analysis.dart';
|
||||||
|
|
||||||
import '../../src/common.dart';
|
import '../../src/common.dart';
|
||||||
|
import '../../src/context.dart';
|
||||||
|
import '../../src/fake_process_manager.dart';
|
||||||
|
import '../../src/test_flutter_command_runner.dart';
|
||||||
|
|
||||||
const String _kFlutterRoot = '/data/flutter';
|
const String _kFlutterRoot = '/data/flutter';
|
||||||
|
const int SIGABRT = -6;
|
||||||
|
|
||||||
void main() {
|
void main() {
|
||||||
testWithoutContext('analyze generate correct errors message', () async {
|
testWithoutContext('analyze generate correct errors message', () async {
|
||||||
@ -35,6 +45,80 @@ void main() {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
group('analyze command', () {
|
||||||
|
FileSystem fileSystem;
|
||||||
|
Platform platform;
|
||||||
|
BufferLogger logger;
|
||||||
|
FakeProcessManager processManager;
|
||||||
|
Terminal terminal;
|
||||||
|
AnalyzeCommand command;
|
||||||
|
CommandRunner<void> runner;
|
||||||
|
|
||||||
|
setUpAll(() {
|
||||||
|
Cache.disableLocking();
|
||||||
|
});
|
||||||
|
|
||||||
|
setUp(() {
|
||||||
|
fileSystem = MemoryFileSystem.test();
|
||||||
|
platform = FakePlatform();
|
||||||
|
logger = BufferLogger.test();
|
||||||
|
processManager = FakeProcessManager.empty();
|
||||||
|
terminal = Terminal.test();
|
||||||
|
command = AnalyzeCommand(
|
||||||
|
artifacts: Artifacts.test(),
|
||||||
|
fileSystem: fileSystem,
|
||||||
|
logger: logger,
|
||||||
|
platform: platform,
|
||||||
|
processManager: processManager,
|
||||||
|
terminal: terminal,
|
||||||
|
);
|
||||||
|
runner = createTestCommandRunner(command);
|
||||||
|
|
||||||
|
// Setup repo roots
|
||||||
|
const String homePath = '/home/user/flutter';
|
||||||
|
Cache.flutterRoot = homePath;
|
||||||
|
for (final String dir in <String>['dev', 'examples', 'packages']) {
|
||||||
|
fileSystem.directory(homePath).childDirectory(dir).createSync(recursive: true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
testUsingContext('SIGABRT throws Exception', () async {
|
||||||
|
const String stderr = 'Something bad happened!';
|
||||||
|
processManager.addCommands(
|
||||||
|
<FakeCommand>[
|
||||||
|
const FakeCommand(
|
||||||
|
// artifact paths are from Artifacts.test() and stable
|
||||||
|
command: <String>[
|
||||||
|
'HostArtifact.engineDartSdkPath/bin/dart',
|
||||||
|
'--disable-dart-dev',
|
||||||
|
'HostArtifact.engineDartSdkPath/bin/snapshots/analysis_server.dart.snapshot',
|
||||||
|
'--disable-server-feature-completion',
|
||||||
|
'--disable-server-feature-search',
|
||||||
|
'--sdk',
|
||||||
|
'HostArtifact.engineDartSdkPath',
|
||||||
|
],
|
||||||
|
exitCode: SIGABRT,
|
||||||
|
stderr: stderr,
|
||||||
|
),
|
||||||
|
],
|
||||||
|
);
|
||||||
|
await expectLater(
|
||||||
|
runner.run(<String>['analyze']),
|
||||||
|
throwsA(
|
||||||
|
isA<Exception>().having(
|
||||||
|
(Exception e) => e.toString(),
|
||||||
|
'description',
|
||||||
|
contains('analysis server exited with code $SIGABRT and output:\n[stderr] $stderr'),
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
},
|
||||||
|
overrides: <Type, Generator>{
|
||||||
|
FileSystem: () => fileSystem,
|
||||||
|
ProcessManager: () => processManager,
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
testWithoutContext('analyze inRepo', () {
|
testWithoutContext('analyze inRepo', () {
|
||||||
final FileSystem fileSystem = MemoryFileSystem.test();
|
final FileSystem fileSystem = MemoryFileSystem.test();
|
||||||
fileSystem.directory(_kFlutterRoot).createSync(recursive: true);
|
fileSystem.directory(_kFlutterRoot).createSync(recursive: true);
|
||||||
|
Loading…
x
Reference in New Issue
Block a user