Kotlin Facet: Configure facet automatically on Gradle project import
This commit is contained in:
@@ -35,6 +35,7 @@ import org.jetbrains.jps.model.java.JavaSourceRootType
|
|||||||
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
|
import org.jetbrains.jps.model.module.JpsModuleSourceRootType
|
||||||
import org.jetbrains.kotlin.config.LanguageVersion
|
import org.jetbrains.kotlin.config.LanguageVersion
|
||||||
import org.jetbrains.kotlin.config.TargetPlatformKind
|
import org.jetbrains.kotlin.config.TargetPlatformKind
|
||||||
|
import org.jetbrains.kotlin.idea.facet.configureFacet
|
||||||
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
||||||
import org.jetbrains.kotlin.idea.facet.initializeIfNeeded
|
import org.jetbrains.kotlin.idea.facet.initializeIfNeeded
|
||||||
import org.jetbrains.kotlin.idea.facet.mavenLibraryId
|
import org.jetbrains.kotlin.idea.facet.mavenLibraryId
|
||||||
@@ -90,22 +91,9 @@ class KotlinMavenImporter : MavenImporter(KotlinPluginGroupId, KotlinPluginArtif
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun configureFacet(mavenProject: MavenProject, modifiableModelsProvider: IdeModifiableModelsProvider, module: Module) {
|
private fun configureFacet(mavenProject: MavenProject, modifiableModelsProvider: IdeModifiableModelsProvider, module: Module) {
|
||||||
val compilerVersion = mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID)?.version ?: return
|
val compilerVersion = mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID)?.version
|
||||||
val artifacts = mavenProject.dependencyArtifactIndex.data[KotlinPluginGroupId]?.values?.flatMap { it.filter { it.isResolved } }
|
?: return
|
||||||
val expectedLibraryIds = TargetPlatformKind.ALL_PLATFORMS.map { it.mavenLibraryId }
|
module.getOrCreateFacet(modifiableModelsProvider).configureFacet(compilerVersion, modifiableModelsProvider)
|
||||||
val stdlibArtifact = artifacts?.firstOrNull { it.artifactId in expectedLibraryIds }
|
|
||||||
|
|
||||||
val facet = module.getOrCreateFacet(modifiableModelsProvider)
|
|
||||||
with(facet.configuration.settings.versionInfo) {
|
|
||||||
targetPlatformKind = null
|
|
||||||
apiLevel = null
|
|
||||||
facet.configuration.settings.initializeIfNeeded(module, modifiableModelsProvider.getModifiableRootModel(module))
|
|
||||||
languageLevel = LanguageVersion.fromFullVersionString(compilerVersion)
|
|
||||||
// Both apiLevel and languageLevel should be initialized in the lines above
|
|
||||||
if (apiLevel!! > languageLevel!!) {
|
|
||||||
apiLevel = languageLevel
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO in theory it should work like this but it doesn't as it couldn't unmark source roots that are not roots anymore.
|
// TODO in theory it should work like this but it doesn't as it couldn't unmark source roots that are not roots anymore.
|
||||||
|
|||||||
@@ -9,6 +9,8 @@
|
|||||||
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
<pluginDescriptions implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradlePluginDescription"/>
|
||||||
</extensions>
|
</extensions>
|
||||||
<extensions defaultExtensionNs="com.intellij">
|
<extensions defaultExtensionNs="com.intellij">
|
||||||
|
<externalProjectDataService implementation="org.jetbrains.kotlin.idea.configuration.KotlinGradleProjectDataService"/>
|
||||||
|
|
||||||
<localInspection
|
<localInspection
|
||||||
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection"
|
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection"
|
||||||
displayName="Kotlin Gradle and IDE plugins versions are different"
|
displayName="Kotlin Gradle and IDE plugins versions are different"
|
||||||
|
|||||||
@@ -0,0 +1,53 @@
|
|||||||
|
/*
|
||||||
|
* 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 org.jetbrains.kotlin.idea.configuration
|
||||||
|
|
||||||
|
import com.intellij.openapi.externalSystem.model.DataNode
|
||||||
|
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||||
|
import com.intellij.openapi.externalSystem.model.project.ProjectData
|
||||||
|
import com.intellij.openapi.externalSystem.service.project.IdeModifiableModelsProvider
|
||||||
|
import com.intellij.openapi.externalSystem.service.project.manage.AbstractProjectDataService
|
||||||
|
import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil
|
||||||
|
import com.intellij.openapi.project.Project
|
||||||
|
import org.jetbrains.kotlin.idea.facet.configureFacet
|
||||||
|
import org.jetbrains.kotlin.idea.facet.getOrCreateFacet
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.gradle.findAll
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
|
||||||
|
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
|
||||||
|
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
|
||||||
|
|
||||||
|
class KotlinGradleProjectDataService : AbstractProjectDataService<GradleSourceSetData, Void>() {
|
||||||
|
override fun getTargetDataKey() = GradleSourceSetData.KEY
|
||||||
|
|
||||||
|
override fun postProcess(
|
||||||
|
toImport: Collection<DataNode<GradleSourceSetData>>,
|
||||||
|
projectData: ProjectData?,
|
||||||
|
project: Project,
|
||||||
|
modelsProvider: IdeModifiableModelsProvider
|
||||||
|
) {
|
||||||
|
for (sourceSetNode in toImport) {
|
||||||
|
val sourceSetData = sourceSetNode.data
|
||||||
|
val ideModule = modelsProvider.findIdeModule(sourceSetData) ?: continue
|
||||||
|
|
||||||
|
val moduleNode = ExternalSystemApiUtil.findParent(sourceSetNode, ProjectKeys.MODULE)
|
||||||
|
val compilerVersion = moduleNode?.findAll(BuildScriptClasspathData.KEY)?.firstOrNull()?.data?.let(::findKotlinPluginVersion)
|
||||||
|
?: continue
|
||||||
|
|
||||||
|
ideModule.getOrCreateFacet(modelsProvider).configureFacet(compilerVersion, modelsProvider)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -146,3 +146,19 @@ fun Module.getOrCreateFacet(modelsProvider: IdeModifiableModelsProvider): Kotlin
|
|||||||
facetModel.addFacet(facet)
|
facetModel.addFacet(facet)
|
||||||
return facet
|
return facet
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fun KotlinFacet.configureFacet(compilerVersion: String, modelsProvider: IdeModifiableModelsProvider) {
|
||||||
|
val module = module
|
||||||
|
with(configuration.settings) {
|
||||||
|
versionInfo.targetPlatformKind = null
|
||||||
|
versionInfo.apiLevel = null
|
||||||
|
initializeIfNeeded(module, modelsProvider.getModifiableRootModel(module))
|
||||||
|
with(versionInfo) {
|
||||||
|
languageLevel = LanguageVersion.fromFullVersionString(compilerVersion) ?: LanguageVersion.LATEST
|
||||||
|
// Both apiLevel and languageLevel should be initialized in the lines above
|
||||||
|
if (apiLevel!! > languageLevel!!) {
|
||||||
|
apiLevel = languageLevel
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+16
-9
@@ -16,6 +16,7 @@
|
|||||||
|
|
||||||
package org.jetbrains.kotlin.idea.inspections.gradle
|
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.model.ProjectKeys
|
||||||
import com.intellij.openapi.roots.ProjectRootManager
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
import com.intellij.psi.PsiFile
|
import com.intellij.psi.PsiFile
|
||||||
@@ -50,7 +51,7 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
|
|||||||
if (dependenciesCall.parent !is PsiFile) return
|
if (dependenciesCall.parent !is PsiFile) return
|
||||||
|
|
||||||
val stdlibStatement = findLibraryStatement(closure, "org.jetbrains.kotlin", libraryId) ?: return
|
val stdlibStatement = findLibraryStatement(closure, "org.jetbrains.kotlin", libraryId) ?: return
|
||||||
val stdlibVersion = getResolvedKotlinStdlibVersion(closure.containingFile, "org.jetbrains.kotlin:$libraryId:") ?: return
|
val stdlibVersion = getResolvedKotlinStdlibVersion(closure.containingFile, libraryId) ?: return
|
||||||
|
|
||||||
onFound(stdlibVersion, stdlibStatement)
|
onFound(stdlibVersion, stdlibStatement)
|
||||||
}
|
}
|
||||||
@@ -99,21 +100,27 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getResolvedKotlinStdlibVersion(file: PsiFile, libraryNameMarker: String): String? {
|
private fun getResolvedKotlinStdlibVersion(file: PsiFile, libraryId: String): String? {
|
||||||
val projectStructureNode = findGradleProjectStructure(file) ?: return null
|
val projectStructureNode = findGradleProjectStructure(file) ?: return null
|
||||||
val module = ProjectRootManager.getInstance(file.project).fileIndex.getModuleForFile(file.virtualFile) ?: return null
|
val module = ProjectRootManager.getInstance(file.project).fileIndex.getModuleForFile(file.virtualFile) ?: return null
|
||||||
|
|
||||||
for (moduleData in projectStructureNode.findAll(ProjectKeys.MODULE).filter { it.data.internalName == module.name }) {
|
for (moduleData in projectStructureNode.findAll(ProjectKeys.MODULE).filter { it.data.internalName == module.name }) {
|
||||||
for (sourceSetData in moduleData.node.findAll(GradleSourceSetData.KEY).filter { it.data.internalName.endsWith("main") }) {
|
moduleData.node.getResolvedKotlinStdlibVersionByModuleData(libraryId)?.let { return it }
|
||||||
for (libraryDependencyData in sourceSetData.node.findAll(ProjectKeys.LIBRARY_DEPENDENCY)) {
|
|
||||||
if (libraryDependencyData.data.externalName.startsWith(libraryNameMarker)) {
|
|
||||||
return libraryDependencyData.data.externalName.substringAfter(libraryNameMarker)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal fun DataNode<*>.getResolvedKotlinStdlibVersionByModuleData(libraryId: String): String? {
|
||||||
|
val libraryNameMarker = "org.jetbrains.kotlin:$libraryId:"
|
||||||
|
for (sourceSetData in findAll(GradleSourceSetData.KEY).filter { it.data.internalName.endsWith("main") }) {
|
||||||
|
for (libraryDependencyData in sourceSetData.node.findAll(ProjectKeys.LIBRARY_DEPENDENCY)) {
|
||||||
|
if (libraryDependencyData.data.externalName.startsWith(libraryNameMarker)) {
|
||||||
|
return libraryDependencyData.data.externalName.substringAfter(libraryNameMarker)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return null
|
||||||
}
|
}
|
||||||
+1
-1
@@ -72,7 +72,7 @@ fun getResolvedKotlinGradleVersion(module: Module): String? {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun findKotlinPluginVersion(classpathData: BuildScriptClasspathData): String? {
|
internal fun findKotlinPluginVersion(classpathData: BuildScriptClasspathData): String? {
|
||||||
for (classPathEntry in classpathData.classpathEntries) {
|
for (classPathEntry in classpathData.classpathEntries) {
|
||||||
for (path in classPathEntry.classesFile) {
|
for (path in classPathEntry.classesFile) {
|
||||||
val uniformedPath = path.replace('\\', '/')
|
val uniformedPath = path.replace('\\', '/')
|
||||||
|
|||||||
Reference in New Issue
Block a user