Skip to content

Commit 804109b

Browse files
bwilkersoncommit-bot@chromium.org
authored andcommitted
Add documentation to completion metrics and clean up a bit of code
Change-Id: I612b5f5953bc0f8d94ad9976e55590097389c62e Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/210740 Reviewed-by: Konstantin Shcheglov <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent d6f4640 commit 804109b

File tree

2 files changed

+45
-22
lines changed

2 files changed

+45
-22
lines changed

pkg/analysis_server/tool/code_completion/completion_metrics.dart

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,32 @@ import 'output_utilities.dart';
5858
import 'relevance_table_generator.dart';
5959
import 'visitors.dart';
6060

61+
/// Completion metrics are computed by taking a single package and iterating
62+
/// over the compilation units in the package. For each unit we visit the AST
63+
/// structure to find all of the places where completion suggestions should be
64+
/// offered (essentially, everywhere that there's a keyword or identifier). At
65+
/// each location we compute the completion suggestions using the same code path
66+
/// used by the analysis server. We then compare the suggestions against the
67+
/// token that was actually at that location in the file.
68+
///
69+
/// This approach has several drawbacks:
70+
///
71+
/// - The AST is always complete and correct, and that's rarely the case for
72+
/// real completion requests. Usually the tree is incomplete and often has a
73+
/// completely different structure because of the way recovery works. We
74+
/// currently have no way of measuring completions under realistic conditions.
75+
///
76+
/// - We can't measure completions for several keywords because the presence of
77+
/// the keyword in the AST causes it to not be suggested.
78+
///
79+
/// - The time it takes to compute the suggestions doesn't include the time
80+
/// required to finish analyzing the file if the analysis hasn't been
81+
/// completed before suggestions are requested. While the times are accurate
82+
/// (within the accuracy of the `Stopwatch` class) they are the minimum
83+
/// possible time. This doesn't give us a measure of how completion will
84+
/// perform in production, but does give us an optimistic approximation.
85+
///
86+
/// The first is arguably the worst of the limitations of our current approach.
6187
Future<void> main(List<String> args) async {
6288
var parser = createArgParser();
6389
var result = parser.parse(args);
@@ -1318,7 +1344,7 @@ class CompletionMetricsComputer {
13181344
var filePath = result.path;
13191345
// Use the ExpectedCompletionsVisitor to compute the set of expected
13201346
// completions for this CompilationUnit.
1321-
final visitor = ExpectedCompletionsVisitor(filePath);
1347+
final visitor = ExpectedCompletionsVisitor(result);
13221348
_resolvedUnitResult.unit.accept(visitor);
13231349

13241350
for (var expectedCompletion in visitor.expectedCompletions) {

pkg/analysis_server/tool/code_completion/visitors.dart

Lines changed: 18 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,11 +5,13 @@
55
import 'package:analysis_server/src/protocol/protocol_internal.dart';
66
import 'package:analysis_server/src/protocol_server.dart' as protocol;
77
import 'package:analysis_server/src/services/completion/dart/keyword_contributor.dart';
8+
import 'package:analyzer/dart/analysis/results.dart';
89
import 'package:analyzer/dart/ast/ast.dart';
910
import 'package:analyzer/dart/ast/syntactic_entity.dart';
1011
import 'package:analyzer/dart/ast/token.dart';
1112
import 'package:analyzer/dart/ast/visitor.dart';
1213
import 'package:analyzer/dart/element/element.dart' as element;
14+
import 'package:analyzer/source/line_info.dart';
1315

1416
class ExpectedCompletion {
1517
final String _filePath;
@@ -122,11 +124,12 @@ class ExpectedCompletion {
122124
}
123125

124126
class ExpectedCompletionsVisitor extends RecursiveAstVisitor<void> {
125-
final List<ExpectedCompletion> expectedCompletions;
127+
/// The result of resolving the file being visited.
128+
final ResolvedUnitResult result;
126129

127-
final String filePath;
128-
129-
late CompilationUnit _enclosingCompilationUnit;
130+
/// The completions that are expected to be produced in the file being
131+
/// visited.
132+
final List<ExpectedCompletion> expectedCompletions = [];
130133

131134
/// This boolean is set to enable whether or not we should assert that some
132135
/// found keyword in Dart syntax should be in the completion set returned from
@@ -141,22 +144,22 @@ class ExpectedCompletionsVisitor extends RecursiveAstVisitor<void> {
141144
/// comment don't yield an error like Dart syntax mistakes would yield.
142145
final bool _doExpectCommentRefs = false;
143146

144-
ExpectedCompletionsVisitor(this.filePath)
145-
: expectedCompletions = <ExpectedCompletion>[];
147+
ExpectedCompletionsVisitor(this.result);
148+
149+
/// Return the path of the file that is being visited.
150+
String get filePath => result.path;
151+
152+
/// Return the line info for the file that is being visited.
153+
LineInfo get lineInfo => result.lineInfo;
146154

147155
void safelyRecordEntity(SyntacticEntity? entity,
148156
{protocol.CompletionSuggestionKind? kind,
149157
protocol.ElementKind? elementKind}) {
150158
// Only record if this entity is not null, has a length, etc.
151-
if (entity != null && entity.offset > 0 && entity.length > 0) {
152-
// Compute the line number at this offset
153-
var lineNumber = _enclosingCompilationUnit.lineInfo!
154-
.getLocation(entity.offset)
155-
.lineNumber;
156-
157-
var columnNumber = _enclosingCompilationUnit.lineInfo!
158-
.getLocation(entity.offset)
159-
.columnNumber;
159+
if (entity != null && entity.offset >= 0 && entity.length > 0) {
160+
var location = lineInfo.getLocation(entity.offset);
161+
var lineNumber = location.lineNumber;
162+
var columnNumber = location.columnNumber;
160163

161164
bool isKeyword() => kind == protocol.CompletionSuggestionKind.KEYWORD;
162165

@@ -314,12 +317,6 @@ class ExpectedCompletionsVisitor extends RecursiveAstVisitor<void> {
314317
super.visitClassTypeAlias(node);
315318
}
316319

317-
@override
318-
void visitCompilationUnit(CompilationUnit node) {
319-
_enclosingCompilationUnit = node;
320-
super.visitCompilationUnit(node);
321-
}
322-
323320
@override
324321
void visitConfiguration(Configuration node) {
325322
safelyRecordKeywordCompletion(node.ifKeyword);

0 commit comments

Comments
 (0)