blob: 41af85cdc4a656762d930379eee07c08bf7f67c7 [file] [log] [blame]
// Copyright (c) 2018, 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 'dart:async';
import 'dart:io' show Directory, Platform, ProcessSignal, exit;
import 'package:analysis_server_client/handler/connection_handler.dart';
import 'package:analysis_server_client/handler/notification_handler.dart';
import 'package:analysis_server_client/protocol.dart';
import 'package:analysis_server_client/server.dart';
import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';
/// A simple application that uses the analysis server to analyze a package.
void main(List<String> args) async {
var target = await parseArgs(args);
print('Analyzing $target');
// Launch the server
var server = Server();
await server.start();
// Connect to the server
var handler = _Handler(server);
server.listenToOutput(notificationProcessor: handler.handleEvent);
if (!await handler.serverConnected(timeLimit: const Duration(seconds: 15))) {
exit(1);
}
// Request analysis
await server.send(SERVER_REQUEST_SET_SUBSCRIPTIONS,
ServerSetSubscriptionsParams([ServerService.STATUS]).toJson());
await server.send(ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS,
AnalysisSetAnalysisRootsParams([target], const []).toJson());
// Continue to watch for analysis until the user presses Ctrl-C
StreamSubscription<ProcessSignal> subscription;
subscription = ProcessSignal.sigint.watch().listen((_) async {
print('Exiting...');
// ignore: unawaited_futures
subscription.cancel();
await server.stop();
});
}
Future<String> parseArgs(List<String> args) async {
if (args.length != 1) {
printUsageAndExit('Expected exactly one directory');
}
final dir = Directory(path.normalize(path.absolute(args[0])));
if (!(await dir.exists())) {
printUsageAndExit('Could not find directory ${dir.path}');
}
return dir.path;
}
void printUsageAndExit(String errorMessage) {
print(errorMessage);
print('');
var appName = path.basename(Platform.script.toFilePath());
print('Usage: $appName <directory path>');
print(' Analyze the *.dart source files in <directory path>');
exit(1);
}
class _Handler with NotificationHandler, ConnectionHandler {
@override
final Server server;
int errorCount = 0;
_Handler(this.server);
@override
void onAnalysisErrors(AnalysisErrorsParams params) {
var errors = params.errors;
var first = true;
for (var error in errors) {
if (error.type.name == 'TODO') {
// Ignore these types of "errors"
continue;
}
if (first) {
first = false;
print('${params.file}:');
}
var loc = error.location;
print(' ${error.message} • ${loc.startLine}:${loc.startColumn}');
++errorCount;
}
}
@override
void onFailedToConnect() {
print('Failed to connect to server');
}
@override
void onProtocolNotSupported(Version version) {
print('Expected protocol version $PROTOCOL_VERSION, but found $version');
}
@override
void onServerError(ServerErrorParams params) {
if (params.isFatal) {
print('Fatal Server Error: ${params.message}');
} else {
print('Server Error: ${params.message}');
}
if (params.stackTrace != null) {
print(params.stackTrace);
}
super.onServerError(params);
}
@override
void onServerStatus(ServerStatusParams params) {
if (!params.analysis.isAnalyzing) {
// Whenever the server stops analyzing,
// print a brief summary of what issues have been found.
if (errorCount == 0) {
print('No issues found.');
} else {
print('Found $errorCount errors/warnings/hints');
}
errorCount = 0;
print('--------- ctrl-c to exit ---------');
}
}
}