analyzer: Extract some public API from WorkspacePackage

Fixes https://github.com/dart-lang/sdk/issues/60725

Change-Id: I63e79075d6538810ddc518e96b5bb7430e55496b
Reviewed-on: https://dart-review.googlesource.com/c/sdk/+/428564
Reviewed-by: Konstantin Shcheglov <scheglov@google.com>
Commit-Queue: Samuel Rawlins <srawlins@google.com>
This commit is contained in:
Sam Rawlins
2025-05-19 16:24:19 -07:00
committed by Commit Queue
parent 55c5febc6a
commit 540efbbb5d
21 changed files with 70 additions and 46 deletions
@@ -386,7 +386,7 @@ class ContextManagerImpl implements ContextManager {
/// options file at the given [path].
void _analyzeAnalysisOptionsYaml(
AnalysisDriver driver,
WorkspacePackage? package,
WorkspacePackageImpl? package,
String path,
) {
var convertedErrors = const <protocol.AnalysisError>[];
@@ -1095,7 +1095,7 @@ class ContextsPage extends DiagnosticPageWithNav {
buf.writeln(writeOption('Workspace root', escape(workspace?.root)));
var workspaceFolder = folder.provider.getFolder(workspace!.root);
void writePackage(WorkspacePackage package) {
void writePackage(WorkspacePackageImpl package) {
buf.writeln(writeOption('Package root', escape(package.root.path)));
if (package is PubPackage) {
buf.writeln(
+7
View File
@@ -4860,6 +4860,13 @@ package:analyzer/utilities/package_config_file_builder.dart:
add (method: void Function({String? languageVersion, required String name, String packageUri, required String rootPath}))
copy (method: PackageConfigFileBuilder Function())
toContent (method: String Function({required String Function(String) toUriStr}))
package:analyzer/workspace/workspace.dart:
WorkspacePackage (class extends Object):
new (constructor: WorkspacePackage Function())
canHavePublicApi (getter: bool)
root (getter: Folder)
contains (method: bool Function(Source))
isInTestDirectory (method: bool Function(File))
dart:async:
Future (referenced)
Stream (referenced)
@@ -485,10 +485,10 @@ class FileState {
/// The [FileSource] of the file with the [uri].
final FileSource source;
/// The [WorkspacePackage] that contains this file.
/// The [WorkspacePackageImpl] that contains this file.
///
/// It might be `null` if the file is outside of the workspace.
final WorkspacePackage? workspacePackage;
final WorkspacePackageImpl? workspacePackage;
/// The [FeatureSet] for this file.
///
@@ -1553,7 +1553,7 @@ class FileSystemState {
FeatureSet _getFeatureSet(
String path,
Uri uri,
WorkspacePackage? workspacePackage,
WorkspacePackageImpl? workspacePackage,
AnalysisOptionsImpl analysisOptions,
) {
var workspacePackageExperiments = workspacePackage?.enabledExperiments;
@@ -1574,7 +1574,7 @@ class FileSystemState {
Version _getLanguageVersion(
String path,
Uri uri,
WorkspacePackage? workspacePackage,
WorkspacePackageImpl? workspacePackage,
AnalysisOptionsImpl analysisOptions,
) {
var workspaceLanguageVersion = workspacePackage?.languageVersion;
@@ -1596,7 +1596,7 @@ class FileSystemState {
OperationPerformanceImpl? performance,
}) {
FileSource uriSource = FileSource(resource, uri);
WorkspacePackage? workspacePackage = _workspace?.findPackageFor(path);
WorkspacePackageImpl? workspacePackage = _workspace?.findPackageFor(path);
AnalysisOptionsImpl analysisOptions = _getAnalysisOptions(resource);
FeatureSet featureSet = _getFeatureSet(
path,
@@ -384,7 +384,7 @@ class LibraryAnalyzer {
var definingUnit = _libraryElement.definingCompilationUnit;
var analysesToContextUnits = <FileAnalysis, LintRuleUnitContext>{};
LintRuleUnitContext? definingContextUnit;
WorkspacePackage? workspacePackage;
WorkspacePackageImpl? workspacePackage;
for (var fileAnalysis in _libraryFiles.values) {
var linterContextUnit = LintRuleUnitContext(
file: fileAnalysis.file.resource,
@@ -21,8 +21,8 @@ class AnnotationVerifier {
/// The current library.
final LibraryElement _currentLibrary;
/// The [WorkspacePackage] in which [_currentLibrary] is declared.
final WorkspacePackage? _workspacePackage;
/// The [WorkspacePackageImpl] in which [_currentLibrary] is declared.
final WorkspacePackageImpl? _workspacePackage;
/// Whether [_currentLibrary] is part of its containing package's public API.
late final bool _inPackagePublicApi =
@@ -80,8 +80,8 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
final WidgetPreviewVerifier _widgetPreviewVerifier;
/// The [WorkspacePackage] in which [_currentLibrary] is declared.
final WorkspacePackage? _workspacePackage;
/// The [WorkspacePackageImpl] in which [_currentLibrary] is declared.
final WorkspacePackageImpl? _workspacePackage;
/// True if inference failures should be reported, otherwise false.
final bool _strictInference;
@@ -98,7 +98,7 @@ class BestPracticesVerifier extends RecursiveAstVisitor<void> {
CompilationUnit unit, {
required TypeSystemImpl typeSystem,
required AnalysisOptions analysisOptions,
required WorkspacePackage? workspacePackage,
required WorkspacePackageImpl? workspacePackage,
}) : _nullType = typeProvider.nullType,
_typeSystem = typeSystem,
_strictInference = analysisOptions.strictInference,
@@ -1618,7 +1618,7 @@ class _InvalidAccessVerifier {
final ErrorReporter _errorReporter;
final LibraryElement _library;
final WorkspacePackage? _workspacePackage;
final WorkspacePackageImpl? _workspacePackage;
final bool _inTemplateSource;
final bool _inTestDirectory;
@@ -354,7 +354,7 @@ abstract class BaseDeprecatedMemberUseVerifier {
}
class DeprecatedMemberUseVerifier extends BaseDeprecatedMemberUseVerifier {
final WorkspacePackage? _workspacePackage;
final WorkspacePackageImpl? _workspacePackage;
final ErrorReporter _errorReporter;
DeprecatedMemberUseVerifier(
+1 -1
View File
@@ -16,7 +16,7 @@ import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/lint/linter_visitor.dart' show NodeLintRegistry;
import 'package:analyzer/src/lint/pub.dart';
import 'package:analyzer/src/lint/state.dart';
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:analyzer/workspace/workspace.dart';
import 'package:meta/meta.dart';
export 'package:analyzer/src/lint/linter_visitor.dart' show NodeLintRegistry;
+2 -2
View File
@@ -23,7 +23,7 @@ class BasicWorkspace extends SimpleWorkspace {
}
@override
WorkspacePackage? findPackageFor(String filePath) {
WorkspacePackageImpl? findPackageFor(String filePath) {
Folder folder = provider.getFolder(filePath);
if (provider.pathContext.isWithin(root, folder.path)) {
return theOnlyPackage;
@@ -55,7 +55,7 @@ class BasicWorkspace extends SimpleWorkspace {
/// Separate from [Packages] or package maps, this class is designed to simply
/// understand whether arbitrary file paths represent libraries declared within
/// a given package in a [BasicWorkspace].
class BasicWorkspacePackage extends WorkspacePackage {
class BasicWorkspacePackage extends WorkspacePackageImpl {
@override
final Folder root;
+1 -1
View File
@@ -586,7 +586,7 @@ class BlazeWorkspace extends Workspace
/// Separate from [Packages] or package maps, this class is designed to simply
/// understand whether arbitrary file paths represent libraries declared within
/// a given package in a [BlazeWorkspace].
class BlazeWorkspacePackage extends WorkspacePackage {
class BlazeWorkspacePackage extends WorkspacePackageImpl {
/// A prefix for any URI of a path in this package.
final String _uriPrefix;
+2 -2
View File
@@ -81,7 +81,7 @@ class GnWorkspace extends Workspace {
}
@override
WorkspacePackage? findPackageFor(String filePath) {
WorkspacePackageImpl? findPackageFor(String filePath) {
var startFolder = provider.getFolder(filePath);
for (var folder in startFolder.withAncestors) {
if (folder.path.length < root.length) {
@@ -210,7 +210,7 @@ class GnWorkspace extends Workspace {
/// Separate from [Packages] or package maps, this class is designed to simply
/// understand whether arbitrary file paths represent libraries declared within
/// a given package in a GnWorkspace.
class GnWorkspacePackage extends WorkspacePackage {
class GnWorkspacePackage extends WorkspacePackageImpl {
@override
final Folder root;
+4 -4
View File
@@ -180,7 +180,7 @@ class PackageConfigWorkspace extends SimpleWorkspace {
/// The contents of the package config file.
late final String? _packageConfigContent;
final Map<String, WorkspacePackage> _workspacePackages = {};
final Map<String, WorkspacePackageImpl> _workspacePackages = {};
factory PackageConfigWorkspace(
ResourceProvider provider, //Packages packages,
@@ -211,7 +211,7 @@ class PackageConfigWorkspace extends SimpleWorkspace {
_packageConfigContent = packageConfigFile.readAsStringSync();
}
Iterable<WorkspacePackage> get allPackages =>
Iterable<WorkspacePackageImpl> get allPackages =>
_workspacePackages.values.toSet();
@override
@@ -305,7 +305,7 @@ class PackageConfigWorkspace extends SimpleWorkspace {
/// can be for a source file or a generated file. Generated files are located
/// in the '.dart_tool/build/generated' folder of the containing package.
@override
WorkspacePackage? findPackageFor(String filePath) {
WorkspacePackageImpl? findPackageFor(String filePath) {
var pathContext = provider.pathContext;
// Must be in this workspace.
if (!pathContext.isWithin(root, filePath)) {
@@ -402,7 +402,7 @@ class PackageConfigWorkspace extends SimpleWorkspace {
/// Separate from [Packages] or package maps, this class is designed to simply
/// understand whether arbitrary file paths represent libraries declared within
/// a given package in a [PackageConfigWorkspace].
class PubPackage extends WorkspacePackage {
class PubPackage extends WorkspacePackageImpl {
static const List<String> _generatedPathParts = [
file_paths.dotDartTool,
file_paths.packageBuild,
+7 -10
View File
@@ -2,6 +2,7 @@
// 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:_fe_analyzer_shared/src/base/analyzer_public_api.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/source/source.dart';
import 'package:analyzer/src/context/packages.dart';
@@ -11,6 +12,7 @@ import 'package:analyzer/src/generated/source.dart'
import 'package:analyzer/src/summary/api_signature.dart';
import 'package:analyzer/src/summary/package_bundle_reader.dart';
import 'package:analyzer/src/workspace/blaze.dart';
import 'package:analyzer/workspace/workspace.dart';
import 'package:meta/meta.dart';
import 'package:pub_semver/pub_semver.dart';
@@ -51,7 +53,7 @@ abstract class Workspace {
/// Separate from [Packages] or package maps, this method is designed to find
/// the package, by its root, in which a library at an arbitrary path is
/// defined.
WorkspacePackage? findPackageFor(String filePath);
WorkspacePackageImpl? findPackageFor(String filePath);
}
/// Abstract superclass of classes that provide information about a package
@@ -60,9 +62,8 @@ abstract class Workspace {
/// Separate from [Packages] or package maps, this class is designed to simply
/// understand whether arbitrary file paths represent libraries declared within
/// a given package in a Workspace.
abstract class WorkspacePackage {
/// Whether this package can have public APIs, that is, the package has marker
/// files like 'pubspec.yaml' or 'BUILD'.
abstract class WorkspacePackageImpl implements WorkspacePackage {
@override
bool get canHavePublicApi => true;
/// Return the experiments enabled for all files in the package.
@@ -79,9 +80,6 @@ abstract class WorkspacePackage {
/// Return `null` if this package does not have a language version override.
Version? get languageVersion => null;
/// The root [Folder] of this package.
Folder get root;
Workspace get workspace;
/// Whether this compilation unit [source] is not within the `lib` or `bin`
@@ -94,8 +92,6 @@ abstract class WorkspacePackage {
return !(libDir.contains(cuPath) || binDir.contains(cuPath));
}
bool contains(Source source);
/// Return a file path for the location of [source].
///
/// If [source]'s URI scheme is package, it's fullName might be unusable (for
@@ -109,7 +105,7 @@ abstract class WorkspacePackage {
}
}
/// Whether [file] is in a "test" directory of this package.
@override
bool isInTestDirectory(File file) {
return false;
}
@@ -126,6 +122,7 @@ abstract class WorkspacePackage {
/// An interface for a workspace that contains a default analysis options file.
/// Classes that provide information of such a workspace should implement this
/// interface.
@AnalyzerPublicApi(message: 'public exported')
class WorkspaceWithDefaultAnalysisOptions {
/// The URI for the default analysis options file.
static const String uri = 'package:dart.analysis_options/default.yaml';
+21
View File
@@ -0,0 +1,21 @@
// Copyright (c) 2025, 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/file_system/file_system.dart';
import 'package:analyzer/source/source.dart';
abstract class WorkspacePackage {
/// Whether this package can have public APIs, that is, the package has marker
/// files like 'pubspec.yaml' or 'BUILD'.
bool get canHavePublicApi;
/// The path to the root of this package.
Folder get root;
/// Whether this package contains [source].
bool contains(Source source);
/// Whether [file] is in a "test" directory of this package.
bool isInTestDirectory(File file);
}
@@ -1136,7 +1136,7 @@ class _AnalysisContextCollectionPrinter {
final Map<AnalysisOptionsImpl, String> _analysisOptions = Map.identity();
final Map<Workspace, (int, String)> _workspaces = Map.identity();
final Map<Workspace, Map<WorkspacePackage, String>> _workspacePackages =
final Map<Workspace, Map<WorkspacePackageImpl, String>> _workspacePackages =
Map.identity();
_AnalysisContextCollectionPrinter({
@@ -1170,7 +1170,7 @@ class _AnalysisContextCollectionPrinter {
return _indexIdOfWorkspace(workspace).$2;
}
String _idOfWorkspacePackage(WorkspacePackage package) {
String _idOfWorkspacePackage(WorkspacePackageImpl package) {
var workspace = package.workspace;
var packages = _workspacePackages[workspace] ??= Map.identity();
if (packages[package] case var id?) {
@@ -1327,7 +1327,7 @@ class _AnalysisContextCollectionPrinter {
}
}
void _writeWorkspacePackage(WorkspacePackage package) {
void _writeWorkspacePackage(WorkspacePackageImpl package) {
var id = _idOfWorkspacePackage(package);
switch (package) {
case BasicWorkspacePackage():
@@ -701,7 +701,7 @@ class BlazeWorkspacePackageTest with ResourceProviderMixin {
BlazeWorkspace.find(resourceProvider, convertPath('/ws/some/code'))!;
var targetFile = newFile('/ws/some/code/lib/code.dart', '');
WorkspacePackage? package = workspace.findPackageFor(targetFile.path);
WorkspacePackageImpl? package = workspace.findPackageFor(targetFile.path);
expect(package, isNull);
}
@@ -717,7 +717,7 @@ class BlazeWorkspacePackageTest with ResourceProviderMixin {
lookForBuildFileSubstitutes: false,
)!;
WorkspacePackage? package = workspace.findPackageFor(
WorkspacePackageImpl? package = workspace.findPackageFor(
convertPath('/ws/some/code/lib/code.dart'),
);
expect(package, isNull);
@@ -582,7 +582,7 @@ class PackageConfigWorkspaceTest with ResourceProviderMixin {
@reflectiveTest
class PubPackageTest extends WorkspacePackageTest {
late final PackageConfigWorkspace myWorkspace;
late final WorkspacePackage myPackage;
late final WorkspacePackageImpl myPackage;
String get fooPackageLibPath => '$fooPackageRootPath/lib';
@@ -3,6 +3,7 @@
// BSD-style license that can be found in the LICENSE file.
import 'package:analyzer/src/workspace/workspace.dart';
import 'package:analyzer/workspace/workspace.dart';
import 'package:analyzer_testing/resource_provider_mixin.dart';
/// Utilities for tests of subclasses of [WorkspacePackage].
@@ -12,6 +13,6 @@ abstract class WorkspacePackageTest with ResourceProviderMixin {
/// Return the package containing the given [path], or `null` if there is no
/// such package in the [workspace].
WorkspacePackage? findPackage(String path) =>
WorkspacePackageImpl? findPackage(String path) =>
workspace.findPackageFor(convertPath(path));
}
+1 -2
View File
@@ -13,8 +13,7 @@ import 'package:analyzer/dart/element/visitor2.dart';
import 'package:analyzer/file_system/file_system.dart';
import 'package:analyzer/src/lint/constants.dart' // ignore: implementation_imports
show ExpressionExtension;
import 'package:analyzer/src/workspace/workspace.dart' // ignore: implementation_imports
show WorkspacePackage;
import 'package:analyzer/workspace/workspace.dart';
import 'package:path/path.dart' as path;
import 'analyzer.dart';
@@ -12,8 +12,7 @@ import 'package:analyzer/dart/element/element.dart';
import 'package:analyzer/error/error.dart';
import 'package:analyzer/src/error/deprecated_member_use_verifier.dart' // ignore: implementation_imports
show BaseDeprecatedMemberUseVerifier;
import 'package:analyzer/src/workspace/workspace.dart' // ignore: implementation_imports
show WorkspacePackage;
import 'package:analyzer/workspace/workspace.dart';
import '../analyzer.dart';