Migrate the completion metrics tool
Change-Id: I6d66ebd2d5cbb32147252927819f9d6533cb4012
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/194882
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Brian Wilkerson <brianwilkerson@google.com>
diff --git a/pkg/analysis_server/tool/code_completion/completion_metrics.dart b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
index d5b2d61..f9c0503 100644
--- a/pkg/analysis_server/tool/code_completion/completion_metrics.dart
+++ b/pkg/analysis_server/tool/code_completion/completion_metrics.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'dart:convert';
import 'dart:io' as io;
import 'dart:math' as math;
@@ -53,7 +51,6 @@
import 'package:analyzer/src/util/performance/operation_performance.dart';
import 'package:analyzer_plugin/src/utilities/completion/optype.dart';
import 'package:args/args.dart';
-import 'package:meta/meta.dart';
import 'metrics_util.dart';
import 'output_utilities.dart';
@@ -65,7 +62,7 @@
var result = parser.parse(args);
if (!validArguments(parser, result)) {
- return io.exit(1);
+ io.exit(1);
}
var options = CompletionMetricsOptions(result);
@@ -116,7 +113,7 @@
} else {
computer.printResults();
}
- return io.exit(code);
+ io.exit(code);
}
/// A [Counter] to track the performance of each of the completion strategies
@@ -203,7 +200,7 @@
}
/// Print usage information for this tool.
-void printUsage(ArgParser parser, {String error}) {
+void printUsage(ArgParser parser, {String? error}) {
if (error != null) {
print(error);
print('');
@@ -286,10 +283,10 @@
final String name;
/// The function to be executed when this metrics collector is enabled.
- final void Function() enableFunction;
+ final void Function()? enableFunction;
/// The function to be executed when this metrics collector is disabled.
- final void Function() disableFunction;
+ final void Function()? disableFunction;
final Counter completionCounter = Counter('all completions');
@@ -441,6 +438,7 @@
/// Perform any operations required in order to revert computing the kind of
/// completions represented by this metrics collector.
void disable() {
+ var disableFunction = this.disableFunction;
if (disableFunction != null) {
disableFunction();
}
@@ -449,6 +447,7 @@
/// Perform any initialization required in order to compute the kind of
/// completions represented by this metrics collector.
void enable() {
+ var enableFunction = this.enableFunction;
if (enableFunction != null) {
enableFunction();
}
@@ -497,11 +496,11 @@
/// If the completion location was requested but missing when computing the
/// [result], then record where that happened.
void _recordMissingInformation(MetricsSuggestionListener listener) {
- var location = listener?.missingCompletionLocation;
+ var location = listener.missingCompletionLocation;
if (location != null) {
missingCompletionLocations.add(location);
} else {
- location = listener?.missingCompletionLocationTable;
+ location = listener.missingCompletionLocationTable;
if (location != null) {
missingCompletionLocationTables.add(location);
}
@@ -568,10 +567,10 @@
final CompletionMetricsOptions options;
- ResolvedUnitResult _resolvedUnitResult;
+ late ResolvedUnitResult _resolvedUnitResult;
/// The int to be returned from the [computeMetrics] call.
- int resultCode;
+ int resultCode = 0;
/// A list of the metrics to be computed.
final List<CompletionMetrics> targetMetrics = [];
@@ -642,12 +641,10 @@
CompletionRequestImpl request,
MetricsSuggestionListener listener,
ExpectedCompletion expectedCompletion,
- String completionLocation,
+ String? completionLocation,
List<protocol.CompletionSuggestion> suggestions,
CompletionMetrics metrics,
int elapsedMS) {
- assert(suggestions != null);
-
var place = placementInSuggestionList(suggestions, expectedCompletion);
metrics.mrrComputer.addRank(place.rank);
@@ -658,14 +655,14 @@
var rank = place.rank;
var suggestion = suggestions[rank - 1];
var actualSuggestion =
- SuggestionData(suggestion, listener.featureMap[suggestion]);
- List<SuggestionData> topSuggestions;
- Map<int, int> precedingRelevanceCounts;
+ SuggestionData(suggestion, listener.featureMap[suggestion]!);
+ List<SuggestionData>? topSuggestions;
+ Map<int, int>? precedingRelevanceCounts;
if (options.printWorstResults) {
topSuggestions = suggestions
.sublist(0, math.min(10, suggestions.length))
.map((suggestion) =>
- SuggestionData(suggestion, listener.featureMap[suggestion]))
+ SuggestionData(suggestion, listener.featureMap[suggestion]!))
.toList();
precedingRelevanceCounts = <int, int>{};
for (var i = 0; i < rank - 1; i++) {
@@ -704,7 +701,7 @@
.count(expectedCompletion.elementKind.toString());
if (options.printMissedCompletionDetails) {
- protocol.CompletionSuggestion closeMatchSuggestion;
+ protocol.CompletionSuggestion? closeMatchSuggestion;
for (var suggestion in suggestions) {
if (suggestion.completion == expectedCompletion.completion) {
closeMatchSuggestion = suggestion;
@@ -790,14 +787,14 @@
];
}
- var groups = metrics.groupMrrComputers.keys.toList();
- groups.sort((first, second) => first.name.compareTo(second.name));
+ var entries = metrics.groupMrrComputers.entries.toList();
+ entries.sort((first, second) => first.key.name.compareTo(second.key.name));
var table = [
['', 'mrr', 'inverse mrr', 'mrr_5', 'inverse mrr_5', 'count'],
toRow(metrics.mrrComputer),
toRow(metrics.successfulMrrComputer),
['', '', '', '', '', ''],
- for (var group in groups) toRow(metrics.groupMrrComputers[group]),
+ for (var entry in entries) toRow(entry.value),
];
rightJustifyColumns(table, [2, 4, 5]);
@@ -890,7 +887,7 @@
elementKinds.sort((first, second) => first.name.compareTo(second.name));
for (var kind in elementKinds) {
table.add(toRow(
- targetMetrics.map((metrics) => metrics.groupMrrComputers[kind])));
+ targetMetrics.map((metrics) => metrics.groupMrrComputers[kind]!)));
}
if (options.printMrrByLocation) {
table.add(blankRow);
@@ -901,7 +898,7 @@
locations.sort();
for (var location in locations) {
table.add(toRow(targetMetrics
- .map((metrics) => metrics.locationMrrComputers[location])));
+ .map((metrics) => metrics.locationMrrComputers[location]!)));
}
}
rightJustifyColumns(table, range(1, table[0].length));
@@ -963,23 +960,23 @@
void printSlowestResults(CompletionMetrics metrics) {
var slowestResults = metrics.slowestResults;
- var groups = slowestResults.keys.toList();
- groups.sort((first, second) => first.name.compareTo(second.name));
+ var entries = slowestResults.entries.toList();
+ entries.sort((first, second) => first.key.name.compareTo(second.key.name));
print('');
printHeading(2, 'The slowest completion results to compute');
- for (var group in groups) {
- _printSlowestResults('In ${group.name}', slowestResults[group]);
+ for (var entry in entries) {
+ _printSlowestResults('In ${entry.key.name}', entry.value);
}
}
void printWorstResults(CompletionMetrics metrics) {
var worstResults = metrics.worstResults;
- var groups = worstResults.keys.toList();
- groups.sort((first, second) => first.name.compareTo(second.name));
+ var entries = worstResults.entries.toList();
+ entries.sort((first, second) => first.key.name.compareTo(second.key.name));
print('');
printHeading(2, 'The worst completion results');
- for (var group in groups) {
- _printWorstResults('In ${group.name}', worstResults[group]);
+ for (var entry in entries) {
+ _printWorstResults('In ${entry.key.name}', entry.value);
}
}
@@ -1006,8 +1003,8 @@
MetricsSuggestionListener listener,
OperationPerformanceImpl performance,
CompletionRequestImpl request,
- [DeclarationsTracker declarationsTracker,
- protocol.CompletionAvailableSuggestionsParams
+ [DeclarationsTracker? declarationsTracker,
+ protocol.CompletionAvailableSuggestionsParams?
availableSuggestionsParams]) async {
List<protocol.CompletionSuggestion> suggestions;
@@ -1048,25 +1045,24 @@
};
for (var availableSuggestionSet
- in availableSuggestionsParams.changedLibraries) {
+ in availableSuggestionsParams!.changedLibraries!) {
var id = availableSuggestionSet.id;
for (var availableSuggestion in availableSuggestionSet.items) {
// Exclude available suggestions where this element kind doesn't match
// an element kind in includedElementKinds.
- var elementKind = availableSuggestion.element?.kind;
- if (elementKind != null &&
- includedElementKinds.contains(elementKind)) {
+ var elementKind = availableSuggestion.element.kind;
+ if (includedElementKinds.contains(elementKind)) {
if (includedSuggestionSetMap.containsKey(id)) {
- var relevance = includedSuggestionSetMap[id].relevance;
+ var relevance = includedSuggestionSetMap[id]!.relevance;
// Search for any matching relevance tags to apply any boosts
if (includedSuggestionRelevanceTagList.isNotEmpty &&
availableSuggestion.relevanceTags != null &&
- availableSuggestion.relevanceTags.isNotEmpty) {
- for (var tag in availableSuggestion.relevanceTags) {
+ availableSuggestion.relevanceTags!.isNotEmpty) {
+ for (var tag in availableSuggestion.relevanceTags!) {
if (includedSuggestionRelevanceTagMap.containsKey(tag)) {
// apply the boost
- relevance += includedSuggestionRelevanceTagMap[tag];
+ relevance += includedSuggestionRelevanceTagMap[tag]!;
}
}
}
@@ -1097,8 +1093,8 @@
// Set the DeclarationsTracker, only call doWork to build up the available
// suggestions if doComputeCompletionsFromAnalysisServer is true.
- DeclarationsTracker declarationsTracker;
- protocol.CompletionAvailableSuggestionsParams availableSuggestionsParams;
+ DeclarationsTracker? declarationsTracker;
+ protocol.CompletionAvailableSuggestionsParams? availableSuggestionsParams;
if (options.availableSuggestions) {
declarationsTracker = DeclarationsTracker(
MemoryByteStore(), PhysicalResourceProvider.INSTANCE);
@@ -1110,11 +1106,6 @@
// Have the AvailableDeclarationsSet computed to use later.
availableSuggestionsParams = createCompletionAvailableSuggestions(
declarationsTracker.allLibraries.toList(), []);
-
- // assert that this object is not null, throw if it is.
- if (availableSuggestionsParams == null) {
- throw Exception('availableSuggestionsParam not computable.');
- }
}
// Loop through each file, resolve the file and call
@@ -1138,7 +1129,7 @@
// Use the ExpectedCompletionsVisitor to compute the set of expected
// completions for this CompilationUnit.
final visitor = ExpectedCompletionsVisitor(filePath);
- _resolvedUnitResult.unit.accept(visitor);
+ _resolvedUnitResult.unit!.accept(visitor);
for (var expectedCompletion in visitor.expectedCompletions) {
var resolvedUnitResult = _resolvedUnitResult;
@@ -1147,7 +1138,7 @@
// have the context reanalyze the file
if (options.overlay != CompletionMetricsOptions.OVERLAY_NONE) {
var overlayContents = _getOverlayContents(
- _resolvedUnitResult.content, expectedCompletion);
+ _resolvedUnitResult.content!, expectedCompletion);
_provider.setOverlay(filePath,
content: overlayContents,
@@ -1162,8 +1153,8 @@
// comparison:
Future<int> handleExpectedCompletion(
- {MetricsSuggestionListener listener,
- @required CompletionMetrics metrics}) async {
+ {required MetricsSuggestionListener listener,
+ required CompletionMetrics metrics}) async {
var stopwatch = Stopwatch()..start();
var request = CompletionRequestImpl(
resolvedUnitResult,
@@ -1172,8 +1163,8 @@
);
var directiveInfo = DartdocDirectiveInfo();
- OpType opType;
- List<protocol.CompletionSuggestion> suggestions;
+ late OpType opType;
+ late List<protocol.CompletionSuggestion> suggestions;
await request.performance.runRequestOperation(
(performance) async {
var dartRequest = await DartCompletionRequestImpl.from(
@@ -1314,10 +1305,10 @@
var actualSuggestion = result.actualSuggestion;
var expected = result.expectedCompletion;
- var topSuggestions = result.topSuggestions;
+ var topSuggestions = result.topSuggestions!;
var topSuggestionCount = topSuggestions.length;
- var preceding = result.precedingRelevanceCounts;
+ var preceding = result.precedingRelevanceCounts!;
var precedingRelevances = preceding.keys.toList();
precedingRelevances.sort();
@@ -1372,7 +1363,7 @@
/// Given some [ResolvedUnitResult] return the first error of high severity
/// if such an error exists, `null` otherwise.
- static err.AnalysisError getFirstErrorOrNull(
+ static err.AnalysisError? getFirstErrorOrNull(
ResolvedUnitResult resolvedUnitResult) {
for (var error in resolvedUnitResult.errors) {
if (error.severity == Severity.error) {
@@ -1492,14 +1483,14 @@
}
CompletionMetricsOptions._(
- {@required this.availableSuggestions,
- @required this.overlay,
- @required this.printMissedCompletionDetails,
- @required this.printMissedCompletionSummary,
- @required this.printMissingInformation,
- @required this.printMrrByLocation,
- @required this.printSlowestResults,
- @required this.printWorstResults})
+ {required this.availableSuggestions,
+ required this.overlay,
+ required this.printMissedCompletionDetails,
+ required this.printMissedCompletionSummary,
+ required this.printMissingInformation,
+ required this.printMrrByLocation,
+ required this.printSlowestResults,
+ required this.printWorstResults})
: assert(overlay == OVERLAY_NONE ||
overlay == OVERLAY_REMOVE_TOKEN ||
overlay == OVERLAY_REMOVE_REST_OF_FILE);
@@ -1509,19 +1500,19 @@
class CompletionResult {
final Place place;
- final CompletionRequestImpl request;
+ final CompletionRequestImpl? request;
final SuggestionData actualSuggestion;
- final List<SuggestionData> topSuggestions;
+ final List<SuggestionData>? topSuggestions;
final ExpectedCompletion expectedCompletion;
- final String completionLocation;
+ final String? completionLocation;
final int elapsedMS;
- final Map<int, int> precedingRelevanceCounts;
+ final Map<int, int>? precedingRelevanceCounts;
CompletionResult(
this.place,
@@ -1539,11 +1530,11 @@
var actualSuggestion = SuggestionData.fromJson(
map['actualSuggestion'] as Map<String, dynamic>);
var topSuggestions = (map['topSuggestions'] as List<dynamic>)
- ?.map((map) => SuggestionData.fromJson(map as Map<String, dynamic>))
- ?.toList();
+ .map((map) => SuggestionData.fromJson(map as Map<String, dynamic>))
+ .toList();
var precedingRelevanceCounts =
(map['precedingRelevanceCounts'] as Map<String, dynamic>)
- ?.map((key, value) => MapEntry(int.parse(key), value as int));
+ .map((key, value) => MapEntry(int.parse(key), value as int));
var expectedCompletion = ExpectedCompletion.fromJson(
map['expectedCompletion'] as Map<String, dynamic>);
var completionLocation = map['completionLocation'] as String;
@@ -1585,8 +1576,8 @@
}
if (entity is SimpleIdentifier &&
entity.parent is TypeName &&
- entity.parent.parent is ConstructorName &&
- entity.parent.parent.parent is InstanceCreationExpression) {
+ entity.parent!.parent is ConstructorName &&
+ entity.parent!.parent!.parent is InstanceCreationExpression) {
return CompletionGroup.constructorElement;
}
return CompletionGroup.classElement;
@@ -1622,9 +1613,9 @@
'actualSuggestion': actualSuggestion.toJson(),
if (topSuggestions != null)
'topSuggestions':
- topSuggestions.map((suggestion) => suggestion.toJson()).toList(),
+ topSuggestions!.map((suggestion) => suggestion.toJson()).toList(),
if (precedingRelevanceCounts != null)
- 'precedingRelevanceCounts': precedingRelevanceCounts
+ 'precedingRelevanceCounts': precedingRelevanceCounts!
.map((key, value) => MapEntry(key.toString(), value)),
'expectedCompletion': expectedCompletion.toJson(),
'completionLocation': completionLocation,
@@ -1634,13 +1625,13 @@
/// Return the element associated with the syntactic [entity], or `null` if
/// there is no such element.
- Element _getElement(SyntacticEntity entity) {
+ Element? _getElement(SyntacticEntity entity) {
if (entity is SimpleIdentifier) {
var element = entity.staticElement;
if (element != null) {
return element;
}
- AstNode node = entity;
+ AstNode? node = entity;
while (node != null) {
var parent = node.parent;
if (parent is AssignmentExpression) {
@@ -1688,11 +1679,11 @@
final double mrr_5;
LocationTableLine(
- {@required this.label,
- @required this.product,
- @required this.count,
- @required this.mrr,
- @required this.mrr_5});
+ {required this.label,
+ required this.product,
+ required this.count,
+ required this.mrr,
+ required this.mrr_5});
}
class MetricsSuggestionListener implements SuggestionListener {
@@ -1710,9 +1701,9 @@
0.0
];
- String missingCompletionLocation;
+ String? missingCompletionLocation;
- String missingCompletionLocationTable;
+ String? missingCompletionLocationTable;
@override
void builtSuggestion(protocol.CompletionSuggestion suggestion) {
@@ -1854,7 +1845,6 @@
case CompletionGroup.unknown:
return 'unknown';
}
- return '<unknown>';
}
}
diff --git a/pkg/analysis_server/tool/code_completion/visitors.dart b/pkg/analysis_server/tool/code_completion/visitors.dart
index a4abe60..5e86cd3 100644
--- a/pkg/analysis_server/tool/code_completion/visitors.dart
+++ b/pkg/analysis_server/tool/code_completion/visitors.dart
@@ -2,8 +2,6 @@
// 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.
-// @dart = 2.9
-
import 'package:analysis_server/src/protocol/protocol_internal.dart';
import 'package:analysis_server/src/protocol_server.dart' as protocol;
import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
@@ -21,15 +19,15 @@
/// Some completions are special cased from the DAS "import" for instance is
/// suggested as a completion "import '';", the completion string here in this
/// instance would have the value "import '';".
- final String _completionString;
+ final String? _completionString;
- final protocol.CompletionSuggestionKind _kind;
+ final protocol.CompletionSuggestionKind? _kind;
final int _lineNumber;
final int _columnNumber;
- final protocol.ElementKind _elementKind;
+ final protocol.ElementKind? _elementKind;
ExpectedCompletion(this._filePath, this._entity, this._lineNumber,
this._columnNumber, this._kind, this._elementKind)
@@ -74,11 +72,11 @@
String get completion => _completionString ?? _entity.toString();
- protocol.ElementKind get elementKind => _elementKind;
+ protocol.ElementKind? get elementKind => _elementKind;
String get filePath => _filePath;
- protocol.CompletionSuggestionKind get kind => _kind;
+ protocol.CompletionSuggestionKind? get kind => _kind;
int get lineNumber => _lineNumber;
@@ -90,9 +88,7 @@
bool matches(protocol.CompletionSuggestion completionSuggestion) {
if (completionSuggestion.completion == completion) {
- if (kind != null &&
- completionSuggestion.kind != null &&
- completionSuggestion.kind != kind) {
+ if (kind != null && completionSuggestion.kind != kind) {
return false;
}
if (elementKind != null &&
@@ -107,14 +103,16 @@
/// Return a map used to represent this expected completion in a JSON structure.
Map<String, dynamic> toJson() {
+ var kind = _kind;
+ var elementKind = _elementKind;
return {
'filePath': _filePath,
'offset': _entity.offset,
'lineNumber': _lineNumber,
'columnNumber': _columnNumber,
'completionString': _completionString,
- if (_kind != null) 'kind': _kind.toJson(),
- if (_elementKind != null) 'elementKind': _elementKind.toJson(),
+ if (kind != null) 'kind': kind.toJson(),
+ if (elementKind != null) 'elementKind': elementKind.toJson(),
};
}
@@ -128,7 +126,7 @@
final String filePath;
- CompilationUnit _enclosingCompilationUnit;
+ late CompilationUnit _enclosingCompilationUnit;
/// This boolean is set to enable whether or not we should assert that some
/// found keyword in Dart syntax should be in the completion set returned from
@@ -144,20 +142,19 @@
final bool _doExpectCommentRefs = false;
ExpectedCompletionsVisitor(this.filePath)
- : expectedCompletions = <ExpectedCompletion>[],
- assert(filePath != null);
+ : expectedCompletions = <ExpectedCompletion>[];
- void safelyRecordEntity(SyntacticEntity entity,
- {protocol.CompletionSuggestionKind kind,
- protocol.ElementKind elementKind}) {
+ void safelyRecordEntity(SyntacticEntity? entity,
+ {protocol.CompletionSuggestionKind? kind,
+ protocol.ElementKind? elementKind}) {
// Only record if this entity is not null, has a length, etc.
if (entity != null && entity.offset > 0 && entity.length > 0) {
// Compute the line number at this offset
- var lineNumber = _enclosingCompilationUnit.lineInfo
+ var lineNumber = _enclosingCompilationUnit.lineInfo!
.getLocation(entity.offset)
.lineNumber;
- var columnNumber = _enclosingCompilationUnit.lineInfo
+ var columnNumber = _enclosingCompilationUnit.lineInfo!
.getLocation(entity.offset)
.columnNumber;
@@ -242,7 +239,7 @@
}
}
- void safelyRecordKeywordCompletion(SyntacticEntity entity) {
+ void safelyRecordKeywordCompletion(SyntacticEntity? entity) {
if (_doExpectKeywordCompletions) {
safelyRecordEntity(entity,
kind: protocol.CompletionSuggestionKind.KEYWORD);
@@ -617,9 +614,10 @@
@override
void visitSimpleIdentifier(SimpleIdentifier node) {
if (_doIncludeSimpleIdentifier(node)) {
- protocol.ElementKind elementKind;
- if (node.staticElement?.kind != null) {
- elementKind = protocol.convertElementKind(node.staticElement.kind);
+ protocol.ElementKind? elementKind;
+ var kind = node.staticElement?.kind;
+ if (kind != null) {
+ elementKind = protocol.convertElementKind(kind);
// If the completed element kind is a getter or setter set the element
// kind to null as the exact kind from the DAS is unknown at this
@@ -651,8 +649,8 @@
// constructor invocation in which case the "Foo" above is
// considered a constructor still
if (elementKind == protocol.ElementKind.CLASS) {
- if (node.parent?.parent is ConstructorName) {
- var constructorName = node.parent.parent as ConstructorName;
+ var constructorName = node.parent?.parent;
+ if (constructorName is ConstructorName) {
var instanceCreationExpression = constructorName.parent;
if (instanceCreationExpression is InstanceCreationExpression &&
constructorName.type.name == node) {
@@ -759,12 +757,13 @@
bool _doIncludeSimpleIdentifier(SimpleIdentifier node) {
// Do not continue if this node is synthetic, or if the node is in a
// declaration context
- if (node == null || node.isSynthetic || node.inDeclarationContext()) {
+ if (node.isSynthetic || node.inDeclarationContext()) {
return false;
}
// If the type of the SimpleIdentifier is dynamic, don't include.
- if (node.staticType != null && node.staticType.isDynamic) {
+ var staticType = node.staticType;
+ if (staticType != null && staticType.isDynamic) {
return false;
}