Kotlin Facet: Detect platform by stdlib dependency in android-gradle projects

#KT-16827 Fixed
This commit is contained in:
Alexey Sedunov
2017-03-14 16:41:11 +03:00
parent 040f5f88f2
commit cf9d7a0470
8 changed files with 281 additions and 18 deletions
@@ -0,0 +1,51 @@
/*
* Copyright 2010-2017 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.
*/
/*
* Copyright 2010-2017 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 org.jetbrains.kotlin.android.configure
import com.android.tools.idea.gradle.AndroidProjectKeys
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import org.jetbrains.kotlin.idea.inspections.gradle.KotlinPlatformGradleDetector
class PlatformAndroidGradleDetector : KotlinPlatformGradleDetector {
override fun getResolvedKotlinStdlibVersionByModuleData(moduleData: DataNode<*>, libraryIds: List<String>): String? {
ExternalSystemApiUtil
.findAllRecursively(moduleData, AndroidProjectKeys.JAVA_PROJECT).asSequence()
.flatMap { it.data.jarLibraryDependencies.asSequence() }
.forEach {
val libraryName = it.name
if (libraryName.substringBeforeLast("-") in libraryIds) return libraryName.substringAfterLast("-")
}
return null
}
}
+1
View File
@@ -42,6 +42,7 @@
<quickFixContributor implementation="org.jetbrains.kotlin.android.quickfix.AndroidQuickFixRegistrar"/>
<projectConfigurator implementation="org.jetbrains.kotlin.android.configure.KotlinAndroidGradleModuleConfigurator"/>
<platformGradleDetector implementation="org.jetbrains.kotlin.android.configure.PlatformAndroidGradleDetector"/>
</extensions>
<project-components>
+2
View File
@@ -41,5 +41,7 @@
interface="org.jetbrains.kotlin.idea.facet.KotlinFacetConfigurationExtension"/>
<extensionPoint name="versionInfoProvider"
interface="org.jetbrains.kotlin.idea.facet.KotlinVersionInfoProvider"/>
<extensionPoint name="platformGradleDetector"
interface="org.jetbrains.kotlin.idea.inspections.gradle.KotlinPlatformGradleDetector"/>
</extensionPoints>
</idea-plugin>
+1
View File
@@ -44,5 +44,6 @@
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleModuleConfigurator"/>
<projectConfigurator implementation="org.jetbrains.kotlin.idea.configuration.KotlinJsGradleModuleConfigurator"/>
<versionInfoProvider implementation="org.jetbrains.kotlin.idea.configuration.GradleKotlinVersionInfoProvider"/>
<platformGradleDetector implementation="org.jetbrains.kotlin.idea.inspections.gradle.DefaultPlatformGradleDetector"/>
</extensions>
</idea-plugin>
@@ -18,7 +18,6 @@ package org.jetbrains.kotlin.idea.inspections.gradle
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.PsiFile
import org.jetbrains.kotlin.idea.versions.MAVEN_STDLIB_ID
@@ -117,13 +116,7 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
}
internal fun DataNode<*>.getResolvedKotlinStdlibVersionByModuleData(libraryIds: List<String>): String? {
for (libraryDependencyData in ExternalSystemApiUtil.findAllRecursively(this, ProjectKeys.LIBRARY_DEPENDENCY)) {
for (libraryId in libraryIds) {
val libraryNameMarker = "org.jetbrains.kotlin:$libraryId:"
if (libraryDependencyData.data.externalName.startsWith(libraryNameMarker)) {
return libraryDependencyData.data.externalName.substringAfter(libraryNameMarker)
}
}
}
return null
return KotlinPlatformGradleDetector.EP_NAME.extensions.asSequence()
.mapNotNull { it.getResolvedKotlinStdlibVersionByModuleData(this, libraryIds) }
.firstOrNull()
}
@@ -0,0 +1,60 @@
/*
* Copyright 2010-2017 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.
*/
/*
* Copyright 2010-2017 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 org.jetbrains.kotlin.idea.inspections.gradle
import com.intellij.openapi.extensions.ExtensionPointName
import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.ProjectKeys
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
interface KotlinPlatformGradleDetector {
companion object {
val EP_NAME: ExtensionPointName<KotlinPlatformGradleDetector> = ExtensionPointName.create("org.jetbrains.kotlin.platformGradleDetector")!!
}
fun getResolvedKotlinStdlibVersionByModuleData(moduleData: DataNode<*>, libraryIds: List<String>): String?
}
class DefaultPlatformGradleDetector : KotlinPlatformGradleDetector {
override fun getResolvedKotlinStdlibVersionByModuleData(moduleData: DataNode<*>, libraryIds: List<String>): String? {
for (libraryDependencyData in ExternalSystemApiUtil.findAllRecursively(moduleData, ProjectKeys.LIBRARY_DEPENDENCY)) {
for (libraryId in libraryIds) {
val libraryNameMarker = "org.jetbrains.kotlin:$libraryId:"
if (libraryDependencyData.data.externalName.startsWith(libraryNameMarker)) {
return libraryDependencyData.data.externalName.substringAfter(libraryNameMarker)
}
}
}
return null
}
}
@@ -23,15 +23,15 @@ import org.jetbrains.kotlin.idea.facet.KotlinFacet
import org.junit.Assert
import org.junit.Test
internal fun GradleImportingTestCase.facetSettings(moduleName: String) = KotlinFacet.get(getModule(moduleName))!!.configuration.settings
internal val GradleImportingTestCase.facetSettings: KotlinFacetSettings
get() = facetSettings("project_main")
internal val GradleImportingTestCase.testFacetSettings: KotlinFacetSettings
get() = facetSettings("project_test")
class GradleFacetImportTest : GradleImportingTestCase() {
private fun facetSettings(moduleName: String) = KotlinFacet.get(getModule(moduleName))!!.configuration.settings
private val facetSettings: KotlinFacetSettings
get() = facetSettings("project_main")
private val testFacetSettings: KotlinFacetSettings
get() = facetSettings("project_test")
@Test
fun testJvmImport() {
createProjectSubFile("build.gradle", """
@@ -0,0 +1,155 @@
/*
* Copyright 2010-2017 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 org.jetbrains.kotlin.idea.codeInsight.gradle
import com.intellij.openapi.util.text.StringUtil
import org.jetbrains.kotlin.config.TargetPlatformKind
import org.junit.Assert
import org.junit.Test
import java.io.File
class GradleFacetImportTest_3_3 : GradleImportingTestCase() {
override fun setUp() {
gradleVersion = "3.3"
super.setUp()
}
@Test
fun testAndroidGradleJsDetection() {
createProjectSubFile("android-module/build.gradle", """
group 'Again'
version '1.0-SNAPSHOT'
buildscript {
repositories {
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:2.3.0-rc1"
}
}
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.1"
defaultConfig {
minSdkVersion 11
targetSdkVersion 23
versionCode 1002003
versionName version
}
dataBinding {
enabled = true
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_7
targetCompatibility JavaVersion.VERSION_1_7
}
buildTypes {
debug {
applicationIdSuffix ".debug"
versionNameSuffix "-debug"
}
release {
minifyEnabled true
shrinkResources true
}
}
}
""")
createProjectSubFile("android-module/src/main/AndroidManifest.xml", """
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="my.test.project" >
</manifest>
""")
createProjectSubFile("js-module/build.gradle", """
group 'Again'
version '1.0-SNAPSHOT'
buildscript {
repositories {
mavenCentral()
maven {
url 'http://dl.bintray.com/kotlin/kotlin-eap-1.1'
}
}
dependencies {
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0")
}
}
apply plugin: 'kotlin2js'
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib-js:1.1.0"
}
""")
createProjectSubFile("build.gradle", """
group 'Again'
version '1.0-SNAPSHOT'
buildscript {
repositories {
mavenLocal()
maven {
url='https://dl.bintray.com/kotlin/kotlin-eap-1.1'
}
jcenter()
}
dependencies {
classpath "com.android.tools.build:gradle:2.3.0-rc1"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.0"
}
}
ext {
androidBuildToolsVersion = '23.0.1'
}
allprojects {
repositories {
mavenLocal()
maven {
url='https://dl.bintray.com/kotlin/kotlin-eap-1.1'
}
jcenter()
}
}
""")
createProjectSubFile("settings.gradle", """
rootProject.name = "android-js-test"
include ':android-module'
include ':js-module'
""")
createProjectSubFile("local.properties", """
sdk.dir=/${StringUtil.escapeBackSlashes(File(homePath).parent + "/dependencies/androidSDK")}
""")
importProject()
with (facetSettings("js-module")) {
Assert.assertEquals(TargetPlatformKind.JavaScript, targetPlatformKind)
}
}
}