mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-02-04 23:39:07 +07:00
[gradle][groovy] IDEA-257715 make GradleDelegatesToProvider responsible for delegate resolving in Project's Closures.
Previously, GradleProjectContributor was responsible for delegate resolving in closures of several Project methods. It was a hardcoded logic: if Closure is a parameter of method foo() from class Project, then let delegate be CLASS_NAME. The new logic implemented in GradleDelegatesToProvider is more flexible. It allows determining a delegate if a called method with Closure has overloaded method with Action<? super AnyDelegateClass>. It covers almost all the cases supported by GradleProjectContributor, and gets triggered before it. So all covered cases were removed from there, except the delegate resolving for Project#configure(...) method. Project#configure(...) has a version with Action<? super T> parameter, but it's not possible to surely resolve T if the version of this method with Closure was called. This commit also has tests covering considered cases for Project. GitOrigin-RevId: e1088ad60a61868856aca4dc0b8e943bc7e04e5f
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ff211722d2
commit
d191022332
@@ -70,7 +70,9 @@ class GradleDelegatesToProvider : GrDelegatesToProvider {
|
||||
return delegate
|
||||
}
|
||||
val fqClassName = delegate.canonicalText
|
||||
if (fqClassName != GRADLE_API_ARTIFACT_HANDLER) {
|
||||
if (fqClassName != GRADLE_API_ARTIFACT_HANDLER
|
||||
&& fqClassName != GRADLE_API_PROJECT
|
||||
) {
|
||||
return delegate
|
||||
}
|
||||
val type = createType(fqClassName, expression)
|
||||
|
||||
@@ -1,13 +1,10 @@
|
||||
// Copyright 2000-2019 JetBrains s.r.o. Use of this source code is governed by the Apache 2.0 license that can be found in the LICENSE file.
|
||||
package org.jetbrains.plugins.gradle.service.resolve
|
||||
|
||||
import com.intellij.psi.PsiClassType
|
||||
import com.intellij.psi.PsiType
|
||||
import com.intellij.util.ProcessingContext
|
||||
import groovy.lang.Closure
|
||||
import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.*
|
||||
import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.blocks.GrClosableBlock
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.path.GrMethodCallExpression
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil.createType
|
||||
import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyClosurePattern
|
||||
import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure
|
||||
@@ -20,12 +17,8 @@ import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo
|
||||
class GradleProjectContributor : GradleMethodContextContributor {
|
||||
companion object {
|
||||
val projectClosure: GroovyClosurePattern = groovyClosure().inMethod(
|
||||
psiMethod(GRADLE_API_PROJECT, "project", "configure", "subprojects", "allprojects")
|
||||
psiMethod(GRADLE_API_PROJECT, "configure")
|
||||
).inMethodResult(saveProjectType)
|
||||
val copySpecClosure: GroovyClosurePattern = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "copy", "copySpec"))
|
||||
val fileTreeClosure: GroovyClosurePattern = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "fileTree"))
|
||||
val filesClosure: GroovyClosurePattern = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "files"))
|
||||
val execClosure: GroovyClosurePattern = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "exec"))
|
||||
}
|
||||
|
||||
override fun getDelegatesToInfo(closure: GrClosableBlock): DelegatesToInfo? {
|
||||
@@ -34,18 +27,6 @@ class GradleProjectContributor : GradleMethodContextContributor {
|
||||
val projectType = createType(GRADLE_API_PROJECT, closure)
|
||||
return DelegatesToInfo(context[projectTypeKey]?.setType(projectType) ?: projectType, Closure.DELEGATE_FIRST)
|
||||
}
|
||||
if (copySpecClosure.accepts(closure)) {
|
||||
return DelegatesToInfo(createType(GRADLE_API_FILE_COPY_SPEC, closure), Closure.DELEGATE_FIRST)
|
||||
}
|
||||
if (fileTreeClosure.accepts(closure)) {
|
||||
return DelegatesToInfo(createType(GRADLE_API_FILE_CONFIGURABLE_FILE_TREE, closure), Closure.DELEGATE_FIRST)
|
||||
}
|
||||
if (filesClosure.accepts(closure)) {
|
||||
return DelegatesToInfo(createType(GRADLE_API_FILE_CONFIGURABLE_FILE_COLLECTION, closure), Closure.DELEGATE_FIRST)
|
||||
}
|
||||
if (execClosure.accepts(closure)) {
|
||||
return DelegatesToInfo(createType(GRADLE_PROCESS_EXEC_SPEC, closure), Closure.DELEGATE_FIRST)
|
||||
}
|
||||
return null
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,8 +3,9 @@ package org.jetbrains.plugins.gradle.dsl
|
||||
|
||||
import com.intellij.psi.PsiMethod
|
||||
import com.intellij.testFramework.assertInstanceOf
|
||||
import groovy.lang.Closure.DELEGATE_FIRST
|
||||
import org.gradle.util.GradleVersion
|
||||
import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.GRADLE_API_PROJECT
|
||||
import org.jetbrains.plugins.gradle.service.resolve.GradleCommonClassNames.*
|
||||
import org.jetbrains.plugins.gradle.testFramework.GradleCodeInsightTestCase
|
||||
import org.jetbrains.plugins.gradle.testFramework.annotations.AllGradleVersionsSource
|
||||
import org.jetbrains.plugins.groovy.lang.psi.api.statements.expressions.GrMethodCall
|
||||
@@ -113,4 +114,68 @@ class GradleProjectTest : GradleCodeInsightTestCase() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@AllGradleVersionsSource("""
|
||||
"project(':') {<caret>}",
|
||||
"allprojects {<caret>}",
|
||||
"subprojects {<caret>}",
|
||||
"configure(project(':')) {<caret>}",
|
||||
"configure([project(':')]) {<caret>}",
|
||||
"beforeEvaluate {<caret>}",
|
||||
"afterEvaluate {<caret>}"
|
||||
""")
|
||||
fun `resolve a delegate in Closures of methods providing Project's context`(
|
||||
gradleVersion: GradleVersion,
|
||||
expression: String
|
||||
) {
|
||||
testEmptyProject(gradleVersion) {
|
||||
testBuildscript(expression) {
|
||||
closureDelegateTest(GRADLE_API_PROJECT, DELEGATE_FIRST)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@AllGradleVersionsSource(PROJECT_CONTEXTS, """
|
||||
"copy{<caret>}",
|
||||
"copySpec{<caret>}"
|
||||
""")
|
||||
fun `resolve a delegate in copy and copySpec Closures`(gradleVersion: GradleVersion, decorator: String, expression: String) {
|
||||
testEmptyProject(gradleVersion) {
|
||||
testBuildscript(decorator, expression) {
|
||||
closureDelegateTest(GRADLE_API_FILE_COPY_SPEC, DELEGATE_FIRST)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@AllGradleVersionsSource(PROJECT_CONTEXTS)
|
||||
fun `resolve a delegate in fileTree Closure`(gradleVersion: GradleVersion, decorator: String) {
|
||||
testEmptyProject(gradleVersion) {
|
||||
testBuildscript(decorator, "fileTree('baseDir'){<caret>}") {
|
||||
closureDelegateTest(GRADLE_API_FILE_CONFIGURABLE_FILE_TREE, DELEGATE_FIRST)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@AllGradleVersionsSource(PROJECT_CONTEXTS)
|
||||
fun `resolve a delegate in files Closure`(gradleVersion: GradleVersion, decorator: String) {
|
||||
testEmptyProject(gradleVersion) {
|
||||
testBuildscript(decorator, "files('paths'){<caret>}") {
|
||||
closureDelegateTest(GRADLE_API_FILE_CONFIGURABLE_FILE_COLLECTION, DELEGATE_FIRST)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ParameterizedTest
|
||||
@AllGradleVersionsSource(PROJECT_CONTEXTS)
|
||||
fun `resolve a delegate in exec Closure`(gradleVersion: GradleVersion, decorator: String) {
|
||||
testEmptyProject(gradleVersion) {
|
||||
testBuildscript(decorator, "exec{<caret>}") {
|
||||
closureDelegateTest(GRADLE_PROCESS_EXEC_SPEC, DELEGATE_FIRST)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user