Unverified Commit c479109e authored by Reid Baker's avatar Reid Baker Committed by GitHub

Fix gradle lints No semantic change should be present. (#141692)

Move static methods together.
Fix property uses of duplicate strings.
Add types wherever obvious
Fix format depth
Add whitespace to top and bottom of classes
Ignore line length for file
Ignore prefer single quote for file
Ignore correction for getFoo used instead of foo

Loosely related to flutter/flutter/issues/123934
parent 6065c426
/* groovylint-disable LineLength, UnnecessaryGString, UnnecessaryGetter */
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
......@@ -6,7 +7,6 @@ import com.android.build.OutputFile
import groovy.json.JsonGenerator
import groovy.xml.QName
import java.nio.file.Paths
import java.util.Set
import org.apache.tools.ant.taskdefs.condition.Os
import org.gradle.api.DefaultTask
import org.gradle.api.GradleException
......@@ -40,6 +40,7 @@ import org.gradle.internal.os.OperatingSystem
* * https://docs.gradle.org/8.0.2/userguide/custom_plugins.html#sec:getting_input_from_the_build
*/
class FlutterExtension {
/** Sets the compileSdkVersion used by default in Flutter app projects. */
final int compileSdkVersion = 34
......@@ -97,6 +98,7 @@ class FlutterExtension {
return flutterVersionName
}
}
// This buildscript block supplies dependencies for this file's own import
......@@ -133,21 +135,22 @@ android {
apply plugin: FlutterPlugin
class FlutterPlugin implements Plugin<Project> {
private static final String DEFAULT_MAVEN_HOST = "https://storage.googleapis.com";
private static final String DEFAULT_MAVEN_HOST = "https://storage.googleapis.com"
/** The platforms that can be passed to the `--Ptarget-platform` flag. */
private static final String PLATFORM_ARM32 = "android-arm";
private static final String PLATFORM_ARM64 = "android-arm64";
private static final String PLATFORM_X86 = "android-x86";
private static final String PLATFORM_X86_64 = "android-x64";
private static final String PLATFORM_ARM32 = "android-arm"
private static final String PLATFORM_ARM64 = "android-arm64"
private static final String PLATFORM_X86 = "android-x86"
private static final String PLATFORM_X86_64 = "android-x64"
/** The ABI architectures supported by Flutter. */
private static final String ARCH_ARM32 = "armeabi-v7a";
private static final String ARCH_ARM64 = "arm64-v8a";
private static final String ARCH_X86 = "x86";
private static final String ARCH_X86_64 = "x86_64";
private static final String ARCH_ARM32 = "armeabi-v7a"
private static final String ARCH_ARM64 = "arm64-v8a"
private static final String ARCH_X86 = "x86"
private static final String ARCH_X86_64 = "x86_64"
private static final String INTERMEDIATES_DIR = "intermediates";
private static final String INTERMEDIATES_DIR = "intermediates"
/** Maps platforms to ABI architectures. */
private static final Map PLATFORM_ARCH_MAP = [
......@@ -162,7 +165,7 @@ class FlutterPlugin implements Plugin<Project> {
* For each APK variant, use the following versions to override the version of the Universal APK.
* Otherwise, the Play Store will complain that the APK variants have the same version.
*/
private static final Map ABI_VERSION = [
private static final Map<String, int> ABI_VERSION = [
(ARCH_ARM32) : 1,
(ARCH_ARM64) : 2,
(ARCH_X86) : 3,
......@@ -176,6 +179,9 @@ class FlutterPlugin implements Plugin<Project> {
PLATFORM_X86_64,
]
private final static String propLocalEngineRepo = "local-engine-repo"
private final static String propProcessResourcesProvider = "processResourcesProvider"
/**
* The name prefix for flutter builds. This is used to identify gradle tasks
* where we expect the flutter tool to provide any error output, and skip the
......@@ -186,7 +192,6 @@ class FlutterPlugin implements Plugin<Project> {
static final String FLUTTER_BUILD_PREFIX = "flutterBuild"
private Project project
private Map baseJar = [:]
private File flutterRoot
private File flutterExecutable
private String localEngine
......@@ -205,11 +210,11 @@ class FlutterPlugin implements Plugin<Project> {
void apply(Project project) {
this.project = project
def rootProject = project.rootProject
Project rootProject = project.rootProject
if (isFlutterAppProject()) {
rootProject.tasks.register("generateLockfiles") {
rootProject.subprojects.each { subproject ->
def gradlew = (OperatingSystem.current().isWindows()) ?
String gradlew = (OperatingSystem.current().isWindows()) ?
"${rootProject.projectDir}/gradlew.bat" : "${rootProject.projectDir}/gradlew"
rootProject.exec {
workingDir(rootProject.projectDir)
......@@ -241,7 +246,7 @@ class FlutterPlugin implements Plugin<Project> {
// Configure the Maven repository.
String hostedRepository = System.env.FLUTTER_STORAGE_BASE_URL ?: DEFAULT_MAVEN_HOST
String repository = useLocalEngine()
? project.property("local-engine-repo")
? project.property(propLocalEngineRepo)
: "$hostedRepository/${engineRealm}download.flutter.io"
rootProject.allprojects {
repositories {
......@@ -254,23 +259,22 @@ class FlutterPlugin implements Plugin<Project> {
// Load shared gradle functions
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "groovy", "native_plugin_loader.groovy")
def extension = project.extensions.create("flutter", FlutterExtension)
def localProperties = new Properties()
def localPropertiesFile = rootProject.file("local.properties")
FlutterExtension extension = project.extensions.create("flutter", FlutterExtension)
Properties localProperties = new Properties()
File localPropertiesFile = rootProject.file("local.properties")
if (localPropertiesFile.exists()) {
localPropertiesFile.withReader("UTF-8") { reader ->
localProperties.load(reader)
}
}
def flutterVersionCode = localProperties.getProperty("flutter.versionCode")
Object flutterVersionCode = localProperties.getProperty("flutter.versionCode")
if (flutterVersionCode == null) {
flutterVersionCode = "1"
}
extension.flutterVersionCode = flutterVersionCode
def flutterVersionName = localProperties.getProperty("flutter.versionName")
Object flutterVersionName = localProperties.getProperty("flutter.versionName")
if (flutterVersionName == null) {
flutterVersionName = "1.0"
}
......@@ -295,9 +299,9 @@ class FlutterPlugin implements Plugin<Project> {
}
}
}
if (project.hasProperty("deferred-component-names")) {
String[] componentNames = project.property("deferred-component-names").split(",").collect {":${it}"}
final String propDeferredComponentNames = "deferred-component-names"
if (project.hasProperty(propDeferredComponentNames)) {
String[] componentNames = project.property(propDeferredComponentNames).split(",").collect {":${it}"}
project.android {
dynamicFeatures = componentNames
}
......@@ -317,10 +321,11 @@ class FlutterPlugin implements Plugin<Project> {
}
String flutterExecutableName = Os.isFamily(Os.FAMILY_WINDOWS) ? "flutter.bat" : "flutter"
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile();
flutterExecutable = Paths.get(flutterRoot.absolutePath, "bin", flutterExecutableName).toFile()
if (project.hasProperty("multidex-enabled") &&
project.property("multidex-enabled").toBoolean()) {
final String propMultidexEnabled = "multidex-enabled"
if (project.hasProperty(propMultidexEnabled) &&
project.property(propMultidexEnabled).toBoolean()) {
String flutterMultidexKeepfile = Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools",
"gradle", "flutter_multidex_keepfile.txt")
project.android {
......@@ -333,7 +338,7 @@ class FlutterPlugin implements Plugin<Project> {
project.dependencies {
implementation("androidx.multidex:multidex:2.0.1")
}
}
}
// Use Kotlin DSL to handle baseApplicationName logic due to Groovy dynamic dispatch bug.
project.apply from: Paths.get(flutterRoot.absolutePath, "packages", "flutter_tools", "gradle", "src", "main", "kotlin", "flutter.gradle.kts")
......@@ -387,12 +392,213 @@ class FlutterPlugin implements Plugin<Project> {
}
private static Boolean shouldShrinkResources(Project project) {
if (project.hasProperty("shrink")) {
return project.property("shrink").toBoolean()
final String propShrink = "shrink"
if (project.hasProperty(propShrink)) {
return project.property(propShrink).toBoolean()
}
return true
}
private static String toCamelCase(List<String> parts) {
if (parts.empty) {
return ""
}
return "${parts[0]}${parts[1..-1].collect { it.capitalize() }.join('')}"
}
private static Properties readPropertiesIfExist(File propertiesFile) {
Properties result = new Properties()
if (propertiesFile.exists()) {
propertiesFile.withReader("UTF-8") { reader -> result.load(reader) }
}
return result
}
private static Boolean isBuiltAsApp(Project project) {
// Projects are built as applications when the they use the `com.android.application`
// plugin.
return project.plugins.hasPlugin("com.android.application")
}
private static void addApiDependencies(Project project, String variantName, Object dependency, Closure config = null) {
String configuration
// `compile` dependencies are now `api` dependencies.
if (project.getConfigurations().findByName("api")) {
configuration = "${variantName}Api"
} else {
configuration = "${variantName}Compile"
}
project.dependencies.add(configuration, dependency, config)
}
// Add a task that can be called on flutter projects that prints the Java version used in Gradle.
//
// Format of the output of this task can be used in debugging what version of Java Gradle is using.
// Not recommended for use in time sensitive commands like `flutter run` or `flutter build` as
// Gradle is slower than we want. Particularly in light of https://github.com/flutter/flutter/issues/119196.
private static void addTaskForJavaVersion(Project project) {
// Warning: the name of this task is used by other code. Change with caution.
project.tasks.register("javaVersion") {
description "Print the current java version used by gradle. "
"see: https://docs.gradle.org/current/javadoc/org/gradle/api/JavaVersion.html"
doLast {
println(JavaVersion.current())
}
}
}
// Add a task that can be called on Flutter projects that prints the available build variants
// in Gradle.
//
// This task prints variants in this format:
//
// BuildVariant: debug
// BuildVariant: release
// BuildVariant: profile
//
// Format of the output of this task is used by `AndroidProject.getBuildVariants`.
private static void addTaskForPrintBuildVariants(Project project) {
// Warning: The name of this task is used by `AndroidProject.getBuildVariants`.
project.tasks.register("printBuildVariants") {
description "Prints out all build variants for this Android project"
doLast {
project.android.applicationVariants.all { variant ->
println "BuildVariant: ${variant.name}"
}
}
}
}
// Add a task that can be called on Flutter projects that outputs app link related project
// settings into a json file.
//
// See https://developer.android.com/training/app-links/ for more information about app link.
//
// The json will be saved in path stored in outputPath parameter.
//
// An example json:
// {
// applicationId: "com.example.app",
// deeplinks: [
// {"scheme":"http", "host":"example.com", "path":".*"},
// {"scheme":"https","host":"example.com","path":".*"}
// ]
// }
//
// The output file is parsed and used by devtool.
private static void addTasksForOutputsAppLinkSettings(Project project) {
project.android.applicationVariants.all { variant ->
// Warning: The name of this task is used by AndroidBuilder.outputsAppLinkSettings
project.tasks.register("output${variant.name.capitalize()}AppLinkSettings") {
description "stores app links settings for the given build variant of this Android project into a json file."
variant.outputs.all { output ->
// Deeplinks are defined in AndroidManifest.xml and is only available after
// `processResourcesProvider`.
Object processResources = output.hasProperty(propProcessResourcesProvider) ?
output.processResourcesProvider.get() : output.processResources
dependsOn processResources.name
}
doLast {
AppLinkSettings appLinkSettings = new AppLinkSettings()
appLinkSettings.applicationId = variant.applicationId
appLinkSettings.deeplinks = [] as Set<Deeplink>
variant.outputs.all { output ->
Object processResources = output.hasProperty(propProcessResourcesProvider) ?
output.processResourcesProvider.get() : output.processResources
def manifest = new XmlParser().parse(processResources.manifestFile)
manifest.application.activity.each { activity ->
activity."meta-data".each { metadata ->
boolean nameAttribute = metadata.attributes().find { it.key == 'android:name' }?.value == 'flutter_deeplinking_enabled'
boolean valueAttribute = metadata.attributes().find { it.key == 'android:value' }?.value == 'true'
if (nameAttribute && valueAttribute) {
appLinkSettings.deeplinkingFlagEnabled = true
}
}
activity."intent-filter".each { appLinkIntent ->
// Print out the host attributes in data tags.
Set<String> schemes = [] as Set<String>
Set<String> hosts = [] as Set<String>
Set<String> paths = [] as Set<String>
IntentFilterCheck intentFilterCheck = new IntentFilterCheck()
if (appLinkIntent.attributes().find { it.key == 'android:autoVerify' }?.value == 'true') {
intentFilterCheck.hasAutoVerify = true
}
appLinkIntent.'action'.each { action ->
if (action.attributes().find { it.key == 'android:name' }?.value == 'android.intent.action.VIEW') {
intentFilterCheck.hasActionView = true
}
}
appLinkIntent.'category'.each { category ->
if (category.attributes().find { it.key == 'android:name' }?.value == 'android.intent.category.DEFAULT') {
intentFilterCheck.hasDefaultCategory = true
}
if (category.attributes().find { it.key == 'android:name' }?.value == 'android.intent.category.BROWSABLE') {
intentFilterCheck.hasBrowsableCategory = true
}
}
appLinkIntent.data.each { data ->
data.attributes().each { entry ->
if (entry.key instanceof QName) {
switch (entry.key.getLocalPart()) {
case "scheme":
schemes.add(entry.value)
break
case "host":
hosts.add(entry.value)
break
case "pathAdvancedPattern":
case "pathPattern":
case "path":
paths.add(entry.value)
break
case "pathPrefix":
paths.add("${entry.value}.*")
break
case "pathSuffix":
paths.add(".*${entry.value}")
break
}
}
}
}
schemes.each { scheme ->
hosts.each { host ->
if (!paths) {
appLinkSettings.deeplinks.add(new Deeplink(scheme: scheme, host: host, path: ".*", intentFilterCheck: intentFilterCheck))
} else {
paths.each { path ->
appLinkSettings.deeplinks.add(new Deeplink(scheme: scheme, host: host, path: path, intentFilterCheck: intentFilterCheck))
}
}
}
}
}
}
}
JsonGenerator generator = new JsonGenerator.Options().build()
new File(project.getProperty("outputPath")).write(generator.toJson(appLinkSettings))
}
}
}
}
/**
* Returns a Flutter build mode suitable for the specified Android buildType.
*
* The BuildType DSL type is not public, and is therefore omitted from the signature.
*
* @return "debug", "profile", or "release" (fall-back).
*/
private static String buildModeFor(buildType) {
if (buildType.name == "profile") {
return "profile"
} else if (buildType.debuggable) {
return "debug"
}
return "release"
}
/**
* Adds the dependencies required by the Flutter project.
* This includes:
......@@ -428,17 +634,6 @@ class FlutterPlugin implements Plugin<Project> {
}
}
/**
* Returns the directory where the plugins are built.
*/
private File getPluginBuildDir() {
// Module projects specify this flag to include plugins in the same repo as the module project.
if (project.ext.has("pluginBuildDir")) {
return project.ext.get("pluginBuildDir")
}
return project.buildDir
}
/**
* Configures the Flutter plugin dependencies.
*
......@@ -473,7 +668,7 @@ class FlutterPlugin implements Plugin<Project> {
* and filtered then with the [doesSupportAndroidPlatform] method instead of
* just using the `plugins.android` list.
*/
private configureLegacyPluginEachProjects(Project project) {
private void configureLegacyPluginEachProjects(Project project) {
try {
if (!settingsGradleFile(project).text.contains("'.flutter-plugins'")) {
return
......@@ -493,8 +688,9 @@ class FlutterPlugin implements Plugin<Project> {
// Plugin has a functioning `android` folder and is included successfully, although it's not supported.
// It must be configured nonetheless, to not throw an "Unresolved reference" exception.
configurePluginProject(it)
/* groovylint-disable-next-line EmptyElseBlock */
} else {
// Plugin has no or an empty `android` folder. No action required.
// Plugin has no or an empty `android` folder. No action required.
}
}
}
......@@ -594,16 +790,17 @@ class FlutterPlugin implements Plugin<Project> {
* If minor or patch are omitted (non-conformant to semantic versioning), they are considered zero.
* If the provided versions in both are equal, the longest version string is returned.
* For example, "2.8.0" vs "2.8" will always consider "2.8.0" to be the most recent version.
* TODO: Remove this or compareVersionStrings. This does not handle strings like "8.6-rc-2".
*/
static String mostRecentSemanticVersion(String version1, String version2) {
List version1Tokenized = version1.tokenize(".")
List version2Tokenized = version2.tokenize(".")
def version1numTokens = version1Tokenized.size()
def version2numTokens = version2Tokenized.size()
def minNumTokens = Math.min(version1numTokens, version2numTokens)
int version1numTokens = version1Tokenized.size()
int version2numTokens = version2Tokenized.size()
int minNumTokens = Math.min(version1numTokens, version2numTokens)
for (int i = 0; i < minNumTokens; i++) {
def num1 = version1Tokenized[i].toInteger()
def num2 = version2Tokenized[i].toInteger()
int num1 = version1Tokenized[i].toInteger()
int num2 = version2Tokenized[i].toInteger()
if (num1 > num2) {
return version1
}
......@@ -640,10 +837,10 @@ class FlutterPlugin implements Plugin<Project> {
}
pluginProject.afterEvaluate {
// Default to int min if using a preview version to skip the sdk check.
int pluginCompileSdkVersion = Integer.MIN_VALUE;
int pluginCompileSdkVersion = Integer.MIN_VALUE
// Stable versions use ints, legacy preview uses string.
if (getCompileSdkFromProject(pluginProject).isInteger()) {
pluginCompileSdkVersion = getCompileSdkFromProject(pluginProject) as int;
pluginCompileSdkVersion = getCompileSdkFromProject(pluginProject) as int
}
maxPluginCompileSdkVersion = Math.max(pluginCompileSdkVersion, maxPluginCompileSdkVersion)
String pluginNdkVersion = pluginProject.android.ndkVersion ?: ndkVersionIfUnspecified
......@@ -668,7 +865,7 @@ class FlutterPlugin implements Plugin<Project> {
* or string version.
*/
private String getCompileSdkFromProject(Project gradleProject) {
return gradleProject.android.compileSdkVersion.substring(8);
return gradleProject.android.compileSdkVersion.substring(8)
}
/**
......@@ -724,13 +921,6 @@ class FlutterPlugin implements Plugin<Project> {
return meta.dependencyGraph as List<Map<String, Object>>
}
private static String toCamelCase(List<String> parts) {
if (parts.empty) {
return ""
}
return "${parts[0]}${parts[1..-1].collect { it.capitalize() }.join('')}"
}
private String resolveProperty(String name, String defaultValue) {
if (localProperties == null) {
localProperties = readPropertiesIfExist(new File(project.projectDir.parentFile, "local.properties"))
......@@ -748,19 +938,12 @@ class FlutterPlugin implements Plugin<Project> {
return result
}
private static Properties readPropertiesIfExist(File propertiesFile) {
Properties result = new Properties()
if (propertiesFile.exists()) {
propertiesFile.withReader("UTF-8") { reader -> result.load(reader) }
}
return result
}
private List<String> getTargetPlatforms() {
if (!project.hasProperty("target-platform")) {
final String propTargetPlatform = "target-platform"
if (!project.hasProperty(propTargetPlatform)) {
return DEFAULT_PLATFORMS
}
return project.property("target-platform").split(",").collect {
return project.property(propTargetPlatform).split(",").collect {
if (!PLATFORM_ARCH_MAP[it]) {
throw new GradleException("Invalid platform: $it.")
}
......@@ -769,26 +952,20 @@ class FlutterPlugin implements Plugin<Project> {
}
private Boolean shouldSplitPerAbi() {
return project.findProperty("split-per-abi")?.toBoolean() ?: false;
return project.findProperty("split-per-abi")?.toBoolean() ?: false
}
private Boolean useLocalEngine() {
return project.hasProperty("local-engine-repo")
return project.hasProperty(propLocalEngineRepo)
}
private Boolean isVerbose() {
return project.findProperty("verbose")?.toBoolean() ?: false;
return project.findProperty("verbose")?.toBoolean() ?: false
}
/** Whether to build the debug app in "fast-start" mode. */
private Boolean isFastStart() {
return project.findProperty("fast-start")?.toBoolean() ?: false;
}
private static Boolean isBuiltAsApp(Project project) {
// Projects are built as applications when the they use the `com.android.application`
// plugin.
return project.plugins.hasPlugin("com.android.application");
return project.findProperty("fast-start")?.toBoolean() ?: false
}
/**
......@@ -798,213 +975,13 @@ class FlutterPlugin implements Plugin<Project> {
*/
private Boolean supportsBuildMode(String flutterBuildMode) {
if (!useLocalEngine()) {
return true;
return true
}
assert(project.hasProperty("local-engine-build-mode"))
final String propLocalEngineBuildMode = "local-engine-build-mode"
assert(project.hasProperty(propLocalEngineBuildMode))
// Don't configure dependencies for a build mode that the local engine
// doesn't support.
return project.property("local-engine-build-mode") == flutterBuildMode
}
private void addCompileOnlyDependency(Project project, String variantName, Object dependency, Closure config = null) {
if (project.state.failure) {
return
}
String configuration;
if (project.getConfigurations().findByName("compileOnly")) {
configuration = "${variantName}CompileOnly";
} else {
configuration = "${variantName}Provided";
}
project.dependencies.add(configuration, dependency, config)
}
private static void addApiDependencies(Project project, String variantName, Object dependency, Closure config = null) {
String configuration;
// `compile` dependencies are now `api` dependencies.
if (project.getConfigurations().findByName("api")) {
configuration = "${variantName}Api";
} else {
configuration = "${variantName}Compile";
}
project.dependencies.add(configuration, dependency, config)
}
// Add a task that can be called on flutter projects that prints the Java version used in Gradle.
//
// Format of the output of this task can be used in debugging what version of Java Gradle is using.
// Not recommended for use in time sensitive commands like `flutter run` or `flutter build` as
// Gradle is slower than we want. Particularly in light of https://github.com/flutter/flutter/issues/119196.
private static void addTaskForJavaVersion(Project project) {
// Warning: the name of this task is used by other code. Change with caution.
project.tasks.register("javaVersion") {
description "Print the current java version used by gradle. "
"see: https://docs.gradle.org/current/javadoc/org/gradle/api/JavaVersion.html"
doLast {
println(JavaVersion.current())
}
}
}
// Add a task that can be called on Flutter projects that prints the available build variants
// in Gradle.
//
// This task prints variants in this format:
//
// BuildVariant: debug
// BuildVariant: release
// BuildVariant: profile
//
// Format of the output of this task is used by `AndroidProject.getBuildVariants`.
private static void addTaskForPrintBuildVariants(Project project) {
// Warning: The name of this task is used by `AndroidProject.getBuildVariants`.
project.tasks.register("printBuildVariants") {
description "Prints out all build variants for this Android project"
doLast {
project.android.applicationVariants.all { variant ->
println "BuildVariant: ${variant.name}";
}
}
}
}
// Add a task that can be called on Flutter projects that outputs app link related project
// settings into a json file.
//
// See https://developer.android.com/training/app-links/ for more information about app link.
//
// The json will be saved in path stored in outputPath parameter.
//
// An example json:
// {
// applicationId: "com.example.app",
// deeplinks: [
// {"scheme":"http", "host":"example.com", "path":".*"},
// {"scheme":"https","host":"example.com","path":".*"}
// ]
// }
//
// The output file is parsed and used by devtool.
private static void addTasksForOutputsAppLinkSettings(Project project) {
project.android.applicationVariants.all { variant ->
// Warning: The name of this task is used by AndroidBuilder.outputsAppLinkSettings
project.tasks.register("output${variant.name.capitalize()}AppLinkSettings") {
description "stores app links settings for the given build variant of this Android project into a json file."
variant.outputs.all { output ->
// Deeplinks are defined in AndroidManifest.xml and is only available after
// `processResourcesProvider`.
def processResources = output.hasProperty("processResourcesProvider") ?
output.processResourcesProvider.get() : output.processResources
dependsOn processResources.name
}
doLast {
def appLinkSettings = new AppLinkSettings()
appLinkSettings.applicationId = variant.applicationId
appLinkSettings.deeplinks = [] as Set<Deeplink>
variant.outputs.all { output ->
def processResources = output.hasProperty("processResourcesProvider") ?
output.processResourcesProvider.get() : output.processResources
def manifest = new XmlParser().parse(processResources.manifestFile)
manifest.application.activity.each { activity ->
activity."meta-data".each { metadata ->
def nameAttribute = metadata.attributes().find { it.key == 'android:name' }?.value == 'flutter_deeplinking_enabled'
def valueAttribute = metadata.attributes().find { it.key == 'android:value' }?.value == 'true'
if (nameAttribute && valueAttribute) {
appLinkSettings.deeplinkingFlagEnabled = true
}
}
activity."intent-filter".each { appLinkIntent ->
// Print out the host attributes in data tags.
def schemes = [] as Set<String>
def hosts = [] as Set<String>
def paths = [] as Set<String>
def intentFilterCheck = new IntentFilterCheck()
if (appLinkIntent.attributes().find { it.key == 'android:autoVerify' }?.value == 'true') {
intentFilterCheck.hasAutoVerify = true
}
appLinkIntent.'action'.each { action ->
if (action.attributes().find { it.key == 'android:name' }?.value == 'android.intent.action.VIEW') {
intentFilterCheck.hasActionView = true
}
}
appLinkIntent.'category'.each { category ->
if (category.attributes().find { it.key == 'android:name' }?.value == 'android.intent.category.DEFAULT') {
intentFilterCheck.hasDefaultCategory = true
}
if (category.attributes().find { it.key == 'android:name' }?.value == 'android.intent.category.BROWSABLE') {
intentFilterCheck.hasBrowsableCategory = true
}
}
appLinkIntent.data.each { data ->
data.attributes().each { entry ->
if (entry.key instanceof QName) {
switch (entry.key.getLocalPart()) {
case "scheme":
schemes.add(entry.value)
break
case "host":
hosts.add(entry.value)
break
case "pathAdvancedPattern":
case "pathPattern":
case "path":
paths.add(entry.value)
break
case "pathPrefix":
paths.add("${entry.value}.*")
break
case "pathSuffix":
paths.add(".*${entry.value}")
break
}
}
}
}
schemes.each {scheme ->
hosts.each { host ->
if (!paths) {
appLinkSettings.deeplinks.add(new Deeplink(scheme: scheme, host: host, path: ".*", intentFilterCheck: intentFilterCheck))
} else {
paths.each { path ->
appLinkSettings.deeplinks.add(new Deeplink(scheme: scheme, host: host, path: path, intentFilterCheck: intentFilterCheck))
}
}
}
}
}
}
}
def generator = new JsonGenerator.Options().build()
new File(project.getProperty("outputPath")).write(generator.toJson(appLinkSettings))
}
}
}
}
/**
* Returns a Flutter build mode suitable for the specified Android buildType.
*
* The BuildType DSL type is not public, and is therefore omitted from the signature.
*
* @return "debug", "profile", or "release" (fall-back).
*/
private static String buildModeFor(buildType) {
if (buildType.name == "profile") {
return "profile"
} else if (buildType.debuggable) {
return "debug"
}
return "release"
}
private static String getEngineArtifactDirName(buildType, targetArch) {
if (buildType.name == "profile") {
return "${targetArch}-profile"
} else if (buildType.debuggable) {
return "${targetArch}"
}
return "${targetArch}-release"
return project.property(propLocalEngineBuildMode) == flutterBuildMode
}
/**
......@@ -1026,8 +1003,9 @@ class FlutterPlugin implements Plugin<Project> {
if (target == null) {
target = "lib/main.dart"
}
if (project.hasProperty("target")) {
target = project.property("target")
final String propTarget = "target"
if (project.hasProperty(propTarget)) {
target = project.property(propTarget)
}
return target
}
......@@ -1062,11 +1040,11 @@ class FlutterPlugin implements Plugin<Project> {
* https://issuetracker.google.com/issues/158753935
*/
private boolean shouldConfigureFlutterTask(Task assembleTask) {
def cliTasksNames = project.gradle.startParameter.taskNames
List<String> cliTasksNames = project.gradle.startParameter.taskNames
if (cliTasksNames.size() != 1 || !cliTasksNames.first().contains("assemble")) {
return true
}
def taskName = cliTasksNames.first().split(":").last()
String taskName = cliTasksNames.first().split(":").last()
if (taskName == "assemble") {
return true
}
......@@ -1099,71 +1077,86 @@ class FlutterPlugin implements Plugin<Project> {
return
}
String[] fileSystemRootsValue = null
if (project.hasProperty("filesystem-roots")) {
fileSystemRootsValue = project.property("filesystem-roots").split("\\|")
final String propFileSystemRoots = "filesystem-roots"
if (project.hasProperty(propFileSystemRoots)) {
fileSystemRootsValue = project.property(propFileSystemRoots).split("\\|")
}
String fileSystemSchemeValue = null
if (project.hasProperty("filesystem-scheme")) {
fileSystemSchemeValue = project.property("filesystem-scheme")
final String propFileSystemScheme = "filesystem-scheme"
if (project.hasProperty(propFileSystemScheme)) {
fileSystemSchemeValue = project.property(propFileSystemScheme)
}
Boolean trackWidgetCreationValue = true
if (project.hasProperty("track-widget-creation")) {
trackWidgetCreationValue = project.property("track-widget-creation").toBoolean()
final String propTrackWidgetCreation = "track-widget-creation"
if (project.hasProperty(propTrackWidgetCreation)) {
trackWidgetCreationValue = project.property(propTrackWidgetCreation).toBoolean()
}
String frontendServerStarterPathValue = null
if (project.hasProperty("frontend-server-starter-path")) {
frontendServerStarterPathValue = project.property("frontend-server-starter-path")
final String propFrontendServerStarterPath = "frontend-server-starter-path"
if (project.hasProperty(propFrontendServerStarterPath)) {
frontendServerStarterPathValue = project.property(propFrontendServerStarterPath)
}
String extraFrontEndOptionsValue = null
if (project.hasProperty("extra-front-end-options")) {
extraFrontEndOptionsValue = project.property("extra-front-end-options")
final String propExtraFrontEndOptions = "extra-front-end-options"
if (project.hasProperty(propExtraFrontEndOptions)) {
extraFrontEndOptionsValue = project.property(propExtraFrontEndOptions)
}
String extraGenSnapshotOptionsValue = null
if (project.hasProperty("extra-gen-snapshot-options")) {
extraGenSnapshotOptionsValue = project.property("extra-gen-snapshot-options")
final String propExtraGenSnapshotOptions = "extra-gen-snapshot-options"
if (project.hasProperty(propExtraGenSnapshotOptions)) {
extraGenSnapshotOptionsValue = project.property(propExtraGenSnapshotOptions)
}
String splitDebugInfoValue = null
if (project.hasProperty("split-debug-info")) {
splitDebugInfoValue = project.property("split-debug-info")
final String propSplitDebugInfo = "split-debug-info"
if (project.hasProperty(propSplitDebugInfo)) {
splitDebugInfoValue = project.property(propSplitDebugInfo)
}
Boolean dartObfuscationValue = false
if (project.hasProperty("dart-obfuscation")) {
dartObfuscationValue = project.property("dart-obfuscation").toBoolean();
final String propDartObfuscation = "dart-obfuscation"
if (project.hasProperty(propDartObfuscation)) {
dartObfuscationValue = project.property(propDartObfuscation).toBoolean()
}
Boolean treeShakeIconsOptionsValue = false
if (project.hasProperty("tree-shake-icons")) {
treeShakeIconsOptionsValue = project.property("tree-shake-icons").toBoolean()
final String propTreeShakeIcons = "tree-shake-icons"
if (project.hasProperty(propTreeShakeIcons)) {
treeShakeIconsOptionsValue = project.property(propTreeShakeIcons).toBoolean()
}
String dartDefinesValue = null
if (project.hasProperty("dart-defines")) {
dartDefinesValue = project.property("dart-defines")
final String propDartDefines = "dart-defines"
if (project.hasProperty(propDartDefines)) {
dartDefinesValue = project.property(propDartDefines)
}
String bundleSkSLPathValue;
if (project.hasProperty("bundle-sksl-path")) {
bundleSkSLPathValue = project.property("bundle-sksl-path")
String bundleSkSLPathValue
final String propBundleSkslPath = "bundle-sksl-path"
if (project.hasProperty(propBundleSkslPath)) {
bundleSkSLPathValue = project.property(propBundleSkslPath)
}
String performanceMeasurementFileValue;
if (project.hasProperty("performance-measurement-file")) {
performanceMeasurementFileValue = project.property("performance-measurement-file")
String performanceMeasurementFileValue
final String propPerformanceMesaurementFile = "performance-measurement-file"
if (project.hasProperty(propPerformanceMesaurementFile)) {
performanceMeasurementFileValue = project.property(propPerformanceMesaurementFile)
}
String codeSizeDirectoryValue;
if (project.hasProperty("code-size-directory")) {
codeSizeDirectoryValue = project.property("code-size-directory")
String codeSizeDirectoryValue
final String propCodeSizeDirectory = "code-size-directory"
if (project.hasProperty(propCodeSizeDirectory)) {
codeSizeDirectoryValue = project.property(propCodeSizeDirectory)
}
Boolean deferredComponentsValue = false
if (project.hasProperty("deferred-components")) {
deferredComponentsValue = project.property("deferred-components").toBoolean()
final String propDeferredComponents = "deferred-components"
if (project.hasProperty(propDeferredComponents)) {
deferredComponentsValue = project.property(propDeferredComponents).toBoolean()
}
Boolean validateDeferredComponentsValue = true
if (project.hasProperty("validate-deferred-components")) {
validateDeferredComponentsValue = project.property("validate-deferred-components").toBoolean()
final String propValidateDeferredComponents = "validate-deferred-components"
if (project.hasProperty(propValidateDeferredComponents)) {
validateDeferredComponentsValue = project.property(propValidateDeferredComponents).toBoolean()
}
addTaskForJavaVersion(project)
if(isFlutterAppProject()) {
if (isFlutterAppProject()) {
addTaskForPrintBuildVariants(project)
addTasksForOutputsAppLinkSettings(project)
}
def targetPlatforms = getTargetPlatforms()
List<String> targetPlatforms = getTargetPlatforms()
def addFlutterDeps = { variant ->
if (shouldSplitPerAbi()) {
variant.outputs.each { output ->
......@@ -1171,7 +1164,7 @@ class FlutterPlugin implements Plugin<Project> {
// for only the output APK, not for the variant itself. Skipping this step simply
// causes Gradle to use the value of variant.versionCode for the APK.
// For more, see https://developer.android.com/studio/build/configure-apk-splits
def abiVersionCode = ABI_VERSION.get(output.getFilter(OutputFile.ABI))
int abiVersionCode = ABI_VERSION.get(output.getFilter(OutputFile.ABI))
if (abiVersionCode != null) {
output.versionCodeOverride =
abiVersionCode * 1000 + variant.versionCode
......@@ -1242,8 +1235,8 @@ class FlutterPlugin implements Plugin<Project> {
}
// Copy the native assets created by build.dart and placed in build/native_assets by flutter assemble.
// The `$project.buildDir` is '.android/Flutter/build/' instead of 'build/'.
def buildDir = "${getFlutterSourceDirectory()}/build"
def nativeAssetsDir = "${buildDir}/native_assets/android/jniLibs/lib"
String buildDir = "${getFlutterSourceDirectory()}/build"
String nativeAssetsDir = "${buildDir}/native_assets/android/jniLibs/lib"
from("${nativeAssetsDir}/${abi}") {
include "*.so"
rename { String filename ->
......@@ -1261,7 +1254,7 @@ class FlutterPlugin implements Plugin<Project> {
) {
dependsOn(compileTask)
with(compileTask.assets)
def currentGradleVersion = project.getGradle().getGradleVersion()
String currentGradleVersion = project.getGradle().getGradleVersion()
// See https://docs.gradle.org/current/javadoc/org/gradle/api/file/ConfigurableFilePermissions.html
// See https://github.com/flutter/flutter/pull/50047
......@@ -1293,7 +1286,7 @@ class FlutterPlugin implements Plugin<Project> {
}
if (!isUsedAsSubproject) {
def variantOutput = variant.outputs.first()
def processResources = variantOutput.hasProperty("processResourcesProvider") ?
def processResources = variantOutput.hasProperty(propProcessResourcesProvider) ?
variantOutput.processResourcesProvider.get() : variantOutput.processResources
processResources.dependsOn(copyFlutterAssetsTask)
}
......@@ -1317,11 +1310,11 @@ class FlutterPlugin implements Plugin<Project> {
project.android.applicationVariants.all { variant ->
Task assembleTask = getAssembleTask(variant)
if (!shouldConfigureFlutterTask(assembleTask)) {
return
return
}
Task copyFlutterAssetsTask = addFlutterDeps(variant)
def variantOutput = variant.outputs.first()
def processResources = variantOutput.hasProperty("processResourcesProvider") ?
def processResources = variantOutput.hasProperty(propProcessResourcesProvider) ?
variantOutput.processResourcesProvider.get() : variantOutput.processResources
processResources.dependsOn(copyFlutterAssetsTask)
......@@ -1354,7 +1347,7 @@ class FlutterPlugin implements Plugin<Project> {
filename += "-${buildModeFor(variant.buildType)}"
project.copy {
from new File("$outputDirectoryStr/${output.outputFileName}")
into new File("${project.buildDir}/outputs/flutter-apk");
into new File("${project.buildDir}/outputs/flutter-apk")
rename {
return "${filename}.apk"
}
......@@ -1362,7 +1355,7 @@ class FlutterPlugin implements Plugin<Project> {
}
}
// Copy the native assets created by build.dart and placed here by flutter assemble.
def nativeAssetsDir = "${project.buildDir}/../native_assets/android/jniLibs/lib/"
String nativeAssetsDir = "${project.buildDir}/../native_assets/android/jniLibs/lib/"
project.android.sourceSets.main.jniLibs.srcDir(nativeAssetsDir)
}
configurePlugins(project)
......@@ -1428,12 +1421,12 @@ class FlutterPlugin implements Plugin<Project> {
List firstVersion = firstString.tokenize(".")
List secondVersion = secondString.tokenize(".")
def commonIndices = Math.min(firstVersion.size(), secondVersion.size())
int commonIndices = Math.min(firstVersion.size(), secondVersion.size())
for (int i = 0; i < commonIndices; i++) {
String firstAtIndex = firstVersion[i]
String secondAtIndex = secondVersion[i]
int firstInt = 0;
int firstInt = 0
int secondInt = 0
try {
if (firstAtIndex.contains("-")) {
......@@ -1467,26 +1460,32 @@ class FlutterPlugin implements Plugin<Project> {
}
class AppLinkSettings {
String applicationId
Set<Deeplink> deeplinks
boolean deeplinkingFlagEnabled
}
class IntentFilterCheck {
boolean hasAutoVerify
boolean hasActionView
boolean hasDefaultCategory
boolean hasBrowsableCategory
}
class Deeplink {
String scheme, host, path
IntentFilterCheck intentFilterCheck
boolean equals(o) {
if (o == null)
if (o == null) {
throw new NullPointerException()
if (o.getClass() != getClass())
}
if (o.getClass() != getClass()) {
return false
}
return scheme == o.scheme &&
host == o.host &&
path == o.path
......@@ -1494,62 +1493,91 @@ class Deeplink {
}
abstract class BaseFlutterTask extends DefaultTask {
@Internal
File flutterRoot
@Internal
File flutterExecutable
@Input
String buildMode
@Input
int minSdkVersion
@Optional @Input
String localEngine
@Optional @Input
String localEngineHost
@Optional @Input
String localEngineSrcPath
@Optional @Input
Boolean fastStart
@Input
String targetPath
@Optional @Input
Boolean verbose
@Optional @Input
String[] fileSystemRoots
@Optional @Input
String fileSystemScheme
@Input
Boolean trackWidgetCreation
@Optional @Input
List<String> targetPlatformValues
@Internal
File sourceDir
@Internal
File intermediateDir
@Optional @Input
String frontendServerStarterPath
@Optional @Input
String extraFrontEndOptions
@Optional @Input
String extraGenSnapshotOptions
@Optional @Input
String splitDebugInfo
@Optional @Input
Boolean treeShakeIcons
@Optional @Input
Boolean dartObfuscation
@Optional @Input
String dartDefines
@Optional @Input
String bundleSkSLPath
@Optional @Input
String codeSizeDirectory;
String codeSizeDirectory
@Optional @Input
String performanceMeasurementFile;
String performanceMeasurementFile
@Optional @Input
Boolean deferredComponents
@Optional @Input
Boolean validateDeferredComponents
@Optional @Input
String flavor
......@@ -1573,7 +1601,7 @@ abstract class BaseFlutterTask extends DefaultTask {
// multiple ABIs, the target name is used to communicate which ones are required
// rather than the TargetPlatform. This allows multiple builds to share the same
// cache.
String[] ruleNames;
String[] ruleNames
if (buildMode == "debug") {
ruleNames = ["debug_android_application"]
} else if (deferredComponents) {
......@@ -1649,9 +1677,11 @@ abstract class BaseFlutterTask extends DefaultTask {
args(ruleNames)
}
}
}
class FlutterTask extends BaseFlutterTask {
@OutputDirectory
File getOutputDirectory() {
return intermediateDir
......@@ -1684,24 +1714,24 @@ class FlutterTask extends BaseFlutterTask {
}
FileCollection readDependencies(File dependenciesFile, Boolean inputs) {
if (dependenciesFile.exists()) {
// Dependencies file has Makefile syntax:
// <target> <files>: <source> <files> <separated> <by> <non-escaped space>
String depText = dependenciesFile.text
// So we split list of files by non-escaped(by backslash) space,
def matcher = depText.split(": ")[inputs ? 1 : 0] =~ /(\\ |[^\s])+/
// then we replace all escaped spaces with regular spaces
def depList = matcher.collect{it[0].replaceAll("\\\\ ", " ")}
return project.files(depList)
}
return project.files();
if (dependenciesFile.exists()) {
// Dependencies file has Makefile syntax:
// <target> <files>: <source> <files> <separated> <by> <non-escaped space>
String depText = dependenciesFile.text
// So we split list of files by non-escaped(by backslash) space,
def matcher = depText.split(": ")[inputs ? 1 : 0] =~ /(\\ |[^\s])+/
// then we replace all escaped spaces with regular spaces
def depList = matcher.collect{ it[0].replaceAll("\\\\ ", " ") }
return project.files(depList)
}
return project.files()
}
@InputFiles
FileCollection getSourceFiles() {
FileCollection sources = project.files()
for (File depfile in getDependenciesFiles()) {
sources += readDependencies(depfile, true)
sources += readDependencies(depfile, true)
}
return sources + project.files("pubspec.yaml")
}
......@@ -1710,7 +1740,7 @@ class FlutterTask extends BaseFlutterTask {
FileCollection getOutputFiles() {
FileCollection sources = project.files()
for (File depfile in getDependenciesFiles()) {
sources += readDependencies(depfile, false)
sources += readDependencies(depfile, false)
}
return sources
}
......@@ -1719,4 +1749,5 @@ class FlutterTask extends BaseFlutterTask {
void build() {
buildBundle()
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment