From 9b1eb0931f5f89ac44d6603f4d1afc1d19223fa6 Mon Sep 17 00:00:00 2001 From: Nikolay Krasko Date: Fri, 8 Jul 2016 16:31:59 +0300 Subject: [PATCH] Refactoring: extract method for getting Kotlin plugin version and remove findAllRecursively usage --- .../DifferentKotlinGradleVersionInspection.kt | 79 +------------- .../gradle/KotlinGradleInspectionVisitor.kt | 100 ++++++++++++++++++ 2 files changed, 101 insertions(+), 78 deletions(-) create mode 100644 idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt 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 afd1de5ec2b..eed008c94d1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentKotlinGradleVersionInspection.kt +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/DifferentKotlinGradleVersionInspection.kt @@ -16,27 +16,13 @@ package org.jetbrains.kotlin.idea.inspections.gradle -import com.intellij.openapi.application.ApplicationManager -import com.intellij.openapi.externalSystem.model.ProjectKeys -import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil -import com.intellij.openapi.externalSystem.util.ExternalSystemUtil -import com.intellij.openapi.roots.ProjectRootManager -import com.intellij.openapi.util.io.FileUtilRt -import com.intellij.psi.PsiFile -import com.intellij.util.BooleanFunction import org.jetbrains.annotations.TestOnly -import org.jetbrains.kotlin.idea.KotlinPluginUtil -import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator -import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID import org.jetbrains.kotlin.idea.versions.bundledRuntimeVersion import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.plugins.gradle.codeInspection.GradleBaseInspection -import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData -import org.jetbrains.plugins.gradle.util.GradleConstants 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.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 @@ -60,24 +46,9 @@ 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 : BaseInspectionVisitor() { + private inner class MyVisitor : KotlinGradleInspectionVisitor() { private val idePluginVersion by lazy { bundledRuntimeVersion() } - override fun visitFile(file: GroovyFileBase?) { - if (file == null || !FileUtilRt.extensionEquals(file.name, GradleConstants.EXTENSION)) return - - val fileIndex = ProjectRootManager.getInstance(file.project).fileIndex - - if (!ApplicationManager.getApplication().isUnitTestMode) { - val module = fileIndex.getModuleForFile(file.virtualFile) ?: return - if (!KotlinPluginUtil.isGradleModule(module)) return - } - - if (fileIndex.isExcluded(file.virtualFile)) return - - super.visitFile(file) - } - override fun visitClosure(closure: GrClosableBlock) { super.visitClosure(closure) @@ -103,9 +74,6 @@ class DifferentKotlinGradleVersionInspection : GradleBaseInspection() { } companion object { - val KOTLIN_PLUGIN_CLASSPATH_MARKER = "${KotlinWithGradleConfigurator.GROUP_ID}:${KotlinWithGradleConfigurator.GRADLE_PLUGIN_ID}:" - val KOTLIN_PLUGIN_PATH_MARKER = "${KotlinWithGradleConfigurator.GROUP_ID}/${KotlinWithGradleConfigurator.GRADLE_PLUGIN_ID}/" - private fun getHeuristicKotlinPluginVersion(classpathStatement: GrCallExpression): String? { val argumentList = when (classpathStatement) { is GrMethodCall -> classpathStatement.argumentList // classpath('argument') @@ -173,50 +141,5 @@ class DifferentKotlinGradleVersionInspection : GradleBaseInspection() { return classPathStatements } - - private fun getResolvedKotlinGradleVersion(file: PsiFile): String? { - val project = file.project - val module = ProjectRootManager.getInstance(file.project).fileIndex.getModuleForFile(file.virtualFile) ?: return null - val projectPath = project.basePath ?: return null - - val projectInfo = ExternalSystemUtil.getExternalProjectInfo(project, GRADLE_SYSTEM_ID, projectPath) ?: return null - val externalProjectStructure = projectInfo.externalProjectStructure ?: return null - - val buildScriptClasspathDataNodes = ExternalSystemApiUtil.findAllRecursively(externalProjectStructure, BooleanFunction { node -> - BuildScriptClasspathData.KEY == node.key - }) - - for (buildScriptClasspathDataNode in buildScriptClasspathDataNodes) { - val moduleNode = buildScriptClasspathDataNode.parent - val moduleData = moduleNode?.getData(ProjectKeys.MODULE) - if (moduleData?.internalName == module.name) { - val buildScriptClasspathData = buildScriptClasspathDataNode.getData(BuildScriptClasspathData.KEY) - if (buildScriptClasspathData != null) { - val kotlinPluginVersion = findKotlinPluginVersion(buildScriptClasspathData) - if (kotlinPluginVersion != null) { - return kotlinPluginVersion - } - } - } - } - - return null - } - - private fun findKotlinPluginVersion(classpathData: BuildScriptClasspathData): String? { - for (classPathEntry in classpathData.classpathEntries) { - for (path in classPathEntry.classesFile) { - val uniformedPath = path.replace('\\', '/') - if (uniformedPath.contains(KOTLIN_PLUGIN_PATH_MARKER)) { - val versionSubstring = uniformedPath.substringAfter(KOTLIN_PLUGIN_PATH_MARKER).substringBefore('/', "") - if (versionSubstring != "") { - return versionSubstring; - } - } - } - } - - return null - } } } \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt new file mode 100644 index 00000000000..39ab36dbc38 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/inspections/gradle/KotlinGradleInspectionVisitor.kt @@ -0,0 +1,100 @@ +/* + * 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.inspections.gradle + +import com.intellij.openapi.application.ApplicationManager +import com.intellij.openapi.externalSystem.model.DataNode +import com.intellij.openapi.externalSystem.model.Key +import com.intellij.openapi.externalSystem.model.ProjectKeys +import com.intellij.openapi.externalSystem.util.ExternalSystemApiUtil +import com.intellij.openapi.externalSystem.util.ExternalSystemUtil +import com.intellij.openapi.roots.ProjectRootManager +import com.intellij.openapi.util.io.FileUtilRt +import com.intellij.psi.PsiFile +import org.jetbrains.kotlin.idea.KotlinPluginUtil +import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator +import org.jetbrains.kotlin.idea.framework.GRADLE_SYSTEM_ID +import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData +import org.jetbrains.plugins.gradle.util.GradleConstants +import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor +import org.jetbrains.plugins.groovy.lang.psi.GroovyFileBase + +val KOTLIN_PLUGIN_CLASSPATH_MARKER = "${KotlinWithGradleConfigurator.GROUP_ID}:${KotlinWithGradleConfigurator.GRADLE_PLUGIN_ID}:" +val KOTLIN_PLUGIN_PATH_MARKER = "${KotlinWithGradleConfigurator.GROUP_ID}/${KotlinWithGradleConfigurator.GRADLE_PLUGIN_ID}/" + +abstract class KotlinGradleInspectionVisitor : BaseInspectionVisitor() { + override fun visitFile(file: GroovyFileBase?) { + if (file == null || !FileUtilRt.extensionEquals(file.name, GradleConstants.EXTENSION)) return + + val fileIndex = ProjectRootManager.getInstance(file.project).fileIndex + + if (!ApplicationManager.getApplication().isUnitTestMode) { + val module = fileIndex.getModuleForFile(file.virtualFile) ?: return + if (!KotlinPluginUtil.isGradleModule(module)) return + } + + if (fileIndex.isExcluded(file.virtualFile)) return + + super.visitFile(file) + } +} + +fun getResolvedKotlinGradleVersion(file: PsiFile): String? { + val project = file.project + val module = ProjectRootManager.getInstance(file.project).fileIndex.getModuleForFile(file.virtualFile) ?: return null + val projectPath = project.basePath ?: return null + + val projectInfo = ExternalSystemUtil.getExternalProjectInfo(project, GRADLE_SYSTEM_ID, projectPath) ?: return null + val projectStructureNode = projectInfo.externalProjectStructure ?: 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) + if (kotlinPluginVersion != null) { + return kotlinPluginVersion + } + } + + return null +} + +private fun findKotlinPluginVersion(classpathData: BuildScriptClasspathData): String? { + for (classPathEntry in classpathData.classpathEntries) { + for (path in classPathEntry.classesFile) { + val uniformedPath = path.replace('\\', '/') + if (uniformedPath.contains(KOTLIN_PLUGIN_PATH_MARKER)) { + val versionSubstring = uniformedPath.substringAfter(KOTLIN_PLUGIN_PATH_MARKER).substringBefore('/', "") + if (versionSubstring != "") { + return versionSubstring; + } + } + } + } + + return null +} + +class NodeWithData(val node: DataNode<*>, val data: T) + +fun DataNode<*>.findAll(key: Key): List> { + val nodes = ExternalSystemApiUtil.findAll(this, key) + return nodes.mapNotNull { + val data = it.getData(key) ?: return@mapNotNull null + NodeWithData(it, data) + } +} +