blob: 1d21baccb3e71482d8fcbe1e40e3d3cf0a89ffd6 [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.
import 'package:analysis_server/src/computer/computer_closing_labels.dart';
import 'package:analysis_server/src/computer/computer_folding.dart';
import 'package:analysis_server/src/computer/computer_outline.dart';
import 'package:analysis_server/src/computer/computer_overrides.dart';
import 'package:analysis_server/src/domains/analysis/implemented_dart.dart';
import 'package:analysis_server/src/legacy_analysis_server.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/exception/exception.dart';
import 'package:analyzer/source/line_info.dart';
import 'package:collection/collection.dart';
Future<void> scheduleImplementedNotification(
LegacyAnalysisServer server,
Iterable<String> files,
) async {
var searchEngine = server.searchEngine;
for (var file in files) {
var unit = server.getCachedResolvedUnit(file)?.unit;
var unitElement = unit?.declaredFragment;
if (unitElement != null) {
try {
var computer = ImplementedComputer(searchEngine, unitElement);
await computer.compute();
var params = protocol.AnalysisImplementedParams(
file,
computer.classes,
computer.members,
);
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
} catch (exception, stackTrace) {
server.instrumentationService.logException(
CaughtException.withMessage(
'Failed to send analysis.implemented notification.',
exception,
stackTrace,
),
);
}
}
}
}
void sendAnalysisNotificationAnalyzedFiles(LegacyAnalysisServer server) {
_sendNotification(server, () {
var analyzedFiles =
server.driverMap.values
.map((driver) => driver.knownFiles)
.flattenedToList
.map((file) => file.path)
.toSet();
// Exclude *.yaml files because IDEA Dart plugin attempts to index
// all the files in folders which contain analyzed files.
analyzedFiles.removeWhere((file) => file.endsWith('.yaml'));
var prevAnalyzedFiles = server.prevAnalyzedFiles;
if (prevAnalyzedFiles != null &&
prevAnalyzedFiles.length == analyzedFiles.length &&
prevAnalyzedFiles.difference(analyzedFiles).isEmpty) {
// No change to the set of analyzed files. No need to send another
// notification.
return;
}
server.prevAnalyzedFiles = analyzedFiles;
var params = protocol.AnalysisAnalyzedFilesParams(analyzedFiles.toList());
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
});
}
void sendAnalysisNotificationClosingLabels(
LegacyAnalysisServer server,
String file,
LineInfo lineInfo,
CompilationUnit dartUnit,
) {
_sendNotification(server, () {
var labels = DartUnitClosingLabelsComputer(lineInfo, dartUnit).compute();
var params = protocol.AnalysisClosingLabelsParams(file, labels);
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
});
}
void sendAnalysisNotificationFlushResults(
LegacyAnalysisServer server,
List<String> files,
) {
_sendNotification(server, () {
if (files.isNotEmpty) {
var params = protocol.AnalysisFlushResultsParams(files);
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
}
});
}
void sendAnalysisNotificationFolding(
LegacyAnalysisServer server,
String file,
LineInfo lineInfo,
CompilationUnit dartUnit,
) {
_sendNotification(server, () {
var regions = DartUnitFoldingComputer(lineInfo, dartUnit).compute();
var params = protocol.AnalysisFoldingParams(file, regions);
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
});
}
void sendAnalysisNotificationOutline(
LegacyAnalysisServer server,
ResolvedUnitResult resolvedUnit,
) {
_sendNotification(server, () {
protocol.FileKind fileKind;
var unit = resolvedUnit.unit;
if (unit.directives.any((d) => d is PartOfDirective)) {
fileKind = protocol.FileKind.PART;
} else {
fileKind = protocol.FileKind.LIBRARY;
}
// compute library name
var libraryName = _computeLibraryName(unit);
// compute Outline
var outline =
DartUnitOutlineComputer(resolvedUnit, withBasicFlutter: true).compute();
// send notification
var params = protocol.AnalysisOutlineParams(
resolvedUnit.path,
fileKind,
outline,
libraryName: libraryName,
);
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
});
}
void sendAnalysisNotificationOverrides(
LegacyAnalysisServer server,
String file,
CompilationUnit dartUnit,
) {
_sendNotification(server, () {
var overrides = DartUnitOverridesComputer(dartUnit).compute();
var params = protocol.AnalysisOverridesParams(file, overrides);
server.sendNotification(
params.toNotification(clientUriConverter: server.uriConverter),
);
});
}
String? _computeLibraryName(CompilationUnit unit) {
for (var directive in unit.directives) {
if (directive is LibraryDirective) {
return directive.name2?.name;
}
}
for (var directive in unit.directives) {
if (directive is PartOfDirective) {
var libraryName = directive.libraryName;
if (libraryName != null) {
return libraryName.name;
}
}
}
return null;
}
/// Runs the given notification producing function [f], catching exceptions.
void _sendNotification(LegacyAnalysisServer server, Function() f) {
try {
f();
} catch (exception, stackTrace) {
server.instrumentationService.logException(
CaughtException.withMessage(
'Failed to send notification',
exception,
stackTrace,
),
);
}
}