| // Copyright (c) 2017, 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:analyzer_plugin/protocol/protocol_generated.dart'; | |
| /// An object that manages the subscriptions for analysis results. | |
| /// | |
| /// Clients may not extend, implement or mix-in this class. | |
| class SubscriptionManager { | |
| /// The current set of subscriptions. | |
| Map<AnalysisService, List<String>>? _subscriptions; | |
| /// Initialize a newly created subscription manager to have no subscriptions. | |
| SubscriptionManager(); | |
| /// Return `true` if the file with the given [filePath] has a subscription for | |
| /// the given [service]. | |
| bool hasSubscriptionForFile(String filePath, AnalysisService service) { | |
| var subscriptions = _subscriptions; | |
| if (subscriptions == null) { | |
| return false; | |
| } | |
| var files = subscriptions[service]; | |
| return files != null && files.contains(filePath); | |
| } | |
| /// Return a list of the services for which the file with the given [filePath] | |
| /// has been subscribed. | |
| List<AnalysisService> servicesForFile(String filePath) { | |
| var services = <AnalysisService>[]; | |
| var subscriptions = _subscriptions; | |
| if (subscriptions != null) { | |
| subscriptions.forEach((AnalysisService service, List<String> files) { | |
| if (files.contains(filePath)) { | |
| services.add(service); | |
| } | |
| }); | |
| } | |
| return services; | |
| } | |
| /// Set the current set of subscriptions to those described by the given map | |
| /// of [subscriptions]. Return a map representing the subset of the | |
| /// subscriptions that are new. These are the subscriptions for which a | |
| /// notification should be sent. The returned map is keyed by the path of each | |
| /// file for which notifications should be send and has values representing | |
| /// the list of services that were added for that file. | |
| Map<String, List<AnalysisService>> setSubscriptions( | |
| Map<AnalysisService, List<String>> subscriptions, | |
| ) { | |
| var newSubscriptions = <String, List<AnalysisService>>{}; | |
| var currentSubscriptions = _subscriptions; | |
| if (currentSubscriptions == null) { | |
| // This is the first time subscriptions have been set, so all of the | |
| // subscriptions are new. | |
| subscriptions.forEach((AnalysisService service, List<String> paths) { | |
| for (var path in paths) { | |
| newSubscriptions | |
| .putIfAbsent(path, () => <AnalysisService>[]) | |
| .add(service); | |
| } | |
| }); | |
| } else { | |
| // The subscriptions have been changed, to we need to compute the | |
| // difference. | |
| subscriptions.forEach((AnalysisService service, List<String> paths) { | |
| var oldPaths = currentSubscriptions[service]; | |
| for (var path in paths) { | |
| if (oldPaths == null || !oldPaths.contains(path)) { | |
| newSubscriptions | |
| .putIfAbsent(path, () => <AnalysisService>[]) | |
| .add(service); | |
| } | |
| } | |
| }); | |
| } | |
| _subscriptions = subscriptions; | |
| return newSubscriptions; | |
| } | |
| } |