Inspection for using deprecated jre artifacts in Gradle (KT-20947)
#KT-20947 In Progress
This commit is contained in:
+1
-1
@@ -101,7 +101,7 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
|
|||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun getResolvedKotlinStdlibVersion(file: PsiFile, libraryIds: List<String>): String? {
|
fun getResolvedKotlinStdlibVersion(file: PsiFile, 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
|
||||||
|
|
||||||
|
|||||||
+152
@@ -0,0 +1,152 @@
|
|||||||
|
/*
|
||||||
|
* 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.codeInspection.ProblemHighlightType
|
||||||
|
import com.intellij.openapi.roots.ModuleRootManager
|
||||||
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiFile
|
||||||
|
import com.intellij.util.text.VersionComparatorUtil
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.KotlinWithGradleConfigurator
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.allModules
|
||||||
|
import org.jetbrains.kotlin.idea.configuration.getWholeModuleGroup
|
||||||
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
|
import org.jetbrains.kotlin.utils.PathUtil
|
||||||
|
import org.jetbrains.plugins.gradle.codeInspection.GradleBaseInspection
|
||||||
|
import org.jetbrains.plugins.groovy.codeInspection.BaseInspectionVisitor
|
||||||
|
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.path.GrCallExpression
|
||||||
|
|
||||||
|
data class LibInfo(
|
||||||
|
val groupId: String,
|
||||||
|
val name: String
|
||||||
|
)
|
||||||
|
|
||||||
|
data class OutdatedLibInfo(
|
||||||
|
val old: LibInfo,
|
||||||
|
val new: LibInfo,
|
||||||
|
val outdatedAfterVersion: String,
|
||||||
|
val message: String
|
||||||
|
)
|
||||||
|
|
||||||
|
private val outdatedLibrariesInformation = listOf(
|
||||||
|
outdatedLib(
|
||||||
|
oldGroupId = KotlinWithGradleConfigurator.GROUP_ID,
|
||||||
|
oldName = PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME, newName = PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME,
|
||||||
|
outdatedAfterVersion = "1.2.0-rc-39",
|
||||||
|
message = "${PathUtil.KOTLIN_JAVA_RUNTIME_JRE7_NAME} is deprecated since 1.2.0 and should be replaced with ${PathUtil.KOTLIN_JAVA_RUNTIME_JDK7_NAME}"),
|
||||||
|
|
||||||
|
outdatedLib(
|
||||||
|
oldGroupId = KotlinWithGradleConfigurator.GROUP_ID,
|
||||||
|
oldName = PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME, newName = PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME,
|
||||||
|
outdatedAfterVersion = "1.2.0-rc-39",
|
||||||
|
message = "${PathUtil.KOTLIN_JAVA_RUNTIME_JRE8_NAME} is deprecated since 1.2.0 and should be replaced with ${PathUtil.KOTLIN_JAVA_RUNTIME_JDK8_NAME}")
|
||||||
|
)
|
||||||
|
|
||||||
|
private val LibInfo.gradleMarker get() = "$groupId:$name:"
|
||||||
|
|
||||||
|
private fun outdatedLib(
|
||||||
|
oldGroupId: String,
|
||||||
|
oldName: String,
|
||||||
|
newGroupId: String = oldGroupId,
|
||||||
|
newName: String = oldName,
|
||||||
|
outdatedAfterVersion: String,
|
||||||
|
message: String): OutdatedLibInfo {
|
||||||
|
return OutdatedLibInfo(
|
||||||
|
old = LibInfo(groupId = oldGroupId, name = oldName),
|
||||||
|
new = LibInfo(groupId = newGroupId, name = newName),
|
||||||
|
outdatedAfterVersion = outdatedAfterVersion,
|
||||||
|
message = message
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
class GradleDependencyInspection : GradleBaseInspection() {
|
||||||
|
override fun buildVisitor(): BaseInspectionVisitor = DependencyFinder()
|
||||||
|
|
||||||
|
private open class DependencyFinder : KotlinGradleInspectionVisitor() {
|
||||||
|
override fun visitClosure(closure: GrClosableBlock) {
|
||||||
|
super.visitClosure(closure)
|
||||||
|
|
||||||
|
val dependenciesCall = closure.getStrictParentOfType<GrMethodCall>() ?: return
|
||||||
|
if (dependenciesCall.invokedExpression.text != "dependencies") return
|
||||||
|
|
||||||
|
val dependencyEntries = GradleHeuristicHelper.findStatementWithPrefix(closure, "compile")
|
||||||
|
for (dependencyStatement in dependencyEntries) {
|
||||||
|
visitDependencyEntry(dependencyStatement)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
open fun visitDependencyEntry(dependencyStatement: GrCallExpression) {
|
||||||
|
for (outdatedInfo in outdatedLibrariesInformation) {
|
||||||
|
val dependencyText = dependencyStatement.text
|
||||||
|
val libMarker = outdatedInfo.old.gradleMarker
|
||||||
|
|
||||||
|
if (dependencyText.contains(libMarker)) {
|
||||||
|
// Should be generified for any library, not exactly Kotlin stdlib
|
||||||
|
val libVersion =
|
||||||
|
DifferentStdlibGradleVersionInspection.getResolvedKotlinStdlibVersion(
|
||||||
|
dependencyStatement.containingFile, listOf(outdatedInfo.old.name)) ?:
|
||||||
|
libraryVersionFromOrderEntry(dependencyStatement.containingFile, outdatedInfo.old.name)
|
||||||
|
|
||||||
|
|
||||||
|
if (libVersion != null && VersionComparatorUtil.COMPARATOR.compare(libVersion, outdatedInfo.outdatedAfterVersion) >= 0) {
|
||||||
|
val reportOnElement = reportOnElement(dependencyStatement, outdatedInfo)
|
||||||
|
|
||||||
|
registerError(
|
||||||
|
reportOnElement, outdatedInfo.message,
|
||||||
|
arrayOf(),
|
||||||
|
ProblemHighlightType.LIKE_DEPRECATED)
|
||||||
|
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun reportOnElement(classpathEntry: GrCallExpression, outdatedInfo: OutdatedLibInfo): PsiElement {
|
||||||
|
val indexOf = classpathEntry.text.indexOf(outdatedInfo.old.name)
|
||||||
|
if (indexOf < 0) return classpathEntry
|
||||||
|
|
||||||
|
return classpathEntry.findElementAt(indexOf) ?: classpathEntry
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun libraryVersionFromOrderEntry(file: PsiFile, libraryId: String): String? {
|
||||||
|
val module = ProjectRootManager.getInstance(file.project).fileIndex.getModuleForFile(file.virtualFile) ?: return null
|
||||||
|
val libMarker = ":$libraryId:"
|
||||||
|
|
||||||
|
for (moduleInGroup in module.getWholeModuleGroup().allModules()) {
|
||||||
|
var libVersion: String? = null
|
||||||
|
ModuleRootManager.getInstance(moduleInGroup).orderEntries().forEachLibrary { library ->
|
||||||
|
if (library.name?.contains(libMarker) == true) {
|
||||||
|
libVersion = library.name?.substringAfterLast(":")
|
||||||
|
}
|
||||||
|
|
||||||
|
// Continue if nothing is found
|
||||||
|
libVersion == null
|
||||||
|
}
|
||||||
|
|
||||||
|
if (libVersion != null) {
|
||||||
|
return libVersion
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
+62
@@ -22,6 +22,7 @@ import com.intellij.openapi.util.Ref
|
|||||||
import com.intellij.openapi.vfs.VirtualFile
|
import com.intellij.openapi.vfs.VirtualFile
|
||||||
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection
|
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentKotlinGradleVersionInspection
|
||||||
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection
|
import org.jetbrains.kotlin.idea.inspections.gradle.DifferentStdlibGradleVersionInspection
|
||||||
|
import org.jetbrains.kotlin.idea.inspections.gradle.GradleDependencyInspection
|
||||||
import org.jetbrains.kotlin.idea.inspections.runInspection
|
import org.jetbrains.kotlin.idea.inspections.runInspection
|
||||||
import org.junit.Assert
|
import org.junit.Assert
|
||||||
import org.junit.Test
|
import org.junit.Test
|
||||||
@@ -190,6 +191,67 @@ class GradleInspectionTest : GradleImportingTestCase() {
|
|||||||
Assert.assertEquals("Kotlin version that is used for building with Gradle (1.0.1) differs from the one bundled into the IDE plugin (\$PLUGIN_VERSION)", problems.single())
|
Assert.assertEquals("Kotlin version that is used for building with Gradle (1.0.1) differs from the one bundled into the IDE plugin (\$PLUGIN_VERSION)", problems.single())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testJreInOldVersion() {
|
||||||
|
val localFile = createProjectSubFile("build.gradle", """
|
||||||
|
group 'Again'
|
||||||
|
version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.60")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jre8:1.1.60"
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
importProject()
|
||||||
|
|
||||||
|
val tool = GradleDependencyInspection()
|
||||||
|
val problems = getInspectionResult(tool, localFile)
|
||||||
|
|
||||||
|
Assert.assertTrue(problems.isEmpty())
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
|
fun testJreIsDeprecated() {
|
||||||
|
val localFile = createProjectSubFile("build.gradle", """
|
||||||
|
group 'Again'
|
||||||
|
version '1.0-SNAPSHOT'
|
||||||
|
|
||||||
|
buildscript {
|
||||||
|
repositories {
|
||||||
|
mavenCentral()
|
||||||
|
}
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.1.60")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
apply plugin: 'kotlin'
|
||||||
|
|
||||||
|
dependencies {
|
||||||
|
compile "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0"
|
||||||
|
}
|
||||||
|
""")
|
||||||
|
importProject()
|
||||||
|
|
||||||
|
val tool = GradleDependencyInspection()
|
||||||
|
val problems = getInspectionResult(tool, localFile)
|
||||||
|
|
||||||
|
Assert.assertTrue(problems.size == 1)
|
||||||
|
Assert.assertEquals("kotlin-stdlib-jre7 is deprecated since 1.2.0 and should be replaced with kotlin-stdlib-jdk7", problems.single())
|
||||||
|
}
|
||||||
|
|
||||||
fun getInspectionResult(tool: LocalInspectionTool, file: VirtualFile): List<String> {
|
fun getInspectionResult(tool: LocalInspectionTool, file: VirtualFile): List<String> {
|
||||||
val resultRef = Ref<List<String>>()
|
val resultRef = Ref<List<String>>()
|
||||||
invokeTestRunnable {
|
invokeTestRunnable {
|
||||||
|
|||||||
@@ -0,0 +1,5 @@
|
|||||||
|
<html>
|
||||||
|
<body>
|
||||||
|
This inspection reports that some deprecated dependency is used in Gradle.
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -39,6 +39,15 @@
|
|||||||
hasStaticDescription="true"
|
hasStaticDescription="true"
|
||||||
level="WARNING"/>
|
level="WARNING"/>
|
||||||
|
|
||||||
|
<localInspection
|
||||||
|
implementationClass="org.jetbrains.kotlin.idea.inspections.gradle.GradleDependencyInspection"
|
||||||
|
displayName="Deprecated library is used in Gradle"
|
||||||
|
groupName="Kotlin"
|
||||||
|
enabledByDefault="true"
|
||||||
|
language="Groovy"
|
||||||
|
hasStaticDescription="true"
|
||||||
|
level="WARNING"/>
|
||||||
|
|
||||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestClassGradleConfigurationProducer"/>
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestClassGradleConfigurationProducer"/>
|
||||||
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestMethodGradleConfigurationProducer"/>
|
<runConfigurationProducer implementation="org.jetbrains.kotlin.idea.run.KotlinTestMethodGradleConfigurationProducer"/>
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user