Add support for "implementation" gradle directive (KT-21746)
#KT-21746 Fixed
This commit is contained in:
+1
-1
@@ -89,7 +89,7 @@ abstract class GradleKotlinFrameworkSupportProvider(
|
||||
.addBuildscriptPropertyDefinition("ext.kotlin_version = '$kotlinVersion'")
|
||||
|
||||
for (dependency in getDependencies(sdk)) {
|
||||
buildScriptData.addDependencyNotation(KotlinWithGradleConfigurator.getGroovyDependencySnippet(dependency))
|
||||
buildScriptData.addDependencyNotation(KotlinWithGradleConfigurator.getGroovyDependencySnippet(dependency, "compile"))
|
||||
}
|
||||
for (dependency in getTestDependencies()) {
|
||||
buildScriptData.addDependencyNotation(
|
||||
|
||||
+7
-5
@@ -20,6 +20,7 @@ import com.intellij.openapi.roots.DependencyScope
|
||||
import com.intellij.openapi.roots.ExternalLibraryDescriptor
|
||||
import com.intellij.psi.PsiElement
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.kotlin.idea.inspections.gradle.GradleHeuristicHelper.PRODUCTION_DEPENDENCY_STATEMENTS
|
||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||
import org.jetbrains.kotlin.psi.*
|
||||
import org.jetbrains.kotlin.psi.psiUtil.getChildrenOfType
|
||||
@@ -105,10 +106,10 @@ class KotlinBuildScriptManipulator(private val kotlinScript: KtFile) : GradleBui
|
||||
override fun getKotlinStdlibVersion(): String? = kotlinScript.getKotlinStdlibVersion()
|
||||
|
||||
private fun KtBlockExpression.addCompileStdlibIfMissing(stdlibArtifactName: String): KtCallExpression? =
|
||||
findCompileStdLib() ?: addExpressionIfMissing(getCompileDependencySnippet(KOTLIN_GROUP_ID, stdlibArtifactName)) as? KtCallExpression
|
||||
findStdLibDependency() ?: addExpressionIfMissing(getCompileDependencySnippet(KOTLIN_GROUP_ID, stdlibArtifactName)) as? KtCallExpression
|
||||
|
||||
private fun KtFile.containsCompileStdLib(): Boolean =
|
||||
findScriptInitializer("dependencies")?.getBlock()?.findCompileStdLib() != null
|
||||
findScriptInitializer("dependencies")?.getBlock()?.findStdLibDependency() != null
|
||||
|
||||
private fun KtFile.containsApplyKotlinPlugin(pluginName: String): Boolean =
|
||||
findScriptInitializer("apply")?.getBlock()?.findPlugin(pluginName) != null
|
||||
@@ -137,7 +138,7 @@ class KotlinBuildScriptManipulator(private val kotlinScript: KtFile) : GradleBui
|
||||
|
||||
private fun KtFile.getKotlinStdlibVersion(): String? {
|
||||
return findScriptInitializer("dependencies")?.getBlock()?.let {
|
||||
val expression = it.findCompileStdLib()?.valueArguments?.firstOrNull()?.getArgumentExpression()
|
||||
val expression = it.findStdLibDependency()?.valueArguments?.firstOrNull()?.getArgumentExpression()
|
||||
when (expression) {
|
||||
is KtCallExpression -> expression.valueArguments[1].text.trim('\"')
|
||||
is KtStringTemplateExpression -> expression.text?.trim('\"')?.substringAfterLast(":")?.removePrefix("$")
|
||||
@@ -146,9 +147,10 @@ class KotlinBuildScriptManipulator(private val kotlinScript: KtFile) : GradleBui
|
||||
}
|
||||
}
|
||||
|
||||
private fun KtBlockExpression.findCompileStdLib(): KtCallExpression? {
|
||||
private fun KtBlockExpression.findStdLibDependency(): KtCallExpression? {
|
||||
return PsiTreeUtil.getChildrenOfType(this, KtCallExpression::class.java)?.find {
|
||||
it.calleeExpression?.text == "compile" && (it.valueArguments.firstOrNull()?.getArgumentExpression()?.isKotlinStdLib() ?: false)
|
||||
val calleeText = it.calleeExpression?.text
|
||||
calleeText in PRODUCTION_DEPENDENCY_STATEMENTS && (it.valueArguments.firstOrNull()?.getArgumentExpression()?.isKotlinStdLib() ?: false)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+1
-1
@@ -264,7 +264,7 @@ abstract class KotlinWithGradleConfigurator : KotlinProjectConfigurator {
|
||||
|
||||
private val KOTLIN_BUILD_SCRIPT_NAME = "build.gradle.kts"
|
||||
|
||||
fun getGroovyDependencySnippet(artifactName: String, scope: String = "compile") =
|
||||
fun getGroovyDependencySnippet(artifactName: String, scope: String) =
|
||||
"$scope \"org.jetbrains.kotlin:$artifactName:\$kotlin_version\""
|
||||
|
||||
fun getGroovyApplyPluginDirective(pluginName: String) = "apply plugin: '$pluginName'"
|
||||
|
||||
+3
-1
@@ -25,6 +25,7 @@ import com.intellij.util.text.VersionComparatorUtil
|
||||
import org.jetbrains.kotlin.idea.configuration.allModules
|
||||
import org.jetbrains.kotlin.idea.configuration.getWholeModuleGroup
|
||||
import org.jetbrains.kotlin.idea.inspections.ReplaceStringInDocumentFix
|
||||
import org.jetbrains.kotlin.idea.inspections.gradle.GradleHeuristicHelper.PRODUCTION_DEPENDENCY_STATEMENTS
|
||||
import org.jetbrains.kotlin.idea.versions.DEPRECATED_LIBRARIES_INFORMATION
|
||||
import org.jetbrains.kotlin.idea.versions.DeprecatedLibInfo
|
||||
import org.jetbrains.kotlin.idea.versions.LibInfo
|
||||
@@ -47,7 +48,8 @@ class DeprecatedGradleDependencyInspection : GradleBaseInspection() {
|
||||
val dependenciesCall = closure.getStrictParentOfType<GrMethodCall>() ?: return
|
||||
if (dependenciesCall.invokedExpression.text != "dependencies") return
|
||||
|
||||
val dependencyEntries = GradleHeuristicHelper.findStatementWithPrefix(closure, "compile")
|
||||
val dependencyEntries = GradleHeuristicHelper.findStatementWithPrefixes(
|
||||
closure, PRODUCTION_DEPENDENCY_STATEMENTS)
|
||||
for (dependencyStatement in dependencyEntries) {
|
||||
visitDependencyEntry(dependencyStatement)
|
||||
}
|
||||
|
||||
+3
-15
@@ -20,8 +20,8 @@ import com.intellij.openapi.externalSystem.model.DataNode
|
||||
import com.intellij.openapi.externalSystem.model.ProjectKeys
|
||||
import com.intellij.openapi.roots.ProjectRootManager
|
||||
import com.intellij.psi.PsiFile
|
||||
import org.jetbrains.kotlin.idea.inspections.gradle.GradleHeuristicHelper.PRODUCTION_DEPENDENCY_STATEMENTS
|
||||
import org.jetbrains.kotlin.idea.versions.*
|
||||
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.groovy.codeInspection.BaseInspectionVisitor
|
||||
@@ -29,7 +29,6 @@ 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.*
|
||||
|
||||
@@ -70,8 +69,6 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
|
||||
}
|
||||
|
||||
companion object {
|
||||
val COMPILE_DEPENDENCY_STATEMENTS = listOf("classpath", "compile")
|
||||
|
||||
fun getKotlinStdlibVersions(gradleFile: GroovyFileBase, libraryId: List<String>): Collection<String> {
|
||||
val versions = LinkedHashSet<String>()
|
||||
val visitor = object : VersionFinder(libraryId) {
|
||||
@@ -88,18 +85,9 @@ class DifferentStdlibGradleVersionInspection : GradleBaseInspection() {
|
||||
}
|
||||
|
||||
private fun findLibraryStatement(closure: GrClosableBlock, libraryGroup: String, libraryIds: List<String>): GrCallExpression? {
|
||||
val applicationStatements = closure.getChildrenOfType<GrCallExpression>()
|
||||
|
||||
for (statement in applicationStatements) {
|
||||
val startExpression = statement.getChildrenOfType<GrReferenceExpression>().firstOrNull() ?: continue
|
||||
if (startExpression.text in COMPILE_DEPENDENCY_STATEMENTS) {
|
||||
if (libraryIds.any { it in statement.text } && statement.text.contains(libraryGroup)) {
|
||||
return statement
|
||||
}
|
||||
}
|
||||
return GradleHeuristicHelper.findStatementWithPrefixes(closure, PRODUCTION_DEPENDENCY_STATEMENTS).firstOrNull { statement ->
|
||||
libraryIds.any { it in statement.text } && statement.text.contains(libraryGroup)
|
||||
}
|
||||
|
||||
return null
|
||||
}
|
||||
|
||||
fun getResolvedKotlinStdlibVersion(file: PsiFile, libraryIds: List<String>): String? {
|
||||
|
||||
+8
-2
@@ -30,6 +30,8 @@ import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrC
|
||||
import java.util.*
|
||||
|
||||
object GradleHeuristicHelper {
|
||||
val PRODUCTION_DEPENDENCY_STATEMENTS = setOf("classpath", "compile", "api", "implementation", "compileOnly", "runtimeOnly")
|
||||
|
||||
fun getHeuristicVersionInBuildScriptDependency(classpathStatement: GrCallExpression): String? {
|
||||
val argumentList = when (classpathStatement) {
|
||||
is GrMethodCall -> classpathStatement.argumentList // classpath('argument')
|
||||
@@ -83,14 +85,18 @@ object GradleHeuristicHelper {
|
||||
return null
|
||||
}
|
||||
|
||||
fun findStatementWithPrefix(closure: GrClosableBlock, prefix: String): List<GrCallExpression> {
|
||||
fun findStatementWithPrefix(closure: GrClosableBlock, prefix: String) =
|
||||
findStatementWithPrefixes(closure, setOf(prefix))
|
||||
|
||||
fun findStatementWithPrefixes(closure: GrClosableBlock, prefixes: Set<String>): List<GrCallExpression> {
|
||||
val applicationStatements = closure.getChildrenOfType<GrCallExpression>()
|
||||
|
||||
val classPathStatements = ArrayList<GrCallExpression>()
|
||||
|
||||
for (statement in applicationStatements) {
|
||||
val startExpression = statement.getChildrenOfType<GrReferenceExpression>().firstOrNull() ?: continue
|
||||
if (prefix == startExpression.text) {
|
||||
val expressionText = startExpression.text ?: continue
|
||||
if (expressionText in prefixes) {
|
||||
classPathStatements.add(statement)
|
||||
}
|
||||
}
|
||||
|
||||
+33
@@ -254,6 +254,39 @@ class GradleConfiguratorTest : GradleImportingTestCase() {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListNonConfiguredModules_ConfiguredWithImplementation() {
|
||||
createProjectSubFile("settings.gradle", "include ':app'")
|
||||
createProjectSubFile(
|
||||
"app/build.gradle", """
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
|
||||
repositories {
|
||||
jcenter()
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.1.3"
|
||||
}
|
||||
""".trimIndent()
|
||||
)
|
||||
createProjectSubFile("app/src/main/java/foo.kt", "")
|
||||
|
||||
importProject()
|
||||
|
||||
runReadAction {
|
||||
assertEmpty(getCanBeConfiguredModulesWithKotlinFiles(myProject))
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testListNonConfiguredModules_ConfiguredOnlyTest() {
|
||||
createProjectSubFile("settings.gradle", "include ':app'")
|
||||
|
||||
+69
@@ -61,6 +61,39 @@ class GradleInspectionTest : GradleImportingTestCase() {
|
||||
Assert.assertEquals("Plugin version (1.0.2) is not the same as library version (1.0.3)", problems.single())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDifferentStdlibGradleVersionWithImplementation() {
|
||||
val localFile = createProjectSubFile(
|
||||
"build.gradle", """
|
||||
group 'Again'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.0.2")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.0.3"
|
||||
}
|
||||
"""
|
||||
)
|
||||
importProject()
|
||||
|
||||
val tool = DifferentStdlibGradleVersionInspection()
|
||||
val problems = getInspectionResult(tool, localFile)
|
||||
|
||||
Assert.assertTrue(problems.size == 1)
|
||||
Assert.assertEquals("Plugin version (1.0.2) is not the same as library version (1.0.3)", problems.single())
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testDifferentStdlibJre7GradleVersion() {
|
||||
val localFile = createProjectSubFile(
|
||||
@@ -274,6 +307,42 @@ class GradleInspectionTest : GradleImportingTestCase() {
|
||||
)
|
||||
}
|
||||
|
||||
@Test
|
||||
fun testJreIsDeprecatedWithImplementation() {
|
||||
val localFile = createProjectSubFile(
|
||||
"build.gradle", """
|
||||
group 'Again'
|
||||
version '1.0-SNAPSHOT'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.2.0")
|
||||
}
|
||||
}
|
||||
|
||||
apply plugin: 'kotlin'
|
||||
|
||||
dependencies {
|
||||
implementation "org.jetbrains.kotlin:kotlin-stdlib-jre7:1.2.0"
|
||||
}
|
||||
"""
|
||||
)
|
||||
importProject()
|
||||
|
||||
val tool = DeprecatedGradleDependencyInspection()
|
||||
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> {
|
||||
val resultRef = Ref<List<String>>()
|
||||
invokeTestRunnable {
|
||||
|
||||
Reference in New Issue
Block a user