blob: c4fceb68a97c47bc24a774879a18486a8a76e4d2 [file] [log] [blame]
// Copyright (c) 2017, the Dart project authors. Please see the AUTHORS file
// for details. All rights reserved. Use of this source code is governed by a
// BSD-style license that can be found in the LICENSE file.
import 'dart:async';
import 'dart:core';
import 'package:analysis_server/protocol/protocol.dart';
import 'package:analysis_server/protocol/protocol_constants.dart';
import 'package:analysis_server/protocol/protocol_generated.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/domain_abstract.dart';
import 'package:analysis_server/src/plugin/plugin_manager.dart';
import 'package:analysis_server/src/plugin/result_merger.dart';
import 'package:analysis_server/src/services/kythe/kythe_visitors.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/src/dart/analysis/driver.dart';
import 'package:analyzer/src/dart/element/inheritance_manager2.dart';
import 'package:analyzer/src/generated/type_system.dart';
import 'package:analyzer_plugin/protocol/protocol.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_common.dart';
import 'package:analyzer_plugin/protocol/protocol_constants.dart' as plugin;
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
/**
* Instances of the class [KytheDomainHandler] implement a [RequestHandler]
* that handles requests in the `kythe` domain.
*/
class KytheDomainHandler extends AbstractRequestHandler {
/**
* Initialize a newly created handler to handle requests for the given [server].
*/
KytheDomainHandler(AnalysisServer server) : super(server);
/**
* Implement the `kythe.getKytheEntries` request.
*/
Future<void> getKytheEntries(Request request) async {
// TODO(brianwilkerson) Determine whether this await is necessary.
await null;
String file = new KytheGetKytheEntriesParams.fromRequest(request).file;
AnalysisDriver driver = server.getAnalysisDriver(file);
if (driver == null) {
server.sendResponse(new Response.getKytheEntriesInvalidFile(request));
} else {
//
// Allow plugins to start computing entries.
//
plugin.KytheGetKytheEntriesParams requestParams =
new plugin.KytheGetKytheEntriesParams(file);
Map<PluginInfo, Future<plugin.Response>> pluginFutures = server
.pluginManager
.broadcastRequest(requestParams, contextRoot: driver.contextRoot);
//
// Compute entries generated by server.
//
List<KytheGetKytheEntriesResult> allResults =
<KytheGetKytheEntriesResult>[];
AnalysisResult result = await server.getAnalysisResult(file);
CompilationUnit unit = result?.unit;
TypeSystem typeSystem = result.libraryElement.context.typeSystem;
if (unit != null && result.exists) {
List<KytheEntry> entries = <KytheEntry>[];
// TODO(brianwilkerson) Figure out how to get the list of files.
List<String> files = <String>[];
result.unit.accept(new KytheDartVisitor(
server.resourceProvider,
entries,
file,
new InheritanceManager2(typeSystem),
result.content));
allResults.add(new KytheGetKytheEntriesResult(entries, files));
}
//
// Add the entries produced by plugins to the server-generated entries.
//
if (pluginFutures != null) {
List<plugin.Response> responses = await waitForResponses(pluginFutures,
requestParameters: requestParams);
for (plugin.Response response in responses) {
plugin.KytheGetKytheEntriesResult result =
new plugin.KytheGetKytheEntriesResult.fromResponse(response);
allResults.add(
new KytheGetKytheEntriesResult(result.entries, result.files));
}
}
//
// Return the result.
//
ResultMerger merger = new ResultMerger();
KytheGetKytheEntriesResult mergedResults =
merger.mergeKytheEntries(allResults);
if (mergedResults == null) {
server.sendResponse(
new KytheGetKytheEntriesResult(<KytheEntry>[], <String>[])
.toResponse(request.id));
} else {
server.sendResponse(new KytheGetKytheEntriesResult(
mergedResults.entries, mergedResults.files)
.toResponse(request.id));
}
}
}
@override
Response handleRequest(Request request) {
try {
String requestName = request.method;
if (requestName == KYTHE_REQUEST_GET_KYTHE_ENTRIES) {
getKytheEntries(request);
return Response.DELAYED_RESPONSE;
}
} on RequestFailure catch (exception) {
return exception.response;
}
return null;
}
}