diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt index e49019b063b..f5ce9205cb8 100644 --- a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/kotlin/org/jetbrains/kotlin/gradle/AbstractKotlinAndroidGradleTests.kt @@ -514,6 +514,17 @@ open class KotlinAndroid70GradleIT : KotlinAndroid36GradleIT() { assertCompiledKotlinSources(project.relativize(affectedSources)) } } + + @Test + fun testNamespaceDSLInsteadOfPackageAttributeInManifest() { + val project = Project("AndroidExtensionsProjectAGP7") + val options = defaultBuildOptions().copy(incremental = false) + + project.build("assembleDebug", options = options) { + assertSuccessful() + assertContains("The 'kotlin-android-extensions' Gradle plugin is deprecated") + } + } } open class KotlinAndroid71GradleIT : KotlinAndroid70GradleIT() { diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/build.gradle new file mode 100644 index 00000000000..46e22f12b3d --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/build.gradle @@ -0,0 +1,25 @@ +apply plugin: 'com.android.application' +apply plugin: 'kotlin-android' +apply plugin: 'kotlin-android-extensions' + +android { + compileSdkVersion 23 + buildToolsVersion "25.0.2" + namespace "com.example.androidextensions" + + defaultConfig { + applicationId "com.example.dagger.kotlin" + minSdkVersion 14 + targetSdkVersion 23 + versionCode 1 + versionName "1.0" + } + sourceSets { + main.java.srcDirs += 'src/main/kotlin' + } +} + +dependencies { + implementation fileTree(dir: 'libs', include: ['*.jar']) + implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/AndroidManifest.xml b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..c3f5a36e644 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/AndroidManifest.xml @@ -0,0 +1,16 @@ + + + + + + + + + + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/java/com/example/androidextensions/MyActivity.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/java/com/example/androidextensions/MyActivity.kt new file mode 100644 index 00000000000..0b8cb004d46 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/java/com/example/androidextensions/MyActivity.kt @@ -0,0 +1,31 @@ +/* + * Copyright 2010-2016 JetBrains s.r.o. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package com.example.androidextensions + +import android.os.Bundle +import android.app.Activity +import kotlinx.android.synthetic.main.activity_main.textView + +class HomeActivity : Activity() { + override fun onCreate(savedInstanceState: Bundle?) { + myUtilFunction() + super.onCreate(savedInstanceState) + setContentView(R.layout.activity_main) + + this.textView.setText("Hello, world!") + } +} diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/java/com/example/androidextensions/noLayoutUsages.kt b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/java/com/example/androidextensions/noLayoutUsages.kt new file mode 100644 index 00000000000..7834a2ddc6d --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/java/com/example/androidextensions/noLayoutUsages.kt @@ -0,0 +1,3 @@ +package com.example.androidextensions + +fun myUtilFunction() = "OK" diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/res/layout/activity_main.xml b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/res/layout/activity_main.xml new file mode 100644 index 00000000000..02b0685b4a4 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/res/layout/activity_main.xml @@ -0,0 +1,9 @@ + + + + + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/res/values/strings.xml b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/res/values/strings.xml new file mode 100644 index 00000000000..67b44b1a8cd --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/app/src/main/res/values/strings.xml @@ -0,0 +1,3 @@ + + kotlin + diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/build.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/build.gradle new file mode 100644 index 00000000000..3e1ecc01cc3 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/build.gradle @@ -0,0 +1,24 @@ +// Top-level build file where you can add configuration options common to all sub-projects/modules. + +buildscript { + repositories { + mavenLocal() + maven { url 'https://maven.google.com' } + mavenCentral() + maven { url = uri("https://jcenter.bintray.com/") } + } + + dependencies { + classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version" + classpath "com.android.tools.build:gradle:$android_tools_version" + } +} + +allprojects { + repositories { + mavenLocal() + maven { url 'https://maven.google.com' } + mavenCentral() + maven { url = uri("https://jcenter.bintray.com/") } + } +} \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/gradle.properties b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/gradle.properties new file mode 100644 index 00000000000..59b261a6689 --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-XX:MaxPermSize=512m \ No newline at end of file diff --git a/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/settings.gradle b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/settings.gradle new file mode 100644 index 00000000000..e7b4def49cb --- /dev/null +++ b/libraries/tools/kotlin-gradle-plugin-integration-tests/src/test/resources/testProject/AndroidExtensionsProjectAGP7/settings.gradle @@ -0,0 +1 @@ +include ':app' diff --git a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt index bd257ff9030..ea1e53a593d 100644 --- a/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt +++ b/libraries/tools/kotlin-gradle-plugin/src/main/kotlin/org/jetbrains/kotlin/gradle/targets/android/internal/AndroidSubplugin.kt @@ -116,7 +116,7 @@ class AndroidSubplugin : val mainSourceSet = sourceSets.getByName("main") val manifestFile = mainSourceSet.manifest.srcFile - val applicationPackage = getApplicationPackageFromManifest(manifestFile) ?: run { + val applicationPackage = getApplicationPackage(androidExtension, manifestFile) ?: run { project.logger.warn( "Application package name is not present in the manifest file (${manifestFile.absolutePath})" ) @@ -182,7 +182,7 @@ class AndroidSubplugin : ) val mainSourceSet = androidExtension.sourceSets.getByName("main") - pluginOptions += SubpluginOption("package", getApplicationPackage(project, mainSourceSet)) + pluginOptions += SubpluginOption("package", getApplicationPackage(androidExtension, project, mainSourceSet)) fun addVariant(name: String, resDirectories: FileCollection) { val optionValue = lazy { @@ -270,9 +270,9 @@ class AndroidSubplugin : return project.files(Callable { lazyFiles.value }) } - private fun getApplicationPackage(project: Project, mainSourceSet: AndroidSourceSet): String { + private fun getApplicationPackage(androidExtension: BaseExtension, project: Project, mainSourceSet: AndroidSourceSet): String { val manifestFile = mainSourceSet.manifest.srcFile - val applicationPackage = getApplicationPackageFromManifest(manifestFile) + val applicationPackage = getApplicationPackage(androidExtension, manifestFile) if (applicationPackage == null) { project.logger.warn( @@ -286,7 +286,34 @@ class AndroidSubplugin : } } - private fun getApplicationPackageFromManifest(manifestFile: File): String? { + private fun getApplicationPackage(androidExtension: BaseExtension, manifestFile: File): String? { + // Starting AGP 7 the package can be set via the DSL namespace value: + // + // android { + // namespace "com.example" + // } + // + // instead of via the "package" attribute in the manifest file. + // + // Starting AGP 8, the package *must* be set via the DSL and the manifest file + // attribute cannot be used. + // + // See https://issuetracker.google.com/issues/172361895 + // + // Therefore, we try to get the package from there first. Since we support AGP versions + // prior to AGP 7, we need to reflectively find and call it. + try { + val method = androidExtension.javaClass.getDeclaredMethod("getNamespace") + val result = method.invoke(androidExtension) + if (result is String && result.isNotEmpty()) { + return result + } + } catch (e: ReflectiveOperationException) { + // Ignore and try parsing manifest. + } + + // Didn't find the namespace getter, or it was not set. Try parsing the + // manifest to find the "package" attribute from there. try { return manifestFile.parseXml().documentElement.getAttribute("package") } catch (e: Exception) {