Refactoring: introduce parameter for getResolvedKotlinStdlibVersionByModuleData

This commit is contained in:
Nikolay Krasko
2018-07-18 13:37:41 +03:00
parent 7358cc5bd6
commit 86a33defd8
7 changed files with 33 additions and 48 deletions
@@ -32,6 +32,7 @@
package org.jetbrains.kotlin.android.configure package org.jetbrains.kotlin.android.configure
import com.android.builder.model.Library
import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys import com.android.tools.idea.gradle.project.sync.idea.data.service.AndroidProjectKeys
import com.intellij.openapi.externalSystem.model.DataNode import com.intellij.openapi.externalSystem.model.DataNode
import com.intellij.openapi.externalSystem.model.project.ModuleData import com.intellij.openapi.externalSystem.model.project.ModuleData
@@ -41,20 +42,19 @@ import org.gradle.tooling.model.UnsupportedMethodException
import org.gradle.tooling.model.idea.IdeaProject import org.gradle.tooling.model.idea.IdeaProject
import org.jetbrains.kotlin.idea.inspections.gradle.KotlinGradleModelFacade import org.jetbrains.kotlin.idea.inspections.gradle.KotlinGradleModelFacade
import org.jetbrains.kotlin.idea.inspections.gradle.findModulesByNames import org.jetbrains.kotlin.idea.inspections.gradle.findModulesByNames
import com.android.builder.model.Library
class AndroidGradleModelFacade : KotlinGradleModelFacade { class AndroidGradleModelFacade : KotlinGradleModelFacade {
override fun getResolvedKotlinStdlibVersionByModuleData(moduleData: DataNode<*>, libraryIds: List<String>): String? { override fun getResolvedVersionByModuleData(moduleData: DataNode<*>, groupId: String, libraryIds: List<String>): String? {
ExternalSystemApiUtil ExternalSystemApiUtil
.findAllRecursively(moduleData, AndroidProjectKeys.JAVA_MODULE_MODEL).asSequence() .findAllRecursively(moduleData, AndroidProjectKeys.JAVA_MODULE_MODEL).asSequence()
.flatMap { it.data.jarLibraryDependencies.asSequence() } .flatMap { it.data.jarLibraryDependencies.asSequence() }
.forEach { .forEach {
val libraryName = it.name val libraryName = it.name
for (libraryId in libraryIds) { for (libraryId in libraryIds) {
val prefix = "$libraryId-" val prefix = "$libraryId-"
if (libraryName.startsWith(prefix)) return libraryName.substringAfter(prefix) if (libraryName.startsWith(prefix)) return libraryName.substringAfter(prefix)
}
} }
}
return null return null
} }
@@ -46,7 +46,7 @@ import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.detectLibraryKind import org.jetbrains.kotlin.idea.framework.detectLibraryKind
import org.jetbrains.kotlin.idea.inspections.gradle.findAll import org.jetbrains.kotlin.idea.inspections.gradle.findAll
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedVersionByModuleData
import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
@@ -168,7 +168,7 @@ fun detectPlatformByPlugin(moduleNode: DataNode<ModuleData>): TargetPlatformKind
private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPlatformKind<*>? { private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPlatformKind<*>? {
val detectedPlatforms = val detectedPlatforms =
mavenLibraryIdToPlatform.entries mavenLibraryIdToPlatform.entries
.filter { moduleNode.getResolvedKotlinStdlibVersionByModuleData(listOf(it.key)) != null } .filter { moduleNode.getResolvedVersionByModuleData(KOTLIN_GROUP_ID, listOf(it.key)) != null }
.map { it.value }.distinct() .map { it.value }.distinct()
return detectedPlatforms.singleOrNull() ?: detectedPlatforms.firstOrNull { it != TargetPlatformKind.Common } return detectedPlatforms.singleOrNull() ?: detectedPlatforms.firstOrNull { it != TargetPlatformKind.Common }
} }
@@ -50,7 +50,7 @@ import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.detectLibraryKind import org.jetbrains.kotlin.idea.framework.detectLibraryKind
import org.jetbrains.kotlin.idea.inspections.gradle.findAll import org.jetbrains.kotlin.idea.inspections.gradle.findAll
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedVersionByModuleData
import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders import org.jetbrains.kotlin.idea.roots.migrateNonJvmSourceFolders
import org.jetbrains.kotlin.psi.UserDataProperty import org.jetbrains.kotlin.psi.UserDataProperty
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
@@ -180,7 +180,7 @@ fun detectPlatformByPlugin(moduleNode: DataNode<ModuleData>): TargetPlatformKind
private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPlatformKind<*>? { private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPlatformKind<*>? {
val detectedPlatforms = val detectedPlatforms =
mavenLibraryIdToPlatform.entries mavenLibraryIdToPlatform.entries
.filter { moduleNode.getResolvedKotlinStdlibVersionByModuleData(listOf(it.key)) != null } .filter { moduleNode.getResolvedVersionByModuleData(KOTLIN_GROUP_ID, listOf(it.key)) != null }
.map { it.value }.distinct() .map { it.value }.distinct()
return detectedPlatforms.singleOrNull() ?: detectedPlatforms.firstOrNull { it != TargetPlatformKind.Common } return detectedPlatforms.singleOrNull() ?: detectedPlatforms.firstOrNull { it != TargetPlatformKind.Common }
} }
@@ -50,7 +50,7 @@ import org.jetbrains.kotlin.idea.framework.JSLibraryKind
import org.jetbrains.kotlin.idea.framework.detectLibraryKind import org.jetbrains.kotlin.idea.framework.detectLibraryKind
import org.jetbrains.kotlin.idea.inspections.gradle.findAll import org.jetbrains.kotlin.idea.inspections.gradle.findAll
import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion import org.jetbrains.kotlin.idea.inspections.gradle.findKotlinPluginVersion
import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedKotlinStdlibVersionByModuleData import org.jetbrains.kotlin.idea.inspections.gradle.getResolvedVersionByModuleData
import org.jetbrains.kotlin.psi.UserDataProperty import org.jetbrains.kotlin.psi.UserDataProperty
import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData import org.jetbrains.plugins.gradle.model.data.BuildScriptClasspathData
import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData import org.jetbrains.plugins.gradle.model.data.GradleSourceSetData
@@ -179,7 +179,7 @@ fun detectPlatformByPlugin(moduleNode: DataNode<ModuleData>): TargetPlatformKind
private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPlatformKind<*>? { private fun detectPlatformByLibrary(moduleNode: DataNode<ModuleData>): TargetPlatformKind<*>? {
val detectedPlatforms = val detectedPlatforms =
mavenLibraryIdToPlatform.entries mavenLibraryIdToPlatform.entries
.filter { moduleNode.getResolvedKotlinStdlibVersionByModuleData(listOf(it.key)) != null } .filter { moduleNode.getResolvedVersionByModuleData(KOTLIN_GROUP_ID, listOf(it.key)) != null }
.map { it.value }.distinct() .map { it.value }.distinct()
return detectedPlatforms.singleOrNull() ?: detectedPlatforms.firstOrNull { it != TargetPlatformKind.Common } return detectedPlatforms.singleOrNull() ?: detectedPlatforms.firstOrNull { it != TargetPlatformKind.Common }
} }
@@ -61,10 +61,9 @@ class DeprecatedGradleDependencyInspection : GradleBaseInspection() {
val libMarker = outdatedInfo.old.gradleMarker val libMarker = outdatedInfo.old.gradleMarker
if (dependencyText.contains(libMarker)) { if (dependencyText.contains(libMarker)) {
// Should be generified for any library, not exactly Kotlin stdlib
val libVersion = val libVersion =
DifferentStdlibGradleVersionInspection.getResolvedKotlinStdlibVersion( DifferentStdlibGradleVersionInspection.getResolvedLibVersion(
dependencyStatement.containingFile, listOf(outdatedInfo.old.name) dependencyStatement.containingFile, outdatedInfo.old.groupId, listOf(outdatedInfo.old.name)
) ?: libraryVersionFromOrderEntry(dependencyStatement.containingFile, outdatedInfo.old.name) ) ?: libraryVersionFromOrderEntry(dependencyStatement.containingFile, outdatedInfo.old.name)
@@ -20,27 +20,26 @@ 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
import org.jetbrains.kotlin.idea.configuration.KOTLIN_GROUP_ID
import org.jetbrains.kotlin.idea.inspections.gradle.GradleHeuristicHelper.PRODUCTION_DEPENDENCY_STATEMENTS import org.jetbrains.kotlin.idea.inspections.gradle.GradleHeuristicHelper.PRODUCTION_DEPENDENCY_STATEMENTS
import org.jetbrains.kotlin.idea.versions.* import org.jetbrains.kotlin.idea.versions.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.plugins.gradle.codeInspection.GradleBaseInspection import org.jetbrains.plugins.gradle.codeInspection.GradleBaseInspection
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor 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.blocks.GrClosableBlock
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrCallExpression
import java.util.*
class DifferentStdlibGradleVersionInspection : GradleBaseInspection() { class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
override fun buildVisitor(): BaseInspectionVisitor = MyVisitor( override fun buildVisitor(): BaseInspectionVisitor = MyVisitor(
listOf(MAVEN_STDLIB_ID, MAVEN_STDLIB_ID_JRE7, MAVEN_STDLIB_ID_JDK7, MAVEN_STDLIB_ID_JRE8, MAVEN_STDLIB_ID_JDK8) KOTLIN_GROUP_ID, listOf(MAVEN_STDLIB_ID, MAVEN_STDLIB_ID_JRE7, MAVEN_STDLIB_ID_JDK7, MAVEN_STDLIB_ID_JRE8, MAVEN_STDLIB_ID_JDK8)
) )
override fun buildErrorString(vararg args: Any) = override fun buildErrorString(vararg args: Any) =
"Plugin version (${args[0]}) is not the same as library version (${args[1]})" "Plugin version (${args[0]}) is not the same as library version (${args[1]})"
private abstract class VersionFinder(private val libraryIds: List<String>) : KotlinGradleInspectionVisitor() { private abstract class VersionFinder(private val groupId: String, private val libraryIds: List<String>) :
KotlinGradleInspectionVisitor() {
protected abstract fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression) protected abstract fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression)
override fun visitClosure(closure: GrClosableBlock) { override fun visitClosure(closure: GrClosableBlock) {
@@ -52,13 +51,13 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
if (dependenciesCall.parent !is PsiFile) return if (dependenciesCall.parent !is PsiFile) return
val stdlibStatement = findLibraryStatement(closure, "org.jetbrains.kotlin", libraryIds) ?: return val stdlibStatement = findLibraryStatement(closure, "org.jetbrains.kotlin", libraryIds) ?: return
val stdlibVersion = getResolvedKotlinStdlibVersion(closure.containingFile, libraryIds) ?: return val stdlibVersion = getResolvedLibVersion(closure.containingFile, groupId, libraryIds) ?: return
onFound(stdlibVersion, stdlibStatement) onFound(stdlibVersion, stdlibStatement)
} }
} }
private inner class MyVisitor(libraryIds: List<String>) : VersionFinder(libraryIds) { private inner class MyVisitor(groupId: String, libraryIds: List<String>) : VersionFinder(groupId, libraryIds) {
override fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression) { override fun onFound(stdlibVersion: String, stdlibStatement: GrCallExpression) {
val gradlePluginVersion = getResolvedKotlinGradleVersion(stdlibStatement.containingFile) val gradlePluginVersion = getResolvedKotlinGradleVersion(stdlibStatement.containingFile)
@@ -69,33 +68,20 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
} }
companion object { companion object {
fun getKotlinStdlibVersions(gradleFile: GroovyFileBase, libraryId: List<String>): Collection<String> {
val versions = LinkedHashSet<String>()
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, libraryIds: List<String>): GrCallExpression? { private fun findLibraryStatement(closure: GrClosableBlock, libraryGroup: String, libraryIds: List<String>): GrCallExpression? {
return GradleHeuristicHelper.findStatementWithPrefixes(closure, PRODUCTION_DEPENDENCY_STATEMENTS).firstOrNull { statement -> return GradleHeuristicHelper.findStatementWithPrefixes(closure, PRODUCTION_DEPENDENCY_STATEMENTS).firstOrNull { statement ->
libraryIds.any { it in statement.text } && statement.text.contains(libraryGroup) libraryIds.any { it in statement.text } && statement.text.contains(libraryGroup)
} }
} }
fun getResolvedKotlinStdlibVersion(file: PsiFile, libraryIds: List<String>): String? { fun getResolvedLibVersion(file: PsiFile, groupId: String, libraryIds: List<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 }) {
moduleData.node.getResolvedKotlinStdlibVersionByModuleData(libraryIds)?.let { return it } moduleData.node.getResolvedVersionByModuleData(groupId, libraryIds)?.let {
return it
}
} }
return null return null
@@ -103,8 +89,8 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
} }
} }
internal fun DataNode<*>.getResolvedKotlinStdlibVersionByModuleData(libraryIds: List<String>): String? { internal fun DataNode<*>.getResolvedVersionByModuleData(groupId: String, libraryIds: List<String>): String? {
return KotlinGradleModelFacade.EP_NAME.extensions.asSequence() return KotlinGradleModelFacade.EP_NAME.extensions.asSequence()
.mapNotNull { it.getResolvedKotlinStdlibVersionByModuleData(this, libraryIds) } .mapNotNull { it.getResolvedVersionByModuleData(this, groupId, libraryIds) }
.firstOrNull() .firstOrNull()
} }
@@ -30,15 +30,15 @@ interface KotlinGradleModelFacade {
val EP_NAME: ExtensionPointName<KotlinGradleModelFacade> = ExtensionPointName.create("org.jetbrains.kotlin.gradleModelFacade") val EP_NAME: ExtensionPointName<KotlinGradleModelFacade> = ExtensionPointName.create("org.jetbrains.kotlin.gradleModelFacade")
} }
fun getResolvedKotlinStdlibVersionByModuleData(moduleData: DataNode<*>, libraryIds: List<String>): String? fun getResolvedVersionByModuleData(moduleData: DataNode<*>, groupId: String, libraryIds: List<String>): String?
fun getDependencyModules(ideModule: DataNode<ModuleData>, gradleIdeaProject: IdeaProject): Collection<DataNode<ModuleData>> fun getDependencyModules(ideModule: DataNode<ModuleData>, gradleIdeaProject: IdeaProject): Collection<DataNode<ModuleData>>
} }
class DefaultGradleModelFacade : KotlinGradleModelFacade { class DefaultGradleModelFacade : KotlinGradleModelFacade {
override fun getResolvedKotlinStdlibVersionByModuleData(moduleData: DataNode<*>, libraryIds: List<String>): String? { override fun getResolvedVersionByModuleData(moduleData: DataNode<*>, groupId: String, libraryIds: List<String>): String? {
for (libraryDependencyData in ExternalSystemApiUtil.findAllRecursively(moduleData, ProjectKeys.LIBRARY_DEPENDENCY)) { for (libraryDependencyData in ExternalSystemApiUtil.findAllRecursively(moduleData, ProjectKeys.LIBRARY_DEPENDENCY)) {
for (libraryId in libraryIds) { for (libraryId in libraryIds) {
val libraryNameMarker = "org.jetbrains.kotlin:$libraryId:" val libraryNameMarker = "$groupId:$libraryId:"
if (libraryDependencyData.data.externalName.startsWith(libraryNameMarker)) { if (libraryDependencyData.data.externalName.startsWith(libraryNameMarker)) {
return libraryDependencyData.data.externalName.substringAfter(libraryNameMarker) return libraryDependencyData.data.externalName.substringAfter(libraryNameMarker)
} }