Use time budget in NotImportedContributor.

Change-Id: Ief0ef8185accd68c7b99132393fa0a4db6be31c4
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/218380
Reviewed-by: Brian Wilkerson <brianwilkerson@google.com>
Commit-Queue: Konstantin Shcheglov <scheglov@google.com>
This commit is contained in:
Konstantin Shcheglov 2021-10-28 17:37:18 +00:00 committed by commit-bot@chromium.org
parent e153f412cb
commit 294aaab9c1
9 changed files with 67 additions and 7 deletions

View file

@ -85,6 +85,9 @@ class CiderCompletionComputer {
<IncludedSuggestionRelevanceTag>[];
var manager = DartCompletionManager(
budget: CompletionBudget(
const Duration(milliseconds: 100),
),
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,

View file

@ -34,7 +34,7 @@ import 'package:analyzer_plugin/utilities/change_builder/change_builder_core.dar
/// [RequestHandler] that handles requests in the completion domain.
class CompletionDomainHandler extends AbstractRequestHandler {
/// The time budget for a completion request.
static const Duration _budgetDuration = Duration(milliseconds: 100);
static Duration budgetDuration = Duration(milliseconds: 100);
/// The maximum number of performance measurements to keep.
static const int performanceListMaxLength = 50;
@ -90,6 +90,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
var suggestions = <CompletionSuggestion>[];
await performance.runAsync('computeSuggestions', (performance) async {
var manager = DartCompletionManager(
budget: budget,
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,
@ -213,7 +214,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
/// Implement the 'completion.getSuggestions2' request.
void getSuggestions2(Request request) async {
var budget = CompletionBudget(_budgetDuration);
var budget = CompletionBudget(budgetDuration);
var params = CompletionGetSuggestions2Params.fromRequest(request);
var file = params.file;
@ -337,7 +338,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
/// Process a `completion.getSuggestions` request.
Future<void> processRequest(Request request) async {
var budget = CompletionBudget(_budgetDuration);
var budget = CompletionBudget(budgetDuration);
final performance = this.performance = CompletionPerformance();

View file

@ -74,7 +74,11 @@ class RuntimeCompletionComputer {
offset: targetOffset,
);
var suggestions = await DartCompletionManager().computeSuggestions(
var suggestions = await DartCompletionManager(
budget: CompletionBudget(
const Duration(milliseconds: 100),
),
).computeSuggestions(
dartRequest,
OperationPerformanceImpl('<root>'),
);

View file

@ -233,6 +233,9 @@ class CompletionHandler
try {
var contributor = DartCompletionManager(
budget: CompletionBudget(
const Duration(milliseconds: 100),
),
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTags,

View file

@ -52,6 +52,10 @@ class CompletionBudget {
CompletionBudget(this._budget);
bool get isEmpty {
return _timer.elapsed > _budget;
}
Duration get left {
var result = _budget - _timer.elapsed;
return result.isNegative ? Duration.zero : result;
@ -61,6 +65,9 @@ class CompletionBudget {
/// [DartCompletionManager] determines if a completion request is Dart specific
/// and forwards those requests to all [DartCompletionContributor]s.
class DartCompletionManager {
/// Time budget to computing suggestions.
final CompletionBudget budget;
/// If not `null`, then instead of using [ImportedReferenceContributor],
/// fill this set with kinds of elements that are applicable at the
/// completion location, so should be suggested from available suggestion
@ -91,6 +98,7 @@ class DartCompletionManager {
/// [includedSuggestionRelevanceTags] must either all be `null` or must all be
/// non-`null`.
DartCompletionManager({
required this.budget,
this.includedElementKinds,
this.includedElementNames,
this.includedSuggestionRelevanceTags,
@ -156,7 +164,7 @@ class DartCompletionManager {
final librariesToImport = this.librariesToImport;
if (librariesToImport != null) {
contributors.add(
NotImportedContributor(request, builder, librariesToImport),
NotImportedContributor(request, builder, budget, librariesToImport),
);
}

View file

@ -2,6 +2,8 @@
// 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 'package:analysis_server/src/provisional/completion/dart/completion_dart.dart';
import 'package:analysis_server/src/services/completion/dart/completion_manager.dart';
import 'package:analysis_server/src/services/completion/dart/local_library_contributor.dart';
@ -17,11 +19,13 @@ import 'package:collection/collection.dart';
/// A contributor of suggestions from not yet imported libraries.
class NotImportedContributor extends DartCompletionContributor {
final CompletionBudget budget;
final List<Uri> librariesToImport;
NotImportedContributor(
DartCompletionRequest request,
SuggestionBuilder builder,
this.budget,
this.librariesToImport,
) : super(request, builder);
@ -37,10 +41,18 @@ class NotImportedContributor extends DartCompletionContributor {
var fsState = analysisDriver.fsState;
var filter = _buildFilter(fsState);
await analysisDriver.discoverAvailableFiles();
try {
await analysisDriver.discoverAvailableFiles().timeout(budget.left);
} on TimeoutException {
return;
}
var knownFiles = fsState.knownFiles.toList();
for (var file in knownFiles) {
if (budget.isEmpty) {
return;
}
if (!filter.shouldInclude(file)) {
continue;
}

View file

@ -73,6 +73,7 @@ class CompletionDomainHandlerGetSuggestions2Test with ResourceProviderMixin {
}
void setUp() {
CompletionDomainHandler.budgetDuration = const Duration(seconds: 30);
serverChannel = MockServerChannel();
var sdkRoot = newFolder('/sdk');
@ -93,6 +94,29 @@ class CompletionDomainHandlerGetSuggestions2Test with ResourceProviderMixin {
);
}
Future<void> test_notImported_emptyBudget() async {
await _configureWithWorkspaceRoot();
// Empty budget, so no not yet imported libraries.
CompletionDomainHandler.budgetDuration = const Duration(milliseconds: 0);
var responseValidator = await _getTestCodeSuggestions('''
void f() {
Rand^
}
''');
responseValidator
..assertComplete()
..assertReplacementBack(4)
..assertLibrariesToImport(includes: [], excludes: [
'dart:core',
'dart:math',
]);
responseValidator.suggestions.withElementClass().assertEmpty();
}
Future<void> test_notImported_pub_dependencies_inLib() async {
// TODO(scheglov) Switch to PubspecYamlFileConfig
newPubspecYamlFile(testPackageRootPath, r'''

View file

@ -57,7 +57,9 @@ class CompletionRunner {
var collection = AnalysisContextCollection(
includedPaths: <String>[analysisRoot],
resourceProvider: resourceProvider);
var contributor = DartCompletionManager();
var contributor = DartCompletionManager(
budget: CompletionBudget(const Duration(seconds: 30)),
);
var statistics = CompletionPerformance();
var stamp = 1;

View file

@ -1205,9 +1205,11 @@ class CompletionMetricsComputer {
availableSuggestionsParams]) async {
List<protocol.CompletionSuggestion> suggestions;
const budgetDuration = Duration(seconds: 30);
if (declarationsTracker == null) {
// available suggestions == false
suggestions = await DartCompletionManager(
budget: CompletionBudget(budgetDuration),
listener: listener,
).computeSuggestions(dartRequest, performance);
} else {
@ -1218,6 +1220,7 @@ class CompletionMetricsComputer {
<protocol.IncludedSuggestionRelevanceTag>[];
var includedSuggestionSetList = <protocol.IncludedSuggestionSet>[];
suggestions = await DartCompletionManager(
budget: CompletionBudget(budgetDuration),
includedElementKinds: includedElementKinds,
includedElementNames: includedElementNames,
includedSuggestionRelevanceTags: includedSuggestionRelevanceTagList,