Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 9 additions & 2 deletions lib/src/dependency_validator.dart
Original file line number Diff line number Diff line change
Expand Up @@ -131,11 +131,16 @@ Future<bool> checkPackage({required String root}) async {
'${bulletItems(publicLessFiles.map((f) => f.path))}\n',
);

// The language version that the dart files of this package are parsed with.
final featureSet = featureSetForPubspec(pubspec);

// Read each file in lib/ and parse the package names from every import and
// export directive.
final packagesUsedInPublicFiles = <String>{};
for (final file in publicDartFiles) {
packagesUsedInPublicFiles.addAll(getDartDirectivePackageNames(file));
packagesUsedInPublicFiles.addAll(
getDartDirectivePackageNames(file, featureSet: featureSet),
);
}
for (final file in publicScssFiles) {
final matches = importScssPackageRegex.allMatches(file.readAsStringSync());
Expand Down Expand Up @@ -201,7 +206,9 @@ Future<bool> checkPackage({required String root}) async {
if (optionsIncludePackage != null) optionsIncludePackage,
};
for (final file in nonPublicDartFiles) {
packagesUsedOutsidePublicDirs.addAll(getDartDirectivePackageNames(file));
packagesUsedOutsidePublicDirs.addAll(
getDartDirectivePackageNames(file, featureSet: featureSet),
);
}
for (final file in nonPublicScssFiles) {
final matches = importScssPackageRegex.allMatches(file.readAsStringSync());
Expand Down
57 changes: 54 additions & 3 deletions lib/src/import_export_ast_visitor.dart
Original file line number Diff line number Diff line change
@@ -1,16 +1,31 @@
import 'dart:io';

import 'package:analyzer/dart/analysis/features.dart';
import 'package:analyzer/dart/analysis/results.dart';
import 'package:analyzer/dart/analysis/utilities.dart';
import 'package:analyzer/dart/ast/ast.dart';
import 'package:analyzer/dart/ast/visitor.dart';
import 'package:pub_semver/pub_semver.dart';
import 'package:pubspec_parse/pubspec_parse.dart';

import 'utils.dart';

/// Returns the list of package names that are exported and imported into the
/// provided dart file
Set<String> getDartDirectivePackageNames(File file) {
/// provided dart file, which is parsed with the given [featureSet].
///
/// See [featureSetForPubspec] for resolving the [featureSet] of the package
/// that [file] belongs to.
Set<String> getDartDirectivePackageNames(
File file, {
required FeatureSet featureSet,
}) {
ParseStringResult parsed;
try {
parsed = parseString(content: file.readAsStringSync(), path: file.path);
parsed = parseString(
content: file.readAsStringSync(),
path: file.path,
featureSet: featureSet,
);
} on ArgumentError catch (e) {
print('Error parsing: ${file.path}');
print(e.message);
Expand All @@ -22,6 +37,42 @@ Set<String> getDartDirectivePackageNames(File file) {
return visitor.packageNames;
}

/// Returns the [FeatureSet] that matches the Dart SDK version declared by the
/// `environment: sdk:` constraint of [pubspec].
///
/// Falls back to [FeatureSet.latestLanguageVersion] when [pubspec] does not
/// declare an SDK constraint with a lower bound.
FeatureSet featureSetForPubspec(Pubspec pubspec) {
final languageVersion = _sdkLanguageVersionOf(pubspec);
if (languageVersion == null) {
logger.fine(
'No SDK version found for ${pubspec.name}, '
'parsing with the latest language version.',
);
return FeatureSet.latestLanguageVersion();
}

logger.fine('Using language version $languageVersion for ${pubspec.name}');
return FeatureSet.fromEnableFlags2(
sdkLanguageVersion: languageVersion,
flags: const [],
);
}

/// Returns the language version implied by the `environment: sdk:` constraint
/// of [pubspec], or null if it has none.
Version? _sdkLanguageVersionOf(Pubspec pubspec) {
final sdkConstraint = pubspec.environment['sdk'];

// `Version` also implements `VersionRange`, with itself as the lower bound.
final minSdkVersion =
sdkConstraint is VersionRange ? sdkConstraint.min : null;
if (minSdkVersion == null) return null;

// A language version is only major.minor.
return Version(minSdkVersion.major, minSdkVersion.minor, 0);
}

class ImportExportVisitor extends GeneralizingAstVisitor {
Set<String> packageNames = {};

Expand Down
Loading