blob: 44d1f02fed4c6ee0eb681225c3c1c3b3b344853c [file] [log] [blame]
// 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 operation.analysis;
import 'package:analysis_server/src/operation/operation.dart';
import 'package:analysis_server/src/analysis_server.dart';
import 'package:analysis_server/src/computer/computer_highlights.dart';
import 'package:analysis_server/src/computer/computer_navigation.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analysis_server/src/constants.dart';
import 'package:analysis_server/src/protocol.dart';
import 'package:analyzer/src/generated/ast.dart';
import 'package:analyzer/src/generated/engine.dart';
import 'package:analyzer/src/generated/error.dart';
import 'package:analyzer/src/generated/java_core.dart';
import 'package:analyzer/src/generated/source.dart';
/**
* Instances of [PerformAnalysisOperation] perform a single analysis task.
*/
class PerformAnalysisOperation extends ServerOperation {
final AnalysisContext context;
final bool isContinue;
PerformAnalysisOperation(this.context, this.isContinue);
@override
ServerOperationPriority get priority {
if (isContinue) {
return ServerOperationPriority.ANALYSIS_CONTINUE;
} else {
return ServerOperationPriority.ANALYSIS;
}
}
@override
void perform(AnalysisServer server) {
//
// TODO(brianwilkerson) Add an optional function-valued parameter to
// performAnalysisTask that will be called when the task has been computed
// but before it is performed and send notification in the function:
//
// AnalysisResult result = context.performAnalysisTask((taskDescription) {
// sendStatusNotification(context.toString(), taskDescription);
// });
// prepare results
AnalysisResult result = context.performAnalysisTask();
List<ChangeNotice> notices = result.changeNotices;
if (notices == null) {
return;
}
// TODO(scheglov) remember known sources
// TODO(scheglov) index units
// TODO(scheglov) schedule notifications
sendNotices(server, notices);
// continue analysis
server.addOperation(new PerformAnalysisOperation(context, true));
}
/**
* Send the information in the given list of notices back to the client.
*/
void sendNotices(AnalysisServer server, List<ChangeNotice> notices) {
for (int i = 0; i < notices.length; i++) {
ChangeNotice notice = notices[i];
Source source = notice.source;
CompilationUnit dartUnit = notice.compilationUnit;
// TODO(scheglov) use default subscriptions
String file = source.fullName;
if (dartUnit != null) {
if (server.hasAnalysisSubscription(AnalysisService.HIGHLIGHTS, file)) {
sendAnalysisNotificationHighlights(server, file, dartUnit);
}
if (server.hasAnalysisSubscription(AnalysisService.NAVIGATION, file)) {
sendAnalysisNotificationNavigation(server, file, dartUnit);
}
if (server.hasAnalysisSubscription(AnalysisService.OUTLINE, file)) {
sendAnalysisNotificationOutline(server, file, dartUnit);
}
}
if (!source.isInSystemLibrary) {
sendAnalysisNotificationErrors(server, file, notice.errors);
}
}
}
}
void sendAnalysisNotificationErrors(AnalysisServer server,
String file, List<AnalysisError> errors) {
Notification notification = new Notification(NOTIFICATION_ERRORS);
notification.setParameter(FILE, file);
notification.setParameter(ERRORS, errors.map(errorToJson).toList());
server.sendNotification(notification);
}
void sendAnalysisNotificationHighlights(AnalysisServer server,
String file, CompilationUnit dartUnit) {
Notification notification = new Notification(NOTIFICATION_HIGHLIGHTS);
notification.setParameter(FILE, file);
notification.setParameter(
REGIONS,
new DartUnitHighlightsComputer(dartUnit).compute());
server.sendNotification(notification);
}
void sendAnalysisNotificationNavigation(AnalysisServer server,
String file, CompilationUnit dartUnit) {
Notification notification = new Notification(NOTIFICATION_NAVIGATION);
notification.setParameter(FILE, file);
notification.setParameter(
REGIONS,
new DartUnitNavigationComputer(dartUnit).compute());
server.sendNotification(notification);
}
void sendAnalysisNotificationOutline(AnalysisServer server,
String file, CompilationUnit dartUnit) {
Notification notification = new Notification(NOTIFICATION_OUTLINE);
notification.setParameter(FILE, file);
notification.setParameter(
OUTLINE,
new DartUnitOutlineComputer(dartUnit).compute());
server.sendNotification(notification);
}
Map<String, Object> errorToJson(AnalysisError analysisError) {
// TODO(paulberry): move this function into the AnalysisError class.
ErrorCode errorCode = analysisError.errorCode;
Map<String, Object> result = {
'file': analysisError.source.fullName,
// TODO(scheglov) add Enum.fullName ?
'errorCode': '${errorCode.runtimeType}.${(errorCode as Enum).name}',
'offset': analysisError.offset,
'length': analysisError.length,
'message': analysisError.message
};
if (analysisError.correction != null) {
result['correction'] = analysisError.correction;
}
return result;
}