diff --git a/pkg/analysis_server/lib/src/context_manager.dart b/pkg/analysis_server/lib/src/context_manager.dart index 76df52c82e5..c334a5c6df5 100644 --- a/pkg/analysis_server/lib/src/context_manager.dart +++ b/pkg/analysis_server/lib/src/context_manager.dart @@ -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 []; diff --git a/pkg/analysis_server/lib/src/status/diagnostics.dart b/pkg/analysis_server/lib/src/status/diagnostics.dart index 639b6c063ae..9999c6a27c6 100644 --- a/pkg/analysis_server/lib/src/status/diagnostics.dart +++ b/pkg/analysis_server/lib/src/status/diagnostics.dart @@ -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( diff --git a/pkg/analyzer/api.txt b/pkg/analyzer/api.txt index 0d69630e425..88cf523bf1d 100644 --- a/pkg/analyzer/api.txt +++ b/pkg/analyzer/api.txt @@ -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) diff --git a/pkg/analyzer/lib/src/dart/analysis/file_state.dart b/pkg/analyzer/lib/src/dart/analysis/file_state.dart index 21d8713c71c..87d423500be 100644 --- a/pkg/analyzer/lib/src/dart/analysis/file_state.dart +++ b/pkg/analyzer/lib/src/dart/analysis/file_state.dart @@ -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, diff --git a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart index 0ceba55a2fd..55daf0f14c2 100644 --- a/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart +++ b/pkg/analyzer/lib/src/dart/analysis/library_analyzer.dart @@ -384,7 +384,7 @@ class LibraryAnalyzer { var definingUnit = _libraryElement.definingCompilationUnit; var analysesToContextUnits = {}; LintRuleUnitContext? definingContextUnit; - WorkspacePackage? workspacePackage; + WorkspacePackageImpl? workspacePackage; for (var fileAnalysis in _libraryFiles.values) { var linterContextUnit = LintRuleUnitContext( file: fileAnalysis.file.resource, diff --git a/pkg/analyzer/lib/src/error/annotation_verifier.dart b/pkg/analyzer/lib/src/error/annotation_verifier.dart index 1489f9dcdaa..94c372791ea 100644 --- a/pkg/analyzer/lib/src/error/annotation_verifier.dart +++ b/pkg/analyzer/lib/src/error/annotation_verifier.dart @@ -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 = diff --git a/pkg/analyzer/lib/src/error/best_practices_verifier.dart b/pkg/analyzer/lib/src/error/best_practices_verifier.dart index 3c1ac0ed22a..797a61a42e6 100644 --- a/pkg/analyzer/lib/src/error/best_practices_verifier.dart +++ b/pkg/analyzer/lib/src/error/best_practices_verifier.dart @@ -80,8 +80,8 @@ class BestPracticesVerifier extends RecursiveAstVisitor { 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 { 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; diff --git a/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart b/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart index 3a5a740e711..84910228851 100644 --- a/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart +++ b/pkg/analyzer/lib/src/error/deprecated_member_use_verifier.dart @@ -354,7 +354,7 @@ abstract class BaseDeprecatedMemberUseVerifier { } class DeprecatedMemberUseVerifier extends BaseDeprecatedMemberUseVerifier { - final WorkspacePackage? _workspacePackage; + final WorkspacePackageImpl? _workspacePackage; final ErrorReporter _errorReporter; DeprecatedMemberUseVerifier( diff --git a/pkg/analyzer/lib/src/lint/linter.dart b/pkg/analyzer/lib/src/lint/linter.dart index 780176d2e28..5cf0a38cdae 100644 --- a/pkg/analyzer/lib/src/lint/linter.dart +++ b/pkg/analyzer/lib/src/lint/linter.dart @@ -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; diff --git a/pkg/analyzer/lib/src/workspace/basic.dart b/pkg/analyzer/lib/src/workspace/basic.dart index 03de9c848a4..4d2837c314d 100644 --- a/pkg/analyzer/lib/src/workspace/basic.dart +++ b/pkg/analyzer/lib/src/workspace/basic.dart @@ -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; diff --git a/pkg/analyzer/lib/src/workspace/blaze.dart b/pkg/analyzer/lib/src/workspace/blaze.dart index 58f9acf4c8e..5675763a91e 100644 --- a/pkg/analyzer/lib/src/workspace/blaze.dart +++ b/pkg/analyzer/lib/src/workspace/blaze.dart @@ -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; diff --git a/pkg/analyzer/lib/src/workspace/gn.dart b/pkg/analyzer/lib/src/workspace/gn.dart index c9d19f730d3..ae14e36c597 100644 --- a/pkg/analyzer/lib/src/workspace/gn.dart +++ b/pkg/analyzer/lib/src/workspace/gn.dart @@ -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; diff --git a/pkg/analyzer/lib/src/workspace/pub.dart b/pkg/analyzer/lib/src/workspace/pub.dart index b13b2f1de73..8052bcdc604 100644 --- a/pkg/analyzer/lib/src/workspace/pub.dart +++ b/pkg/analyzer/lib/src/workspace/pub.dart @@ -180,7 +180,7 @@ class PackageConfigWorkspace extends SimpleWorkspace { /// The contents of the package config file. late final String? _packageConfigContent; - final Map _workspacePackages = {}; + final Map _workspacePackages = {}; factory PackageConfigWorkspace( ResourceProvider provider, //Packages packages, @@ -211,7 +211,7 @@ class PackageConfigWorkspace extends SimpleWorkspace { _packageConfigContent = packageConfigFile.readAsStringSync(); } - Iterable get allPackages => + Iterable 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 _generatedPathParts = [ file_paths.dotDartTool, file_paths.packageBuild, diff --git a/pkg/analyzer/lib/src/workspace/workspace.dart b/pkg/analyzer/lib/src/workspace/workspace.dart index 7bfc15d0719..96c4b5ea402 100644 --- a/pkg/analyzer/lib/src/workspace/workspace.dart +++ b/pkg/analyzer/lib/src/workspace/workspace.dart @@ -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'; diff --git a/pkg/analyzer/lib/workspace/workspace.dart b/pkg/analyzer/lib/workspace/workspace.dart new file mode 100644 index 00000000000..96af9afa47c --- /dev/null +++ b/pkg/analyzer/lib/workspace/workspace.dart @@ -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); +} diff --git a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart index ba2750229dc..3aa769bab07 100644 --- a/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart +++ b/pkg/analyzer/test/src/dart/analysis/analysis_context_collection_test.dart @@ -1136,7 +1136,7 @@ class _AnalysisContextCollectionPrinter { final Map _analysisOptions = Map.identity(); final Map _workspaces = Map.identity(); - final Map> _workspacePackages = + final Map> _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(): diff --git a/pkg/analyzer/test/src/workspace/blaze_test.dart b/pkg/analyzer/test/src/workspace/blaze_test.dart index 5728fcd5676..7aa4d122688 100644 --- a/pkg/analyzer/test/src/workspace/blaze_test.dart +++ b/pkg/analyzer/test/src/workspace/blaze_test.dart @@ -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); diff --git a/pkg/analyzer/test/src/workspace/pub_test.dart b/pkg/analyzer/test/src/workspace/pub_test.dart index ae73c970aee..7f7fdeb140b 100644 --- a/pkg/analyzer/test/src/workspace/pub_test.dart +++ b/pkg/analyzer/test/src/workspace/pub_test.dart @@ -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'; diff --git a/pkg/analyzer/test/src/workspace/workspace_test_support.dart b/pkg/analyzer/test/src/workspace/workspace_test_support.dart index 720fac3c751..51c63a14861 100644 --- a/pkg/analyzer/test/src/workspace/workspace_test_support.dart +++ b/pkg/analyzer/test/src/workspace/workspace_test_support.dart @@ -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)); } diff --git a/pkg/linter/lib/src/ast.dart b/pkg/linter/lib/src/ast.dart index a076c85db64..4bae82e93fe 100644 --- a/pkg/linter/lib/src/ast.dart +++ b/pkg/linter/lib/src/ast.dart @@ -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'; diff --git a/pkg/linter/lib/src/rules/deprecated_member_use_from_same_package.dart b/pkg/linter/lib/src/rules/deprecated_member_use_from_same_package.dart index dfa6f49a8c4..848b671e229 100644 --- a/pkg/linter/lib/src/rules/deprecated_member_use_from_same_package.dart +++ b/pkg/linter/lib/src/rules/deprecated_member_use_from_same_package.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';