@@ -395,21 +395,6 @@ RunProcess runProcess = Process.run;
395
395
@visibleForTesting
396
396
bool platformIsWindows = Platform .isWindows;
397
397
398
- /// An error thrown when [CustomLintPlugin._visitSelfAndTransitiveDependencies] tries to iterate over
399
- /// the dependencies of a package, but the package cannot be found in
400
- /// the `package_config.json` .
401
- class UnresolvedTransitiveDependencyException implements Exception {
402
- UnresolvedTransitiveDependencyException ._(this .dependencyName);
403
-
404
- /// The dependency that failed to resolve
405
- final String dependencyName;
406
-
407
- @override
408
- String toString () {
409
- return 'Unresolved transitive dependency: $dependencyName . Did you forget to run "pub get"?' ;
410
- }
411
- }
412
-
413
398
String ? _findOptionsForPubspec (String pubspecPath) {
414
399
final analysisOptions = File (join (pubspecPath, 'analysis_options.yaml' ));
415
400
if (analysisOptions.existsSync ()) return analysisOptions.path;
@@ -1009,34 +994,6 @@ class CustomLintProject {
1009
994
}
1010
995
}
1011
996
1012
- class _PackageAndPubspec {
1013
- _PackageAndPubspec ({required this .package, required this .parentPubspec});
1014
-
1015
- final Package package;
1016
- final Pubspec parentPubspec;
1017
- }
1018
-
1019
- class _PackageNameAndPubspec {
1020
- _PackageNameAndPubspec ({
1021
- required this .packageName,
1022
- required this .parentPubspec,
1023
- });
1024
-
1025
- static Iterable <_PackageNameAndPubspec > fromPubspecDependencies (
1026
- Pubspec pubspec,
1027
- ) {
1028
- return pubspec.dependencies.keys.map (
1029
- (packageName) => _PackageNameAndPubspec (
1030
- packageName: packageName,
1031
- parentPubspec: pubspec,
1032
- ),
1033
- );
1034
- }
1035
-
1036
- final String packageName;
1037
- final Pubspec parentPubspec;
1038
- }
1039
-
1040
997
/// A custom_lint plugin and its version constraints.
1041
998
@internal
1042
999
class CustomLintPlugin {
@@ -1075,80 +1032,6 @@ class CustomLintPlugin {
1075
1032
1076
1033
/// The version constraints in the project's `pubspec.yaml` .
1077
1034
final PubspecDependency constraint;
1078
-
1079
- /// Returns an iterable of the transitive dependencies of a Dart project
1080
- /// located at the given [directory] . The function uses the `pubspec.yaml`
1081
- /// and `package_config.json` files of the project to resolve the
1082
- /// transitive dependencies.
1083
- ///
1084
- /// The function uses a breadth-first search algorithm to traverse the
1085
- /// dependency tree. The root project's dependencies are processed first,
1086
- /// followed by their transitive dependencies, and so on.
1087
- ///
1088
- /// If a transitive dependency cannot be resolved (i.e., it is not listed
1089
- /// in the `package_config.json` file), the function throws an
1090
- /// [UnresolvedTransitiveDependencyException] .
1091
- ///
1092
- /// The function will also throw if a pubspec/package_config.json could not
1093
- /// be decoded, such as if the file is missing or incorrectly formatted.
1094
- ///
1095
- /// Example usage:
1096
- /// ```dart
1097
- /// final dependencies = _listTransitiveDependencies('/path/to/my/project').toList();
1098
- /// ```
1099
- Iterable <_PackageAndPubspec > _visitSelfAndTransitiveDependencies (
1100
- PubspecCache pubspecCache,
1101
- ) sync * {
1102
- yield _PackageAndPubspec (
1103
- package: package,
1104
- parentPubspec: ownerPubspec,
1105
- );
1106
-
1107
- // A map of of the packages defined in package_config.json for fast lookup.
1108
- // This avoids an O(n^2) lookup in the loop below.
1109
- final packages = Map .fromEntries (
1110
- ownerPackageConfig.packages.map ((e) => MapEntry (e.name, e)),
1111
- );
1112
-
1113
- // Only queue "dependencies" but no "dev_dependencies" or "dependency_overrides".
1114
- // This is plugins are considered in to be in "release mode", in which case
1115
- // dev only dependencies are not included.
1116
- final dependenciesToVisit = ListQueue <_PackageNameAndPubspec >.of (
1117
- _PackageNameAndPubspec .fromPubspecDependencies (pubspec),
1118
- );
1119
-
1120
- /// The set of already visited pubspecs
1121
- final visited = < String > {};
1122
-
1123
- while (dependenciesToVisit.isNotEmpty) {
1124
- // Check if the dependency is already visited
1125
- final dependency = dependenciesToVisit.removeFirst ();
1126
- if (! visited.add (dependency.packageName)) continue ;
1127
-
1128
- // Emit the dependency's package metadata.
1129
- final package = packages[dependency.packageName];
1130
- if (package == null ) {
1131
- throw UnresolvedTransitiveDependencyException ._(dependency.packageName);
1132
- }
1133
-
1134
- final packageDir = Directory .fromUri (package.root);
1135
- // TODO test error
1136
- final dependencyPubspec = pubspecCache (packageDir);
1137
-
1138
- yield _PackageAndPubspec (
1139
- package: package,
1140
- parentPubspec: dependency.parentPubspec,
1141
- );
1142
-
1143
- // Now queue the dependencies of the dependency to be emitted too.
1144
- // Only queue "dependencies" but no "dev_dependencies" or "dependency_overrides".
1145
- // This is plugins are considered in to be in "release mode", in which case
1146
- // dev only dependencies are not included.
1147
- dependenciesToVisit.addAll (
1148
- _PackageNameAndPubspec .fromPubspecDependencies (dependencyPubspec),
1149
- );
1150
- }
1151
- }
1152
1035
}
1153
1036
1154
1037
/// A dependency in a `pubspec.yaml` .
@@ -1317,201 +1200,3 @@ class SdkPubspecDependency extends PubspecDependency {
1317
1200
return 'From SDK: ${dependency .sdk }' ;
1318
1201
}
1319
1202
}
1320
-
1321
- class _ConflictEntry {
1322
- _ConflictEntry (
1323
- this .plugin,
1324
- this .project,
1325
- this .packageMeta, {
1326
- required this .workingDirectory,
1327
- });
1328
-
1329
- final CustomLintPlugin plugin;
1330
- final CustomLintProject project;
1331
- final _PackageAndPubspec packageMeta;
1332
- final Directory workingDirectory;
1333
-
1334
- /// Whether [packageMeta] is the plugin itself.
1335
- late final bool _isPlugin = packageMeta.package.name == plugin.name;
1336
-
1337
- String get _name => packageMeta.package.name;
1338
-
1339
- PubspecDependency _dependency () {
1340
- // Short path for when the constraint is readily available.
1341
- if (_isPlugin) return plugin.constraint;
1342
-
1343
- final dependency = packageMeta.parentPubspec.getDependency (_name);
1344
- if (dependency == null ) {
1345
- // TODO test error
1346
- throw ArgumentError (
1347
- 'Package ${packageMeta .parentPubspec .name } does not depend on package $_name \n ${packageMeta .parentPubspec .dependencies }' ,
1348
- );
1349
- }
1350
-
1351
- return PubspecDependency .fromDependency (dependency);
1352
- }
1353
-
1354
- String buildConflictHeader () {
1355
- if (_isPlugin) {
1356
- return 'Plugin $_name :' ;
1357
- }
1358
- return 'Package $_name :' ;
1359
- }
1360
-
1361
- String buildConflictingMessage () {
1362
- final trailingMessage = _isPlugin
1363
- ? 'Used by project "${project .pubspec .name }" at "${project .directory .relativeTo (workingDirectory )}"'
1364
- : 'Used by plugin "${plugin .name }" at "${plugin .directory .relativeTo (workingDirectory )}" '
1365
- 'in the project "${project .pubspec .name }" at "${project .directory .relativeTo (workingDirectory )}"' ;
1366
- return '''
1367
- - ${_dependency ().buildShortDescription ()}
1368
- Resolved with ${packageMeta .package .root .toFilePath ()}
1369
- $trailingMessage ''' ;
1370
- }
1371
- }
1372
-
1373
- /// A class that checks if there are conflicting packages in the context roots.
1374
- class _ConflictingPackagesChecker {
1375
- final _entries = < _ConflictEntry > [];
1376
-
1377
- /// Registers a [Package] and its associated [CustomLintPlugin] /[CustomLintProject]
1378
- /// to be checked against version conflicts.
1379
- void addPluginPackage (
1380
- CustomLintProject project,
1381
- CustomLintPlugin plugin,
1382
- _PackageAndPubspec package, {
1383
- required Directory workingDirectory,
1384
- }) {
1385
- _entries.add (
1386
- _ConflictEntry (
1387
- plugin,
1388
- project,
1389
- package,
1390
- workingDirectory: workingDirectory,
1391
- ),
1392
- );
1393
- }
1394
-
1395
- /// Throws an error if there are conflicting packages.
1396
- void throwErrorIfConflictingPackages () {
1397
- final packageNameRootMap = < String , Set <Uri >> {};
1398
- // Group packages by name and collect all unique roots,
1399
- // since we're using a set
1400
- for (final entry in _entries) {
1401
- final entriesForName =
1402
- packageNameRootMap[entry.packageMeta.package.name] ?? = {};
1403
- entriesForName.add (entry.packageMeta.package.root);
1404
- }
1405
-
1406
- // Find packages with more than one root
1407
- final packagesWithConflictingVersions = packageNameRootMap.entries
1408
- .where ((entry) => entry.value.length > 1 )
1409
- .map ((e) => e.key)
1410
- .toSet ();
1411
-
1412
- // If there are no conflicting versions, return
1413
- if (packagesWithConflictingVersions.isEmpty) return ;
1414
-
1415
- throw PackageVersionConflictException ._(
1416
- packagesWithConflictingVersions,
1417
- _entries,
1418
- );
1419
- }
1420
- }
1421
-
1422
- /// An error thrown if a custom_lint workspace contains two or more projects
1423
- /// which depend on the same package (directly or transitively) with different versions.
1424
- class PackageVersionConflictException implements Exception {
1425
- PackageVersionConflictException ._(
1426
- this ._packagesWithConflictingVersions,
1427
- this ._entries,
1428
- );
1429
-
1430
- final Set <String > _packagesWithConflictingVersions;
1431
- final List <_ConflictEntry > _entries;
1432
-
1433
- @override
1434
- String toString () {
1435
- final conflictingEntriesByPackages = Map .fromEntries (
1436
- _packagesWithConflictingVersions.map (
1437
- (packageName) => MapEntry (
1438
- packageName,
1439
- _entries
1440
- .where ((entry) => entry.packageMeta.package.name == packageName)
1441
- .sortedBy ((value) => value.project.pubspec.name),
1442
- ),
1443
- ),
1444
- );
1445
-
1446
- final errorMessageBuilder = StringBuffer ('''
1447
- PackageVersionConflictException – Some dependencies with conflicting versions were identified:
1448
-
1449
- ''' );
1450
-
1451
- // Build conflicting packages message
1452
- for (final conflictingEntriesForPackage
1453
- in conflictingEntriesByPackages.values) {
1454
- errorMessageBuilder.writeln (
1455
- conflictingEntriesForPackage.first.buildConflictHeader (),
1456
- );
1457
- for (final conflictEntry in conflictingEntriesForPackage) {
1458
- errorMessageBuilder.writeln (conflictEntry.buildConflictingMessage ());
1459
- }
1460
- errorMessageBuilder.writeln ();
1461
- }
1462
-
1463
- errorMessageBuilder
1464
- ..writeln (
1465
- 'This is not supported. Custom_lint shares the analysis between all'
1466
- ' packages. As such, all plugins are started under a single process,'
1467
- ' sharing the dependencies of all the packages that use custom_lint. '
1468
- "Since there's a single process for all plugins, if 2 plugins try to"
1469
- ' use different versions for a dependency, the process cannot be '
1470
- 'reasonably started. Please make sure all packages have the same version.' ,
1471
- )
1472
- ..writeln ('You could run the following commands to try fixing this:' )
1473
- ..writeln ();
1474
-
1475
- // Organize conflicting packages by project instead of by name
1476
- final conflictingEntriesByProjects =
1477
- < CustomLintProject , List <_ConflictEntry >> {};
1478
- for (final conflictingEntriesForPackage
1479
- in conflictingEntriesByPackages.values) {
1480
- for (final conflictEntry in conflictingEntriesForPackage) {
1481
- final project = conflictEntry.project;
1482
- final projectConflictingEntries =
1483
- conflictingEntriesByProjects[project] ?? [];
1484
- projectConflictingEntries.add (conflictEntry);
1485
- conflictingEntriesByProjects[project] = projectConflictingEntries;
1486
- }
1487
- }
1488
-
1489
- // Build fix commands
1490
- for (final conflictingEntriesForProject
1491
- in conflictingEntriesByProjects.entries) {
1492
- final pubspec = conflictingEntriesForProject.key.pubspec;
1493
- final isFlutter = pubspec.dependencies.containsKey ('flutter' );
1494
-
1495
- final command = isFlutter ? 'flutter' : 'dart' ;
1496
-
1497
- final conflictingPackageEntries = conflictingEntriesForProject.value;
1498
- final conflictingPackagesNames = conflictingPackageEntries
1499
- .map ((entry) => entry.packageMeta.package.name)
1500
- .join (' ' );
1501
-
1502
- errorMessageBuilder
1503
- ..writeln ('cd ${conflictingEntriesForProject .key .directory .path }' )
1504
- ..writeln ('$command pub upgrade $conflictingPackagesNames ' );
1505
- }
1506
-
1507
- return errorMessageBuilder.toString ();
1508
- }
1509
- }
1510
-
1511
- extension on Pubspec {
1512
- Dependency ? getDependency (String name) {
1513
- return dependencies[name] ??
1514
- devDependencies[name] ??
1515
- dependencyOverrides[name];
1516
- }
1517
- }
0 commit comments