Protect flutter analyze --suggestions from erroring on missing AGP value. (#137719)
Fixes #137600
Protect flutter analyze --suggestions from null error when AGP value is missing
Update template with a reference to new agp definition location
Look for AGP version being set in settings.gradle (change to templates happened in dbe0ccd885 (diff-20537fb84ee37894a3f3d9723a06bcf2674290ee25aa83332c2524a1f7546a6d)
This commit is contained in:
parent
969a8750a5
commit
4d21a026e5
@ -71,19 +71,31 @@ const String maxKnownAgpVersion = '8.3';
|
|||||||
// compatible Java version.
|
// compatible Java version.
|
||||||
const String oldestDocumentedJavaAgpCompatibilityVersion = '4.2';
|
const String oldestDocumentedJavaAgpCompatibilityVersion = '4.2';
|
||||||
|
|
||||||
|
// Constant used in [_buildAndroidGradlePluginRegExp] and
|
||||||
|
// [_settingsAndroidGradlePluginRegExp] to identify the version section.
|
||||||
|
const String _versionGroupName = 'version';
|
||||||
|
|
||||||
|
// AGP can be defined in build.gradle
|
||||||
// Expected content:
|
// Expected content:
|
||||||
// "classpath 'com.android.tools.build:gradle:7.3.0'"
|
// "classpath 'com.android.tools.build:gradle:7.3.0'"
|
||||||
// Parentheticals are use to group which helps with version extraction.
|
// ?<version> is used to name the version group which helps with extraction.
|
||||||
// "...build:gradle:(...)" where group(1) should be the version string.
|
final RegExp _buildAndroidGradlePluginRegExp =
|
||||||
final RegExp _androidGradlePluginRegExp =
|
RegExp(r'com\.android\.tools\.build:gradle:(?<version>\d+\.\d+\.\d+)');
|
||||||
RegExp(r'com\.android\.tools\.build:gradle:(\d+\.\d+\.\d+)');
|
|
||||||
|
// AGP can be defined in settings.gradle.
|
||||||
|
// Expected content:
|
||||||
|
// "id "com.android.application" version "{{agpVersion}}""
|
||||||
|
// ?<version> is used to name the version group which helps with extraction.
|
||||||
|
final RegExp _settingsAndroidGradlePluginRegExp = RegExp(
|
||||||
|
r'^\s+id\s+"com.android.application"\s+version\s+"(?<version>\d+\.\d+\.\d+)"',
|
||||||
|
multiLine: true);
|
||||||
|
|
||||||
// Expected content format (with lines above and below).
|
// Expected content format (with lines above and below).
|
||||||
// Version can have 2 or 3 numbers.
|
// Version can have 2 or 3 numbers.
|
||||||
// 'distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip'
|
// 'distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-all.zip'
|
||||||
// '^\s*' protects against commented out lines.
|
// '^\s*' protects against commented out lines.
|
||||||
final RegExp distributionUrlRegex =
|
final RegExp distributionUrlRegex =
|
||||||
RegExp(r'^\s*distributionUrl\s*=\s*.*\.zip', multiLine: true);
|
RegExp(r'^\s*distributionUrl\s*=\s*.*\.zip', multiLine: true);
|
||||||
|
|
||||||
// Modified version of the gradle distribution url match designed to only match
|
// Modified version of the gradle distribution url match designed to only match
|
||||||
// gradle.org urls so that we can guarantee any modifications to the url
|
// gradle.org urls so that we can guarantee any modifications to the url
|
||||||
@ -199,7 +211,7 @@ String getGradleVersionForAndroidPlugin(Directory directory, Logger logger) {
|
|||||||
return templateDefaultGradleVersion;
|
return templateDefaultGradleVersion;
|
||||||
}
|
}
|
||||||
final String buildFileContent = buildFile.readAsStringSync();
|
final String buildFileContent = buildFile.readAsStringSync();
|
||||||
final Iterable<Match> pluginMatches = _androidGradlePluginRegExp.allMatches(buildFileContent);
|
final Iterable<Match> pluginMatches = _buildAndroidGradlePluginRegExp.allMatches(buildFileContent);
|
||||||
if (pluginMatches.isEmpty) {
|
if (pluginMatches.isEmpty) {
|
||||||
logger.printTrace("$buildFile doesn't provide an AGP version, assuming Gradle version: $templateDefaultGradleVersion");
|
logger.printTrace("$buildFile doesn't provide an AGP version, assuming Gradle version: $templateDefaultGradleVersion");
|
||||||
return templateDefaultGradleVersion;
|
return templateDefaultGradleVersion;
|
||||||
@ -309,8 +321,9 @@ OS: Mac OS X 13.2.1 aarch64
|
|||||||
/// Returns the Android Gradle Plugin (AGP) version that the current project
|
/// Returns the Android Gradle Plugin (AGP) version that the current project
|
||||||
/// depends on when found, null otherwise.
|
/// depends on when found, null otherwise.
|
||||||
///
|
///
|
||||||
/// The Android plugin version is specified in the [build.gradle] file within
|
/// The Android plugin version is specified in the [build.gradle] or
|
||||||
/// the project's Android directory ([androidDirectory]).
|
/// [settings.gradle] file within the project's
|
||||||
|
/// Android directory ([androidDirectory]).
|
||||||
String? getAgpVersion(Directory androidDirectory, Logger logger) {
|
String? getAgpVersion(Directory androidDirectory, Logger logger) {
|
||||||
final File buildFile = androidDirectory.childFile('build.gradle');
|
final File buildFile = androidDirectory.childFile('build.gradle');
|
||||||
if (!buildFile.existsSync()) {
|
if (!buildFile.existsSync()) {
|
||||||
@ -318,15 +331,34 @@ String? getAgpVersion(Directory androidDirectory, Logger logger) {
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String buildFileContent = buildFile.readAsStringSync();
|
final String buildFileContent = buildFile.readAsStringSync();
|
||||||
final Iterable<Match> pluginMatches =
|
final RegExpMatch? buildMatch =
|
||||||
_androidGradlePluginRegExp.allMatches(buildFileContent);
|
_buildAndroidGradlePluginRegExp.firstMatch(buildFileContent);
|
||||||
if (pluginMatches.isEmpty) {
|
if (buildMatch != null) {
|
||||||
logger.printTrace("$buildFile doesn't provide an AGP version");
|
final String? androidPluginVersion =
|
||||||
|
buildMatch.namedGroup(_versionGroupName);
|
||||||
|
logger.printTrace('$buildFile provides AGP version: $androidPluginVersion');
|
||||||
|
return androidPluginVersion;
|
||||||
|
}
|
||||||
|
logger.printTrace(
|
||||||
|
"$buildFile doesn't provide an AGP version. Checking settings.");
|
||||||
|
final File settingsFile = androidDirectory.childFile('settings.gradle');
|
||||||
|
if (!settingsFile.existsSync()) {
|
||||||
|
logger.printTrace('$settingsFile does not exist.');
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
final String? androidPluginVersion = pluginMatches.first.group(1);
|
final String settingsFileContent = settingsFile.readAsStringSync();
|
||||||
logger.printTrace('$buildFile provides AGP version: $androidPluginVersion');
|
final RegExpMatch? settingsMatch =
|
||||||
return androidPluginVersion;
|
_settingsAndroidGradlePluginRegExp.firstMatch(settingsFileContent);
|
||||||
|
|
||||||
|
if (settingsMatch != null) {
|
||||||
|
final String? androidPluginVersion =
|
||||||
|
settingsMatch.namedGroup(_versionGroupName);
|
||||||
|
logger.printTrace(
|
||||||
|
'$settingsFile provides AGP version: $androidPluginVersion');
|
||||||
|
return androidPluginVersion;
|
||||||
|
}
|
||||||
|
logger.printTrace("$settingsFile doesn't provide an AGP version.");
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
String _formatParseWarning(String content) {
|
String _formatParseWarning(String content) {
|
||||||
|
@ -608,15 +608,20 @@ class AndroidProject extends FlutterProjectPlatform {
|
|||||||
final bool compatibleGradleAgp = gradle.validateGradleAndAgp(globals.logger,
|
final bool compatibleGradleAgp = gradle.validateGradleAndAgp(globals.logger,
|
||||||
gradleV: gradleVersion, agpV: agpVersion);
|
gradleV: gradleVersion, agpV: agpVersion);
|
||||||
|
|
||||||
final bool compatibleJavaGradle = gradle.validateJavaAndGradle(globals.logger,
|
final bool compatibleJavaGradle = gradle.validateJavaAndGradle(
|
||||||
javaV: javaVersion, gradleV: gradleVersion);
|
globals.logger,
|
||||||
|
javaV: javaVersion,
|
||||||
|
gradleV: gradleVersion);
|
||||||
|
|
||||||
// Begin description formatting.
|
// Begin description formatting.
|
||||||
if (!compatibleGradleAgp) {
|
if (!compatibleGradleAgp) {
|
||||||
|
final String gradleDescription = agpVersion != null
|
||||||
|
? 'Update Gradle to at least "${gradle.getGradleVersionFor(agpVersion)}".'
|
||||||
|
: '';
|
||||||
description = '''
|
description = '''
|
||||||
Incompatible Gradle/AGP versions. \n
|
Incompatible Gradle/AGP versions. \n
|
||||||
Gradle Version: $gradleVersion, AGP Version: $agpVersion
|
Gradle Version: $gradleVersion, AGP Version: $agpVersion
|
||||||
Update Gradle to at least "${gradle.getGradleVersionFor(agpVersion!)}".\n
|
$gradleDescription\n
|
||||||
See the link below for more information:
|
See the link below for more information:
|
||||||
$gradleAgpCompatUrl
|
$gradleAgpCompatUrl
|
||||||
''';
|
''';
|
||||||
|
@ -6,6 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// AGP version is set in settings.gradle.
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@ buildscript {
|
|||||||
}
|
}
|
||||||
|
|
||||||
dependencies {
|
dependencies {
|
||||||
|
// AGP version is set in settings.gradle.
|
||||||
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -469,6 +469,51 @@ allprojects {
|
|||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
testWithoutContext('returns the AGP version when in settings', () async {
|
||||||
|
final Directory androidDirectory = fileSystem.directory('/android')
|
||||||
|
..createSync();
|
||||||
|
// File must exist and can not have agp defined.
|
||||||
|
androidDirectory.childFile('build.gradle').writeAsStringSync(r'');
|
||||||
|
androidDirectory.childFile('settings.gradle').writeAsStringSync(r'''
|
||||||
|
pluginManagement {
|
||||||
|
def flutterSdkPath = {
|
||||||
|
def properties = new Properties()
|
||||||
|
file("local.properties").withInputStream { properties.load(it) }
|
||||||
|
def flutterSdkPath = properties.getProperty("flutter.sdk")
|
||||||
|
assert flutterSdkPath != null, "flutter.sdk not set in local.properties"
|
||||||
|
return flutterSdkPath
|
||||||
|
}
|
||||||
|
settings.ext.flutterSdkPath = flutterSdkPath()
|
||||||
|
|
||||||
|
includeBuild("${settings.ext.flutterSdkPath}/packages/flutter_tools/gradle")
|
||||||
|
|
||||||
|
repositories {
|
||||||
|
google()
|
||||||
|
mavenCentral()
|
||||||
|
gradlePluginPortal()
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id "dev.flutter.flutter-gradle-plugin" version "1.0.0" apply false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
plugins {
|
||||||
|
id "dev.flutter.flutter-plugin-loader" version "1.0.0"
|
||||||
|
// Decoy value to ensure we ignore commented out lines.
|
||||||
|
// id "com.android.application" version "6.1.0" apply false
|
||||||
|
id "com.android.application" version "7.3.0" apply false
|
||||||
|
}
|
||||||
|
|
||||||
|
include ":app"
|
||||||
|
''');
|
||||||
|
|
||||||
|
expect(
|
||||||
|
getAgpVersion(androidDirectory, BufferLogger.test()),
|
||||||
|
'7.3.0',
|
||||||
|
);
|
||||||
|
});
|
||||||
|
|
||||||
group('validates gradle/agp versions', () {
|
group('validates gradle/agp versions', () {
|
||||||
final List<GradleAgpTestData> testData = <GradleAgpTestData>[
|
final List<GradleAgpTestData> testData = <GradleAgpTestData>[
|
||||||
// Values too new *these need to be updated* when
|
// Values too new *these need to be updated* when
|
||||||
|
@ -659,6 +659,48 @@ dependencies {
|
|||||||
androidSdk: androidSdk,
|
androidSdk: androidSdk,
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
|
group('_', () {
|
||||||
|
final FakeProcessManager processManager;
|
||||||
|
final Java java;
|
||||||
|
final AndroidStudio androidStudio;
|
||||||
|
final FakeAndroidSdkWithDir androidSdk;
|
||||||
|
final FileSystem fileSystem = getFileSystemForPlatform();
|
||||||
|
java = FakeJava(version: Version(11, 0, 2));
|
||||||
|
processManager = FakeProcessManager.empty();
|
||||||
|
androidStudio = FakeAndroidStudio();
|
||||||
|
androidSdk =
|
||||||
|
FakeAndroidSdkWithDir(fileSystem.currentDirectory);
|
||||||
|
fileSystem.currentDirectory
|
||||||
|
.childDirectory(androidStudio.javaPath!)
|
||||||
|
.createSync();
|
||||||
|
_testInMemory(
|
||||||
|
'null agp only',
|
||||||
|
() async {
|
||||||
|
const String gradleV = '7.0.3';
|
||||||
|
final FlutterProject? project = await configureGradleAgpForTest(
|
||||||
|
gradleV: gradleV,
|
||||||
|
agpV: '',
|
||||||
|
);
|
||||||
|
final CompatibilityResult value =
|
||||||
|
await project!.android.hasValidJavaGradleAgpVersions();
|
||||||
|
expect(value.success, isFalse);
|
||||||
|
// Should not have the valid string.
|
||||||
|
expect(
|
||||||
|
value.description,
|
||||||
|
isNot(
|
||||||
|
contains(RegExp(AndroidProject.validJavaGradleAgpString))));
|
||||||
|
// On gradle/agp error print help url null value for agp.
|
||||||
|
expect(value.description,
|
||||||
|
contains(RegExp(AndroidProject.gradleAgpCompatUrl)));
|
||||||
|
expect(value.description, contains(RegExp(gradleV)));
|
||||||
|
expect(value.description, contains(RegExp('null')));
|
||||||
|
},
|
||||||
|
java: java,
|
||||||
|
androidStudio: androidStudio,
|
||||||
|
processManager: processManager,
|
||||||
|
androidSdk: androidSdk,
|
||||||
|
);
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
group('language', () {
|
group('language', () {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user