From a0ff5f8b3fa3642919bb942624f460f685801e05 Mon Sep 17 00:00:00 2001 From: Dan Rubel Date: Wed, 26 Sep 2018 14:31:27 +0000 Subject: [PATCH] Add stub implementation for analysis server edit.dartfix Change-Id: Iefaec93366c5a6910e3c2e7dfebc91e8905922c2 Reviewed-on: https://dart-review.googlesource.com/76520 Reviewed-by: Brian Wilkerson Commit-Queue: Dan Rubel --- .../lib/protocol/protocol.dart | 2 +- .../lib/src/edit/edit_dartfix.dart | 15 +++ .../lib/src/edit/edit_domain.dart | 19 ++++ pkg/analyzer_cli/lib/src/fix/driver.dart | 105 +++++++++++------- pkg/analyzer_cli/lib/src/fix/server.dart | 16 ++- 5 files changed, 111 insertions(+), 46 deletions(-) create mode 100644 pkg/analysis_server/lib/src/edit/edit_dartfix.dart diff --git a/pkg/analysis_server/lib/protocol/protocol.dart b/pkg/analysis_server/lib/protocol/protocol.dart index c113e65f8f00d..1c87fb2d7d69a 100644 --- a/pkg/analysis_server/lib/protocol/protocol.dart +++ b/pkg/analysis_server/lib/protocol/protocol.dart @@ -402,7 +402,7 @@ class Response { Response.formatInvalidFile(Request request) : this(request.id, error: new RequestError(RequestErrorCode.FORMAT_INVALID_FILE, - 'Error during `edit.format`: invalid file.')); + 'Error during `${request.method}`: invalid file.')); /** * Initialize a newly created instance to represent the FORMAT_WITH_ERROR diff --git a/pkg/analysis_server/lib/src/edit/edit_dartfix.dart b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart new file mode 100644 index 0000000000000..99397ab6bae03 --- /dev/null +++ b/pkg/analysis_server/lib/src/edit/edit_dartfix.dart @@ -0,0 +1,15 @@ +// Copyright (c) 2014, 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 'package:analysis_server/protocol/protocol.dart'; + +class EditDartFix { + final Request request; + + EditDartFix(this.request); + + Future compute() async { + return new Response.formatInvalidFile(request); + } +} diff --git a/pkg/analysis_server/lib/src/edit/edit_domain.dart b/pkg/analysis_server/lib/src/edit/edit_domain.dart index 221af2e80beec..66c7323eea703 100644 --- a/pkg/analysis_server/lib/src/edit/edit_domain.dart +++ b/pkg/analysis_server/lib/src/edit/edit_domain.dart @@ -13,6 +13,7 @@ import 'package:analysis_server/src/analysis_server.dart'; import 'package:analysis_server/src/collections.dart'; import 'package:analysis_server/src/computer/import_elements_computer.dart'; import 'package:analysis_server/src/domain_abstract.dart'; +import 'package:analysis_server/src/edit/edit_dartfix.dart'; import 'package:analysis_server/src/plugin/plugin_manager.dart'; import 'package:analysis_server/src/plugin/result_converter.dart'; import 'package:analysis_server/src/protocol_server.dart' hide Element; @@ -260,6 +261,21 @@ class EditDomainHandler extends AbstractRequestHandler { new EditGetFixesResult(errorFixesList).toResponse(request.id)); } + Future dartfix(Request request) async { + // TODO(danrubel): Fix only the included sources + //EditDartfixParams params = new EditDartfixParams.fromRequest(request); + + // TODO(danrubel): Add support for dartfix plugins + + // + // Compute fixes + // + var dartFix = new EditDartFix(request); + Response response = await dartFix.compute(); + + server.sendResponse(response); + } + Future getPostfixCompletion(Request request) async { // TODO(brianwilkerson) Determine whether this await is necessary. await null; @@ -346,6 +362,9 @@ class EditDomainHandler extends AbstractRequestHandler { } else if (requestName == EDIT_REQUEST_GET_FIXES) { getFixes(request); return Response.DELAYED_RESPONSE; + } else if (requestName == EDIT_REQUEST_DARTFIX) { + dartfix(request); + return Response.DELAYED_RESPONSE; } else if (requestName == EDIT_REQUEST_GET_REFACTORING) { return _getRefactoring(request); } else if (requestName == EDIT_REQUEST_IMPORT_ELEMENTS) { diff --git a/pkg/analyzer_cli/lib/src/fix/driver.dart b/pkg/analyzer_cli/lib/src/fix/driver.dart index 5888e26ceb051..ac43e4c3895cc 100644 --- a/pkg/analyzer_cli/lib/src/fix/driver.dart +++ b/pkg/analyzer_cli/lib/src/fix/driver.dart @@ -3,19 +3,22 @@ // BSD-style license that can be found in the LICENSE file. import 'dart:async'; +import 'package:analysis_server/protocol/protocol_constants.dart'; import 'package:analyzer_cli/src/fix/options.dart'; import 'package:analyzer_cli/src/fix/server.dart'; import 'package:analysis_server/src/protocol/protocol_internal.dart'; import 'package:analysis_server/protocol/protocol_generated.dart'; import 'package:analyzer_plugin/protocol/protocol_common.dart'; -class Driver { - static const timeout = const Duration(seconds: 5); +// For development +const runAnalysisServerFromSource = false; +class Driver { final Server server = new Server(); Completer serverConnected; Completer analysisComplete; + int errorCount; bool verbose; Future start(List args) async { @@ -27,49 +30,68 @@ class Driver { } verbose = options.verbose; - serverConnected = new Completer(); - analysisComplete = new Completer(); - await startServer(options); - outSink.writeln('Analyzing...'); - await setupAnalysis(options); - - // TODO(danrubel): Request fixes rather than waiting for analysis complete - await analysisComplete.future; - - outSink.writeln('Analysis complete.'); - await stopServer(server); + bool normalShutdown = false; + try { + await performAnalysis(options); + await requestFixes(options); + normalShutdown = true; + } finally { + try { + await stopServer(server); + } catch (_) { + if (normalShutdown) { + rethrow; + } + } + } } Future startServer(Options options) async { + const connectTimeout = const Duration(seconds: 15); + serverConnected = new Completer(); if (options.verbose) { server.debugStdio(); } verboseOut('Starting...'); - await server.start(sdkPath: options.sdkPath); + await server.start( + sdkPath: options.sdkPath, useSnapshot: !runAnalysisServerFromSource); server.listenToOutput(dispatchNotification); - return serverConnected.future.timeout(timeout, onTimeout: () { + return serverConnected.future.timeout(connectTimeout, onTimeout: () { printAndFail('Failed to connect to server'); }); } - Future setupAnalysis(Options options) async { + Future performAnalysis(Options options) async { + analysisComplete = new Completer(); + errorCount = 0; + outSink.writeln('Analyzing...'); verboseOut('Setup analysis'); - - await server.send("server.setSubscriptions", + await server.send(SERVER_REQUEST_SET_SUBSCRIPTIONS, new ServerSetSubscriptionsParams([ServerService.STATUS]).toJson()); - await server.send( - "analysis.setAnalysisRoots", + ANALYSIS_REQUEST_SET_ANALYSIS_ROOTS, new AnalysisSetAnalysisRootsParams( options.analysisRoots, const [], ).toJson()); + await analysisComplete.future; + verboseOut('Analysis complete.'); + if (errorCount > 0) { + // TODO: Ask "Do you want to continue given # of errors?" + } + } + + Future requestFixes(Options options) async { + outSink.writeln('Calculating fixes...'); + Map response = await server.send(EDIT_REQUEST_DARTFIX, + new EditDartfixParams(options.analysisRoots).toJson()); + print(response); } Future stopServer(Server server) async { verboseOut('Stopping...'); - await server.send("server.shutdown", null); + await server.send(SERVER_REQUEST_SHUTDOWN, null); await server.exitCode.timeout(const Duration(seconds: 5), onTimeout: () { return server.kill('server failed to exit'); }); @@ -82,94 +104,94 @@ class Driver { void dispatchNotification(String event, params) { ResponseDecoder decoder = new ResponseDecoder(null); switch (event) { - case "server.connected": + case SERVER_NOTIFICATION_CONNECTED: onServerConnected( new ServerConnectedParams.fromJson(decoder, 'params', params)); break; -// case "server.error": +// case SERVER_NOTIFICATION_ERROR: // outOfTestExpect(params, isServerErrorParams); // _onServerError // .add(new ServerErrorParams.fromJson(decoder, 'params', params)); // break; - case "server.status": + case SERVER_NOTIFICATION_STATUS: onServerStatus( new ServerStatusParams.fromJson(decoder, 'params', params)); break; -// case "analysis.analyzedFiles": +// case ANALYSIS_NOTIFICATION_ANALYZED_FILES: // outOfTestExpect(params, isAnalysisAnalyzedFilesParams); // _onAnalysisAnalyzedFiles.add(new AnalysisAnalyzedFilesParams.fromJson( // decoder, 'params', params)); // break; -// case "analysis.closingLabels": +// case ANALYSIS_NOTIFICATION_CLOSING_LABELS: // outOfTestExpect(params, isAnalysisClosingLabelsParams); // _onAnalysisClosingLabels.add(new AnalysisClosingLabelsParams.fromJson( // decoder, 'params', params)); // break; - case "analysis.errors": + case ANALYSIS_NOTIFICATION_ERRORS: onAnalysisErrors( new AnalysisErrorsParams.fromJson(decoder, 'params', params)); break; -// case "analysis.flushResults": +// case ANALYSIS_NOTIFICATION_FLUSH_RESULTS: // outOfTestExpect(params, isAnalysisFlushResultsParams); // _onAnalysisFlushResults.add( // new AnalysisFlushResultsParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.folding": +// case ANALYSIS_NOTIFICATION_FOLDING: // outOfTestExpect(params, isAnalysisFoldingParams); // _onAnalysisFolding // .add(new AnalysisFoldingParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.highlights": +// case ANALYSIS_NOTIFICATION_HIGHLIGHTS: // outOfTestExpect(params, isAnalysisHighlightsParams); // _onAnalysisHighlights.add( // new AnalysisHighlightsParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.implemented": +// case ANALYSIS_NOTIFICATION_IMPLEMENTED: // outOfTestExpect(params, isAnalysisImplementedParams); // _onAnalysisImplemented.add( // new AnalysisImplementedParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.invalidate": +// case ANALYSIS_NOTIFICATION_INVALIDATE: // outOfTestExpect(params, isAnalysisInvalidateParams); // _onAnalysisInvalidate.add( // new AnalysisInvalidateParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.navigation": +// case ANALYSIS_NOTIFICATION_NAVIGATION: // outOfTestExpect(params, isAnalysisNavigationParams); // _onAnalysisNavigation.add( // new AnalysisNavigationParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.occurrences": +// case ANALYSIS_NOTIFICATION_OCCURRENCES: // outOfTestExpect(params, isAnalysisOccurrencesParams); // _onAnalysisOccurrences.add( // new AnalysisOccurrencesParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.outline": +// case ANALYSIS_NOTIFICATION_OUTLINE: // outOfTestExpect(params, isAnalysisOutlineParams); // _onAnalysisOutline // .add(new AnalysisOutlineParams.fromJson(decoder, 'params', params)); // break; -// case "analysis.overrides": +// case ANALYSIS_NOTIFICATION_OVERRIDES: // outOfTestExpect(params, isAnalysisOverridesParams); // _onAnalysisOverrides.add( // new AnalysisOverridesParams.fromJson(decoder, 'params', params)); // break; -// case "completion.results": +// case COMPLETION_NOTIFICATION_RESULTS: // outOfTestExpect(params, isCompletionResultsParams); // _onCompletionResults.add( // new CompletionResultsParams.fromJson(decoder, 'params', params)); // break; -// case "search.results": +// case SEARCH_NOTIFICATION_RESULTS: // outOfTestExpect(params, isSearchResultsParams); // _onSearchResults // .add(new SearchResultsParams.fromJson(decoder, 'params', params)); // break; -// case "execution.launchData": +// case EXECUTION_NOTIFICATION_LAUNCH_DATA: // outOfTestExpect(params, isExecutionLaunchDataParams); // _onExecutionLaunchData.add( // new ExecutionLaunchDataParams.fromJson(decoder, 'params', params)); // break; -// case "flutter.outline": +// case FLUTTER_NOTIFICATION_OUTLINE: // outOfTestExpect(params, isFlutterOutlineParams); // _onFlutterOutline // .add(new FlutterOutlineParams.fromJson(decoder, 'params', params)); @@ -185,6 +207,9 @@ class Driver { if (errors.isNotEmpty) { outSink.writeln(params.file); for (AnalysisError error in errors) { + if (error.severity == AnalysisErrorSeverity.ERROR) { + ++errorCount; + } Location loc = error.location; outSink.writeln(' ${error.message}' ' at ${loc.startLine}:${loc.startColumn}'); diff --git a/pkg/analyzer_cli/lib/src/fix/server.dart b/pkg/analyzer_cli/lib/src/fix/server.dart index 66f031c9f525a..bfaee1a188d97 100644 --- a/pkg/analyzer_cli/lib/src/fix/server.dart +++ b/pkg/analyzer_cli/lib/src/fix/server.dart @@ -94,14 +94,20 @@ class Server { * upward to the 'test' dir, and then going up one more directory. */ String findRoot(String pathname) { - while (!['benchmark', 'test'].contains(basename(pathname))) { + while (true) { String parent = dirname(pathname); if (parent.length >= pathname.length) { throw new Exception("Can't find root directory"); } + String name = basename(pathname); + if (['benchmark', 'test'].contains(name)) { + return parent; + } + if (name == 'pkg') { + return join(pathname, 'analysis_server'); + } pathname = parent; } - return dirname(pathname); } /** @@ -223,6 +229,7 @@ class Server { String sdkPath, int servicesPort, bool useAnalysisHighlight2: false, + bool useSnapshot: true, }) async { if (_process != null) { throw new Exception('Process already started'); @@ -230,11 +237,10 @@ class Server { _time.start(); String dartBinary = Platform.executable; - // The integration tests run 3x faster when run from snapshots (you need to - // run test.py with --use-sdk). - final bool useSnapshot = true; String serverPath; + // The integration tests run 3x faster when run from snapshots (you need to + // run test.py with --use-sdk). if (useSnapshot) { // Look for snapshots/analysis_server.dart.snapshot. serverPath = normalize(join(dirname(Platform.resolvedExecutable),