// 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 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(serverRequestSetSubscriptions, ServerSetSubscriptionsParams([ServerService.STATUS]).toJson()); await server.send(analysisRequestSetAnalysisRoots, AnalysisSetAnalysisRootsParams([target], const []).toJson()); // Continue to watch for analysis until the user presses Ctrl-C late StreamSubscription subscription; subscription = ProcessSignal.sigint.watch().listen((_) async { print('Exiting...'); // ignore: unawaited_futures subscription.cancel(); await server.stop(); }); } Future parseArgs(List 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 '); print(' Analyze the *.dart source files in '); exit(1); } class _Handler with NotificationHandler, ConnectionHandler { @override final Server server; int errorCount = 0; new(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}'); } print(params.stackTrace); super.onServerError(params); } @override void onServerStatus(ServerStatusParams params) { var analysisStatus = params.analysis; if (analysisStatus != null && !analysisStatus.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 ---------'); } } }