Drop package rpc (#488)
diff --git a/analysis_options.yaml b/analysis_options.yaml
index e773966..a812034 100644
--- a/analysis_options.yaml
+++ b/analysis_options.yaml
@@ -4,11 +4,11 @@
strong-mode:
implicit-casts: false
exclude:
- - 'dart-sdk/**'
- - 'third_party/**'
- - 'doc/generated/**'
- - 'flutter/**'
- - 'lib/src/protos/**'
+ - "dart-sdk/**"
+ - "third_party/**"
+ - "doc/generated/**"
+ - "flutter/**"
+ - "lib/src/protos/**"
linter:
rules:
diff --git a/lib/services_dev.dart b/lib/services_dev.dart
index ea620f5..3a0c77c 100644
--- a/lib/services_dev.dart
+++ b/lib/services_dev.dart
@@ -6,19 +6,16 @@
library services_dev;
import 'dart:async';
-import 'dart:convert';
import 'dart:io';
import 'package:args/args.dart';
import 'package:logging/logging.dart';
-import 'package:rpc/rpc.dart';
import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as shelf;
import 'src/common.dart';
-import 'src/common_server.dart';
+import 'src/common_server_api.dart';
import 'src/common_server_impl.dart';
-import 'src/common_server_proto.dart';
import 'src/flutter_web.dart';
import 'src/sdk_manager.dart';
import 'src/server_cache.dart';
@@ -43,19 +40,6 @@
final sdk = sdkPath;
- void printExit(String doc) {
- print(doc);
- exit(0);
- }
-
- if (result['discovery'] as bool) {
- final serverUrl = result['server-url'] as String;
- EndpointsServer.generateDiscovery(SdkManager.flutterSdk, serverUrl)
- .then(printExit);
-
- return;
- }
-
Logger.root.level = Level.FINER;
Logger.root.onRecord.listen((LogRecord record) {
print(record);
@@ -79,43 +63,16 @@
});
}
- static Future<String> generateDiscovery(
- FlutterSdk flutterSdk, String serverUrl) async {
- final flutterWebManager = FlutterWebManager(flutterSdk);
- final commonServerImpl = CommonServerImpl(
- sdkPath,
- flutterWebManager,
- _ServerContainer(),
- _Cache(),
- );
- final commonServer = CommonServer(commonServerImpl);
- await commonServerImpl.init();
- final apiServer = ApiServer(apiPrefix: '/api', prettyPrint: true)
- ..addApi(commonServer);
- apiServer.enableDiscoveryApi();
-
- final uri = Uri.parse('/api/discovery/v1/apis/dartservices/v1/rest');
- final request = HttpApiRequest('GET', uri, <String, dynamic>{},
- Stream<List<int>>.fromIterable(<List<int>>[]));
- final response = await apiServer.handleHttpApiRequest(request);
- return utf8.decode(await response.body.first);
- }
-
final int port;
HttpServer server;
Pipeline pipeline;
Handler handler;
- ApiServer apiServer;
- bool discoveryEnabled;
- CommonServer commonServer;
- CommonServerProto commonServerProto;
+ CommonServerApi commonServerApi;
FlutterWebManager flutterWebManager;
EndpointsServer._(String sdkPath, this.port) {
- discoveryEnabled = false;
-
flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
final commonServerImpl = CommonServerImpl(
sdkPath,
@@ -123,50 +80,14 @@
_ServerContainer(),
_Cache(),
);
- commonServer = CommonServer(commonServerImpl);
- commonServerProto = CommonServerProto(commonServerImpl);
+ commonServerApi = CommonServerApi(commonServerImpl);
commonServerImpl.init();
- apiServer = ApiServer(apiPrefix: '/api', prettyPrint: true)
- ..addApi(commonServer);
-
- pipeline = Pipeline()
+ pipeline = const Pipeline()
.addMiddleware(logRequests())
.addMiddleware(_createCustomCorsHeadersMiddleware());
- handler = pipeline.addHandler((request) {
- if (request.requestedUri.path.startsWith(PROTO_API_URL_PREFIX)) {
- return commonServerProto.router.handler(request);
- }
- return _apiHandler(request);
- });
- }
-
- Future<Response> _apiHandler(Request request) {
- if (!discoveryEnabled) {
- apiServer.enableDiscoveryApi();
- discoveryEnabled = true;
- }
-
- // NOTE: We could read in the request body here and parse it similar to the
- // _parseRequest method to determine content-type and dispatch to e.g. a
- // plain text handler if we want to support that.
- final apiRequest = HttpApiRequest(
- request.method, request.requestedUri, request.headers, request.read());
-
- // Promote text/plain requests to application/json.
- if (apiRequest.headers['content-type'] == 'text/plain; charset=utf-8') {
- apiRequest.headers['content-type'] = 'application/json; charset=utf-8';
- }
-
- return apiServer
- .handleHttpApiRequest(apiRequest)
- .then((HttpApiResponse apiResponse) {
- // TODO(jcollins-g): use sendApiResponse helper?
- return Response(apiResponse.status,
- body: apiResponse.body,
- headers: Map<String, String>.from(apiResponse.headers));
- });
+ handler = pipeline.addHandler(commonServerApi.router.handler);
}
Response printUsage(Request request, dynamic e, StackTrace stackTrace) {
diff --git a/lib/services_gae.dart b/lib/services_gae.dart
index b063207..e580b71 100644
--- a/lib/services_gae.dart
+++ b/lib/services_gae.dart
@@ -9,19 +9,16 @@
import 'package:appengine/appengine.dart' as ae;
import 'package:logging/logging.dart';
-import 'package:rpc/rpc.dart' as rpc;
import 'package:shelf/shelf_io.dart' as shelf_io;
import 'src/common.dart';
-import 'src/common_server.dart';
+import 'src/common_server_api.dart';
import 'src/common_server_impl.dart';
-import 'src/common_server_proto.dart';
import 'src/flutter_web.dart';
import 'src/sdk_manager.dart';
import 'src/server_cache.dart';
-const String _API = '/api';
-const String _API_V1_PREFIX = '/api/dartservices/v1';
+const String _API_PREFIX = '/api/dartservices/';
const String _healthCheck = '/_ah/health';
const String _readynessCheck = '/_ah/ready';
@@ -63,10 +60,8 @@
final String redisServerUri;
bool discoveryEnabled;
- rpc.ApiServer apiServer;
- CommonServer commonServer;
CommonServerImpl commonServerImpl;
- CommonServerProto commonServerProto;
+ CommonServerApi commonServerApi;
GaeServer(this.sdkPath, this.redisServerUri) {
hierarchicalLoggingEnabled = true;
@@ -87,11 +82,7 @@
io.Platform.environment['GAE_VERSION'],
),
);
- commonServer = CommonServer(commonServerImpl);
- commonServerProto = CommonServerProto(commonServerImpl);
- // Enabled pretty printing of returned json for debuggability.
- apiServer = rpc.ApiServer(apiPrefix: _API, prettyPrint: true)
- ..addApi(commonServer);
+ commonServerApi = CommonServerApi(commonServerImpl);
}
Future<dynamic> start([int gaePort = 8080]) async {
@@ -111,10 +102,8 @@
await _processReadynessRequest(request);
} else if (request.uri.path == _healthCheck) {
await _processHealthRequest(request);
- } else if (request.uri.path.startsWith(_API_V1_PREFIX)) {
- await _processApiRequest(request);
- } else if (request.uri.path.startsWith(PROTO_API_URL_PREFIX)) {
- await shelf_io.handleRequest(request, commonServerProto.router.handler);
+ } else if (request.uri.path.startsWith(_API_PREFIX)) {
+ await shelf_io.handleRequest(request, commonServerApi.router.handler);
} else {
await _processDefaultRequest(request);
}
@@ -173,32 +162,6 @@
await request.response.close();
}
- Future _processApiRequest(io.HttpRequest request) async {
- if (!discoveryEnabled) {
- apiServer.enableDiscoveryApi();
- discoveryEnabled = true;
- }
- // NOTE: We could read in the request body here and parse it similar to
- // the _parseRequest method to determine content-type and dispatch to e.g.
- // a plain text handler if we want to support that.
- final apiRequest = rpc.HttpApiRequest.fromHttpRequest(request);
-
- // Dartpad sends data as plain text, we need to promote this to
- // application/json to ensure that the rpc library processes it correctly
- try {
- apiRequest.headers['content-type'] = 'application/json; charset=utf-8';
- final apiResponse = await apiServer.handleHttpApiRequest(apiRequest);
- await rpc.sendApiResponse(apiResponse, request.response);
- } catch (e) {
- // This should only happen in the case where there is a bug in the rpc
- // package. Otherwise it always returns an HttpApiResponse.
- _logger.warning('Failed with error: $e when trying to call '
- 'method at \'${request.uri.path}\'.');
- request.response.statusCode = io.HttpStatus.internalServerError;
- await request.response.close();
- }
- }
-
Future _processDefaultRequest(io.HttpRequest request) async {
request.response.statusCode = io.HttpStatus.notFound;
await request.response.close();
diff --git a/lib/src/analysis_server.dart b/lib/src/analysis_server.dart
index 4b3401a..19ae44f 100644
--- a/lib/src/analysis_server.dart
+++ b/lib/src/analysis_server.dart
@@ -6,15 +6,16 @@
library services.analysis_server;
import 'dart:async';
+import 'dart:convert';
import 'dart:io';
import 'package:analysis_server_lib/analysis_server_lib.dart';
import 'package:logging/logging.dart';
import 'package:path/path.dart' as path;
-import 'api_classes.dart' as api;
import 'common.dart';
import 'flutter_web.dart';
+import 'protos/dart_services.pb.dart' as proto;
import 'pub.dart';
import 'scheduler.dart';
@@ -24,12 +25,12 @@
/// to stdout.
bool dumpServerMessages = false;
-final String _WARMUP_SRC_HTML =
+const String _WARMUP_SRC_HTML =
"import 'dart:html'; main() { int b = 2; b++; b. }";
-final String _WARMUP_SRC = 'main() { int b = 2; b++; b. }';
+const String _WARMUP_SRC = 'main() { int b = 2; b++; b. }';
// Use very long timeouts to ensure that the server has enough time to restart.
-final Duration _ANALYSIS_SERVER_TIMEOUT = Duration(seconds: 35);
+const Duration _ANALYSIS_SERVER_TIMEOUT = Duration(seconds: 35);
class AnalysisServerWrapper {
final String sdkPath;
@@ -111,15 +112,15 @@
// Return when the analysis server exits. We introduce a delay so that when
// we terminate the analysis server we can exit normally.
return analysisServer.processCompleter.future.then((int code) {
- return Future<int>.delayed(Duration(seconds: 1), () {
+ return Future<int>.delayed(const Duration(seconds: 1), () {
return code;
});
});
}
- Future<api.CompleteResponse> complete(String src, int offset) async {
+ Future<proto.CompleteResponse> complete(String src, int offset) async {
final sources = <String, String>{kMainDart: src};
- final location = api.Location.from(kMainDart, offset);
+ final location = Location(kMainDart, offset);
final results =
await _completeImpl(sources, location.sourceName, location.offset);
@@ -144,37 +145,44 @@
}
});
- return api.CompleteResponse(
- results.replacementOffset,
- results.replacementLength,
- suggestions.map((CompletionSuggestion c) => c.toMap()).toList(),
- );
+ return proto.CompleteResponse()
+ ..replacementOffset = results.replacementOffset
+ ..replacementLength = results.replacementLength
+ ..completions
+ .addAll(suggestions.map((CompletionSuggestion c) => proto.Completion()
+ ..completion.addAll(c.toMap().map((key, value) {
+ // TODO: Properly support Lists, Maps (this is a hack).
+ if (value is Map || value is List) {
+ value = json.encode(value);
+ }
+ return MapEntry(key.toString(), value.toString());
+ }))));
}
- Future<api.FixesResponse> getFixes(String src, int offset) {
+ Future<proto.FixesResponse> getFixes(String src, int offset) {
return getFixesMulti(
<String, String>{kMainDart: src},
- api.Location.from(kMainDart, offset),
+ Location(kMainDart, offset),
);
}
- Future<api.FixesResponse> getFixesMulti(
- Map<String, String> sources, api.Location location) async {
+ Future<proto.FixesResponse> getFixesMulti(
+ Map<String, String> sources, Location location) async {
final results =
await _getFixesImpl(sources, location.sourceName, location.offset);
- final responseFixes = results.fixes.map(_convertAnalysisErrorFix).toList();
- return api.FixesResponse(responseFixes);
+ final responseFixes = results.fixes.map(_convertAnalysisErrorFix);
+ return proto.FixesResponse()..fixes.addAll(responseFixes);
}
- Future<api.AssistsResponse> getAssists(String src, int offset) async {
+ Future<proto.AssistsResponse> getAssists(String src, int offset) async {
final sources = {kMainDart: src};
- final sourceName = api.Location.from(kMainDart, offset).sourceName;
+ final sourceName = Location(kMainDart, offset).sourceName;
final results = await _getAssistsImpl(sources, sourceName, offset);
final fixes = _convertSourceChangesToCandidateFixes(results.assists);
- return api.AssistsResponse(fixes);
+ return proto.AssistsResponse()..assists.addAll(fixes);
}
- Future<api.FormatResponse> format(String src, int offset) {
+ Future<proto.FormatResponse> format(String src, int offset) {
return _formatImpl(src, offset).then((FormatResult editResult) {
final edits = editResult.edits;
@@ -186,10 +194,14 @@
edit.offset, edit.offset + edit.length, edit.replacement);
}
- return api.FormatResponse(src, editResult.selectionOffset);
+ return proto.FormatResponse()
+ ..newString = src
+ ..offset = editResult.selectionOffset;
}).catchError((dynamic error) {
_logger.fine('format error: $error');
- return api.FormatResponse(src, offset);
+ return proto.FormatResponse()
+ ..newString = src
+ ..offset = offset;
});
}
@@ -232,13 +244,14 @@
}, timeoutDuration: _ANALYSIS_SERVER_TIMEOUT));
}
- Future<api.AnalysisResults> analyze(String source) {
+ Future<proto.AnalysisResults> analyze(String source) {
var sources = <String, String>{kMainDart: source};
_logger
.fine('analyzeMulti: Scheduler queue: ${serverScheduler.queueCount}');
- return serverScheduler.schedule(ClosureTask<api.AnalysisResults>(() async {
+ return serverScheduler
+ .schedule(ClosureTask<proto.AnalysisResults>(() async {
clearErrors();
final analysisCompleter = getAnalysisCompleteCompleter();
@@ -248,15 +261,14 @@
// Calculate the issues.
final issues = getErrors().map((AnalysisError error) {
- return api.AnalysisIssue.fromIssue(
- error.severity.toLowerCase(),
- error.location.startLine,
- error.message,
- charStart: error.location.offset,
- charLength: error.location.length,
- sourceName: path.basename(error.location.file),
- hasFixes: error.hasFix,
- );
+ return proto.AnalysisIssue()
+ ..kind = error.severity.toLowerCase()
+ ..line = error.location.startLine
+ ..message = error.message
+ ..sourceName = path.basename(error.location.file)
+ ..hasFixes = error.hasFix
+ ..charStart = error.location.offset
+ ..charLength = error.location.length;
}).toList();
issues.sort();
@@ -268,10 +280,9 @@
.addAll(filterSafePackagesFromImports(getAllImportsFor(source)));
}
- return api.AnalysisResults(
- issues,
- packageImports.toList(),
- );
+ return proto.AnalysisResults()
+ ..issues.addAll(issues)
+ ..packageImports.addAll(packageImports);
}, timeoutDuration: _ANALYSIS_SERVER_TIMEOUT));
}
@@ -289,7 +300,7 @@
final analysisCompleter = getAnalysisCompleteCompleter();
await _loadSources(sources);
await analysisCompleter.future;
- final length = 1;
+ const length = 1;
final assists =
await analysisServer.edit.getAssists(path, offset, length);
await _unloadSources();
@@ -298,16 +309,16 @@
}
/// Convert between the Analysis Server type and the API protocol types.
- static api.ProblemAndFixes _convertAnalysisErrorFix(
+ static proto.ProblemAndFixes _convertAnalysisErrorFix(
AnalysisErrorFixes analysisFixes) {
final problemMessage = analysisFixes.error.message;
final problemOffset = analysisFixes.error.location.offset;
final problemLength = analysisFixes.error.location.length;
- final possibleFixes = <api.CandidateFix>[];
+ final possibleFixes = <proto.CandidateFix>[];
for (final sourceChange in analysisFixes.fixes) {
- final edits = <api.SourceEdit>[];
+ final edits = <proto.SourceEdit>[];
// A fix that tries to modify other files is considered invalid.
@@ -321,23 +332,29 @@
}
for (final sourceEdit in sourceFileEdit.edits) {
- edits.add(api.SourceEdit.fromChanges(
- sourceEdit.offset, sourceEdit.length, sourceEdit.replacement));
+ edits.add(proto.SourceEdit()
+ ..offset = sourceEdit.offset
+ ..length = sourceEdit.length
+ ..replacement = sourceEdit.replacement);
}
}
if (!invalidFix) {
- final possibleFix =
- api.CandidateFix.fromEdits(sourceChange.message, edits);
+ final possibleFix = proto.CandidateFix()
+ ..message = sourceChange.message
+ ..edits.addAll(edits);
possibleFixes.add(possibleFix);
}
}
- return api.ProblemAndFixes.fromList(
- possibleFixes, problemMessage, problemOffset, problemLength);
+ return proto.ProblemAndFixes()
+ ..fixes.addAll(possibleFixes)
+ ..problemMessage = problemMessage
+ ..offset = problemOffset
+ ..length = problemLength;
}
- static List<api.CandidateFix> _convertSourceChangesToCandidateFixes(
+ static List<proto.CandidateFix> _convertSourceChangesToCandidateFixes(
List<SourceChange> sourceChanges) {
- final assists = <api.CandidateFix>[];
+ final assists = <proto.CandidateFix>[];
for (final sourceChange in sourceChanges) {
for (final sourceFileEdit in sourceChange.edits) {
@@ -345,17 +362,23 @@
break;
}
- final apiSourceEdits = sourceFileEdit.edits.map((sourceEdit) {
- return api.SourceEdit.fromChanges(
- sourceEdit.offset, sourceEdit.length, sourceEdit.replacement);
- }).toList();
+ final sourceEdits = sourceFileEdit.edits.map((sourceEdit) {
+ return proto.SourceEdit()
+ ..offset = sourceEdit.offset
+ ..length = sourceEdit.length
+ ..replacement = sourceEdit.replacement;
+ });
- assists.add(api.CandidateFix.fromEdits(
- sourceChange.message,
- apiSourceEdits,
- sourceChange.selection?.offset,
- _convertLinkedEditGroups(sourceChange.linkedEditGroups),
- ));
+ final candidateFix = proto.CandidateFix();
+ candidateFix.message = sourceChange.message;
+ candidateFix.edits.addAll(sourceEdits);
+ final selectionOffset = sourceChange.selection?.offset;
+ if (selectionOffset != null) {
+ candidateFix.selectionOffset = selectionOffset;
+ }
+ candidateFix.linkedEditGroups
+ .addAll(_convertLinkedEditGroups(sourceChange.linkedEditGroups));
+ assists.add(candidateFix);
}
}
@@ -364,17 +387,19 @@
/// Convert a list of the analysis server's [LinkedEditGroup]s into the API's
/// equivalent.
- static List<api.LinkedEditGroup> _convertLinkedEditGroups(
- List<LinkedEditGroup> groups) {
- return groups?.map<api.LinkedEditGroup>((g) {
- return api.LinkedEditGroup(
- g.positions?.map((p) => p.offset)?.toList(),
- g.length,
- g.suggestions
- ?.map((s) => api.LinkedEditSuggestion(s.value, s.kind))
- ?.toList(),
- );
- })?.toList();
+ static Iterable<proto.LinkedEditGroup> _convertLinkedEditGroups(
+ Iterable<LinkedEditGroup> groups) {
+ return groups?.map<proto.LinkedEditGroup>((g) {
+ return proto.LinkedEditGroup()
+ ..positions.addAll(g.positions?.map((p) => p.offset)?.toList())
+ ..length = g.length
+ ..suggestions.addAll(g.suggestions
+ ?.map((s) => proto.LinkedEditSuggestion()
+ ..value = s.value
+ ..kind = s.kind)
+ ?.toList());
+ }) ??
+ [];
}
/// Cleanly shutdown the Analysis Server.
@@ -383,7 +408,7 @@
// --pause-isolates-on-exit from working; fix.
return analysisServer.server
.shutdown()
- .timeout(Duration(seconds: 1))
+ .timeout(const Duration(seconds: 1))
.catchError((dynamic e) => null);
}
@@ -451,7 +476,7 @@
path.join(_sourceDirPath, sourceName);
/// Warm up the analysis server to be ready for use.
- Future<api.CompleteResponse> warmup({bool useHtml = false}) =>
+ Future<proto.CompleteResponse> warmup({bool useHtml = false}) =>
complete(useHtml ? _WARMUP_SRC_HTML : _WARMUP_SRC, 10);
final Set<String> _overlayPaths = <String>{};
@@ -561,3 +586,10 @@
return errors;
}
}
+
+class Location {
+ final String sourceName;
+ final int offset;
+
+ const Location(this.sourceName, this.offset);
+}
diff --git a/lib/src/api_classes.dart b/lib/src/api_classes.dart
deleted file mode 100644
index 945a321..0000000
--- a/lib/src/api_classes.dart
+++ /dev/null
@@ -1,314 +0,0 @@
-// 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.
-
-/// All classes exported over the RPC protocol.
-library services.api_classes;
-
-import 'dart:convert';
-
-import 'package:rpc/rpc.dart';
-
-class AnalysisResults {
- final List<AnalysisIssue> issues;
-
- @ApiProperty(description: 'The package imports parsed from the source.')
- final List<String> packageImports;
-
- AnalysisResults(this.issues, this.packageImports);
-}
-
-class AnalysisIssue implements Comparable<AnalysisIssue> {
- final String kind;
- final int line;
- final String message;
- final String sourceName;
-
- final bool hasFixes;
-
- final int charStart;
- final int charLength;
-
- AnalysisIssue.fromIssue(this.kind, this.line, this.message,
- {this.charStart,
- this.charLength,
- this.sourceName,
- this.hasFixes = false});
-
- Map<String, dynamic> toMap() {
- final m = <String, dynamic>{'kind': kind, 'line': line, 'message': message};
- if (charStart != null) m['charStart'] = charStart;
- if (charLength != null) m['charLength'] = charLength;
- if (hasFixes != null) m['hasFixes'] = hasFixes;
- if (sourceName != null) m['sourceName'] = sourceName;
-
- return m;
- }
-
- @override
- int compareTo(AnalysisIssue other) => line - other.line;
-
- @override
- String toString() => '$kind: $message [$line]';
-}
-
-class SourceRequest {
- @ApiProperty(required: true, description: 'The Dart source.')
- String source;
-
- @ApiProperty(description: 'An optional offset into the source code.')
- int offset;
-}
-
-class SourcesRequest {
- @ApiProperty(required: true, description: 'Map of names to Sources.')
- Map<String, String> sources;
-
- @ApiProperty(description: 'An optional location in the source code.')
- Location location;
-
- @ApiProperty(description: 'Ignored: always treated as true.')
- @deprecated
- bool strongMode;
-}
-
-class Location {
- String sourceName;
- int offset;
-
- Location();
-
- Location.from(this.sourceName, this.offset);
-}
-
-class CompileRequest {
- @ApiProperty(required: true, description: 'The Dart source.')
- String source;
-
- @ApiProperty(
- description:
- 'Return the Dart to JS source map; optional (defaults to false).')
- bool returnSourceMap;
-}
-
-class CompileResponse {
- final String result;
- final String sourceMap;
-
- CompileResponse(this.result, [this.sourceMap]);
-}
-
-class CompileDDCRequest {
- @ApiProperty(required: true, description: 'The Dart source.')
- String source;
-}
-
-class CompileDDCResponse {
- final String result;
- final String modulesBaseUrl;
-
- CompileDDCResponse(this.result, this.modulesBaseUrl);
-}
-
-class CounterRequest {
- @ApiProperty(required: true)
- String name;
-}
-
-class CounterResponse {
- final int count;
-
- CounterResponse(this.count);
-}
-
-class DocumentResponse {
- final Map<String, String> info;
-
- DocumentResponse(this.info);
-}
-
-class CompleteResponse {
- @ApiProperty(
- description: 'The offset of the start of the text to be replaced.')
- final int replacementOffset;
-
- @ApiProperty(description: 'The length of the text to be replaced.')
- final int replacementLength;
-
- final List<Map<String, String>> completions;
-
- CompleteResponse(this.replacementOffset, this.replacementLength,
- List<Map<dynamic, dynamic>> completions)
- : completions = _convert(completions);
-
- /// Convert any non-string values from the contained maps.
- static List<Map<String, String>> _convert(List<Map<dynamic, dynamic>> list) {
- return list.map<Map<String, String>>((Map<dynamic, dynamic> m) {
- final newMap = <String, String>{};
- for (final key in m.keys.cast<String>()) {
- dynamic data = m[key];
- // TODO: Properly support Lists, Maps (this is a hack).
- if (data is Map || data is List) {
- data = json.encode(data);
- }
- newMap[key.toString()] = '$data';
- }
- return newMap;
- }).toList();
- }
-}
-
-class FixesResponse {
- final List<ProblemAndFixes> fixes;
-
- FixesResponse(this.fixes);
-}
-
-/// Represents a problem detected during analysis, and a set of possible
-/// ways of resolving the problem.
-class ProblemAndFixes {
- // TODO(lukechurch): consider consolidating this with [AnalysisIssue]
- final List<CandidateFix> fixes;
- final String problemMessage;
- final int offset;
- final int length;
-
- ProblemAndFixes() : this.fromList(<CandidateFix>[]);
-
- ProblemAndFixes.fromList(
- [this.fixes, this.problemMessage, this.offset, this.length]);
-}
-
-class LinkedEditSuggestion {
- @ApiProperty(
- description: 'The value that could be used to replace all of the linked '
- 'edit regions.')
- final String value;
-
- @ApiProperty(description: 'The kind of value being proposed.')
- final String kind;
-
- LinkedEditSuggestion(this.value, this.kind);
-}
-
-class LinkedEditGroup {
- @ApiProperty(
- description: 'The positions of the regions that should be edited '
- 'simultaneously.')
- final List<int> positions;
-
- @ApiProperty(
- description: 'The length of the regions that should be edited '
- 'simultaneously.')
- final int length;
-
- @ApiProperty(
- description: 'Pre-computed suggestions for what every region might want '
- 'to be changed to.')
- final List<LinkedEditSuggestion> suggestions;
-
- LinkedEditGroup(this.positions, this.length, this.suggestions);
-}
-
-/// Represents a possible way of solving an Analysis Problem.
-class CandidateFix {
- final String message;
- final List<SourceEdit> edits;
- final int selectionOffset;
- final List<LinkedEditGroup> linkedEditGroups;
-
- CandidateFix() : this.fromEdits();
-
- CandidateFix.fromEdits([
- this.message,
- this.edits,
- this.selectionOffset,
- this.linkedEditGroups,
- ]);
-}
-
-/// Represents a reformatting of the code.
-class FormatResponse {
- @ApiProperty(description: 'The formatted source code.')
- final String newString;
-
- @ApiProperty(
- description: 'The (optional) new offset of the cursor; can be `null`.')
- final int offset;
-
- FormatResponse(this.newString, [this.offset = 0]);
-}
-
-/// Represents a single edit-point change to a source file.
-class SourceEdit {
- final int offset;
- final int length;
- final String replacement;
-
- SourceEdit() : this.fromChanges();
-
- SourceEdit.fromChanges([this.offset, this.length, this.replacement]);
-
- String applyTo(String target) {
- if (offset >= replacement.length) {
- throw 'Offset beyond end of string';
- } else if (offset + length >= replacement.length) {
- throw 'Change beyond end of string';
- }
-
- final pre = '${target.substring(0, offset)}';
- final post = '${target.substring(offset + length)}';
- return '$pre$replacement$post';
- }
-}
-
-/// The response from the `/assists` service call.
-class AssistsResponse {
- final List<CandidateFix> assists;
-
- AssistsResponse(this.assists);
-}
-
-/// The response from the `/version` service call.
-class VersionResponse {
- @ApiProperty(
- description: 'The Dart SDK version that DartServices is compatible with. '
- 'This will be a semver string.')
- final String sdkVersion;
-
- @ApiProperty(
- description:
- 'The full Dart SDK version that DartServices is compatible with.')
- final String sdkVersionFull;
-
- @ApiProperty(
- description: 'The Dart SDK version that the server is running on. This '
- 'will start with a semver string, and have a space and other build '
- 'details appended.')
- final String runtimeVersion;
-
- @ApiProperty(description: 'The App Engine version.')
- final String appEngineVersion;
-
- @ApiProperty(description: 'The dart-services backend version.')
- final String servicesVersion;
-
- @ApiProperty(description: 'The Flutter SDK version.')
- final String flutterVersion;
-
- @ApiProperty(description: "The Flutter SDK's Dart version.")
- final String flutterDartVersion;
-
- @ApiProperty(description: "The Flutter SDK's full Dart version.")
- final String flutterDartVersionFull;
-
- VersionResponse(
- {this.sdkVersion,
- this.sdkVersionFull,
- this.runtimeVersion,
- this.appEngineVersion,
- this.servicesVersion,
- this.flutterDartVersion,
- this.flutterDartVersionFull,
- this.flutterVersion});
-}
diff --git a/lib/src/common_server.dart b/lib/src/common_server.dart
deleted file mode 100644
index aa29900..0000000
--- a/lib/src/common_server.dart
+++ /dev/null
@@ -1,102 +0,0 @@
-// 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 services.common_server;
-
-import 'dart:async';
-
-import 'package:rpc/rpc.dart';
-
-import 'api_classes.dart';
-import 'common_server_impl.dart' show BadRequest, CommonServerImpl;
-export 'common_server_impl.dart' show log, ServerContainer;
-
-@ApiClass(name: 'dartservices', version: 'v1')
-class CommonServer {
- final CommonServerImpl _impl;
-
- CommonServer(this._impl);
-
- @ApiMethod(
- method: 'POST',
- path: 'analyze',
- description:
- 'Analyze the given Dart source code and return any resulting '
- 'analysis errors or warnings.')
- Future<AnalysisResults> analyze(SourceRequest request) =>
- _convertBadRequest(() => _impl.analyze(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'compile',
- description: 'Compile the given Dart source code and return the '
- 'resulting JavaScript; this uses the dart2js compiler.')
- Future<CompileResponse> compile(CompileRequest request) =>
- _convertBadRequest(() => _impl.compile(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'compileDDC',
- description: 'Compile the given Dart source code and return the '
- 'resulting JavaScript; this uses the DDC compiler.')
- Future<CompileDDCResponse> compileDDC(CompileRequest request) =>
- _convertBadRequest(() => _impl.compileDDC(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'complete',
- description:
- 'Get the valid code completion results for the given offset.')
- Future<CompleteResponse> complete(SourceRequest request) =>
- _convertBadRequest(() => _impl.complete(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'fixes',
- description: 'Get any quick fixes for the given source code location.')
- Future<FixesResponse> fixes(SourceRequest request) =>
- _convertBadRequest(() => _impl.fixes(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'assists',
- description: 'Get assists for the given source code location.')
- Future<AssistsResponse> assists(SourceRequest request) =>
- _convertBadRequest(() => _impl.assists(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'format',
- description: 'Format the given Dart source code and return the results. '
- 'If an offset is supplied in the request, the new position for that '
- 'offset in the formatted code will be returned.')
- Future<FormatResponse> format(SourceRequest request) =>
- _convertBadRequest(() => _impl.format(request));
-
- @ApiMethod(
- method: 'POST',
- path: 'document',
- description: 'Return the relevant dartdoc information for the element at '
- 'the given offset.')
- Future<DocumentResponse> document(SourceRequest request) =>
- _convertBadRequest(() => _impl.document(request));
-
- @ApiMethod(
- method: 'GET',
- path: 'version',
- description: 'Return the current SDK version for DartServices.')
- Future<VersionResponse> version() =>
- _convertBadRequest(() => _impl.version());
-}
-
-Future<T> _convertBadRequest<T>(Future<T> Function() fun) async {
- try {
- return await fun();
- } catch (e) {
- if (e is BadRequest) {
- throw BadRequestError(e.cause);
- }
- throw BadRequestError(e.toString());
- }
-}
diff --git a/lib/src/common_server_api.dart b/lib/src/common_server_api.dart
new file mode 100644
index 0000000..2e118c4
--- /dev/null
+++ b/lib/src/common_server_api.dart
@@ -0,0 +1,176 @@
+// Copyright (c) 2020, 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 services.common_server_api;
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:meta/meta.dart';
+import 'package:protobuf/protobuf.dart';
+import 'package:shelf/shelf.dart';
+import 'package:shelf_router/shelf_router.dart';
+
+import 'common_server_impl.dart' show CommonServerImpl, BadRequest;
+import 'protos/dart_services.pb.dart' as proto;
+
+export 'common_server_impl.dart' show log, ServerContainer;
+
+part 'common_server_api.g.dart'; // generated with 'pub run build_runner build'
+
+const PROTOBUF_CONTENT_TYPE = 'application/x-protobuf';
+const JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
+const PROTO_API_URL_PREFIX = '/api/dartservices/<apiVersion>';
+
+class CommonServerApi {
+ final CommonServerImpl _impl;
+
+ CommonServerApi(this._impl);
+
+ @Route.post('$PROTO_API_URL_PREFIX/analyze')
+ Future<Response> analyze(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.SourceRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
+ transform: _impl.analyze);
+
+ @Route.post('$PROTO_API_URL_PREFIX/compile')
+ Future<Response> compile(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.CompileRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.CompileRequest.fromBuffer(bytes),
+ transform: _impl.compile);
+
+ @Route.post('$PROTO_API_URL_PREFIX/compileDDC')
+ Future<Response> compileDDC(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.CompileDDCRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.CompileDDCRequest.fromBuffer(bytes),
+ transform: _impl.compileDDC);
+
+ @Route.post('$PROTO_API_URL_PREFIX/complete')
+ Future<Response> complete(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.SourceRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
+ transform: _impl.complete);
+
+ @Route.post('$PROTO_API_URL_PREFIX/fixes')
+ Future<Response> fixes(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.SourceRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
+ transform: _impl.fixes);
+
+ @Route.post('$PROTO_API_URL_PREFIX/assists')
+ Future<Response> assists(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.SourceRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
+ transform: _impl.assists);
+
+ @Route.post('$PROTO_API_URL_PREFIX/format')
+ Future<Response> format(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.SourceRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
+ transform: _impl.format);
+
+ @Route.post('$PROTO_API_URL_PREFIX/document')
+ Future<Response> document(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.SourceRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
+ transform: _impl.document);
+
+ @Route.post('$PROTO_API_URL_PREFIX/version')
+ Future<Response> versionPost(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.VersionRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.VersionRequest.fromBuffer(bytes),
+ transform: _impl.version);
+
+ @Route.get('$PROTO_API_URL_PREFIX/version')
+ Future<Response> versionGet(Request request, String apiVersion) =>
+ _processRequest(request,
+ decodeFromJSON: (json) =>
+ proto.VersionRequest.create()..mergeFromProto3Json(json),
+ decodeFromProto: (bytes) => proto.VersionRequest.fromBuffer(bytes),
+ transform: _impl.version);
+
+ Router get router => _$CommonServerApiRouter(this);
+
+ // We are serving requests that are arriving in both Protobuf binary encoding,
+ // and Protobuf JSON encoding. To handle this we need the ability to decode
+ // the requests and encode the responses. We also need to know how to do the
+ // work the request is requesting.
+
+ Future<Response> _processRequest<I, O extends GeneratedMessage>(
+ Request request, {
+ @required I Function(List<int> bytes) decodeFromProto,
+ @required I Function(Object json) decodeFromJSON,
+ @required Future<O> Function(I input) transform,
+ }) async {
+ if (request.mimeType == PROTOBUF_CONTENT_TYPE) {
+ // Dealing with binary Protobufs
+ final body = <int>[];
+ await for (final chunk in request.read()) {
+ body.addAll(chunk);
+ }
+ try {
+ final response = await transform(decodeFromProto(body));
+ return Response.ok(
+ response.writeToBuffer(),
+ headers: _PROTOBUF_HEADERS,
+ );
+ } on BadRequest catch (e) {
+ return Response(400,
+ headers: _PROTOBUF_HEADERS,
+ body: (proto.BadRequest.create()
+ ..error = (proto.ErrorMessage.create()..message = e.cause))
+ .writeToBuffer());
+ }
+ } else {
+ // Dealing with JSON encoded Protobufs
+ final body = await request.readAsString();
+ try {
+ final response = await transform(
+ decodeFromJSON(body.isNotEmpty ? json.decode(body) : {}));
+ return Response.ok(
+ _jsonEncoder.convert(response.toProto3Json()),
+ encoding: utf8,
+ headers: _JSON_HEADERS,
+ );
+ } on BadRequest catch (e) {
+ return Response(400,
+ headers: _JSON_HEADERS,
+ encoding: utf8,
+ body: _jsonEncoder.convert((proto.BadRequest.create()
+ ..error = (proto.ErrorMessage.create()..message = e.cause))
+ .toProto3Json()));
+ }
+ }
+ }
+
+ final JsonEncoder _jsonEncoder = const JsonEncoder.withIndent(' ');
+
+ static const _JSON_HEADERS = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Content-Type': JSON_CONTENT_TYPE
+ };
+
+ static const _PROTOBUF_HEADERS = {
+ 'Access-Control-Allow-Origin': '*',
+ 'Content-Type': PROTOBUF_CONTENT_TYPE
+ };
+}
diff --git a/lib/src/common_server_api.g.dart b/lib/src/common_server_api.g.dart
new file mode 100644
index 0000000..f2e9900
--- /dev/null
+++ b/lib/src/common_server_api.g.dart
@@ -0,0 +1,30 @@
+// GENERATED CODE - DO NOT MODIFY BY HAND
+
+part of services.common_server_api;
+
+// **************************************************************************
+// ShelfRouterGenerator
+// **************************************************************************
+
+Router _$CommonServerApiRouter(CommonServerApi service) {
+ final router = Router();
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/analyze', service.analyze);
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/compile', service.compile);
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/compileDDC', service.compileDDC);
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/complete', service.complete);
+ router.add('POST', r'/api/dartservices/<apiVersion>/fixes', service.fixes);
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/assists', service.assists);
+ router.add('POST', r'/api/dartservices/<apiVersion>/format', service.format);
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/document', service.document);
+ router.add(
+ 'POST', r'/api/dartservices/<apiVersion>/version', service.versionPost);
+ router.add(
+ 'GET', r'/api/dartservices/<apiVersion>/version', service.versionGet);
+ return router;
+}
diff --git a/lib/src/common_server_impl.dart b/lib/src/common_server_impl.dart
index 61b49e2..544c015 100644
--- a/lib/src/common_server_impl.dart
+++ b/lib/src/common_server_impl.dart
@@ -14,15 +14,15 @@
import '../version.dart';
import 'analysis_server.dart';
-import 'api_classes.dart';
import 'common.dart';
import 'compiler.dart';
import 'flutter_web.dart';
+import 'protos/dart_services.pb.dart' as proto;
import 'pub.dart';
import 'sdk_manager.dart';
import 'server_cache.dart';
-final Duration _standardExpiration = Duration(hours: 1);
+const Duration _standardExpiration = Duration(hours: 1);
final Logger log = Logger('common_server');
class BadRequest implements Exception {
@@ -118,62 +118,90 @@
flutterAnalysisServer.shutdown(),
compiler.dispose(),
Future<dynamic>.sync(cache.shutdown)
- ]).timeout(Duration(minutes: 1));
+ ]).timeout(const Duration(minutes: 1));
}
- Future<AnalysisResults> analyze(SourceRequest request) {
+ Future<proto.AnalysisResults> analyze(proto.SourceRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+
return _analyze(request.source);
}
- Future<CompileResponse> compile(CompileRequest request) {
+ Future<proto.CompileResponse> compile(proto.CompileRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+
return _compileDart2js(request.source,
returnSourceMap: request.returnSourceMap ?? false);
}
- Future<CompileDDCResponse> compileDDC(CompileRequest request) {
+ Future<proto.CompileDDCResponse> compileDDC(proto.CompileDDCRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+
return _compileDDC(request.source);
}
- Future<CompleteResponse> complete(SourceRequest request) {
- if (request.offset == null) {
+ Future<proto.CompleteResponse> complete(proto.SourceRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+ if (!request.hasOffset()) {
throw BadRequest('Missing parameter: \'offset\'');
}
return _complete(request.source, request.offset);
}
- Future<FixesResponse> fixes(SourceRequest request) {
- if (request.offset == null) {
+ Future<proto.FixesResponse> fixes(proto.SourceRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+ if (!request.hasOffset()) {
throw BadRequest('Missing parameter: \'offset\'');
}
return _fixes(request.source, request.offset);
}
- Future<AssistsResponse> assists(SourceRequest request) {
- if (request.offset == null) {
+ Future<proto.AssistsResponse> assists(proto.SourceRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+ if (!request.hasOffset()) {
throw BadRequest('Missing parameter: \'offset\'');
}
return _assists(request.source, request.offset);
}
- Future<FormatResponse> format(SourceRequest request) {
- return _format(request.source, offset: request.offset);
- }
-
- Future<DocumentResponse> document(SourceRequest request) {
- return _document(request.source, request.offset);
- }
-
- Future<VersionResponse> version() =>
- Future<VersionResponse>.value(_version());
-
- Future<AnalysisResults> _analyze(String source) async {
- if (source == null) {
+ Future<proto.FormatResponse> format(proto.SourceRequest request) {
+ if (!request.hasSource()) {
throw BadRequest('Missing parameter: \'source\'');
}
+ return _format(request.source, offset: request.offset ?? 0);
+ }
+
+ Future<proto.DocumentResponse> document(proto.SourceRequest request) {
+ if (!request.hasSource()) {
+ throw BadRequest('Missing parameter: \'source\'');
+ }
+ if (!request.hasOffset()) {
+ throw BadRequest('Missing parameter: \'offset\'');
+ }
+
+ return _document(request.source, request.offset);
+ }
+
+ Future<proto.VersionResponse> version(proto.VersionRequest _) =>
+ Future<proto.VersionResponse>.value(_version());
+
+ Future<proto.AnalysisResults> _analyze(String source) async {
await _checkPackageReferencesInitFlutterWeb(source);
try {
@@ -191,14 +219,10 @@
}
}
- Future<CompileResponse> _compileDart2js(
+ Future<proto.CompileResponse> _compileDart2js(
String source, {
bool returnSourceMap = false,
}) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
-
await _checkPackageReferencesInitFlutterWeb(source);
final sourceHash = _hashSource(source);
@@ -208,11 +232,10 @@
final result = await checkCache(memCacheKey);
if (result != null) {
log.info('CACHE: Cache hit for compileDart2js');
- final resultObj = JsonDecoder().convert(result);
- return CompileResponse(
- resultObj['compiledJS'] as String,
- returnSourceMap ? resultObj['sourceMap'] as String : null,
- );
+ final resultObj = const JsonDecoder().convert(result);
+ return proto.CompileResponse()
+ ..result = resultObj['compiledJS'] as String
+ ..sourceMap = returnSourceMap ? resultObj['sourceMap'] as String : null;
}
log.info('CACHE: MISS for compileDart2js');
@@ -229,13 +252,18 @@
'${outputSize}kb of JavaScript in ${ms}ms using dart2js.');
final sourceMap = returnSourceMap ? results.sourceMap : null;
- final cachedResult = JsonEncoder().convert(<String, String>{
+ final cachedResult = const JsonEncoder().convert(<String, String>{
'compiledJS': results.compiledJS,
'sourceMap': sourceMap,
});
// Don't block on cache set.
unawaited(setCache(memCacheKey, cachedResult));
- return CompileResponse(results.compiledJS, sourceMap);
+ final compileResponse = proto.CompileResponse();
+ compileResponse.result = results.compiledJS;
+ if (sourceMap != null) {
+ compileResponse.sourceMap = sourceMap;
+ }
+ return compileResponse;
} else {
final problems = results.problems;
final errors = problems.map(_printCompileProblem).join('\n');
@@ -249,11 +277,7 @@
});
}
- Future<CompileDDCResponse> _compileDDC(String source) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
-
+ Future<proto.CompileDDCResponse> _compileDDC(String source) async {
await _checkPackageReferencesInitFlutterWeb(source);
final sourceHash = _hashSource(source);
@@ -262,11 +286,10 @@
final result = await checkCache(memCacheKey);
if (result != null) {
log.info('CACHE: Cache hit for compileDDC');
- final resultObj = JsonDecoder().convert(result);
- return CompileDDCResponse(
- resultObj['compiledJS'] as String,
- resultObj['modulesBaseUrl'] as String,
- );
+ final resultObj = const JsonDecoder().convert(result);
+ return proto.CompileDDCResponse()
+ ..result = resultObj['compiledJS'] as String
+ ..modulesBaseUrl = resultObj['modulesBaseUrl'] as String;
}
log.info('CACHE: MISS for compileDDC');
@@ -280,13 +303,15 @@
log.info('PERF: Compiled $lineCount lines of Dart into '
'${outputSize}kb of JavaScript in ${ms}ms using DDC.');
- final cachedResult = JsonEncoder().convert(<String, String>{
+ final cachedResult = const JsonEncoder().convert(<String, String>{
'compiledJS': results.compiledJS,
'modulesBaseUrl': results.modulesBaseUrl,
});
// Don't block on cache set.
unawaited(setCache(memCacheKey, cachedResult));
- return CompileDDCResponse(results.compiledJS, results.modulesBaseUrl);
+ return proto.CompileDDCResponse()
+ ..result = results.compiledJS
+ ..modulesBaseUrl = results.modulesBaseUrl;
} else {
final problems = results.problems;
final errors = problems.map(_printCompileProblem).join('\n');
@@ -300,14 +325,7 @@
});
}
- Future<DocumentResponse> _document(String source, int offset) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (offset == null) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
+ Future<proto.DocumentResponse> _document(String source, int offset) async {
await _checkPackageReferencesInitFlutterWeb(source);
final watch = Stopwatch()..start();
@@ -316,7 +334,7 @@
await getCorrectAnalysisServer(source).dartdoc(source, offset);
docInfo ??= <String, String>{};
log.info('PERF: Computed dartdoc in ${watch.elapsedMilliseconds}ms.');
- return DocumentResponse(docInfo);
+ return proto.DocumentResponse()..info.addAll(docInfo);
} catch (e, st) {
log.severe('Error during dartdoc', e, st);
await restart();
@@ -324,24 +342,17 @@
}
}
- VersionResponse _version() => VersionResponse(
- sdkVersion: SdkManager.sdk.version,
- sdkVersionFull: SdkManager.sdk.versionFull,
- runtimeVersion: vmVersion,
- servicesVersion: servicesVersion,
- appEngineVersion: container.version,
- flutterDartVersion: SdkManager.flutterSdk.version,
- flutterDartVersionFull: SdkManager.flutterSdk.versionFull,
- flutterVersion: SdkManager.flutterSdk.flutterVersion);
+ proto.VersionResponse _version() => proto.VersionResponse()
+ ..sdkVersion = SdkManager.sdk.version
+ ..sdkVersionFull = SdkManager.sdk.versionFull
+ ..runtimeVersion = vmVersion
+ ..servicesVersion = servicesVersion
+ ..appEngineVersion = container.version
+ ..flutterDartVersion = SdkManager.flutterSdk.version
+ ..flutterDartVersionFull = SdkManager.flutterSdk.versionFull
+ ..flutterVersion = SdkManager.flutterSdk.flutterVersion;
- Future<CompleteResponse> _complete(String source, int offset) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (offset == null) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
+ Future<proto.CompleteResponse> _complete(String source, int offset) async {
await _checkPackageReferencesInitFlutterWeb(source);
final watch = Stopwatch()..start();
@@ -357,14 +368,7 @@
}
}
- Future<FixesResponse> _fixes(String source, int offset) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (offset == null) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
+ Future<proto.FixesResponse> _fixes(String source, int offset) async {
await _checkPackageReferencesInitFlutterWeb(source);
final watch = Stopwatch()..start();
@@ -374,14 +378,7 @@
return response;
}
- Future<AssistsResponse> _assists(String source, int offset) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (offset == null) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
+ Future<proto.AssistsResponse> _assists(String source, int offset) async {
await _checkPackageReferencesInitFlutterWeb(source);
final watch = Stopwatch()..start();
@@ -391,12 +388,7 @@
return response;
}
- Future<FormatResponse> _format(String source, {int offset}) async {
- if (source == null) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- offset ??= 0;
-
+ Future<proto.FormatResponse> _format(String source, {int offset}) async {
final watch = Stopwatch()..start();
final response =
diff --git a/lib/src/common_server_proto.dart b/lib/src/common_server_proto.dart
deleted file mode 100644
index a9443e5..0000000
--- a/lib/src/common_server_proto.dart
+++ /dev/null
@@ -1,365 +0,0 @@
-// Copyright (c) 2020, 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 services.common_server_proto;
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:meta/meta.dart';
-import 'package:protobuf/protobuf.dart';
-import 'package:shelf/shelf.dart';
-import 'package:shelf_router/shelf_router.dart';
-
-import 'api_classes.dart' as api;
-import 'common_server_impl.dart' show CommonServerImpl, BadRequest;
-import 'protos/dart_services.pb.dart' as proto;
-
-export 'common_server_impl.dart' show log, ServerContainer;
-
-part 'common_server_proto.g.dart'; // generated with 'pub run build_runner build'
-
-const PROTOBUF_CONTENT_TYPE = 'application/x-protobuf';
-const JSON_CONTENT_TYPE = 'application/json; charset=utf-8';
-const PROTO_API_URL_PREFIX = '/api/dartservices/v2';
-
-class CommonServerProto {
- final CommonServerImpl _impl;
-
- CommonServerProto(this._impl);
-
- @Route.post('$PROTO_API_URL_PREFIX/analyze')
- Future<Response> analyze(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.SourceRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
- transform: _analyze);
-
- Future<proto.AnalysisResults> _analyze(proto.SourceRequest request) async {
- if (!request.hasSource()) {
- throw BadRequest('Missing parameter: \'source\'');
- }
-
- final apiRequest = api.SourceRequest()
- ..source = request.source
- ..offset = request.offset;
- final apiResponse = await _impl.analyze(apiRequest);
-
- return proto.AnalysisResults()
- ..packageImports.addAll(apiResponse.packageImports)
- ..issues.addAll(
- apiResponse.issues.map(
- (issue) => proto.AnalysisIssue()
- ..kind = issue.kind
- ..line = issue.line
- ..message = issue.message
- ..sourceName = issue.sourceName
- ..hasFixes = issue.hasFixes
- ..charStart = issue.charStart
- ..charLength = issue.charLength,
- ),
- );
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/compile')
- Future<Response> compile(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.CompileRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.CompileRequest.fromBuffer(bytes),
- transform: _compile);
-
- Future<proto.CompileResponse> _compile(proto.CompileRequest request) async {
- final apiRequest = api.CompileRequest()
- ..source = request.source
- ..returnSourceMap = request.returnSourceMap;
- final apiResponse = await _impl.compile(apiRequest);
- final response = proto.CompileResponse()..result = apiResponse.result;
- if (apiResponse.sourceMap != null) {
- response.sourceMap = apiResponse.sourceMap;
- }
- return response;
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/compileDDC')
- Future<Response> compileDDC(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.CompileRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.CompileRequest.fromBuffer(bytes),
- transform: _compileDDC);
-
- Future<proto.CompileDDCResponse> _compileDDC(
- proto.CompileRequest request) async {
- final apiRequest = api.CompileRequest()
- ..source = request.source
- ..returnSourceMap = request.returnSourceMap;
- final apiResponse = await _impl.compileDDC(apiRequest);
-
- return proto.CompileDDCResponse()
- ..result = apiResponse.result
- ..modulesBaseUrl = apiResponse.modulesBaseUrl;
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/complete')
- Future<Response> complete(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.SourceRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
- transform: _complete);
-
- Future<proto.CompleteResponse> _complete(proto.SourceRequest request) async {
- if (!request.hasSource()) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (!request.hasOffset()) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
- final apiRequest = api.SourceRequest()
- ..offset = request.offset
- ..source = request.source;
- final apiResponse = await _impl.complete(apiRequest);
-
- return proto.CompleteResponse()
- ..replacementOffset = apiResponse.replacementOffset
- ..replacementLength = apiResponse.replacementLength
- ..completions.addAll(
- apiResponse.completions.map(
- (completion) => proto.Completion()..completion.addAll(completion),
- ),
- );
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/fixes')
- Future<Response> fixes(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.SourceRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
- transform: _fixes);
-
- Future<proto.FixesResponse> _fixes(proto.SourceRequest request) async {
- if (!request.hasSource()) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (!request.hasOffset()) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
- final apiRequest = api.SourceRequest()
- ..offset = request.offset
- ..source = request.source;
- final apiResponse = await _impl.fixes(apiRequest);
-
- return proto.FixesResponse()
- ..fixes.addAll(
- apiResponse.fixes.map(
- (apiFix) => proto.ProblemAndFixes()
- ..problemMessage = apiFix.problemMessage
- ..offset = apiFix.offset
- ..length = apiFix.length
- ..fixes.addAll(
- apiFix.fixes.map(_transformCandidateFix),
- ),
- ),
- );
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/assists')
- Future<Response> assists(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.SourceRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
- transform: _assists);
-
- Future<proto.AssistsResponse> _assists(proto.SourceRequest request) async {
- if (!request.hasSource()) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (!request.hasOffset()) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
- final apiRequest = api.SourceRequest()
- ..offset = request.offset
- ..source = request.source;
- final apiResponse = await _impl.assists(apiRequest);
-
- return proto.AssistsResponse()
- ..assists.addAll(
- apiResponse.assists.map(_transformCandidateFix),
- );
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/format')
- Future<Response> format(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.SourceRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
- transform: _format);
-
- Future<proto.FormatResponse> _format(proto.SourceRequest request) async {
- if (!request.hasSource()) {
- throw BadRequest('Missing parameter: \'source\'');
- }
-
- final apiRequest = api.SourceRequest()
- ..offset = request.offset
- ..source = request.source;
- final apiResponse = await _impl.format(apiRequest);
-
- return proto.FormatResponse()
- ..newString = apiResponse.newString
- ..offset = apiResponse.offset;
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/document')
- Future<Response> document(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.SourceRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.SourceRequest.fromBuffer(bytes),
- transform: _document);
-
- Future<proto.DocumentResponse> _document(proto.SourceRequest request) async {
- if (!request.hasSource()) {
- throw BadRequest('Missing parameter: \'source\'');
- }
- if (!request.hasOffset()) {
- throw BadRequest('Missing parameter: \'offset\'');
- }
-
- final apiRequest = api.SourceRequest()
- ..offset = request.offset
- ..source = request.source;
- final apiResponse = await _impl.document(apiRequest);
-
- return proto.DocumentResponse()..info.addAll(apiResponse.info);
- }
-
- @Route.post('$PROTO_API_URL_PREFIX/version')
- Future<Response> versionPost(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.VersionRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.VersionRequest.fromBuffer(bytes),
- transform: _version);
-
- @Route.get('$PROTO_API_URL_PREFIX/version')
- Future<Response> versionGet(Request request) => _processRequest(request,
- decodeFromJSON: (json) =>
- proto.VersionRequest.create()..mergeFromProto3Json(json),
- decodeFromProto: (bytes) => proto.VersionRequest.fromBuffer(bytes),
- transform: _version);
-
- Future<proto.VersionResponse> _version(proto.VersionRequest request) async {
- final apiResponse = await _impl.version();
-
- return proto.VersionResponse()
- ..sdkVersion = apiResponse.sdkVersion
- ..sdkVersionFull = apiResponse.sdkVersionFull
- ..runtimeVersion = apiResponse.runtimeVersion
- ..appEngineVersion = apiResponse.appEngineVersion
- ..servicesVersion = apiResponse.servicesVersion
- ..flutterDartVersion = apiResponse.flutterDartVersion
- ..flutterDartVersionFull = apiResponse.flutterDartVersionFull
- ..flutterVersion = apiResponse.flutterVersion;
- }
-
- proto.CandidateFix _transformCandidateFix(api.CandidateFix candidateFix) {
- final result = proto.CandidateFix()..message = candidateFix.message;
- if (candidateFix.edits != null) {
- result.edits.addAll(
- candidateFix.edits.map(
- (edit) => proto.SourceEdit()
- ..offset = edit.offset
- ..length = edit.length
- ..replacement = edit.replacement,
- ),
- );
- }
- if (candidateFix.linkedEditGroups != null) {
- result.linkedEditGroups.addAll(
- candidateFix.linkedEditGroups.map(
- (group) => proto.LinkedEditGroup()
- ..positions.addAll(group.positions)
- ..length = group.length
- ..suggestions.addAll(
- group.suggestions.map(
- (suggestion) => proto.LinkedEditSuggestion()
- ..value = suggestion.value
- ..kind = suggestion.kind,
- ),
- ),
- ),
- );
- }
- if (candidateFix.selectionOffset != null) {
- result.selectionOffset = candidateFix.selectionOffset;
- }
- return result;
- }
-
- Router get router => _$CommonServerProtoRouter(this);
-
- // We are serving requests that are arriving in both Protobuf binary encoding,
- // and Protobuf JSON encoding. To handle this we need the ability to decode
- // the requests and encode the responses. We also need to know how to do the
- // work the request is requesting.
-
- Future<Response> _processRequest<I, O extends GeneratedMessage>(
- Request request, {
- @required I Function(List<int> bytes) decodeFromProto,
- @required I Function(Object json) decodeFromJSON,
- @required Future<O> Function(I input) transform,
- }) async {
- if (request.mimeType == PROTOBUF_CONTENT_TYPE) {
- // Dealing with binary Protobufs
- final body = <int>[];
- await for (final chunk in request.read()) {
- body.addAll(chunk);
- }
- try {
- final response = await transform(decodeFromProto(body));
- return Response.ok(
- response.writeToBuffer(),
- headers: _PROTOBUF_HEADERS,
- );
- } on BadRequest catch (e) {
- return Response(400,
- headers: _PROTOBUF_HEADERS,
- body: (proto.BadRequest.create()
- ..error = (proto.ErrorMessage.create()..message = e.cause))
- .writeToBuffer());
- }
- } else {
- // Dealing with JSON encoded Protobufs
- final body = await request.readAsString();
- try {
- final response = await transform(
- decodeFromJSON(body.isNotEmpty ? json.decode(body) : {}));
- return Response.ok(
- _jsonEncoder.convert(response.toProto3Json()),
- encoding: utf8,
- headers: _JSON_HEADERS,
- );
- } on BadRequest catch (e) {
- return Response(400,
- headers: _JSON_HEADERS,
- encoding: utf8,
- body: _jsonEncoder.convert((proto.BadRequest.create()
- ..error = (proto.ErrorMessage.create()..message = e.cause))
- .toProto3Json()));
- }
- }
- }
-
- final JsonEncoder _jsonEncoder = JsonEncoder.withIndent(' ');
-
- static const _JSON_HEADERS = {
- 'Access-Control-Allow-Origin': '*',
- 'Content-Type': JSON_CONTENT_TYPE
- };
-
- static const _PROTOBUF_HEADERS = {
- 'Access-Control-Allow-Origin': '*',
- 'Content-Type': PROTOBUF_CONTENT_TYPE
- };
-}
diff --git a/lib/src/common_server_proto.g.dart b/lib/src/common_server_proto.g.dart
deleted file mode 100644
index 64e5fef..0000000
--- a/lib/src/common_server_proto.g.dart
+++ /dev/null
@@ -1,22 +0,0 @@
-// GENERATED CODE - DO NOT MODIFY BY HAND
-
-part of services.common_server_proto;
-
-// **************************************************************************
-// ShelfRouterGenerator
-// **************************************************************************
-
-Router _$CommonServerProtoRouter(CommonServerProto service) {
- final router = Router();
- router.add('POST', r'/api/dartservices/v2/analyze', service.analyze);
- router.add('POST', r'/api/dartservices/v2/compile', service.compile);
- router.add('POST', r'/api/dartservices/v2/compileDDC', service.compileDDC);
- router.add('POST', r'/api/dartservices/v2/complete', service.complete);
- router.add('POST', r'/api/dartservices/v2/fixes', service.fixes);
- router.add('POST', r'/api/dartservices/v2/assists', service.assists);
- router.add('POST', r'/api/dartservices/v2/format', service.format);
- router.add('POST', r'/api/dartservices/v2/document', service.document);
- router.add('POST', r'/api/dartservices/v2/version', service.versionPost);
- router.add('GET', r'/api/dartservices/v2/version', service.versionGet);
- return router;
-}
diff --git a/lib/src/protos/dart_services.pb.dart b/lib/src/protos/dart_services.pb.dart
index 63fc84f..d53e751 100644
--- a/lib/src/protos/dart_services.pb.dart
+++ b/lib/src/protos/dart_services.pb.dart
@@ -64,6 +64,48 @@
void clearReturnSourceMap() => clearField(2);
}
+class CompileDDCRequest extends $pb.GeneratedMessage {
+ static final $pb.BuilderInfo _i = $pb.BuilderInfo('CompileDDCRequest',
+ package: const $pb.PackageName('dart_services.api'),
+ createEmptyInstance: create)
+ ..aOS(1, 'source')
+ ..hasRequiredFields = false;
+
+ CompileDDCRequest._() : super();
+ factory CompileDDCRequest() => create();
+ factory CompileDDCRequest.fromBuffer($core.List<$core.int> i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromBuffer(i, r);
+ factory CompileDDCRequest.fromJson($core.String i,
+ [$pb.ExtensionRegistry r = $pb.ExtensionRegistry.EMPTY]) =>
+ create()..mergeFromJson(i, r);
+ CompileDDCRequest clone() => CompileDDCRequest()..mergeFromMessage(this);
+ CompileDDCRequest copyWith(void Function(CompileDDCRequest) updates) =>
+ super.copyWith((message) => updates(message as CompileDDCRequest));
+ $pb.BuilderInfo get info_ => _i;
+ @$core.pragma('dart2js:noInline')
+ static CompileDDCRequest create() => CompileDDCRequest._();
+ CompileDDCRequest createEmptyInstance() => create();
+ static $pb.PbList<CompileDDCRequest> createRepeated() =>
+ $pb.PbList<CompileDDCRequest>();
+ @$core.pragma('dart2js:noInline')
+ static CompileDDCRequest getDefault() => _defaultInstance ??=
+ $pb.GeneratedMessage.$_defaultFor<CompileDDCRequest>(create);
+ static CompileDDCRequest _defaultInstance;
+
+ @$pb.TagNumber(1)
+ $core.String get source => $_getSZ(0);
+ @$pb.TagNumber(1)
+ set source($core.String v) {
+ $_setString(0, v);
+ }
+
+ @$pb.TagNumber(1)
+ $core.bool hasSource() => $_has(0);
+ @$pb.TagNumber(1)
+ void clearSource() => clearField(1);
+}
+
class SourceRequest extends $pb.GeneratedMessage {
static final $pb.BuilderInfo _i = $pb.BuilderInfo('SourceRequest',
package: const $pb.PackageName('dart_services.api'),
diff --git a/lib/src/protos/dart_services.pbjson.dart b/lib/src/protos/dart_services.pbjson.dart
index aa7d708..0834843 100644
--- a/lib/src/protos/dart_services.pbjson.dart
+++ b/lib/src/protos/dart_services.pbjson.dart
@@ -13,6 +13,13 @@
],
};
+const CompileDDCRequest$json = {
+ '1': 'CompileDDCRequest',
+ '2': [
+ {'1': 'source', '3': 1, '4': 1, '5': 9, '10': 'source'},
+ ],
+};
+
const SourceRequest$json = {
'1': 'SourceRequest',
'2': [
diff --git a/lib/src/server_cache.dart b/lib/src/server_cache.dart
index 3bddaf4..538c71a 100644
--- a/lib/src/server_cache.dart
+++ b/lib/src/server_cache.dart
@@ -11,7 +11,7 @@
import 'package:pedantic/pedantic.dart';
import 'package:quiver/cache.dart';
-import 'common_server.dart' show log;
+import 'common_server_impl.dart' show log;
import 'sdk_manager.dart';
abstract class ServerCache {
@@ -121,7 +121,7 @@
_reconnect();
});
})
- .timeout(Duration(milliseconds: _connectionRetryMaxMs))
+ .timeout(const Duration(milliseconds: _connectionRetryMaxMs))
.catchError((_) {
log.severe(
'$_logPrefix: Unable to connect to redis server, reconnecting in ${nextRetryMs}ms ...');
diff --git a/lib/src/summarize.dart b/lib/src/summarize.dart
index 5a1833d..8062120 100644
--- a/lib/src/summarize.dart
+++ b/lib/src/summarize.dart
@@ -6,7 +6,7 @@
import 'package:crypto/crypto.dart';
-import 'api_classes.dart';
+import 'protos/dart_services.pb.dart' as proto;
/// Instances of this class take string input of dart code as well as an
/// analysis result, and output a text description ofthe code's size, packages,
@@ -15,7 +15,7 @@
final String dart;
final String html;
final String css;
- final AnalysisResults analysis;
+ final proto.AnalysisResults analysis;
_SummarizeToken storage;
int _randomizer;
@@ -276,15 +276,15 @@
List<String> packageImports;
- List<AnalysisIssue> errors;
+ List<proto.AnalysisIssue> errors;
- _SummarizeToken(String input, {AnalysisResults analysis}) {
+ _SummarizeToken(String input, {proto.AnalysisResults analysis}) {
linesCode = _linesOfCode(input);
if (analysis != null) {
- errorPresent =
- analysis.issues.any((AnalysisIssue issue) => issue.kind == 'error');
- warningPresent =
- analysis.issues.any((AnalysisIssue issue) => issue.kind == 'warning');
+ errorPresent = analysis.issues
+ .any((proto.AnalysisIssue issue) => issue.kind == 'error');
+ warningPresent = analysis.issues
+ .any((proto.AnalysisIssue issue) => issue.kind == 'warning');
packageCount = analysis.packageImports.length;
packageImports = analysis.packageImports;
errors = analysis.issues;
diff --git a/protos/dart_services.proto b/protos/dart_services.proto
index 06f664a..aa20424 100644
--- a/protos/dart_services.proto
+++ b/protos/dart_services.proto
@@ -14,6 +14,11 @@
bool returnSourceMap = 2;
}
+message CompileDDCRequest {
+ // The Dart source.
+ string source = 1;
+}
+
message SourceRequest {
// The Dart source.
string source = 1;
diff --git a/pubspec.lock b/pubspec.lock
index 046fac5..1c54f7d 100644
--- a/pubspec.lock
+++ b/pubspec.lock
@@ -2,7 +2,7 @@
# See https://dart.dev/tools/pub/glossary#lockfile
packages:
_discoveryapis_commons:
- dependency: "direct main"
+ dependency: transitive
description:
name: _discoveryapis_commons
url: "https://pub.dartlang.org"
@@ -14,7 +14,7 @@
name: _fe_analyzer_shared
url: "https://pub.dartlang.org"
source: hosted
- version: "2.1.0"
+ version: "2.2.0"
analysis_server_lib:
dependency: "direct main"
description:
@@ -28,7 +28,7 @@
name: analyzer
url: "https://pub.dartlang.org"
source: hosted
- version: "0.39.6"
+ version: "0.39.7"
appengine:
dependency: "direct main"
description:
@@ -91,7 +91,7 @@
name: build_resolvers
url: "https://pub.dartlang.org"
source: hosted
- version: "1.3.4"
+ version: "1.3.6"
build_runner:
dependency: "direct dev"
description:
@@ -204,13 +204,6 @@
url: "https://pub.dartlang.org"
source: hosted
version: "0.4.0"
- discoveryapis_generator:
- dependency: "direct dev"
- description:
- name: discoveryapis_generator
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.9.11"
fixnum:
dependency: transitive
description:
@@ -422,7 +415,7 @@
name: path
url: "https://pub.dartlang.org"
source: hosted
- version: "1.6.4"
+ version: "1.7.0"
pedantic:
dependency: "direct dev"
description:
@@ -465,13 +458,6 @@
url: "https://pub.dartlang.org"
source: hosted
version: "2.1.3"
- rpc:
- dependency: "direct main"
- description:
- name: rpc
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.6.2"
shelf:
dependency: "direct main"
description:
@@ -626,20 +612,6 @@
url: "https://pub.dartlang.org"
source: hosted
version: "1.1.6"
- uri:
- dependency: transitive
- description:
- name: uri
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.11.3+1"
- utf:
- dependency: transitive
- description:
- name: utf
- url: "https://pub.dartlang.org"
- source: hosted
- version: "0.9.0+5"
uuid:
dependency: "direct main"
description:
@@ -653,7 +625,7 @@
name: vm_service
url: "https://pub.dartlang.org"
source: hosted
- version: "4.0.0"
+ version: "4.0.1"
watcher:
dependency: transitive
description:
diff --git a/pubspec.yaml b/pubspec.yaml
index 69e4fd8..94456d9 100644
--- a/pubspec.yaml
+++ b/pubspec.yaml
@@ -6,7 +6,6 @@
sdk: ^2.7.2
dependencies:
- _discoveryapis_commons: 0.1.9
analyzer: ^0.39.0
analysis_server_lib: ^0.1.4
appengine: ^0.10.3
@@ -20,7 +19,6 @@
path: ^1.6.2
protobuf: ^1.0.1
quiver: ^2.0.3
- rpc: ^0.6.2
shelf: ^0.7.5
shelf_router: ^0.7.0+1
uuid: ^2.0.0
@@ -31,7 +29,6 @@
build_runner: ^1.3.1
codemirror: ^0.5.6
coverage: ^0.13.0
- discoveryapis_generator: ^0.9.11
grinder: ^0.8.0
# TODO(brettmorgan): return to mock_request pub package after it is
# published with https://github.com/thosakwe/mock_request/pull/3
diff --git a/test/all.dart b/test/all.dart
index 59fd367..4fb2e80 100644
--- a/test/all.dart
+++ b/test/all.dart
@@ -5,12 +5,10 @@
library services.all_test;
import 'analysis_server_test.dart' as analysis_server_test;
-import 'api_classes_test.dart' as api_classes_test;
import 'bench_test.dart' as bench_test;
-import 'common_server_api_v1_test.dart' as common_server_api_v1_test;
-import 'common_server_api_v2_protobuf_test.dart'
- as common_server_api_v2_protobuf_test;
-import 'common_server_api_v2_test.dart' as common_server_api_v2_test;
+import 'common_server_api_protobuf_test.dart'
+ as common_server_api_protobuf_test;
+import 'common_server_api_test.dart' as common_server_api_test;
import 'common_test.dart' as common_test;
import 'compiler_test.dart' as compiler_test;
import 'flutter_web_test.dart' as flutter_web_test;
@@ -22,11 +20,9 @@
void main() async {
analysis_server_test.defineTests();
- api_classes_test.defineTests();
bench_test.defineTests();
- common_server_api_v1_test.defineTests();
- common_server_api_v2_test.defineTests();
- common_server_api_v2_protobuf_test.defineTests();
+ common_server_api_test.defineTests();
+ common_server_api_protobuf_test.defineTests();
common_test.defineTests();
compiler_test.defineTests();
flutter_web_test.defineTests();
diff --git a/test/analysis_server_test.dart b/test/analysis_server_test.dart
index f290954..bd0dd7b 100644
--- a/test/analysis_server_test.dart
+++ b/test/analysis_server_test.dart
@@ -5,7 +5,7 @@
library services.analyzer_server_test;
import 'package:dart_services/src/analysis_server.dart';
-import 'package:dart_services/src/api_classes.dart';
+import 'package:dart_services/src/protos/dart_services.pb.dart' as proto;
import 'package:dart_services/src/common.dart';
import 'package:dart_services/src/flutter_web.dart';
import 'package:dart_services/src/sdk_manager.dart';
@@ -75,9 +75,7 @@
test('simple_completion', () {
// Just after i.
- return analysisServer
- .complete(completionCode, 32)
- .then((CompleteResponse results) {
+ return analysisServer.complete(completionCode, 32).then((results) {
expect(results.replacementLength, 0);
expect(results.replacementOffset, 32);
expect(completionsContains(results, 'abs'), true);
@@ -87,12 +85,10 @@
test('repro #126 - completions polluted on second request', () {
// https://github.com/dart-lang/dart-services/issues/126
- return analysisServer
- .complete(completionFilterCode, 17)
- .then((CompleteResponse results) {
+ return analysisServer.complete(completionFilterCode, 17).then((results) {
return analysisServer
.complete(completionFilterCode, 17)
- .then((CompleteResponse results) {
+ .then((results) {
expect(results.replacementLength, 2);
expect(results.replacementOffset, 16);
expect(completionsContains(results, 'print'), true);
@@ -104,11 +100,9 @@
test('import_test', () {
final testCode = "import '/'; main() { int a = 0; a. }";
- return analysisServer
- .complete(testCode, 9)
- .then((CompleteResponse results) {
- expect(results.completions.every((Map<String, String> completion) {
- return completion['completion'].startsWith('dart:');
+ return analysisServer.complete(testCode, 9).then((results) {
+ expect(results.completions.every((completion) {
+ return completion.completion['completion'].startsWith('dart:');
}), true);
});
});
@@ -116,9 +110,7 @@
test('import_and_other_test', () {
final testCode = "import '/'; main() { int a = 0; a. }";
- return analysisServer
- .complete(testCode, 34)
- .then((CompleteResponse results) {
+ return analysisServer.complete(testCode, 34).then((results) {
expect(completionsContains(results, 'abs'), true);
});
});
@@ -216,5 +208,6 @@
});
}
-bool completionsContains(CompleteResponse response, String completion) =>
- response.completions.any((map) => map['completion'] == completion);
+bool completionsContains(proto.CompleteResponse response, String expected) =>
+ response.completions
+ .any((completion) => completion.completion['completion'] == expected);
diff --git a/test/api_classes_test.dart b/test/api_classes_test.dart
deleted file mode 100644
index b947376..0000000
--- a/test/api_classes_test.dart
+++ /dev/null
@@ -1,30 +0,0 @@
-// 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 services.api_classes_test;
-
-import 'package:dart_services/src/api_classes.dart';
-import 'package:test/test.dart';
-
-void main() => defineTests();
-
-void defineTests() {
- group('AnalysisIssue', () {
- test('toMap', () {
- final issue =
- AnalysisIssue.fromIssue('error', 1, 'not found', charStart: 123);
- final m = issue.toMap();
- expect(m['kind'], 'error');
- expect(m['line'], 1);
- expect(m['message'], isNotNull);
- expect(m['charStart'], isNotNull);
- expect(m['charLength'], isNull);
- });
-
- test('toString', () {
- final issue = AnalysisIssue.fromIssue('error', 1, 'not found');
- expect(issue.toString(), isNotNull);
- });
- });
-}
diff --git a/test/common_server_api_v2_protobuf_test.dart b/test/common_server_api_protobuf_test.dart
similarity index 96%
rename from test/common_server_api_v2_protobuf_test.dart
rename to test/common_server_api_protobuf_test.dart
index b24f0c8..c4aa222 100644
--- a/test/common_server_api_v2_protobuf_test.dart
+++ b/test/common_server_api_protobuf_test.dart
@@ -2,15 +2,14 @@
// 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 services.common_server_api_v2_protobuf_test;
+library services.common_server_api_protobuf_test;
import 'dart:async';
import 'dart:convert';
import 'package:dart_services/src/common.dart';
-import 'package:dart_services/src/common_server.dart';
import 'package:dart_services/src/common_server_impl.dart';
-import 'package:dart_services/src/common_server_proto.dart';
+import 'package:dart_services/src/common_server_api.dart';
import 'package:dart_services/src/flutter_web.dart';
import 'package:dart_services/src/sdk_manager.dart';
import 'package:dart_services/src/server_cache.dart';
@@ -57,7 +56,7 @@
void main() => defineTests();
void defineTests() {
- CommonServerProto commonServerProto;
+ CommonServerApi commonServerApi;
CommonServerImpl commonServerImpl;
FlutterWebManager flutterWebManager;
@@ -68,25 +67,25 @@
String path,
GeneratedMessage message,
) async {
- assert(commonServerProto != null);
+ assert(commonServerApi != null);
final uri = Uri.parse('/api/$path');
final request = MockHttpRequest('POST', uri);
request.headers.add('content-type', JSON_CONTENT_TYPE);
request.add(utf8.encode(json.encode(message.toProto3Json())));
await request.close();
- await shelf_io.handleRequest(request, commonServerProto.router.handler);
+ await shelf_io.handleRequest(request, commonServerApi.router.handler);
return request.response;
}
Future<MockHttpResponse> _sendGetRequest(
String path,
) async {
- assert(commonServerProto != null);
+ assert(commonServerApi != null);
final uri = Uri.parse('/api/$path');
final request = MockHttpRequest('POST', uri);
request.headers.add('content-type', JSON_CONTENT_TYPE);
await request.close();
- await shelf_io.handleRequest(request, commonServerProto.router.handler);
+ await shelf_io.handleRequest(request, commonServerApi.router.handler);
return request.response;
}
@@ -97,7 +96,7 @@
flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
commonServerImpl =
CommonServerImpl(sdkPath, flutterWebManager, container, cache);
- commonServerProto = CommonServerProto(commonServerImpl);
+ commonServerApi = CommonServerApi(commonServerImpl);
await commonServerImpl.init();
// Some piece of initialization doesn't always happen fast enough for this
diff --git a/test/common_server_api_test.dart b/test/common_server_api_test.dart
new file mode 100644
index 0000000..08e9839
--- /dev/null
+++ b/test/common_server_api_test.dart
@@ -0,0 +1,466 @@
+// 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 services.common_server_api_test;
+
+import 'dart:async';
+import 'dart:convert';
+
+import 'package:dart_services/src/common.dart';
+import 'package:dart_services/src/common_server_impl.dart';
+import 'package:dart_services/src/common_server_api.dart';
+import 'package:dart_services/src/flutter_web.dart';
+import 'package:dart_services/src/sdk_manager.dart';
+import 'package:dart_services/src/server_cache.dart';
+import 'package:logging/logging.dart';
+import 'package:mock_request/mock_request.dart';
+import 'package:shelf/shelf_io.dart' as shelf_io;
+import 'package:test/test.dart';
+
+const versions = ['v1', 'v2'];
+
+const quickFixesCode = r'''
+import 'dart:async';
+void main() {
+ int i = 0;
+}
+''';
+
+const preFormattedCode = r'''
+void main()
+{
+int i = 0;
+}
+''';
+
+const postFormattedCode = r'''
+void main() {
+ int i = 0;
+}
+''';
+
+const formatBadCode = r'''
+void main()
+{
+ print('foo')
+}
+''';
+
+const assistCode = r'''
+main() {
+ int v = 0;
+}
+''';
+
+void main() => defineTests();
+
+void defineTests() {
+ CommonServerApi commonServerApi;
+ CommonServerImpl commonServerImpl;
+ FlutterWebManager flutterWebManager;
+
+ MockContainer container;
+ MockCache cache;
+
+ Future<MockHttpResponse> _sendPostRequest(
+ String path,
+ dynamic jsonData,
+ ) async {
+ assert(commonServerApi != null);
+ final uri = Uri.parse('/api/$path');
+ final request = MockHttpRequest('POST', uri);
+ request.headers.add('content-type', JSON_CONTENT_TYPE);
+ request.add(utf8.encode(json.encode(jsonData)));
+ await request.close();
+ await shelf_io.handleRequest(request, commonServerApi.router.handler);
+ return request.response;
+ }
+
+ Future<MockHttpResponse> _sendGetRequest(
+ String path,
+ ) async {
+ assert(commonServerApi != null);
+ final uri = Uri.parse('/api/$path');
+ final request = MockHttpRequest('POST', uri);
+ request.headers.add('content-type', JSON_CONTENT_TYPE);
+ await request.close();
+ await shelf_io.handleRequest(request, commonServerApi.router.handler);
+ return request.response;
+ }
+
+ group('CommonServerProto JSON', () {
+ setUpAll(() async {
+ container = MockContainer();
+ cache = MockCache();
+ flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
+ commonServerImpl =
+ CommonServerImpl(sdkPath, flutterWebManager, container, cache);
+ commonServerApi = CommonServerApi(commonServerImpl);
+ await commonServerImpl.init();
+
+ // Some piece of initialization doesn't always happen fast enough for this
+ // request to work in time for the test. So try it here until the server
+ // returns something valid.
+ // TODO(jcollins-g): determine which piece of initialization isn't
+ // happening and deal with that in warmup/init.
+ {
+ var decodedJson = {};
+ final jsonData = {'source': sampleCodeError};
+ while (decodedJson.isEmpty) {
+ final response =
+ await _sendPostRequest('dartservices/v2/analyze', jsonData);
+ expect(response.statusCode, 200);
+ expect(response.headers['content-type'],
+ ['application/json; charset=utf-8']);
+ final data = await response.transform(utf8.decoder).join();
+ decodedJson = json.decode(data) as Map<dynamic, dynamic>;
+ }
+ }
+ });
+
+ tearDownAll(() async {
+ await commonServerImpl.shutdown();
+ });
+
+ setUp(() {
+ log.onRecord.listen((LogRecord rec) {
+ print('${rec.level.name}: ${rec.time}: ${rec.message}');
+ });
+ });
+
+ tearDown(log.clearListeners);
+
+ test('analyze Dart', () async {
+ for (final version in versions) {
+ final jsonData = {'source': sampleCode};
+ final response =
+ await _sendPostRequest('dartservices/$version/analyze', jsonData);
+ expect(response.statusCode, 200);
+ final data = await response.transform(utf8.decoder).join();
+ expect(json.decode(data), {});
+ }
+ });
+
+ test('analyze Flutter', () async {
+ for (final version in versions) {
+ final jsonData = {'source': sampleCodeFlutter};
+ final response =
+ await _sendPostRequest('dartservices/$version/analyze', jsonData);
+ expect(response.statusCode, 200);
+ final data = await response.transform(utf8.decoder).join();
+ expect(json.decode(data), {
+ 'packageImports': ['flutter']
+ });
+ }
+ });
+
+ test('analyze errors', () async {
+ for (final version in versions) {
+ final jsonData = {'source': sampleCodeError};
+ final response =
+ await _sendPostRequest('dartservices/$version/analyze', jsonData);
+ expect(response.statusCode, 200);
+ expect(response.headers['content-type'],
+ ['application/json; charset=utf-8']);
+ final data = await response.transform(utf8.decoder).join();
+ final expectedJson = {
+ 'issues': [
+ {
+ 'kind': 'error',
+ 'line': 2,
+ 'sourceName': 'main.dart',
+ 'message': "Expected to find ';'.",
+ 'hasFixes': true,
+ 'charStart': 29,
+ 'charLength': 1
+ }
+ ]
+ };
+ expect(json.decode(data), expectedJson);
+ }
+ });
+
+ test('analyze negative-test noSource', () async {
+ for (final version in versions) {
+ final jsonData = {};
+ final response =
+ await _sendPostRequest('dartservices/$version/analyze', jsonData);
+ expect(response.statusCode, 400);
+ }
+ });
+
+ test('compile', () async {
+ for (final version in versions) {
+ final jsonData = {'source': sampleCode};
+ final response =
+ await _sendPostRequest('dartservices/$version/compile', jsonData);
+ expect(response.statusCode, 200);
+ final data = await response.transform(utf8.decoder).join();
+ expect(json.decode(data), isNotEmpty);
+ }
+ });
+
+ test('compile error', () async {
+ for (final version in versions) {
+ final jsonData = {'source': sampleCodeError};
+ final response =
+ await _sendPostRequest('dartservices/$version/compile', jsonData);
+ expect(response.statusCode, 400);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data, isNotEmpty);
+ expect(data['error']['message'], contains('Error: Expected'));
+ }
+ });
+
+ test('compile negative-test noSource', () async {
+ for (final version in versions) {
+ final jsonData = {};
+ final response =
+ await _sendPostRequest('dartservices/$version/compile', jsonData);
+ expect(response.statusCode, 400);
+ }
+ });
+
+ test('compileDDC', () async {
+ for (final version in versions) {
+ final jsonData = {'source': sampleCode};
+ final response = await _sendPostRequest(
+ 'dartservices/$version/compileDDC', jsonData);
+ expect(response.statusCode, 200);
+ final data = await response.transform(utf8.decoder).join();
+ expect(json.decode(data), isNotEmpty);
+ }
+ });
+
+ test('complete', () async {
+ for (final version in versions) {
+ final jsonData = {'source': 'void main() {print("foo");}', 'offset': 1};
+ final response =
+ await _sendPostRequest('dartservices/$version/complete', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data, isNotEmpty);
+ }
+ });
+
+ test('complete no data', () async {
+ for (final version in versions) {
+ final response =
+ await _sendPostRequest('dartservices/$version/complete', {});
+ expect(response.statusCode, 400);
+ }
+ });
+
+ test('complete param missing', () async {
+ for (final version in versions) {
+ final jsonData = {'offset': 1};
+ final response =
+ await _sendPostRequest('dartservices/$version/complete', jsonData);
+ expect(response.statusCode, 400);
+ }
+ });
+
+ test('complete param missing 2', () async {
+ for (final version in versions) {
+ final jsonData = {'source': 'void main() {print("foo");}'};
+ final response =
+ await _sendPostRequest('dartservices/$version/complete', jsonData);
+ expect(response.statusCode, 400);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data['error']['message'], 'Missing parameter: \'offset\'');
+ }
+ });
+
+ test('document', () async {
+ for (final version in versions) {
+ final jsonData = {
+ 'source': 'void main() {print("foo");}',
+ 'offset': 17
+ };
+ final response =
+ await _sendPostRequest('dartservices/$version/document', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data, isNotEmpty);
+ }
+ });
+
+ test('document little data', () async {
+ for (final version in versions) {
+ final jsonData = {'source': 'void main() {print("foo");}', 'offset': 2};
+ final response =
+ await _sendPostRequest('dartservices/$version/document', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data, {
+ 'info': {},
+ });
+ }
+ });
+
+ test('document no data', () async {
+ for (final version in versions) {
+ final jsonData = {
+ 'source': 'void main() {print("foo");}',
+ 'offset': 12
+ };
+ final response =
+ await _sendPostRequest('dartservices/$version/document', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data, {'info': {}});
+ }
+ });
+
+ test('document negative-test noSource', () async {
+ for (final version in versions) {
+ final jsonData = {'offset': 12};
+ final response =
+ await _sendPostRequest('dartservices/$version/document', jsonData);
+ expect(response.statusCode, 400);
+ }
+ });
+
+ test('document negative-test noOffset', () async {
+ for (final version in versions) {
+ final jsonData = {'source': 'void main() {print("foo");}'};
+ final response =
+ await _sendPostRequest('dartservices/$version/document', jsonData);
+ expect(response.statusCode, 400);
+ }
+ });
+
+ test('format', () async {
+ for (final version in versions) {
+ final jsonData = {'source': preFormattedCode};
+ final response =
+ await _sendPostRequest('dartservices/$version/format', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data['newString'], postFormattedCode);
+ }
+ });
+
+ test('format bad code', () async {
+ for (final version in versions) {
+ final jsonData = {'source': formatBadCode};
+ final response =
+ await _sendPostRequest('dartservices/$version/format', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data['newString'], formatBadCode);
+ }
+ });
+
+ test('format position', () async {
+ for (final version in versions) {
+ final jsonData = {'source': preFormattedCode, 'offset': 21};
+ final response =
+ await _sendPostRequest('dartservices/$version/format', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data['newString'], postFormattedCode);
+ expect(data['offset'], 24);
+ }
+ });
+
+ test('fix', () async {
+ for (final version in versions) {
+ final jsonData = {'source': quickFixesCode, 'offset': 10};
+ final response =
+ await _sendPostRequest('dartservices/$version/fixes', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ final fixes = data['fixes'];
+ expect(fixes.length, 1);
+ final problemAndFix = fixes[0];
+ expect(problemAndFix['problemMessage'], isNotNull);
+ }
+ });
+
+ test('fixes completeness', () async {
+ for (final version in versions) {
+ final jsonData = {
+ 'source': '''
+void main() {
+ for (int i = 0; i < 4; i++) {
+ print('hello \$i')
+ }
+}
+''',
+ 'offset': 67,
+ };
+ final response =
+ await _sendPostRequest('dartservices/$version/fixes', jsonData);
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data, {
+ 'fixes': [
+ {
+ 'fixes': [
+ {
+ 'message': "Insert ';'",
+ 'edits': [
+ {'offset': 67, 'length': 0, 'replacement': ';'}
+ ]
+ }
+ ],
+ 'problemMessage': "Expected to find ';'.",
+ 'offset': 66,
+ 'length': 1
+ }
+ ]
+ });
+ }
+ });
+
+ test('assist', () async {
+ for (final version in versions) {
+ final jsonData = {'source': assistCode, 'offset': 15};
+ final response =
+ await _sendPostRequest('dartservices/$version/assists', jsonData);
+ expect(response.statusCode, 200);
+
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ final assists = data['assists'] as List;
+ expect(assists, hasLength(2));
+ expect(assists.first['edits'], isNotNull);
+ expect(assists.first['edits'], hasLength(1));
+ expect(assists.where((m) {
+ final map = m as Map<String, dynamic>;
+ return map['message'] == 'Remove type annotation';
+ }), isNotEmpty);
+ }
+ });
+
+ test('version', () async {
+ for (final version in versions) {
+ final response = await _sendGetRequest('dartservices/$version/version');
+ expect(response.statusCode, 200);
+ final data = json.decode(await response.transform(utf8.decoder).join());
+ expect(data['sdkVersion'], isNotNull);
+ expect(data['runtimeVersion'], isNotNull);
+ }
+ });
+ });
+}
+
+class MockContainer implements ServerContainer {
+ @override
+ String get version => vmVersion;
+}
+
+class MockCache implements ServerCache {
+ @override
+ Future<String> get(String key) => Future.value(null);
+
+ @override
+ Future set(String key, String value, {Duration expiration}) => Future.value();
+
+ @override
+ Future remove(String key) => Future.value();
+
+ @override
+ Future<void> shutdown() => Future.value();
+}
diff --git a/test/common_server_api_v1_test.dart b/test/common_server_api_v1_test.dart
deleted file mode 100644
index f7fdad2..0000000
--- a/test/common_server_api_v1_test.dart
+++ /dev/null
@@ -1,408 +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 services.common_server_api_v1_test;
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:dart_services/src/common.dart';
-import 'package:dart_services/src/common_server.dart';
-import 'package:dart_services/src/common_server_impl.dart';
-import 'package:dart_services/src/flutter_web.dart';
-import 'package:dart_services/src/sdk_manager.dart';
-import 'package:dart_services/src/server_cache.dart';
-import 'package:logging/logging.dart';
-import 'package:rpc/rpc.dart';
-import 'package:test/test.dart';
-
-const quickFixesCode = r'''
-import 'dart:async';
-void main() {
- int i = 0;
-}
-''';
-
-const preFormattedCode = r'''
-void main()
-{
-int i = 0;
-}
-''';
-
-const postFormattedCode = r'''
-void main() {
- int i = 0;
-}
-''';
-
-const formatBadCode = r'''
-void main()
-{
- print('foo')
-}
-''';
-
-const assistCode = r'''
-main() {
- int v = 0;
-}
-''';
-
-void main() => defineTests();
-
-void defineTests() {
- CommonServer server;
- CommonServerImpl commonServerImpl;
- ApiServer apiServer;
- FlutterWebManager flutterWebManager;
-
- MockContainer container;
- MockCache cache;
-
- Future<HttpApiResponse> _sendPostRequest(String path, jsonData) {
- assert(apiServer != null);
- final uri = Uri.parse('/api/$path');
- final body = Stream.fromIterable([utf8.encode(json.encode(jsonData))]);
- final request = HttpApiRequest(
- 'POST', uri, {'content-type': 'application/json; charset=utf-8'}, body);
- return apiServer.handleHttpApiRequest(request);
- }
-
- Future<HttpApiResponse> _sendGetRequest(String path, [String queryParams]) {
- assert(apiServer != null);
- final uri = Uri.parse(
- queryParams == null ? '/api/$path' : '/api/$path?$queryParams');
- final body = Stream<List<int>>.fromIterable([]);
- final request = HttpApiRequest(
- 'GET', uri, {'content-type': 'application/json; charset=utf-8'}, body);
- return apiServer.handleHttpApiRequest(request);
- }
-
- group('CommonServer', () {
- setUpAll(() async {
- container = MockContainer();
- cache = MockCache();
- flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
- commonServerImpl =
- CommonServerImpl(sdkPath, flutterWebManager, container, cache);
- server = CommonServer(commonServerImpl);
- await commonServerImpl.init();
-
- apiServer = ApiServer(apiPrefix: '/api', prettyPrint: true);
- apiServer.addApi(server);
-
- // Some piece of initialization doesn't always happen fast enough for this
- // request to work in time for the test. So try it here until the server
- // returns something valid.
- // TODO(jcollins-g): determine which piece of initialization isn't
- // happening and deal with that in warmup/init.
- {
- var decodedJson = {};
- final jsonData = {'source': sampleCodeError};
- while (decodedJson.isEmpty) {
- final response =
- await _sendPostRequest('dartservices/v1/analyze', jsonData);
- expect(response.status, 200);
- expect(response.headers['content-type'],
- 'application/json; charset=utf-8');
- final data = await response.body.first;
- decodedJson = json.decode(utf8.decode(data)) as Map<dynamic, dynamic>;
- }
- }
- });
-
- tearDownAll(() async {
- await commonServerImpl.shutdown();
- });
-
- setUp(() {
- log.onRecord.listen((LogRecord rec) {
- print('${rec.level.name}: ${rec.time}: ${rec.message}');
- });
- });
-
- tearDown(log.clearListeners);
-
- test('analyze Dart', () async {
- final jsonData = {'source': sampleCode};
- final response =
- await _sendPostRequest('dartservices/v1/analyze', jsonData);
- expect(response.status, 200);
- final data = await response.body.first;
- expect(
- json.decode(utf8.decode(data)), {'issues': [], 'packageImports': []});
- });
-
- test('analyze Flutter', () async {
- final jsonData = {'source': sampleCodeFlutter};
- final response =
- await _sendPostRequest('dartservices/v1/analyze', jsonData);
- expect(response.status, 200);
- final data = await response.body.first;
- expect(json.decode(utf8.decode(data)), {
- 'issues': [],
- 'packageImports': ['flutter']
- });
- });
-
- test('analyze errors', () async {
- final jsonData = {'source': sampleCodeError};
- final response =
- await _sendPostRequest('dartservices/v1/analyze', jsonData);
- expect(response.status, 200);
- expect(
- response.headers['content-type'], 'application/json; charset=utf-8');
- final data = await response.body.first;
- final expectedJson = {
- 'issues': [
- {
- 'kind': 'error',
- 'line': 2,
- 'sourceName': 'main.dart',
- 'message': "Expected to find ';'.",
- 'hasFixes': true,
- 'charStart': 29,
- 'charLength': 1
- }
- ],
- 'packageImports': []
- };
- expect(json.decode(utf8.decode(data)), expectedJson);
- });
-
- test('analyze negative-test noSource', () async {
- final jsonData = {};
- final response =
- await _sendPostRequest('dartservices/v1/analyze', jsonData);
- expect(response.status, 400);
- });
-
- test('compile', () async {
- final jsonData = {'source': sampleCode};
- final response =
- await _sendPostRequest('dartservices/v1/compile', jsonData);
- expect(response.status, 200);
- final data = await response.body.first;
- expect(json.decode(utf8.decode(data)), isNotEmpty);
- });
-
- test('compile error', () async {
- final jsonData = {'source': sampleCodeError};
- final response =
- await _sendPostRequest('dartservices/v1/compile', jsonData);
- expect(response.status, 400);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data, isNotEmpty);
- expect(data['error']['message'], contains('Error: Expected'));
- });
-
- test('compile negative-test noSource', () async {
- final jsonData = {};
- final response =
- await _sendPostRequest('dartservices/v1/compile', jsonData);
- expect(response.status, 400);
- });
-
- test('compileDDC', () async {
- final jsonData = {'source': sampleCode};
- final response =
- await _sendPostRequest('dartservices/v1/compileDDC', jsonData);
- expect(response.status, 200);
- final data = await response.body.first;
- expect(json.decode(utf8.decode(data)), isNotEmpty);
- });
-
- test('complete', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 1};
- final response =
- await _sendPostRequest('dartservices/v1/complete', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data, isNotEmpty);
- });
-
- test('complete no data', () async {
- final response = await _sendPostRequest('dartservices/v1/complete', {});
- expect(response.status, 400);
- });
-
- test('complete param missing', () async {
- final jsonData = {'offset': 1};
- final response =
- await _sendPostRequest('dartservices/v1/complete', jsonData);
- expect(response.status, 400);
- });
-
- test('complete param missing 2', () async {
- final jsonData = {'source': 'void main() {print("foo");}'};
- final response =
- await _sendPostRequest('dartservices/v1/complete', jsonData);
- expect(response.status, 400);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data['error']['message'], 'Missing parameter: \'offset\'');
- });
-
- test('document', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 17};
- final response =
- await _sendPostRequest('dartservices/v1/document', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data, isNotEmpty);
- });
-
- test('document little data', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 2};
- final response =
- await _sendPostRequest('dartservices/v1/document', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data, {
- 'info': {},
- });
- });
-
- test('document no data', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 12};
- final response =
- await _sendPostRequest('dartservices/v1/document', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data, {'info': {}});
- });
-
- test('document negative-test noSource', () async {
- final jsonData = {'offset': 12};
- final response =
- await _sendPostRequest('dartservices/v1/document', jsonData);
- expect(response.status, 400);
- });
-
- test('document negative-test noOffset', () async {
- final jsonData = {'source': 'void main() {print("foo");}'};
- final response =
- await _sendPostRequest('dartservices/v1/document', jsonData);
- expect(response.status, 400);
- });
-
- test('format', () async {
- final jsonData = {'source': preFormattedCode};
- final response =
- await _sendPostRequest('dartservices/v1/format', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data['newString'], postFormattedCode);
- });
-
- test('format bad code', () async {
- final jsonData = {'source': formatBadCode};
- final response =
- await _sendPostRequest('dartservices/v1/format', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data['newString'], formatBadCode);
- });
-
- test('format position', () async {
- final jsonData = {'source': preFormattedCode, 'offset': 21};
- final response =
- await _sendPostRequest('dartservices/v1/format', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data['newString'], postFormattedCode);
- expect(data['offset'], 24);
- });
-
- test('fix', () async {
- final jsonData = {'source': quickFixesCode, 'offset': 10};
- final response =
- await _sendPostRequest('dartservices/v1/fixes', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- final fixes = data['fixes'];
- expect(fixes.length, 1);
- final problemAndFix = fixes[0];
- expect(problemAndFix['problemMessage'], isNotNull);
- });
-
- test('fixes completeness', () async {
- final jsonData = {
- 'source': '''
-void main() {
- for (int i = 0; i < 4; i++) {
- print('hello \$i')
- }
-}
-''',
- 'offset': 67,
- };
- final response =
- await _sendPostRequest('dartservices/v1/fixes', jsonData);
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data, {
- 'fixes': [
- {
- 'fixes': [
- {
- 'message': "Insert ';'",
- 'edits': [
- {'offset': 67, 'length': 0, 'replacement': ';'}
- ]
- }
- ],
- 'problemMessage': "Expected to find ';'.",
- 'offset': 66,
- 'length': 1
- }
- ]
- });
- });
-
- test('assist', () async {
- final jsonData = {'source': assistCode, 'offset': 15};
- final response =
- await _sendPostRequest('dartservices/v1/assists', jsonData);
- expect(response.status, 200);
-
- final data = json.decode(utf8.decode(await response.body.first));
- final assists = data['assists'] as List;
- expect(assists, hasLength(2));
- expect(assists.first['edits'], isNotNull);
- expect(assists.first['edits'], hasLength(1));
- expect(assists.where((m) {
- final map = m as Map<String, dynamic>;
- return map['message'] == 'Remove type annotation';
- }), isNotEmpty);
- });
-
- test('version', () async {
- final response = await _sendGetRequest('dartservices/v1/version');
- expect(response.status, 200);
- final data = json.decode(utf8.decode(await response.body.first));
- expect(data['sdkVersion'], isNotNull);
- expect(data['runtimeVersion'], isNotNull);
- });
- });
-}
-
-class MockContainer implements ServerContainer {
- @override
- String get version => vmVersion;
-}
-
-class MockCache implements ServerCache {
- @override
- Future<String> get(String key) => Future.value(null);
-
- @override
- Future set(String key, String value, {Duration expiration}) => Future.value();
-
- @override
- Future remove(String key) => Future.value();
-
- @override
- Future<void> shutdown() => Future.value();
-}
diff --git a/test/common_server_api_v2_test.dart b/test/common_server_api_v2_test.dart
deleted file mode 100644
index b29e16e..0000000
--- a/test/common_server_api_v2_test.dart
+++ /dev/null
@@ -1,410 +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 services.common_server_api_v2_test;
-
-import 'dart:async';
-import 'dart:convert';
-
-import 'package:dart_services/src/common.dart';
-import 'package:dart_services/src/common_server.dart';
-import 'package:dart_services/src/common_server_impl.dart';
-import 'package:dart_services/src/common_server_proto.dart';
-import 'package:dart_services/src/flutter_web.dart';
-import 'package:dart_services/src/sdk_manager.dart';
-import 'package:dart_services/src/server_cache.dart';
-import 'package:logging/logging.dart';
-import 'package:mock_request/mock_request.dart';
-import 'package:shelf/shelf_io.dart' as shelf_io;
-import 'package:test/test.dart';
-
-const quickFixesCode = r'''
-import 'dart:async';
-void main() {
- int i = 0;
-}
-''';
-
-const preFormattedCode = r'''
-void main()
-{
-int i = 0;
-}
-''';
-
-const postFormattedCode = r'''
-void main() {
- int i = 0;
-}
-''';
-
-const formatBadCode = r'''
-void main()
-{
- print('foo')
-}
-''';
-
-const assistCode = r'''
-main() {
- int v = 0;
-}
-''';
-
-void main() => defineTests();
-
-void defineTests() {
- CommonServerProto commonServerProto;
- CommonServerImpl commonServerImpl;
- FlutterWebManager flutterWebManager;
-
- MockContainer container;
- MockCache cache;
-
- Future<MockHttpResponse> _sendPostRequest(
- String path,
- dynamic jsonData,
- ) async {
- assert(commonServerProto != null);
- final uri = Uri.parse('/api/$path');
- final request = MockHttpRequest('POST', uri);
- request.headers.add('content-type', JSON_CONTENT_TYPE);
- request.add(utf8.encode(json.encode(jsonData)));
- await request.close();
- await shelf_io.handleRequest(request, commonServerProto.router.handler);
- return request.response;
- }
-
- Future<MockHttpResponse> _sendGetRequest(
- String path,
- ) async {
- assert(commonServerProto != null);
- final uri = Uri.parse('/api/$path');
- final request = MockHttpRequest('POST', uri);
- request.headers.add('content-type', JSON_CONTENT_TYPE);
- await request.close();
- await shelf_io.handleRequest(request, commonServerProto.router.handler);
- return request.response;
- }
-
- group('CommonServerProto JSON', () {
- setUpAll(() async {
- container = MockContainer();
- cache = MockCache();
- flutterWebManager = FlutterWebManager(SdkManager.flutterSdk);
- commonServerImpl =
- CommonServerImpl(sdkPath, flutterWebManager, container, cache);
- commonServerProto = CommonServerProto(commonServerImpl);
- await commonServerImpl.init();
-
- // Some piece of initialization doesn't always happen fast enough for this
- // request to work in time for the test. So try it here until the server
- // returns something valid.
- // TODO(jcollins-g): determine which piece of initialization isn't
- // happening and deal with that in warmup/init.
- {
- var decodedJson = {};
- final jsonData = {'source': sampleCodeError};
- while (decodedJson.isEmpty) {
- final response =
- await _sendPostRequest('dartservices/v2/analyze', jsonData);
- expect(response.statusCode, 200);
- expect(response.headers['content-type'],
- ['application/json; charset=utf-8']);
- final data = await response.transform(utf8.decoder).join();
- decodedJson = json.decode(data) as Map<dynamic, dynamic>;
- }
- }
- });
-
- tearDownAll(() async {
- await commonServerImpl.shutdown();
- });
-
- setUp(() {
- log.onRecord.listen((LogRecord rec) {
- print('${rec.level.name}: ${rec.time}: ${rec.message}');
- });
- });
-
- tearDown(log.clearListeners);
-
- test('analyze Dart', () async {
- final jsonData = {'source': sampleCode};
- final response =
- await _sendPostRequest('dartservices/v2/analyze', jsonData);
- expect(response.statusCode, 200);
- final data = await response.transform(utf8.decoder).join();
- expect(json.decode(data), {});
- });
-
- test('analyze Flutter', () async {
- final jsonData = {'source': sampleCodeFlutter};
- final response =
- await _sendPostRequest('dartservices/v2/analyze', jsonData);
- expect(response.statusCode, 200);
- final data = await response.transform(utf8.decoder).join();
- expect(json.decode(data), {
- 'packageImports': ['flutter']
- });
- });
-
- test('analyze errors', () async {
- final jsonData = {'source': sampleCodeError};
- final response =
- await _sendPostRequest('dartservices/v2/analyze', jsonData);
- expect(response.statusCode, 200);
- expect(response.headers['content-type'],
- ['application/json; charset=utf-8']);
- final data = await response.transform(utf8.decoder).join();
- final expectedJson = {
- 'issues': [
- {
- 'kind': 'error',
- 'line': 2,
- 'sourceName': 'main.dart',
- 'message': "Expected to find ';'.",
- 'hasFixes': true,
- 'charStart': 29,
- 'charLength': 1
- }
- ]
- };
- expect(json.decode(data), expectedJson);
- });
-
- test('analyze negative-test noSource', () async {
- final jsonData = {};
- final response =
- await _sendPostRequest('dartservices/v2/analyze', jsonData);
- expect(response.statusCode, 400);
- });
-
- test('compile', () async {
- final jsonData = {'source': sampleCode};
- final response =
- await _sendPostRequest('dartservices/v2/compile', jsonData);
- expect(response.statusCode, 200);
- final data = await response.transform(utf8.decoder).join();
- expect(json.decode(data), isNotEmpty);
- });
-
- test('compile error', () async {
- final jsonData = {'source': sampleCodeError};
- final response =
- await _sendPostRequest('dartservices/v2/compile', jsonData);
- expect(response.statusCode, 400);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data, isNotEmpty);
- expect(data['error']['message'], contains('Error: Expected'));
- });
-
- test('compile negative-test noSource', () async {
- final jsonData = {};
- final response =
- await _sendPostRequest('dartservices/v2/compile', jsonData);
- expect(response.statusCode, 400);
- });
-
- test('compileDDC', () async {
- final jsonData = {'source': sampleCode};
- final response =
- await _sendPostRequest('dartservices/v2/compileDDC', jsonData);
- expect(response.statusCode, 200);
- final data = await response.transform(utf8.decoder).join();
- expect(json.decode(data), isNotEmpty);
- });
-
- test('complete', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 1};
- final response =
- await _sendPostRequest('dartservices/v2/complete', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data, isNotEmpty);
- });
-
- test('complete no data', () async {
- final response = await _sendPostRequest('dartservices/v2/complete', {});
- expect(response.statusCode, 400);
- });
-
- test('complete param missing', () async {
- final jsonData = {'offset': 1};
- final response =
- await _sendPostRequest('dartservices/v2/complete', jsonData);
- expect(response.statusCode, 400);
- });
-
- test('complete param missing 2', () async {
- final jsonData = {'source': 'void main() {print("foo");}'};
- final response =
- await _sendPostRequest('dartservices/v2/complete', jsonData);
- expect(response.statusCode, 400);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data['error']['message'], 'Missing parameter: \'offset\'');
- });
-
- test('document', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 17};
- final response =
- await _sendPostRequest('dartservices/v2/document', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data, isNotEmpty);
- });
-
- test('document little data', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 2};
- final response =
- await _sendPostRequest('dartservices/v2/document', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data, {
- 'info': {},
- });
- });
-
- test('document no data', () async {
- final jsonData = {'source': 'void main() {print("foo");}', 'offset': 12};
- final response =
- await _sendPostRequest('dartservices/v2/document', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data, {'info': {}});
- });
-
- test('document negative-test noSource', () async {
- final jsonData = {'offset': 12};
- final response =
- await _sendPostRequest('dartservices/v2/document', jsonData);
- expect(response.statusCode, 400);
- });
-
- test('document negative-test noOffset', () async {
- final jsonData = {'source': 'void main() {print("foo");}'};
- final response =
- await _sendPostRequest('dartservices/v2/document', jsonData);
- expect(response.statusCode, 400);
- });
-
- test('format', () async {
- final jsonData = {'source': preFormattedCode};
- final response =
- await _sendPostRequest('dartservices/v2/format', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data['newString'], postFormattedCode);
- });
-
- test('format bad code', () async {
- final jsonData = {'source': formatBadCode};
- final response =
- await _sendPostRequest('dartservices/v2/format', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data['newString'], formatBadCode);
- });
-
- test('format position', () async {
- final jsonData = {'source': preFormattedCode, 'offset': 21};
- final response =
- await _sendPostRequest('dartservices/v2/format', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data['newString'], postFormattedCode);
- expect(data['offset'], 24);
- });
-
- test('fix', () async {
- final jsonData = {'source': quickFixesCode, 'offset': 10};
- final response =
- await _sendPostRequest('dartservices/v2/fixes', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- final fixes = data['fixes'];
- expect(fixes.length, 1);
- final problemAndFix = fixes[0];
- expect(problemAndFix['problemMessage'], isNotNull);
- });
-
- test('fixes completeness', () async {
- final jsonData = {
- 'source': '''
-void main() {
- for (int i = 0; i < 4; i++) {
- print('hello \$i')
- }
-}
-''',
- 'offset': 67,
- };
- final response =
- await _sendPostRequest('dartservices/v2/fixes', jsonData);
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data, {
- 'fixes': [
- {
- 'fixes': [
- {
- 'message': "Insert ';'",
- 'edits': [
- {'offset': 67, 'length': 0, 'replacement': ';'}
- ]
- }
- ],
- 'problemMessage': "Expected to find ';'.",
- 'offset': 66,
- 'length': 1
- }
- ]
- });
- });
-
- test('assist', () async {
- final jsonData = {'source': assistCode, 'offset': 15};
- final response =
- await _sendPostRequest('dartservices/v2/assists', jsonData);
- expect(response.statusCode, 200);
-
- final data = json.decode(await response.transform(utf8.decoder).join());
- final assists = data['assists'] as List;
- expect(assists, hasLength(2));
- expect(assists.first['edits'], isNotNull);
- expect(assists.first['edits'], hasLength(1));
- expect(assists.where((m) {
- final map = m as Map<String, dynamic>;
- return map['message'] == 'Remove type annotation';
- }), isNotEmpty);
- });
-
- test('version', () async {
- final response = await _sendGetRequest('dartservices/v2/version');
- expect(response.statusCode, 200);
- final data = json.decode(await response.transform(utf8.decoder).join());
- expect(data['sdkVersion'], isNotNull);
- expect(data['runtimeVersion'], isNotNull);
- });
- });
-}
-
-class MockContainer implements ServerContainer {
- @override
- String get version => vmVersion;
-}
-
-class MockCache implements ServerCache {
- @override
- Future<String> get(String key) => Future.value(null);
-
- @override
- Future set(String key, String value, {Duration expiration}) => Future.value();
-
- @override
- Future remove(String key) => Future.value();
-
- @override
- Future<void> shutdown() => Future.value();
-}
diff --git a/tool/fuzz_driver.dart b/tool/fuzz_driver.dart
index a766202..8a14f2a 100644
--- a/tool/fuzz_driver.dart
+++ b/tool/fuzz_driver.dart
@@ -13,15 +13,13 @@
import 'dart:math';
import 'package:dart_services/src/analysis_server.dart' as analysis_server;
-import 'package:dart_services/src/api_classes.dart';
import 'package:dart_services/src/common.dart';
-import 'package:dart_services/src/common_server.dart';
import 'package:dart_services/src/common_server_impl.dart';
import 'package:dart_services/src/compiler.dart' as comp;
import 'package:dart_services/src/flutter_web.dart';
import 'package:dart_services/src/sdk_manager.dart';
import 'package:dart_services/src/server_cache.dart';
-import 'package:rpc/rpc.dart';
+import 'package:dart_services/src/protos/dart_services.pb.dart' as proto;
bool _SERVER_BASED_CALL = false;
bool _VERBOSE = false;
@@ -29,9 +27,7 @@
bool _DUMP_PERF = false;
bool _DUMP_DELTA = false;
-CommonServer server;
CommonServerImpl commonServerImpl;
-ApiServer apiServer;
MockContainer container;
MockCache cache;
analysis_server.AnalysisServerWrapper analysisServer;
@@ -133,11 +129,8 @@
cache = MockCache();
commonServerImpl =
CommonServerImpl(sdkPath, flutterWebManager, container, cache);
- server = CommonServer(commonServerImpl);
await commonServerImpl.init();
- apiServer = ApiServer(apiPrefix: '/api', prettyPrint: true)..addApi(server);
-
analysisServer =
analysis_server.AnalysisServerWrapper(sdkPath, flutterWebManager);
await analysisServer.init();
@@ -244,10 +237,10 @@
lastOffset = null;
if (_SERVER_BASED_CALL) {
- final request = SourceRequest();
+ final request = proto.SourceRequest();
request.source = src;
- await withTimeOut(server.analyze(request));
- await withTimeOut(server.analyze(request));
+ await withTimeOut(commonServerImpl.analyze(request));
+ await withTimeOut(commonServerImpl.analyze(request));
} else {
await withTimeOut(analysisServer.analyze(src));
await withTimeOut(analysisServer.analyze(src));
@@ -263,9 +256,9 @@
lastOffset = null;
if (_SERVER_BASED_CALL) {
- final request = CompileRequest();
+ final request = proto.CompileRequest();
request.source = src;
- await withTimeOut(server.compile(request));
+ await withTimeOut(commonServerImpl.compile(request));
} else {
await withTimeOut(compiler.compile(src));
}
@@ -284,10 +277,10 @@
if (i % 1000 == 0 && i > 0) print('INC: $i docs completed');
lastOffset = i;
if (_SERVER_BASED_CALL) {
- final request = SourceRequest();
+ final request = proto.SourceRequest();
request.source = src;
request.offset = i;
- log(await withTimeOut(server.document(request)));
+ log(await withTimeOut(commonServerImpl.document(request)));
} else {
log(await withTimeOut(analysisServer.dartdoc(src, i)));
}
@@ -306,10 +299,10 @@
if (i % 1000 == 0 && i > 0) print('INC: $i completes');
lastOffset = i;
if (_SERVER_BASED_CALL) {
- final request = SourceRequest()
+ final request = proto.SourceRequest()
..source = src
..offset = i;
- await withTimeOut(server.complete(request));
+ await withTimeOut(commonServerImpl.complete(request));
} else {
await withTimeOut(wrapper.complete(src, i));
}
@@ -328,10 +321,10 @@
if (i % 1000 == 0 && i > 0) print('INC: $i fixes');
lastOffset = i;
if (_SERVER_BASED_CALL) {
- final request = SourceRequest();
+ final request = proto.SourceRequest();
request.source = src;
request.offset = i;
- await withTimeOut(server.fixes(request));
+ await withTimeOut(commonServerImpl.fixes(request));
} else {
await withTimeOut(wrapper.getFixes(src, i));
}
@@ -345,10 +338,10 @@
final sw = Stopwatch()..start();
final i = 0;
lastOffset = i;
- final request = SourceRequest();
+ final request = proto.SourceRequest();
request.source = src;
request.offset = i;
- log(await withTimeOut(server.format(request)));
+ log(await withTimeOut(commonServerImpl.format(request)));
return sw.elapsedMilliseconds;
}
diff --git a/tool/grind.dart b/tool/grind.dart
index 5b1926b..f91ac5f 100644
--- a/tool/grind.dart
+++ b/tool/grind.dart
@@ -234,40 +234,17 @@
log('warning: fuzz testing is a noop, see #301');
}
-@Task('Update discovery files and run all checks prior to deployment')
-@Depends(setupFlutterSubmodule, updateDockerVersion, generateProtos, discovery,
- analyze, test, fuzz, validateStorageArtifacts)
+@Task('Update generated files and run all checks prior to deployment')
+@Depends(setupFlutterSubmodule, updateDockerVersion, generateProtos, analyze,
+ test, fuzz, validateStorageArtifacts)
void deploy() {
log('Run: gcloud app deploy --project=dart-services --no-promote');
}
@Task()
-@Depends(generateProtos, discovery, analyze, fuzz, buildStorageArtifacts)
+@Depends(generateProtos, analyze, fuzz, buildStorageArtifacts)
void buildbot() => null;
-@Task('Generate the discovery doc and Dart library from the annotated API')
-void discovery() {
- final result = Process.runSync(
- Platform.executable, ['bin/server_dev.dart', '--discovery']);
-
- if (result.exitCode != 0) {
- throw 'Error generating the discovery document\n${result.stderr}';
- }
-
- final discoveryFile = File('doc/generated/dartservices.json');
- discoveryFile.parent.createSync();
- log('writing ${discoveryFile.path}');
- discoveryFile.writeAsStringSync('${result.stdout.trim()}\n');
-
- // Generate the Dart library from the json discovery file.
- Pub.global.activate('discoveryapis_generator');
- Pub.global.run('discoveryapis_generator:generate', arguments: [
- 'files',
- '--input-dir=doc/generated',
- '--output-dir=doc/generated'
- ]);
-}
-
@Task('Generate Protobuf classes')
void generateProtos() async {
await runWithLogging(