diff --git a/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/facet/MavenKotlinVersionInfoProvider.kt b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/facet/MavenKotlinVersionInfoProvider.kt new file mode 100644 index 00000000000..5d678c49b9a --- /dev/null +++ b/idea/idea-maven/src/org/jetbrains/kotlin/idea/maven/facet/MavenKotlinVersionInfoProvider.kt @@ -0,0 +1,38 @@ +/* + * 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.maven.facet + +import com.intellij.openapi.module.Module +import org.jetbrains.idea.maven.project.MavenProjectsManager +import org.jetbrains.kotlin.idea.facet.KotlinFacetConfiguration +import org.jetbrains.kotlin.idea.facet.KotlinVersionInfoProvider +import org.jetbrains.kotlin.idea.facet.mavenLibraryId +import org.jetbrains.kotlin.idea.maven.configuration.KotlinMavenConfigurator + +class MavenKotlinVersionInfoProvider : KotlinVersionInfoProvider { + override fun getCompilerVersion(module: Module): String? { + val projectsManager = MavenProjectsManager.getInstance(module.project) + val mavenProject = projectsManager.findProject(module) ?: return null + return mavenProject.findPlugin(KotlinMavenConfigurator.GROUP_ID, KotlinMavenConfigurator.MAVEN_PLUGIN_ID)?.version + } + + override fun getLibraryVersions(module: Module, targetPlatform: KotlinFacetConfiguration.TargetPlatform): Collection { + val projectsManager = MavenProjectsManager.getInstance(module.project) + val mavenProject = projectsManager.findProject(module) ?: return emptyList() + return mavenProject.findDependencies(KotlinMavenConfigurator.GROUP_ID, targetPlatform.mavenLibraryId).map { it.version }.distinct() + } +} diff --git a/idea/src/META-INF/extensions/common.xml b/idea/src/META-INF/extensions/common.xml index bf32bf2d7e3..094a626e586 100644 --- a/idea/src/META-INF/extensions/common.xml +++ b/idea/src/META-INF/extensions/common.xml @@ -36,5 +36,7 @@ area="IDEA_PROJECT"/> + diff --git a/idea/src/META-INF/gradle.xml b/idea/src/META-INF/gradle.xml index b0bf733fb90..6f8b70b9c34 100644 --- a/idea/src/META-INF/gradle.xml +++ b/idea/src/META-INF/gradle.xml @@ -1,6 +1,8 @@ + + diff --git a/idea/src/META-INF/maven.xml b/idea/src/META-INF/maven.xml index 1ecf8ad08f6..3d38512ed1f 100644 --- a/idea/src/META-INF/maven.xml +++ b/idea/src/META-INF/maven.xml @@ -2,6 +2,8 @@ + + diff --git a/idea/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinVersionInfoProvider.kt b/idea/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinVersionInfoProvider.kt new file mode 100644 index 00000000000..0c0e0ca4742 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/configuration/GradleKotlinVersionInfoProvider.kt @@ -0,0 +1,51 @@ +/* + * 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.util.ExternalSystemApiUtil +import com.intellij.openapi.module.Module +import org.jetbrains.kotlin.idea.facet.KotlinFacetConfiguration +import org.jetbrains.kotlin.idea.facet.KotlinVersionInfoProvider +import org.jetbrains.kotlin.idea.facet.mavenLibraryId +import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection +import org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection +import org.jetbrains.kotlin.idea.refactoring.toPsiFile +import org.jetbrains.kotlin.idea.refactoring.toVirtualFile +import org.jetbrains.plugins.gradle.service.project.data.ExternalProjectDataCache +import org.jetbrains.plugins.gradle.util.GradleConstants +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase +import java.io.File + +class GradleKotlinVersionInfoProvider : KotlinVersionInfoProvider { + private fun getGradleFile(module: Module): GroovyFileBase? { + val rootDir = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return null + val externalProjectDataCache = ExternalProjectDataCache.getInstance(module.project) + val rootProject = externalProjectDataCache.getRootExternalProject(GradleConstants.SYSTEM_ID, File(rootDir)) ?: return null + val buildFile = rootProject.buildFile ?: return null + return buildFile.toVirtualFile()?.toPsiFile(module.project) as? GroovyFileBase ?: return null + } + + override fun getCompilerVersion(module: Module): String? { + return getGradleFile(module)?.let { DifferentKotlinGradleVersionInspection.getKotlinPluginVersion(it) } + } + + override fun getLibraryVersions(module: Module, targetPlatform: KotlinFacetConfiguration.TargetPlatform): Collection { + return getGradleFile(module)?.let { + DifferentStdlibGradleVersionInspection.getKotlinStdlibVersions(it, targetPlatform.mavenLibraryId) + } ?: emptyList() + } +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/FrameworkLibraryValidatorWithDynamicDescription.kt b/idea/src/org/jetbrains/kotlin/idea/facet/FrameworkLibraryValidatorWithDynamicDescription.kt index 29ee3e95ffa..02ecf95a964 100644 --- a/idea/src/org/jetbrains/kotlin/idea/facet/FrameworkLibraryValidatorWithDynamicDescription.kt +++ b/idea/src/org/jetbrains/kotlin/idea/facet/FrameworkLibraryValidatorWithDynamicDescription.kt @@ -25,6 +25,8 @@ import com.intellij.ide.IdeBundle import com.intellij.openapi.roots.ui.configuration.libraries.AddCustomLibraryDialog import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription import com.intellij.openapi.roots.ui.configuration.libraries.LibraryPresentationManager +import org.jetbrains.kotlin.idea.framework.JSLibraryStdDescription +import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription import javax.swing.JComponent // Based on com.intellij.facet.impl.ui.libraries.FrameworkLibraryValidatorImpl @@ -32,10 +34,27 @@ class FrameworkLibraryValidatorWithDynamicDescription( private val context: LibrariesValidatorContext, private val validatorsManager: FacetValidatorsManager, private val libraryCategoryName: String, - private val getLibraryDescription: () -> CustomLibraryDescription + private val getTargetPlatform: () -> KotlinFacetConfiguration.TargetPlatform ) : FrameworkLibraryValidator() { + private val KotlinFacetConfiguration.TargetPlatform.libraryDescription: CustomLibraryDescription + get() { + val project = context.module.project + return when (this) { + KotlinFacetConfiguration.TargetPlatform.JVM_1_6, KotlinFacetConfiguration.TargetPlatform.JVM_1_8 -> + JavaRuntimeLibraryDescription(project) + KotlinFacetConfiguration.TargetPlatform.JS -> + JSLibraryStdDescription(project) + } + } + override fun check(): ValidationResult { - val libraryDescription = getLibraryDescription() + val targetPlatform = getTargetPlatform() + + if (KotlinVersionInfoProvider.EP_NAME.extensions.any { it.getLibraryVersions(context.module, targetPlatform).isNotEmpty() }) { + return ValidationResult.OK + } + + val libraryDescription = targetPlatform.libraryDescription val libraryKinds = libraryDescription.suitableLibraryKinds var found = false val presentationManager = LibraryPresentationManager.getInstance() diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/KotlinFacetEditorTab.kt b/idea/src/org/jetbrains/kotlin/idea/facet/KotlinFacetEditorTab.kt index 61b42ac87e9..2e3ee4d0231 100644 --- a/idea/src/org/jetbrains/kotlin/idea/facet/KotlinFacetEditorTab.kt +++ b/idea/src/org/jetbrains/kotlin/idea/facet/KotlinFacetEditorTab.kt @@ -19,10 +19,7 @@ package org.jetbrains.kotlin.idea.facet import com.intellij.facet.impl.ui.libraries.DelegatingLibrariesValidatorContext import com.intellij.facet.ui.* import com.intellij.facet.ui.libraries.FrameworkLibraryValidator -import com.intellij.openapi.roots.ui.configuration.libraries.CustomLibraryDescription import com.intellij.util.ui.FormBuilder -import org.jetbrains.kotlin.idea.framework.JSLibraryStdDescription -import org.jetbrains.kotlin.idea.framework.JavaRuntimeLibraryDescription import org.jetbrains.kotlin.idea.util.DescriptionAware import java.awt.BorderLayout import java.awt.Component @@ -54,15 +51,7 @@ class KotlinFacetEditorTab( } } - private val KotlinFacetConfiguration.TargetPlatform.libraryDescription: CustomLibraryDescription - get() { - return when (this) { - KotlinFacetConfiguration.TargetPlatform.JVM_1_6, KotlinFacetConfiguration.TargetPlatform.JVM_1_8 -> - JavaRuntimeLibraryDescription(editorContext.project) - KotlinFacetConfiguration.TargetPlatform.JS -> - JSLibraryStdDescription(editorContext.project) - } - } + private val languageVersionComboBox = JComboBox(KotlinFacetConfiguration.LanguageLevel.values()).apply { @@ -87,7 +76,7 @@ class KotlinFacetEditorTab( DelegatingLibrariesValidatorContext(editorContext), validatorsManager, "kotlin" - ) { (targetPlatformComboBox.selectedItem as KotlinFacetConfiguration.TargetPlatform).libraryDescription } + ) { targetPlatformComboBox.selectedItem as KotlinFacetConfiguration.TargetPlatform } validatorsManager.registerValidator(libraryValidator) validatorsManager.registerValidator(versionValidator) diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProvider.kt b/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProvider.kt new file mode 100644 index 00000000000..0814158426a --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/facet/KotlinVersionInfoProvider.kt @@ -0,0 +1,29 @@ +/* + * 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.facet + +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.openapi.module.Module + +interface KotlinVersionInfoProvider { + companion object { + val EP_NAME: ExtensionPointName = ExtensionPointName.create("org.jetbrains.kotlin.versionInfoProvider")!! + } + + fun getCompilerVersion(module: Module): String? + fun getLibraryVersions(module: Module, targetPlatform: KotlinFacetConfiguration.TargetPlatform): Collection +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt b/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt index 48829540a00..e41bdaf1f10 100644 --- a/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt +++ b/idea/src/org/jetbrains/kotlin/idea/facet/facetUtils.kt @@ -16,25 +16,39 @@ package org.jetbrains.kotlin.idea.facet -import com.intellij.framework.library.LibraryVersionProperties import com.intellij.openapi.module.Module import com.intellij.openapi.projectRoots.JavaSdk import com.intellij.openapi.projectRoots.JavaSdkVersion import com.intellij.openapi.roots.LibraryOrderEntry import com.intellij.openapi.roots.ModuleRootManager import com.intellij.openapi.roots.ModuleRootModel -import com.intellij.openapi.roots.libraries.LibraryPresentationProvider import com.intellij.util.text.VersionComparatorUtil import org.jetbrains.kotlin.idea.framework.JSLibraryStdPresentationProvider import org.jetbrains.kotlin.idea.framework.JavaRuntimePresentationProvider import org.jetbrains.kotlin.idea.framework.getLibraryProperties +import org.jetbrains.kotlin.idea.maven.configuration.KotlinJavaMavenConfigurator +import org.jetbrains.kotlin.idea.maven.configuration.KotlinJavascriptMavenConfigurator import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion private fun getRuntimeLibraryVersions( module: Module, rootModel: ModuleRootModel?, - presentationProvider: LibraryPresentationProvider -): List { + targetPlatform: KotlinFacetConfiguration.TargetPlatform +): Collection { + val presentationProvider = when (targetPlatform) { + KotlinFacetConfiguration.TargetPlatform.JS -> + JSLibraryStdPresentationProvider.getInstance() + KotlinFacetConfiguration.TargetPlatform.JVM_1_6, + KotlinFacetConfiguration.TargetPlatform.JVM_1_8 -> + JavaRuntimePresentationProvider.getInstance() + } + + KotlinVersionInfoProvider.EP_NAME + .extensions + .map { it.getLibraryVersions(module, targetPlatform) } + .firstOrNull { it.isNotEmpty() } + ?.let { return it } + return (rootModel ?: ModuleRootManager.getInstance(module)) .orderEntries .asSequence() @@ -44,9 +58,9 @@ private fun getRuntimeLibraryVersions( } private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel?): KotlinFacetConfiguration.TargetPlatform { - getRuntimeLibraryVersions(module, rootModel, JSLibraryStdPresentationProvider.getInstance()) - .firstOrNull() - ?.let { return KotlinFacetConfiguration.TargetPlatform.JS } + if (getRuntimeLibraryVersions(module, rootModel, KotlinFacetConfiguration.TargetPlatform.JS).any()) { + return KotlinFacetConfiguration.TargetPlatform.JS + } val sdk = ((rootModel ?: ModuleRootManager.getInstance(module))).sdk val sdkVersion = (sdk?.sdkType as? JavaSdk)?.getVersion(sdk!!) @@ -56,8 +70,15 @@ private fun getDefaultTargetPlatform(module: Module, rootModel: ModuleRootModel? } } -private fun getDefaultLanguageLevel(explicitVersion: String? = null): KotlinFacetConfiguration.LanguageLevel { - val libVersion = explicitVersion ?: bundledRuntimeVersion() +private fun getDefaultLanguageLevel( + module: Module, + explicitVersion: String? = null +): KotlinFacetConfiguration.LanguageLevel { + val libVersion = explicitVersion + ?: KotlinVersionInfoProvider.EP_NAME.extensions + .mapNotNull { it.getCompilerVersion(module) } + .minWith(VersionComparatorUtil.COMPARATOR) + ?: bundledRuntimeVersion() return when { libVersion.startsWith("1.0") -> KotlinFacetConfiguration.LanguageLevel.KOTLIN_1_0 else -> KotlinFacetConfiguration.LanguageLevel.KOTLIN_1_1 @@ -69,16 +90,9 @@ internal fun getLibraryLanguageLevel( rootModel: ModuleRootModel?, targetPlatform: KotlinFacetConfiguration.TargetPlatform? ): KotlinFacetConfiguration.LanguageLevel { - val presentationProvider = when (targetPlatform) { - KotlinFacetConfiguration.TargetPlatform.JS -> - JSLibraryStdPresentationProvider.getInstance() - KotlinFacetConfiguration.TargetPlatform.JVM_1_6, - KotlinFacetConfiguration.TargetPlatform.JVM_1_8, - null -> - JavaRuntimePresentationProvider.getInstance() - } - val minVersion = getRuntimeLibraryVersions(module, rootModel, presentationProvider).minWith(VersionComparatorUtil.COMPARATOR) - return getDefaultLanguageLevel(minVersion) + val minVersion = getRuntimeLibraryVersions(module, rootModel, targetPlatform ?: KotlinFacetConfiguration.TargetPlatform.JVM_1_8) + .minWith(VersionComparatorUtil.COMPARATOR) + return getDefaultLanguageLevel(module, minVersion) } internal fun KotlinFacetConfiguration.VersionInfo.initializeIfNeeded(module: Module, rootModel: ModuleRootModel?) { @@ -87,7 +101,7 @@ internal fun KotlinFacetConfiguration.VersionInfo.initializeIfNeeded(module: Mod } if (languageLevel == null) { - languageLevel = getDefaultLanguageLevel() + languageLevel = getDefaultLanguageLevel(module) } if (apiLevel == null) { @@ -100,3 +114,14 @@ internal fun Module.getKotlinVersionInfo(rootModel: ModuleRootModel? = null): Ko versionInfo.initializeIfNeeded(this, rootModel) return versionInfo } + +val KotlinFacetConfiguration.TargetPlatform.mavenLibraryId: String + get() { + return when (this) { + KotlinFacetConfiguration.TargetPlatform.JVM_1_6, + KotlinFacetConfiguration.TargetPlatform.JVM_1_8 -> + KotlinJavaMavenConfigurator.STD_LIB_ID + KotlinFacetConfiguration.TargetPlatform.JS -> + KotlinJavascriptMavenConfigurator.STD_LIB_ID + } + } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentKotlinGradleVersionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentKotlinGradleVersionInspection.kt index eed008c94d1..521cfe7d988 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentKotlinGradleVersionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentKotlinGradleVersionInspection.kt @@ -23,6 +23,8 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.plugins.gradle.codeInspection.GradleBaseInspection import org.jetbrains.plugins.groovy.codeInspection.BaseInspection import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement import org.jetbrains.plugins.groovy.lang.psi.api.statements.GrVariableDeclaration import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrAssignmentExpression @@ -46,8 +48,8 @@ class DifferentKotlinGradleVersionInspection : GradleBaseInspection() { return "Kotlin version that is used for building with Gradle (${args[0]}) differs from the one bundled into the IDE plugin (${args[1]})" } - private inner class MyVisitor : KotlinGradleInspectionVisitor() { - private val idePluginVersion by lazy { bundledRuntimeVersion() } + private abstract class VersionFinder : KotlinGradleInspectionVisitor() { + protected abstract fun onFound(kotlinPluginVersion: String, kotlinPluginStatement: GrCallExpression) override fun visitClosure(closure: GrClosableBlock) { super.visitClosure(closure) @@ -67,6 +69,14 @@ class DifferentKotlinGradleVersionInspection : GradleBaseInspection() { getResolvedKotlinGradleVersion(closure.containingFile) ?: return + onFound(kotlinPluginVersion, kotlinPluginStatement) + } + } + + private inner class MyVisitor: VersionFinder() { + private val idePluginVersion by lazy { bundledRuntimeVersion() } + + override fun onFound(kotlinPluginVersion: String, kotlinPluginStatement: GrCallExpression) { if (kotlinPluginVersion != idePluginVersion) { registerError(kotlinPluginStatement, kotlinPluginVersion, testVersionMessage ?: idePluginVersion) } @@ -74,6 +84,21 @@ class DifferentKotlinGradleVersionInspection : GradleBaseInspection() { } companion object { + fun getKotlinPluginVersion(gradleFile: GroovyFileBase): String? { + var version: String? = null + val visitor = object : VersionFinder() { + override fun visitElement(element: GroovyPsiElement) { + element.acceptChildren(this) + } + + override fun onFound(kotlinPluginVersion: String, kotlinPluginStatement: GrCallExpression) { + version = kotlinPluginVersion + } + } + gradleFile.accept(visitor) + return version + } + private fun getHeuristicKotlinPluginVersion(classpathStatement: GrCallExpression): String? { val argumentList = when (classpathStatement) { is GrMethodCall -> classpathStatement.argumentList // classpath('argument') diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentStdlibGradleVersionInspection.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentStdlibGradleVersionInspection.kt index e86601bc709..7cd5831eed0 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentStdlibGradleVersionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentStdlibGradleVersionInspection.kt @@ -24,18 +24,23 @@ import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.plugins.gradle.codeInspection.GradleBaseInspection import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase +import org.jetbrains.plugins.groovy.lang.psi.GroovyPsiElement import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrReferenceExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression +import java.util.* class DifferentStdlibGradleVersionInspection : GradleBaseInspection() { - override fun buildVisitor(): BaseInspectionVisitor = MyVisitor() + override fun buildVisitor(): BaseInspectionVisitor = MyVisitor("kotlin-stdlib") override fun buildErrorString(vararg args: Any) = "Plugin version (${args[0]}) is not the same as library version (${args[1]})" - private inner class MyVisitor : KotlinGradleInspectionVisitor() { + private abstract class VersionFinder(private val libraryId: String) : KotlinGradleInspectionVisitor() { + protected abstract fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression) + override fun visitClosure(closure: GrClosableBlock) { super.visitClosure(closure) @@ -47,7 +52,13 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() { val stdlibStatement = findLibraryStatement(closure, "org.jetbrains.kotlin", "kotlin-stdlib") ?: return val stdlibVersion = getResolvedKotlinStdlibVersion(closure.containingFile, "org.jetbrains.kotlin:kotlin-stdlib:") ?: return - val gradlePluginVersion = getResolvedKotlinGradleVersion(closure.containingFile) + onFound(stdlibVersion, stdlibStatement) + } + } + + private inner class MyVisitor(libraryId: String): VersionFinder(libraryId) { + override fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression) { + val gradlePluginVersion = getResolvedKotlinGradleVersion(stdlibStatement.containingFile) if (stdlibVersion != gradlePluginVersion) { registerError(stdlibStatement, gradlePluginVersion, stdlibVersion) @@ -58,6 +69,21 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() { companion object { val COMPILE_DEPENDENCY_STATEMENTS = listOf("classpath", "compile") + fun getKotlinStdlibVersions(gradleFile: GroovyFileBase, libraryId: String): Collection { + val versions = LinkedHashSet() + val visitor = object : VersionFinder(libraryId) { + override fun visitElement(element: GroovyPsiElement) { + element.acceptChildren(this) + } + + override fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression) { + versions += stdlibVersion + } + } + gradleFile.accept(visitor) + return versions + } + private fun findLibraryStatement(closure: GrClosableBlock, libraryGroup: String, libraryId: String): GrCallExpression? { val applicationStatements = closure.getChildrenOfType() diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt index 0c621615e1f..edf0464f686 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt @@ -23,6 +23,8 @@ import com.intellij.openapi.externalSystem.model.ProjectKeys import com.intellij.openapi.externalSystem.model.project.ProjectData import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil import com.intellij.openapi.externalSystem.util.ExternalSystemUtil +import com.intellij.openapi.module.Module +import com.intellij.openapi.module.ModuleUtilCore import com.intellij.openapi.roots.ProjectRootManager import com.intellij.openapi.util.io.FileUtilRt import com.intellij.psi.PsiFile @@ -54,10 +56,11 @@ abstract class KotlinGradleInspectionVisitor : BaseInspectionVisitor() { } } -fun getResolvedKotlinGradleVersion(file: PsiFile): String? { - val module = ProjectRootManager.getInstance(file.project).fileIndex.getModuleForFile(file.virtualFile) ?: return null - val projectStructureNode = findGradleProjectStructure(file) ?: return null +fun getResolvedKotlinGradleVersion(file: PsiFile) = + ModuleUtilCore.findModuleForFile(file.virtualFile, file.project)?.let { getResolvedKotlinGradleVersion(it) } +fun getResolvedKotlinGradleVersion(module: Module): String? { + val projectStructureNode = findGradleProjectStructure(module) ?: return null for (moduleData in projectStructureNode.findAll(ProjectKeys.MODULE).filter { it.data.internalName == module.name }) { val buildScriptClasspathData = moduleData.node.findAll(BuildScriptClasspathData.KEY).firstOrNull()?.data ?: continue val kotlinPluginVersion = findKotlinPluginVersion(buildScriptClasspathData) @@ -95,11 +98,11 @@ fun DataNode<*>.findAll(key: Key): List> { } } -fun findGradleProjectStructure(file: PsiFile): DataNode? { - val project = file.project - val module = ProjectRootManager.getInstance(project).fileIndex.getModuleForFile(file.virtualFile) ?: return null - val externalProjectPath = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return null +fun findGradleProjectStructure(file: PsiFile) = + ModuleUtilCore.findModuleForFile(file.virtualFile, file.project)?.let { findGradleProjectStructure(it) } - val projectInfo = ExternalSystemUtil.getExternalProjectInfo(project, GRADLE_SYSTEM_ID, externalProjectPath) ?: return null +fun findGradleProjectStructure(module: Module): DataNode? { + val externalProjectPath = ExternalSystemApiUtil.getExternalProjectPath(module) ?: return null + val projectInfo = ExternalSystemUtil.getExternalProjectInfo(module.project, GRADLE_SYSTEM_ID, externalProjectPath) ?: return null return projectInfo.externalProjectStructure }