Skip to content
This repository was archived by the owner on Feb 25, 2025. It is now read-only.

Commit d901f73

Browse files
DanTupcommit-bot@chromium.org
authored andcommitted
[Analyzer] Add code completion for Pub package names
Change-Id: I0fa8fb1c2801e2acb2d2cf75f7efecf4f9058eeb Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/176120 Reviewed-by: Brian Wilkerson <[email protected]> Reviewed-by: Jonas Jensen <[email protected]> Commit-Queue: Brian Wilkerson <[email protected]>
1 parent dd1c3a3 commit d901f73

22 files changed

+958
-57
lines changed

pkg/analysis_server/lib/src/analysis_server.dart

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,7 @@ import 'package:analyzer/src/util/file_paths.dart' as file_paths;
5454
import 'package:analyzer_plugin/protocol/protocol_common.dart' hide Element;
5555
import 'package:analyzer_plugin/src/utilities/navigation/navigation.dart';
5656
import 'package:analyzer_plugin/utilities/navigation/navigation_dart.dart';
57+
import 'package:http/http.dart' as http;
5758
import 'package:telemetry/crash_reporting.dart';
5859
import 'package:telemetry/telemetry.dart' as telemetry;
5960
import 'package:watcher/watcher.dart';
@@ -127,6 +128,7 @@ class AnalysisServer extends AbstractAnalysisServer {
127128
DartSdkManager sdkManager,
128129
CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
129130
InstrumentationService instrumentationService, {
131+
http.Client httpClient,
130132
RequestStatisticsHelper requestStatistics,
131133
DiagnosticServer diagnosticServer,
132134
this.detachableFileSystemManager,
@@ -137,6 +139,7 @@ class AnalysisServer extends AbstractAnalysisServer {
137139
crashReportingAttachmentsBuilder,
138140
baseResourceProvider,
139141
instrumentationService,
142+
httpClient,
140143
NotificationManager(channel, baseResourceProvider.pathContext),
141144
requestStatistics: requestStatistics,
142145
) {
@@ -421,6 +424,14 @@ class AnalysisServer extends AbstractAnalysisServer {
421424

422425
/// Set the priority files to the given [files].
423426
void setPriorityFiles(String requestId, List<String> files) {
427+
bool isPubspec(String filePath) =>
428+
file_paths.isPubspecYaml(resourceProvider.pathContext, filePath);
429+
430+
// When a pubspec is opened, trigger package name caching for completion.
431+
if (!pubPackageService.isRunning && files.any(isPubspec)) {
432+
pubPackageService.beginPackageNamePreload();
433+
}
434+
424435
priorityFiles.clear();
425436
priorityFiles.addAll(files);
426437
// Set priority files in drivers.
@@ -429,7 +440,12 @@ class AnalysisServer extends AbstractAnalysisServer {
429440
});
430441
}
431442

443+
@override
432444
Future<void> shutdown() {
445+
super.shutdown();
446+
447+
pubApi.close();
448+
433449
if (options.analytics != null) {
434450
options.analytics
435451
.waitForLastPing(timeout: Duration(milliseconds: 200))

pkg/analysis_server/lib/src/analysis_server_abstract.dart

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44

55
import 'dart:core';
66
import 'dart:io' as io;
7+
import 'dart:io';
78

89
import 'package:analysis_server/src/analysis_server.dart';
910
import 'package:analysis_server/src/collections.dart';
@@ -15,6 +16,8 @@ import 'package:analysis_server/src/plugin/plugin_watcher.dart';
1516
import 'package:analysis_server/src/server/crash_reporting_attachments.dart';
1617
import 'package:analysis_server/src/server/diagnostic_server.dart';
1718
import 'package:analysis_server/src/services/correction/namespace.dart';
19+
import 'package:analysis_server/src/services/pub/pub_api.dart';
20+
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
1821
import 'package:analysis_server/src/services/search/element_visitors.dart';
1922
import 'package:analysis_server/src/services/search/search_engine.dart';
2023
import 'package:analysis_server/src/services/search/search_engine_internal.dart';
@@ -42,6 +45,8 @@ import 'package:analyzer/src/dartdoc/dartdoc_directive_info.dart';
4245
import 'package:analyzer/src/generated/sdk.dart';
4346
import 'package:analyzer/src/services/available_declarations.dart';
4447
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
48+
import 'package:http/http.dart' as http;
49+
import 'package:meta/meta.dart';
4550

4651
/// Implementations of [AbstractAnalysisServer] implement a server that listens
4752
/// on a [CommunicationChannel] for analysis messages and process them.
@@ -93,6 +98,12 @@ abstract class AbstractAnalysisServer {
9398
/// or `null` if the initial analysis is not yet complete
9499
ServerPerformance performanceAfterStartup;
95100

101+
/// A client for making requests to the pub.dev API.
102+
final PubApi pubApi;
103+
104+
/// A service for fetching pub.dev package details.
105+
PubPackageService pubPackageService;
106+
96107
/// The class into which performance information is currently being recorded.
97108
/// During startup, this will be the same as [performanceDuringStartup]
98109
/// and after startup is complete, this switches to [performanceAfterStartup].
@@ -126,9 +137,14 @@ abstract class AbstractAnalysisServer {
126137
this.crashReportingAttachmentsBuilder,
127138
ResourceProvider baseResourceProvider,
128139
this.instrumentationService,
140+
http.Client httpClient,
129141
this.notificationManager, {
130142
this.requestStatistics,
131-
}) : resourceProvider = OverlayResourceProvider(baseResourceProvider) {
143+
}) : resourceProvider = OverlayResourceProvider(baseResourceProvider),
144+
pubApi = PubApi(instrumentationService, httpClient,
145+
Platform.environment['PUB_HOSTED_URL']) {
146+
pubPackageService =
147+
PubPackageService(instrumentationService, baseResourceProvider, pubApi);
132148
performance = performanceDuringStartup;
133149

134150
pluginManager = PluginManager(
@@ -398,6 +414,11 @@ abstract class AbstractAnalysisServer {
398414
bool fatal = false,
399415
});
400416

417+
@mustCallSuper
418+
void shutdown() {
419+
pubPackageService.shutdown();
420+
}
421+
401422
/// Return the path to the location of the byte store on disk, or `null` if
402423
/// there is no on-disk byte store.
403424
String _getByteStorePath() {

pkg/analysis_server/lib/src/domain_completion.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ class CompletionDomainHandler extends AbstractRequestHandler {
163163
var generator = FixDataGenerator(provider);
164164
return generator.getSuggestions(file, offset);
165165
} else if (file_paths.isPubspecYaml(pathContext, file)) {
166-
var generator = PubspecGenerator(provider);
166+
var generator = PubspecGenerator(provider, server.pubPackageService);
167167
return generator.getSuggestions(file, offset);
168168
}
169169
return const YamlCompletionResults.empty();

pkg/analysis_server/lib/src/lsp/handlers/handler_completion.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,8 @@ class CompletionHandler
115115
} else if (file_paths.isFixDataYaml(pathContext, path.result)) {
116116
generator = FixDataGenerator(server.resourceProvider);
117117
} else if (file_paths.isPubspecYaml(pathContext, path.result)) {
118-
generator = PubspecGenerator(server.resourceProvider);
118+
generator = PubspecGenerator(
119+
server.resourceProvider, server.pubPackageService);
119120
}
120121
if (generator != null) {
121122
serverResultsFuture = _getServerYamlItems(

pkg/analysis_server/lib/src/lsp/lsp_analysis_server.dart

Lines changed: 19 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -43,10 +43,11 @@ import 'package:analyzer/source/line_info.dart';
4343
import 'package:analyzer/src/dart/analysis/driver.dart' as nd;
4444
import 'package:analyzer/src/dart/analysis/status.dart' as nd;
4545
import 'package:analyzer/src/generated/sdk.dart';
46+
import 'package:analyzer/src/util/file_paths.dart' as file_paths;
4647
import 'package:analyzer_plugin/protocol/protocol_common.dart' as plugin;
4748
import 'package:analyzer_plugin/protocol/protocol_generated.dart' as plugin;
4849
import 'package:analyzer_plugin/src/protocol/protocol_internal.dart' as plugin;
49-
import 'package:path/path.dart';
50+
import 'package:http/http.dart' as http;
5051
import 'package:watcher/watcher.dart';
5152

5253
/// Instances of the class [LspAnalysisServer] implement an LSP-based server
@@ -134,6 +135,7 @@ class LspAnalysisServer extends AbstractAnalysisServer {
134135
DartSdkManager sdkManager,
135136
CrashReportingAttachmentsBuilder crashReportingAttachmentsBuilder,
136137
InstrumentationService instrumentationService, {
138+
http.Client httpClient,
137139
DiagnosticServer diagnosticServer,
138140
}) : super(
139141
options,
@@ -142,6 +144,7 @@ class LspAnalysisServer extends AbstractAnalysisServer {
142144
crashReportingAttachmentsBuilder,
143145
baseResourceProvider,
144146
instrumentationService,
147+
httpClient,
145148
LspNotificationManager(channel, baseResourceProvider.pathContext),
146149
) {
147150
notificationManager.server = this;
@@ -185,8 +188,14 @@ class LspAnalysisServer extends AbstractAnalysisServer {
185188
RefactoringWorkspace get refactoringWorkspace => _refactoringWorkspace ??=
186189
RefactoringWorkspace(driverMap.values, searchEngine);
187190

188-
void addPriorityFile(String path) {
189-
final didAdd = priorityFiles.add(path);
191+
void addPriorityFile(String filePath) {
192+
// When a pubspec is opened, trigger package name caching for completion.
193+
if (!pubPackageService.isRunning &&
194+
file_paths.isPubspecYaml(resourceProvider.pathContext, filePath)) {
195+
pubPackageService.beginPackageNamePreload();
196+
}
197+
198+
final didAdd = priorityFiles.add(filePath);
190199
assert(didAdd);
191200
if (didAdd) {
192201
_updateDriversAndPluginsPriorityFiles();
@@ -616,7 +625,10 @@ class LspAnalysisServer extends AbstractAnalysisServer {
616625
return MessageActionItem.fromJson(response.result);
617626
}
618627

628+
@override
619629
Future<void> shutdown() {
630+
super.shutdown();
631+
620632
// Defer closing the channel so that the shutdown response can be sent and
621633
// logged.
622634
Future(() {
@@ -664,13 +676,15 @@ class LspAnalysisServer extends AbstractAnalysisServer {
664676
..addAll(_temporaryAnalysisRoots.values);
665677

666678
final excludedPaths = clientConfiguration.analysisExcludedFolders
667-
.expand((excludePath) => isAbsolute(excludePath)
679+
.expand((excludePath) => resourceProvider.pathContext
680+
.isAbsolute(excludePath)
668681
? [excludePath]
669682
// Apply the relative path to each open workspace folder.
670683
// TODO(dantup): Consider supporting per-workspace config by
671684
// calling workspace/configuration whenever workspace folders change
672685
// and caching the config for each one.
673-
: _explicitAnalysisRoots.map((root) => join(root, excludePath)))
686+
: _explicitAnalysisRoots.map(
687+
(root) => resourceProvider.pathContext.join(root, excludePath)))
674688
.toSet();
675689

676690
// If the roots didn't actually change from the last time they were set

pkg/analysis_server/lib/src/lsp/mapping.dart

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -308,12 +308,10 @@ lsp.CompletionItem declarationToCompletionItem(
308308
return lsp.CompletionItem(
309309
label: label,
310310
kind: completionKind,
311-
tags: supportedTags.isNotEmpty
312-
? [
313-
if (supportsDeprecatedTag && declaration.isDeprecated)
314-
lsp.CompletionItemTag.Deprecated
315-
]
316-
: null,
311+
tags: nullIfEmpty([
312+
if (supportsDeprecatedTag && declaration.isDeprecated)
313+
lsp.CompletionItemTag.Deprecated
314+
]),
317315
commitCharacters:
318316
includeCommitCharacters ? lsp.dartCompletionCommitCharacters : null,
319317
detail: getDeclarationCompletionDetail(declaration, completionKind,
@@ -631,6 +629,8 @@ lsp.LocationLink navigationTargetToLocationLink(
631629
);
632630
}
633631

632+
List<T> nullIfEmpty<T>(List<T> items) => items.isEmpty ? null : items;
633+
634634
/// Returns the file system path for a TextDocumentIdentifier.
635635
ErrorOr<String> pathOfDoc(lsp.TextDocumentIdentifier doc) =>
636636
pathOfUri(Uri.tryParse(doc?.uri));
@@ -782,6 +782,8 @@ lsp.CompletionItemKind suggestionKindToCompletionItemKind(
782782
return const [lsp.CompletionItemKind.Variable];
783783
case server.CompletionSuggestionKind.PARAMETER:
784784
return const [lsp.CompletionItemKind.Value];
785+
case server.CompletionSuggestionKind.PACKAGE_NAME:
786+
return const [lsp.CompletionItemKind.Module];
785787
default:
786788
return const [];
787789
}
@@ -894,12 +896,10 @@ lsp.CompletionItem toCompletionItem(
894896
return lsp.CompletionItem(
895897
label: label,
896898
kind: completionKind,
897-
tags: supportedTags.isNotEmpty
898-
? [
899-
if (supportsDeprecatedTag && suggestion.isDeprecated)
900-
lsp.CompletionItemTag.Deprecated
901-
]
902-
: null,
899+
tags: nullIfEmpty([
900+
if (supportsDeprecatedTag && suggestion.isDeprecated)
901+
lsp.CompletionItemTag.Deprecated
902+
]),
903903
commitCharacters:
904904
includeCommitCharacters ? dartCompletionCommitCharacters : null,
905905
data: resolutionData,

pkg/analysis_server/lib/src/services/completion/yaml/analysis_options_generator.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -47,7 +47,7 @@ class AnalysisOptionsGenerator extends YamlCompletionGenerator {
4747
/// Initialize a newly created suggestion generator for analysis options
4848
/// files.
4949
AnalysisOptionsGenerator(ResourceProvider resourceProvider)
50-
: super(resourceProvider);
50+
: super(resourceProvider, null);
5151

5252
@override
5353
Producer get topLevelProducer => analysisOptionsProducer;

pkg/analysis_server/lib/src/services/completion/yaml/fix_data_generator.dart

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,8 @@ class FixDataGenerator extends YamlCompletionGenerator {
7272
}));
7373

7474
/// Initialize a newly created suggestion generator for fix data files.
75-
FixDataGenerator(ResourceProvider resourceProvider) : super(resourceProvider);
75+
FixDataGenerator(ResourceProvider resourceProvider)
76+
: super(resourceProvider, null);
7677

7778
@override
7879
Producer get topLevelProducer => fixDataProducer;

pkg/analysis_server/lib/src/services/completion/yaml/producer.dart

Lines changed: 12 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
// BSD-style license that can be found in the LICENSE file.
44

55
import 'package:analysis_server/src/protocol_server.dart';
6+
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
67
import 'package:analyzer/file_system/file_system.dart';
78
import 'package:meta/meta.dart';
89
import 'package:path/path.dart' as path;
@@ -179,6 +180,12 @@ abstract class Producer {
179180
CompletionSuggestion(CompletionSuggestionKind.IDENTIFIER, relevance,
180181
identifier, identifier.length, 0, false, false);
181182

183+
/// A utility method used to create a suggestion for the package [packageName].
184+
CompletionSuggestion packageName(String packageName,
185+
{int relevance = 1000}) =>
186+
CompletionSuggestion(CompletionSuggestionKind.PACKAGE_NAME, relevance,
187+
packageName, packageName.length, 0, false, false);
188+
182189
/// Return the completion suggestions appropriate to this location.
183190
Iterable<CompletionSuggestion> suggestions(YamlCompletionRequest request);
184191
}
@@ -188,6 +195,9 @@ class YamlCompletionRequest {
188195
/// The resource provider used to access the file system.
189196
final ResourceProvider resourceProvider;
190197

198+
/// The Pub package service used for looking up package names/versions.
199+
final PubPackageService pubPackageService;
200+
191201
/// The absolute path of the file in which completions are being requested.
192202
final String filePath;
193203

@@ -198,5 +208,6 @@ class YamlCompletionRequest {
198208
YamlCompletionRequest(
199209
{@required this.filePath,
200210
@required this.precedingText,
201-
@required this.resourceProvider});
211+
@required this.resourceProvider,
212+
@required this.pubPackageService});
202213
}

pkg/analysis_server/lib/src/services/completion/yaml/pubspec_generator.dart

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,26 @@
22
// for details. All rights reserved. Use of this source code is governed by a
33
// BSD-style license that can be found in the LICENSE file.
44

5+
import 'package:analysis_server/src/protocol_server.dart';
56
import 'package:analysis_server/src/services/completion/yaml/producer.dart';
67
import 'package:analysis_server/src/services/completion/yaml/yaml_completion_generator.dart';
8+
import 'package:analysis_server/src/services/pub/pub_package_service.dart';
79
import 'package:analyzer/file_system/file_system.dart';
810

11+
/// An object that represents the location of a package name.
12+
class PubPackageNameProducer extends Producer {
13+
const PubPackageNameProducer();
14+
15+
@override
16+
Iterable<CompletionSuggestion> suggestions(
17+
YamlCompletionRequest request) sync* {
18+
final cachedPackages = request.pubPackageService.cachedPackages;
19+
var relevance = cachedPackages.length;
20+
yield* cachedPackages.map((package) =>
21+
packageName('${package.packageName}: ', relevance: relevance--));
22+
}
23+
}
24+
925
/// A completion generator that can produce completion suggestions for pubspec
1026
/// files.
1127
class PubspecGenerator extends YamlCompletionGenerator {
@@ -24,8 +40,8 @@ class PubspecGenerator extends YamlCompletionGenerator {
2440
'flutter': EmptyProducer(),
2541
'sdk': EmptyProducer(),
2642
}),
27-
'dependencies': EmptyProducer(),
28-
'dev_dependencies': EmptyProducer(),
43+
'dependencies': PubPackageNameProducer(),
44+
'dev_dependencies': PubPackageNameProducer(),
2945
// TODO(brianwilkerson) Suggest names already listed under 'dependencies'
3046
// and 'dev_dependencies'.
3147
'dependency_overrides': EmptyProducer(),
@@ -78,7 +94,9 @@ class PubspecGenerator extends YamlCompletionGenerator {
7894
});
7995

8096
/// Initialize a newly created suggestion generator for pubspec files.
81-
PubspecGenerator(ResourceProvider resourceProvider) : super(resourceProvider);
97+
PubspecGenerator(
98+
ResourceProvider resourceProvider, PubPackageService pubPackageService)
99+
: super(resourceProvider, pubPackageService);
82100

83101
@override
84102
Producer get topLevelProducer => pubspecProducer;

0 commit comments

Comments
 (0)