in lib/src/tag/tagger.dart [358:445]
void nullSafetyTags(List<String> tags, List<Explanation> explanations) {
const _nullSafeTag = 'is:null-safe';
try {
var foundIssues = false;
final sdkConstraintFinder = PathFinder<String>(_packageGraph, (
String packageDir,
) {
final pubspec = _pubspecCache.pubspecOfPackage(packageDir);
return pubspec.sdkConstraintStatus.hasOptedIntoNullSafety
? null
: (path) => Explanation(
'Package is not null safe',
'Because:\n${PackageGraph.formatPath(path)} '
'that doesn\'t opt in to null safety',
tag: _nullSafeTag,
);
});
final sdkConstraintResult =
sdkConstraintFinder.findViolation(packageName);
if (sdkConstraintResult != null) {
explanations.add(sdkConstraintResult);
foundIssues = true;
} else {
for (final runtime in Runtime.recognizedRuntimes) {
final optOutViolationFinder = PathFinder<Uri>(
LibraryGraph(_session, runtime.declaredVariables),
(library) {
if (library.scheme == 'dart-ext') return null;
final resolvedPath = _session.uriConverter.uriToPath(library);
if (resolvedPath == null) {
return (path) => Explanation(
'Unable to access import.',
'Because:\n${LibraryGraph.formatPath(path)} where $library is inaccessible.',
tag: _nullSafeTag,
);
}
final unit = parsedUnitFromUri(_session, library);
if (unit == null) return null;
final languageVersionToken = unit.languageVersionToken;
if (languageVersionToken == null) return null;
// dart:ui has no package name. So we cannot trivially look it up in
// the allowed experiments. We just assume it is opted in.
if (!library.isScheme('package')) return null;
if (!isNullSafety(Version(
languageVersionToken.major, languageVersionToken.minor, 0))) {
return (path) => Explanation(
'Package is not null safe',
'Because:\n${LibraryGraph.formatPath(path)} where $library '
'is opting out from null safety.',
tag: _nullSafeTag,
);
}
return null;
},
);
for (final library in _publicLibraries) {
final nullSafetyResult =
optOutViolationFinder.findViolation(library);
if (nullSafetyResult != null) {
explanations.add(nullSafetyResult);
foundIssues = true;
}
}
// If we have a problem one runtime, there is no need to explore the
// other runtimes... Also if we do, we are likely to just duplicate
// explanations.
if (foundIssues) {
break;
}
}
}
if (!foundIssues) {
tags.add(_nullSafeTag);
}
} on TagException catch (e) {
explanations.add(Explanation(
'Tag detection failed.',
e.message,
tag: _nullSafeTag,
));
}
}