Server clean-up

R=scheglov@google.com

Review URL: https://codereview.chromium.org//795833005

git-svn-id: https://dart.googlecode.com/svn/branches/bleeding_edge/dart@42780 260f80e4-7a28-3924-810f-c04153c831b5
This commit is contained in:
brianwilkerson@google.com 2015-01-12 17:34:14 +00:00
parent cc33fcab6b
commit 4a8c341ecf
10 changed files with 96 additions and 866 deletions

View file

@ -1,183 +0,0 @@
// 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 'dart:async';
import 'dart:io';
import 'package:analysis_server/src/analysis_manager.dart';
import 'package:args/args.dart';
/**
* Start analysis server as a separate process and use the websocket protocol
* to analyze the application specified on the command line.
*/
void main(List<String> args) {
new _DartDependencyAnalyzer(args).run().catchError((error, stack) {
print('Analysis failed: $error');
if (stack != null) {
print(stack);
}
});
}
/**
* Instances of [_DartDependencyAnalyzer] launch an analysis server and use
* that server to analyze the dependencies of an application.
*/
class _DartDependencyAnalyzer {
/**
* The name of the application that is used to start the dependency analyzer.
*/
static const BINARY_NAME = 'dartdeps';
/**
* The name of the option used to specify the Dart SDK.
*/
static const String DART_SDK_OPTION = 'dart-sdk';
/**
* The name of the option used to print usage information.
*/
static const String HELP_OPTION = 'help';
/**
* The name of the option used to specify an already running server.
*/
static const String SERVER_OPTION = 'server';
/**
* The command line arguments.
*/
final List<String> args;
/**
* The path to the Dart SDK used during analysis.
*/
String sdkPath;
/**
* The manager for the analysis server.
*/
AnalysisManager manager;
_DartDependencyAnalyzer(this.args);
/**
* Use the given manager to perform the analysis.
*/
void analyze(AnalysisManager manager) {
if (manager == null) {
return;
}
this.manager = manager;
print('Analyzing...');
}
/**
* Print information about how to use the server.
*/
void printUsage(ArgParser parser) {
print('Usage: $BINARY_NAME [flags] <application_directory>');
print('');
print('Supported flags are:');
print(parser.usage);
}
/**
* Parse the command line arguments to determine the application to be
* analyzed, then launch and manage an analysis server to do the work.
*/
Future run() {
return new Future(start).then(analyze).whenComplete(stop);
}
/**
* Parse the command line arguments to determine the application to be
* analyzed, then launch an analysis server.
* Return `null` if the command line arguments are invalid.
*/
Future<AnalysisManager> start() {
ArgParser parser = new ArgParser();
parser.addOption(DART_SDK_OPTION, help: '[sdkPath] path to Dart SDK');
parser.addFlag(
HELP_OPTION,
help: 'print this help message without starting analysis',
defaultsTo: false,
negatable: false);
parser.addOption(
SERVER_OPTION,
help: '[serverUrl] use an analysis server thats already running');
// Parse arguments
ArgResults results;
try {
results = parser.parse(args);
} on FormatException catch (e) {
print(e.message);
print('');
printUsage(parser);
exitCode = 1;
return null;
}
if (results[HELP_OPTION]) {
printUsage(parser);
return null;
}
sdkPath = results[DART_SDK_OPTION];
if (sdkPath is! String) {
print('Missing path to Dart SDK');
printUsage(parser);
return null;
}
Directory sdkDir = new Directory(sdkPath);
if (!sdkDir.existsSync()) {
print('Specified Dart SDK does not exist: $sdkPath');
printUsage(parser);
return null;
}
if (results.rest.length == 0) {
printUsage(parser);
exitCode = 1;
return null;
}
Directory appDir = new Directory(results.rest[0]);
if (!appDir.existsSync()) {
print('Specified application directory does not exist: $appDir');
print('');
printUsage(parser);
exitCode = 1;
return null;
}
if (results.rest.length > 1) {
print('Unexpected arguments after $appDir');
print('');
printUsage(parser);
exitCode = 1;
return null;
}
// Connect to an already running analysis server
String serverUrl = results[SERVER_OPTION];
if (serverUrl != null) {
return AnalysisManager.connect(serverUrl);
}
// Launch and connect to a new analysis server
// Assume that the analysis server entry point is in the same directory
StringBuffer path = new StringBuffer();
path.write(FileSystemEntity.parentOf(Platform.script.toFilePath()));
path.write(Platform.pathSeparator);
path.write('server.dart');
return AnalysisManager.start(path.toString());
}
/**
* Stop the analysis server.
*/
void stop() {
if (manager != null) {
manager.stop();
}
}
}

View file

@ -1,171 +0,0 @@
// 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 'dart:async';
import 'dart:io';
import 'package:args/args.dart';
import 'package:matcher/matcher.dart';
import 'package:path/path.dart' as path;
import 'fuzz/server_manager.dart';
/**
* Start analysis server as a separate process and use the stdio to communicate
* with the server.
*/
void main(List<String> args) {
new _FuzzTest().run(args);
}
/**
* Instances of [_FuzzTest] launch and test an analysis server.
* You must specify the location of the Dart SDK and the directory
* containing sources to be analyzed.
*/
class _FuzzTest {
/**
* The name of the application that is used to start the fuzz tester.
*/
static const BINARY_NAME = 'fuzz';
//TODO (danrubel) extract common behavior for use in multiple test scenarios
//TODO (danrubel) cleanup test to use async/await for better readability
// VM flag --enable_async
static const String DART_SDK_OPTION = 'dart-sdk';
static const String HELP_OPTION = 'help';
File serverSnapshot;
Directory appDir;
/// Parse the arguments and initialize the receiver
/// Return `true` if proper arguments were provided
bool parseArgs(List<String> args) {
ArgParser parser = new ArgParser();
void error(String errMsg) {
stderr.writeln(errMsg);
print('');
_printUsage(parser);
exitCode = 11;
}
parser.addOption(DART_SDK_OPTION, help: '[sdkPath] path to Dart SDK');
parser.addFlag(
HELP_OPTION,
help: 'print this help message without starting analysis',
defaultsTo: false,
negatable: false);
ArgResults results;
try {
results = parser.parse(args);
} on FormatException catch (e) {
error(e.message);
return false;
}
if (results[HELP_OPTION]) {
_printUsage(parser);
return false;
}
String sdkPath = results[DART_SDK_OPTION];
if (sdkPath is! String) {
error('Missing path to Dart SDK');
return false;
}
Directory sdkDir = new Directory(sdkPath);
if (!sdkDir.existsSync()) {
error('Specified Dart SDK does not exist: $sdkPath');
return false;
}
if (results.rest.length == 0) {
error('Expected directory to analyze');
return false;
}
appDir = new Directory(results.rest[0]);
if (!appDir.existsSync()) {
error('Specified application directory does not exist: $appDir');
return false;
}
if (results.rest.length > 1) {
error('Unexpected arguments after $appDir');
return false;
}
serverSnapshot = new File(
path.join(sdkDir.path, 'bin', 'snapshots', 'analysis_server.dart.snapshot'));
if (!serverSnapshot.existsSync()) {
error('Analysis Server snapshot not found: $serverSnapshot');
return false;
}
return true;
}
/// Main entry point for launching, testing, and shutting down the server
void run(List<String> args) {
if (!parseArgs(args)) return;
ServerManager.start(serverSnapshot.path).then((ServerManager manager) {
runZoned(() {
test(manager).then(manager.stop).then((_) {
expect(manager.errorOccurred, isFalse);
print('Test completed successfully');
});
}, onError: (error, stack) {
stderr.writeln(error);
print(stack);
exitCode = 12;
manager.stop();
});
});
}
/// Use manager to exercise the analysis server
Future test(ServerManager manager) {
// perform initial analysis
return manager.analyze(appDir).then((AnalysisResults analysisResults) {
print(
'Found ${analysisResults.errorCount} errors,'
' ${analysisResults.warningCount} warnings,'
' and ${analysisResults.hintCount} hints in ${analysisResults.elapsed}');
// edit a method body
return manager.openFileNamed(
'domain_completion.dart').then((Editor editor) {
return editor.moveAfter('Response processRequest(Request request) {');
}).then((Editor editor) {
return editor.replace(0, '\nOb');
}).then((Editor editor) {
// request code completion and assert results
return editor.getSuggestions().then((List<CompletionResults> list) {
expect(list, isNotNull);
expect(list.length, equals(0));
list.forEach((CompletionResults results) {
print(
'${results.elapsed} received ${results.suggestionCount} suggestions');
});
return editor;
});
}).then((Editor editor) {
print('tests complete');
});
});
}
// void _printAnalysisSummary(AnalysisResults results) {
// print(
// 'Found ${results.errorCount} errors, ${results.warningCount} warnings,'
// ' and ${results.hintCount} hints in $results.elapsed');
// }
/// Print information about how to use the server.
void _printUsage(ArgParser parser) {
print('Usage: $BINARY_NAME [flags] <application_directory>');
print('');
print('Supported flags are:');
print(parser.usage);
}
}

View file

@ -1,9 +0,0 @@
This directory contains code for fuzz testing the analysis server
and for generating timing information for tracking server performance.
Run:
Launch fuzz.dart located in the parent directory.
Overview:
fuzz.dart - main entry point and simple example of exercizing server
server_manager.dart - provides high level API for launching and driving server

View file

@ -1,85 +0,0 @@
// 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.
part of server.manager;
/**
* A client channel that logs communication to stdout
* and handles errors received from the server.
*/
class LoggingClientChannel implements ClientCommunicationChannel {
final ClientCommunicationChannel channel;
int serverErrorCount = 0;
LoggingClientChannel(this.channel) {
channel.notificationStream.listen((Notification notification) {
_logNotification(notification);
if (notification.event == 'server.error') {
ServerErrorParams error =
new ServerErrorParams.fromNotification(notification);
_handleError(
'Server reported error: ${error.message}',
error.stackTrace);
}
});
}
@override
Stream<Notification> get notificationStream => channel.notificationStream;
@override
void set notificationStream(Stream<Notification> _notificationStream) {
throw 'invalid operation';
}
@override
Stream<Response> get responseStream => channel.responseStream;
@override
void set responseStream(Stream<Response> _responseStream) {
throw 'invalid operation';
}
@override
Future close() {
print('Requesting client channel be closed');
return channel.close().then((_) {
print('Client channel closed');
});
}
@override
Future<Response> sendRequest(Request request) {
_logOperation('=>', request);
return channel.sendRequest(request).then((Response response) {
RequestError error = response.error;
if (error != null) {
error.code;
stderr.write('Server Error ${error.code}: ${error.message}');
print(error.stackTrace);
exitCode = 31;
}
_logOperation('<=', request);
return response;
});
}
void _handleError(String errMsg, String stackTrace) {
//error.isFatal;
stderr.writeln('>>> Server reported exception');
stderr.writeln(errMsg);
print(stackTrace);
serverErrorCount++;
}
void _logNotification(Notification notification) {
print('<= ${notification.event}');
}
void _logOperation(String direction, Request request) {
String id = request.id.padLeft(5);
String method = request.method.padRight(20);
print('$direction $id $method');
}
}

View file

@ -1,365 +0,0 @@
// 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.
library server.manager;
import 'dart:async';
import 'dart:convert';
import 'dart:io';
import 'package:matcher/matcher.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analysis_server/src/channel/channel.dart';
import 'package:analysis_server/src/channel/byte_stream_channel.dart';
part 'logging_client_channel.dart';
/**
* The results returned by [ServerManager].analyze(...) once analysis
* has finished.
*/
class AnalysisResults {
Duration elapsed;
int errorCount = 0;
int hintCount = 0;
int warningCount = 0;
}
/**
* [CompletionResults] contains the completion results returned by the server
* along with the elapse time to receive those completions.
*/
class CompletionResults {
final Duration elapsed;
final CompletionResultsParams params;
CompletionResults(this.elapsed, this.params);
int get suggestionCount => params.results.length;
}
/**
* [Editor] is a virtual editor for inspecting and modifying a file's content
* and updating the server with those modifications.
*/
class Editor {
final ServerManager manager;
final File file;
int offset = 0;
String _content = null;
Editor(this.manager, this.file);
/// Return a future that returns the file content
Future<String> get content {
if (_content != null) {
return new Future.value(_content);
}
return file.readAsString().then((String content) {
_content = content;
return _content;
});
}
/**
* Request completion suggestions from the server.
* Return a future that completes with the completions sent.
*/
Future<List<CompletionResults>> getSuggestions() {
Request request = new CompletionGetSuggestionsParams(
file.path,
offset).toRequest(manager._nextRequestId);
Stopwatch stopwatch = new Stopwatch()..start();
return manager.channel.sendRequest(request).then((Response response) {
String completionId =
new CompletionGetSuggestionsResult.fromResponse(response).id;
var completer = new Completer<List<CompletionResults>>();
List<CompletionResults> results = [];
// Listen for completion suggestions
StreamSubscription<Notification> subscription;
subscription =
manager.channel.notificationStream.listen((Notification notification) {
if (notification.event == 'completion.results') {
CompletionResultsParams params =
new CompletionResultsParams.fromNotification(notification);
if (params.id == completionId) {
results.add(new CompletionResults(stopwatch.elapsed, params));
if (params.isLast) {
stopwatch.stop();
subscription.cancel();
completer.complete(results);
}
}
}
});
return completer.future;
});
}
/**
* Move the virtual cursor after the given pattern in the source.
* Return a future that completes once the cursor has been moved.
*/
Future<Editor> moveAfter(String pattern) {
return content.then((String content) {
offset = content.indexOf(pattern);
return this;
});
}
/**
* Replace the specified number of characters at the current cursor location
* with the given text, but do not save that content to disk.
* Return a future that completes once the server has been notified.
*/
Future<Editor> replace(int replacementLength, String text) {
return content.then((String oldContent) {
StringBuffer sb = new StringBuffer();
sb.write(oldContent.substring(0, offset));
sb.write(text);
sb.write(oldContent.substring(offset));
_content = sb.toString();
SourceEdit sourceEdit = new SourceEdit(offset, replacementLength, text);
Request request = new AnalysisUpdateContentParams({
file.path: new ChangeContentOverlay([sourceEdit])
}).toRequest(manager._nextRequestId);
offset += text.length;
return manager.channel.sendRequest(request).then((Response response) {
return this;
});
});
}
}
/**
* [ServerManager] is used to launch and manage an analysis server
* running in a separate process.
*/
class ServerManager {
/**
* The analysis server process being managed or `null` if not started.
*/
Process process;
/**
* The root directory containing the Dart source files to be analyzed.
*/
Directory appDir;
/**
* The channel used to communicate with the analysis server.
*/
LoggingClientChannel _channel;
/**
* The identifier used in the most recent request to the server.
* See [_nextRequestId].
*/
int _lastRequestId = 0;
/**
* `true` if a server exception was detected on stderr as opposed to an
* exception that the server reported via the server.error notification.
*/
bool _unreportedServerException = false;
/**
* `true` if the [stop] method has been called.
*/
bool _stopRequested = false;
/**
* Return the channel used to communicate with the analysis server.
*/
ClientCommunicationChannel get channel => _channel;
/**
* Return `true` if a server error occurred.
*/
bool get errorOccurred =>
_unreportedServerException || (_channel.serverErrorCount > 0);
String get _nextRequestId => (++_lastRequestId).toString();
/**
* Direct the server to analyze all sources in the given directory,
* all sub directories recursively, and any source referenced sources
* outside this directory hierarch such as referenced packages.
* Return a future that completes when the analysis is finished.
*/
Future<AnalysisResults> analyze(Directory appDir) {
this.appDir = appDir;
Stopwatch stopwatch = new Stopwatch()..start();
Request request = new AnalysisSetAnalysisRootsParams(
[appDir.path],
[]).toRequest(_nextRequestId);
// Request analysis
return channel.sendRequest(request).then((Response response) {
AnalysisResults results = new AnalysisResults();
StreamSubscription<Notification> subscription;
Completer<AnalysisResults> completer = new Completer<AnalysisResults>();
subscription =
channel.notificationStream.listen((Notification notification) {
// Gather analysis results
if (notification.event == 'analysis.errors') {
AnalysisErrorsParams params =
new AnalysisErrorsParams.fromNotification(notification);
params.errors.forEach((AnalysisError error) {
AnalysisErrorSeverity severity = error.severity;
if (severity == AnalysisErrorSeverity.ERROR) {
results.errorCount += 1;
} else if (severity == AnalysisErrorSeverity.WARNING) {
results.warningCount += 1;
} else if (severity == AnalysisErrorSeverity.INFO) {
results.hintCount += 1;
} else {
print('Unknown error severity: ${severity.name}');
}
});
}
// Stop gathering once analysis is complete
if (notification.event == 'server.status') {
ServerStatusParams status =
new ServerStatusParams.fromNotification(notification);
AnalysisStatus analysis = status.analysis;
if (analysis != null && !analysis.isAnalyzing) {
stopwatch.stop();
results.elapsed = stopwatch.elapsed;
subscription.cancel();
completer.complete(results);
}
}
});
return completer.future;
});
}
/**
* Send a request to the server for its version information
* and return a future that completes with the result.
*/
Future<ServerGetVersionResult> getVersion() {
Request request = new ServerGetVersionParams().toRequest(_nextRequestId);
return channel.sendRequest(request).then((Response response) {
return new ServerGetVersionResult.fromResponse(response);
});
}
/**
* Notify the server that the given file will be edited.
* Return a virtual editor for inspecting and modifying the file's content.
*/
Future<Editor> openFileNamed(String fileName) {
return _findFile(fileName, appDir).then((File file) {
if (file == null) {
throw 'Failed to find file named $fileName in ${appDir.path}';
}
file = file.absolute;
Request request =
new AnalysisSetPriorityFilesParams([file.path]).toRequest(_nextRequestId);
return channel.sendRequest(request).then((Response response) {
return new Editor(this, file);
});
});
}
/**
* Send a request for notifications.
* Return when the server has acknowledged that request.
*/
Future setSubscriptions() {
Request request = new ServerSetSubscriptionsParams(
[ServerService.STATUS]).toRequest(_nextRequestId);
return channel.sendRequest(request);
}
/**
* Stop the analysis server.
* Return a future that completes when the server is terminated.
*/
Future stop([_]) {
_stopRequested = true;
print("Requesting server shutdown");
Request request = new ServerShutdownParams().toRequest(_nextRequestId);
Duration waitTime = new Duration(seconds: 5);
return channel.sendRequest(request).timeout(waitTime, onTimeout: () {
print('Expected shutdown response');
}).then((Response response) {
return channel.close().then((_) => process.exitCode);
}).timeout(new Duration(seconds: 2), onTimeout: () {
print('Expected server to shutdown');
process.kill();
});
}
/**
* Locate the given file in the directory tree.
*/
Future<File> _findFile(String fileName, Directory appDir) {
return appDir.list(recursive: true).firstWhere((FileSystemEntity entity) {
return entity is File && entity.path.endsWith(fileName);
});
}
/**
* Launch an analysis server and open a connection to that server.
*/
Future<ServerManager> _launchServer(String pathToServer) {
List<String> serverArgs = [pathToServer];
return Process.start(Platform.executable, serverArgs).catchError((error) {
exitCode = 21;
throw 'Failed to launch analysis server: $error';
}).then((Process process) {
this.process = process;
_channel = new LoggingClientChannel(
new ByteStreamClientChannel(process.stdout, process.stdin));
// simple out of band exception handling
process.stderr.transform(
new Utf8Codec().decoder).transform(new LineSplitter()).listen((String line) {
if (!_unreportedServerException) {
_unreportedServerException = true;
stderr.writeln('>>> Unreported server exception');
}
stderr.writeln('server.stderr: $line');
});
// watch for unexpected process termination and catch the exit code
process.exitCode.then((int code) {
if (!_stopRequested) {
fail('Unexpected server termination: $code');
}
if (code != null && code != 0) {
exitCode = code;
}
print('Server stopped: $code');
});
return channel.notificationStream.first.then((Notification notification) {
print('Server connection established');
return setSubscriptions().then((_) {
return getVersion().then((ServerGetVersionResult result) {
print('Server version ${result.version}');
return this;
});
});
});
});
}
/**
* Launch analysis server in a separate process
* and return a future with a manager for that analysis server.
*/
static Future<ServerManager> start(String serverPath) {
return new ServerManager()._launchServer(serverPath);
}
}

View file

@ -2,12 +2,12 @@
// 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/driver.dart';
import 'package:analysis_server/starter.dart';
/**
* Create and run an HTTP-based analysis server.
* Create and run an analysis server.
*/
void main(List<String> args) {
Driver driver = new Driver();
driver.start(args);
ServerStarter starter = new ServerStarter();
starter.start(args);
}

View file

@ -7,13 +7,14 @@ library driver;
import 'dart:async';
import 'dart:io';
import 'package:analysis_server/http_server.dart';
import 'package:analysis_server/plugin/plugin.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/plugin/plugin_impl.dart';
import 'package:analysis_server/src/plugin/server_plugin.dart';
import 'package:analysis_server/src/server/http_server.dart';
import 'package:analysis_server/src/server/stdio_server.dart';
import 'package:analysis_server/src/socket_server.dart';
import 'package:analysis_server/stdio_server.dart';
import 'package:analysis_server/starter.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/incremental_logger.dart';
@ -54,7 +55,7 @@ void _initIncrementalLogger(String spec) {
* server application. It is responsible for parsing command line options
* and starting the HTTP and/or stdio servers.
*/
class Driver {
class Driver implements ServerStarter {
/**
* The name of the application that is used to start a server.
*/
@ -144,53 +145,11 @@ class Driver {
}
/**
* Use the given command-line arguments to start this server.
* Use the given command-line [arguments] to start this server.
*/
void start(List<String> args) {
ArgParser parser = new ArgParser();
parser.addOption(
CLIENT_ID,
help: "an identifier used to identify the client");
parser.addFlag(
ENABLE_INCREMENTAL_RESOLUTION_API,
help: "enable using incremental resolution for API changes",
defaultsTo: false,
negatable: false);
parser.addFlag(
ENABLE_INSTRUMENTATION_OPTION,
help: "enable sending instrumentation information to a server",
defaultsTo: false,
negatable: false);
parser.addFlag(
HELP_OPTION,
help: "print this help message without starting a server",
defaultsTo: false,
negatable: false);
parser.addOption(
INCREMENTAL_RESOLUTION_LOG,
help: "the description of the incremental resolution log");
parser.addFlag(
INCREMENTAL_RESOLUTION_VALIDATION,
help: "enable validation of incremental resolution results (slow)",
defaultsTo: false,
negatable: false);
parser.addFlag(
INTERNAL_PRINT_TO_CONSOLE,
help: "enable sending `print` output to the console",
defaultsTo: false,
negatable: false);
parser.addOption(
PORT_OPTION,
help: "[port] the port on which the server will listen");
parser.addOption(SDK_OPTION, help: "[path] the path to the sdk");
parser.addFlag(
NO_ERROR_NOTIFICATION,
help:
"disable sending all analysis error notifications to the server (not yet implemented)",
defaultsTo: false,
negatable: false);
ArgResults results = parser.parse(args);
void start(List<String> arguments) {
ArgParser parser = _createArgParser();
ArgResults results = parser.parse(arguments);
if (results[HELP_OPTION]) {
_printUsage(parser);
return;
@ -309,6 +268,56 @@ class Driver {
return runZoned(callback, zoneSpecification: zoneSpecification);
}
/**
* Create and return the parser used to parse the command-line arguments.
*/
ArgParser _createArgParser() {
ArgParser parser = new ArgParser();
parser.addOption(
CLIENT_ID,
help: "an identifier used to identify the client");
parser.addFlag(
ENABLE_INCREMENTAL_RESOLUTION_API,
help: "enable using incremental resolution for API changes",
defaultsTo: false,
negatable: false);
parser.addFlag(
ENABLE_INSTRUMENTATION_OPTION,
help: "enable sending instrumentation information to a server",
defaultsTo: false,
negatable: false);
parser.addFlag(
HELP_OPTION,
help: "print this help message without starting a server",
defaultsTo: false,
negatable: false);
parser.addOption(
INCREMENTAL_RESOLUTION_LOG,
help: "the description of the incremental resolution log");
parser.addFlag(
INCREMENTAL_RESOLUTION_VALIDATION,
help: "enable validation of incremental resolution results (slow)",
defaultsTo: false,
negatable: false);
parser.addFlag(
INTERNAL_PRINT_TO_CONSOLE,
help: "enable sending `print` output to the console",
defaultsTo: false,
negatable: false);
parser.addOption(
PORT_OPTION,
help: "[port] the port on which the server will listen");
parser.addOption(SDK_OPTION, help: "[path] the path to the sdk");
parser.addFlag(
NO_ERROR_NOTIFICATION,
help:
"disable sending all analysis error notifications to the server (not yet implemented)",
defaultsTo: false,
negatable: false);
return parser;
}
/**
* Print information about how to use the server.
*/

View file

@ -0,0 +1,34 @@
// Copyright (c) 2015, 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.
library driver;
import 'package:analysis_server/plugin/plugin.dart';
import 'package:analysis_server/src/server/driver.dart';
import 'package:analyzer/instrumentation/instrumentation.dart';
/**
* An object that can be used to start an analysis server.
*/
abstract class ServerStarter {
/**
* Initialize a newly created starter to start up an analysis server.
*/
factory ServerStarter() = Driver;
/**
* Set the instrumentation [server] that is to be used by the analysis server.
*/
void set instrumentationServer(InstrumentationServer server);
/**
* Set the [plugins] that are defined outside the analysis_server package.
*/
void set userDefinedPlugins(List<Plugin> plugins);
/**
* Use the given command-line [arguments] to start this server.
*/
void start(List<String> arguments);
}