blob: 186ccf7e0e9f356d20744ed787602fd254b98f22 [file] [edit]
// 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.
@TestOn('!windows')
library;
import 'dart:io';
import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:package_config/package_config.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:test/test.dart';
void main() async {
final packageConfig = (await findPackageConfig(Directory.current))!;
test(
'public arg parser library depends on package:args and internal utils',
() {
checkTransitiveDependencies(
packageConfig,
Uri.parse('package:dart_mcp_server/arg_parser.dart'),
const ['args', 'dart_mcp_server'],
);
},
);
test('checkTransitiveDependencies', () {
expect(
() => checkTransitiveDependencies(
packageConfig,
Uri.parse('package:test/test.dart'),
const ['test_api'],
),
throwsA(
isA<TestFailure>().having(
(e) => e.message,
'message',
allOf(
contains(
'Library package:test/test.dart references disallowed packages',
),
contains('test_core'),
),
),
),
);
});
}
/// Checks that [libraryUri] and all its transitive dependencies only have
/// directives referencing [allowedPackages].
void checkTransitiveDependencies(
PackageConfig packageConfig,
Uri libraryUri,
Iterable<String> allowedPackages, {
Set<Uri>? visited,
}) {
visited ??= {};
if (!visited.add(libraryUri)) {
return;
}
final languageVersion =
packageConfig[libraryUri.pathSegments.first]!.languageVersion!;
final parsed = parseFile(
path: packageConfig.resolve(libraryUri)!.path,
featureSet: FeatureSet.fromEnableFlags2(
sdkLanguageVersion: Version(
languageVersion.major,
languageVersion.minor,
0,
),
flags: const [],
),
);
final uriDirectives = parsed.unit.directives.whereType<UriBasedDirective>();
final resolvedUris = uriDirectives
.map((d) => d.uri.stringValue!)
.where((uriString) => !uriString.startsWith('dart:'))
.map((uriString) => libraryUri.resolve(uriString));
final referencedPackages = {
for (final uri in resolvedUris) uri.pathSegments.first,
};
expect(
allowedPackages,
containsAll(referencedPackages),
reason:
'Library $libraryUri references disallowed packages '
'$referencedPackages',
);
for (final uri in resolvedUris) {
checkTransitiveDependencies(
packageConfig,
uri,
allowedPackages,
visited: visited,
);
}
}