mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
gradle: honor closure delegatesTo type in case of methods name conflicts
This commit is contained in:
+5
-1
@@ -46,6 +46,8 @@ import org.jetbrains.plugins.groovy.lang.psi.patterns.groovyClosure
|
||||
import org.jetbrains.plugins.groovy.lang.psi.patterns.psiMethod
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyCommonClassNames.GROOVY_LANG_CLOSURE
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_KEY
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DELEGATES_TO_STRATEGY_KEY
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.DelegatesToInfo
|
||||
|
||||
/**
|
||||
@@ -148,7 +150,9 @@ class GradleExtensionsContributor : GradleMethodContextContributor {
|
||||
if (parent is GrMethodCallExpressionImpl && parent.argumentList.namedArguments.isNotEmpty()) {
|
||||
addParameter("args", JAVA_UTIL_MAP, true)
|
||||
}
|
||||
addParameter("configuration", GROOVY_LANG_CLOSURE, true)
|
||||
val closureParam = addAndGetParameter("configuration", GROOVY_LANG_CLOSURE, true)
|
||||
closureParam.putUserData(DELEGATES_TO_KEY, gradleTask.typeFqn)
|
||||
closureParam.putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.OWNER_FIRST)
|
||||
}
|
||||
if (!processor.execute(methodBuilder, state)) return false
|
||||
break
|
||||
|
||||
+5
-2
@@ -45,8 +45,8 @@ class GradleMiscContributor : GradleMethodContextContributor {
|
||||
val useJUnitClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_TASKS_TESTING_TEST, "useJUnit"))
|
||||
val testLoggingClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_TASKS_TESTING_TEST, "testLogging"))
|
||||
val downloadClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_PROJECT, "download"))
|
||||
val domainCollectionWithTypeClosure = groovyClosure().inMethod(psiMethod("org.gradle.api.DomainObjectCollection", "withType"))
|
||||
|
||||
val domainCollectionWithTypeClosure = groovyClosure().inMethod(psiMethod(GRADLE_API_DOMAIN_OBJECT_COLLECTION, "withType"))
|
||||
// val publicationsClosure = groovyClosure().inMethod(psiMethod("org.gradle.api.publish.PublishingExtension", "publications"))
|
||||
val downloadSpecFqn = "de.undercouch.gradle.tasks.download.DownloadSpec"
|
||||
val pluginDependenciesSpecFqn = "org.gradle.plugin.use.PluginDependenciesSpec"
|
||||
}
|
||||
@@ -61,6 +61,9 @@ class GradleMiscContributor : GradleMethodContextContributor {
|
||||
if (downloadClosure.accepts(closure)) {
|
||||
return DelegatesToInfo(TypesUtil.createType(downloadSpecFqn, closure), Closure.DELEGATE_FIRST)
|
||||
}
|
||||
// if (publicationsClosure.accepts(closure)) {
|
||||
// return DelegatesToInfo(TypesUtil.createType("org.gradle.api.publish.PublicationContainer", closure), Closure.DELEGATE_FIRST)
|
||||
// }
|
||||
|
||||
if (domainCollectionWithTypeClosure.accepts(closure)) {
|
||||
val parent = closure.parent
|
||||
|
||||
+13
-12
@@ -126,14 +126,15 @@ class GradleNonCodeMembersContributor : NonCodeMembersContributor() {
|
||||
if (GradleResolverUtil.canBeMethodOf("set" + propCandidate.capitalize(), psiClass)) return
|
||||
|
||||
val closure = PsiTreeUtil.getParentOfType(place, GrClosableBlock::class.java)
|
||||
if (closure != null) {
|
||||
val info = getDelegatesToInfo(closure)
|
||||
if (info != null) {
|
||||
val fqNameToDelegate = TypesUtil.getQualifiedName(info.typeToDelegate) ?: return
|
||||
val classToDelegate = psiManager.findClassWithCache(fqNameToDelegate, place.resolveScope) ?: return
|
||||
if (GradleResolverUtil.canBeMethodOf(propCandidate, classToDelegate)) return
|
||||
if (GradleResolverUtil.canBeMethodOf("get" + propCandidate.capitalize(), classToDelegate)) return
|
||||
if (GradleResolverUtil.canBeMethodOf("set" + propCandidate.capitalize(), classToDelegate)) return
|
||||
val typeToDelegate = closure?.let { getDelegatesToInfo(it)?.typeToDelegate }
|
||||
if (typeToDelegate != null) {
|
||||
val fqNameToDelegate = TypesUtil.getQualifiedName(typeToDelegate) ?: return
|
||||
val classToDelegate = psiManager.findClassWithCache(fqNameToDelegate, place.resolveScope) ?: return
|
||||
if (classToDelegate !== aClass) {
|
||||
val parent = place.parent
|
||||
if (parent is GrMethodCall) {
|
||||
if (canBeMethodOf(propCandidate, parent, typeToDelegate)) return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -158,10 +159,10 @@ class GradleNonCodeMembersContributor : NonCodeMembersContributor() {
|
||||
val wrappedBase = GrLightMethodBuilder(place.manager, "configure").apply {
|
||||
returnType = domainObjectType
|
||||
containingClass = aClass
|
||||
addParameter("configureClosure", GROOVY_LANG_CLOSURE, true).apply {
|
||||
putUserData(DELEGATES_TO_KEY, domainObjectFqn)
|
||||
putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.DELEGATE_FIRST)
|
||||
}
|
||||
val closureParam = addAndGetParameter("configuration", GROOVY_LANG_CLOSURE, true)
|
||||
closureParam.putUserData(DELEGATES_TO_KEY, domainObjectFqn)
|
||||
closureParam.putUserData(DELEGATES_TO_STRATEGY_KEY, Closure.OWNER_FIRST)
|
||||
|
||||
val method = aClass.findMethodsByName("create", true).firstOrNull { it.parameterList.parametersCount == argsCount }
|
||||
if (method != null) navigationElement = method
|
||||
}
|
||||
|
||||
@@ -18,11 +18,23 @@ package org.jetbrains.plugins.gradle.service.resolve
|
||||
import com.intellij.openapi.util.Key
|
||||
import com.intellij.psi.*
|
||||
import com.intellij.psi.scope.PsiScopeProcessor
|
||||
import com.intellij.psi.util.PsiTreeUtil
|
||||
import org.jetbrains.plugins.gradle.util.GradleConstants.EXTENSION
|
||||
import org.jetbrains.plugins.groovy.codeInspection.assignment.GrMethodCallInfo
|
||||
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.impl.GroovyPsiManager
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.statements.expressions.TypesUtil
|
||||
import org.jetbrains.plugins.groovy.lang.psi.impl.synthetic.GroovyScriptClass
|
||||
import org.jetbrains.plugins.groovy.lang.psi.patterns.GroovyPatterns
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.GroovyPropertyUtils
|
||||
import org.jetbrains.plugins.groovy.lang.psi.util.PsiUtil
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.NON_CODE
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.ResolveUtil.processAllDeclarations
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.delegatesTo.getDelegatesToInfo
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.AccessorResolverProcessor
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.ClassHint
|
||||
import org.jetbrains.plugins.groovy.lang.resolve.processors.MethodResolverProcessor
|
||||
import java.util.*
|
||||
|
||||
/**
|
||||
@@ -44,6 +56,23 @@ fun processDeclarations(aClass: PsiClass,
|
||||
aClass.processDeclarations(processor, state, null, place)
|
||||
}
|
||||
else {
|
||||
val propCandidate = place.references.singleOrNull()?.canonicalText
|
||||
if (propCandidate != null) {
|
||||
val closure = PsiTreeUtil.getParentOfType(place, GrClosableBlock::class.java)
|
||||
val typeToDelegate = closure?.let { getDelegatesToInfo(it)?.typeToDelegate }
|
||||
if (typeToDelegate != null) {
|
||||
val fqNameToDelegate = TypesUtil.getQualifiedName(typeToDelegate) ?: return true
|
||||
val classToDelegate = GroovyPsiManager.getInstance(place.project).findClassWithCache(fqNameToDelegate,
|
||||
place.resolveScope) ?: return true
|
||||
if (classToDelegate !== aClass) {
|
||||
val parent = place.parent
|
||||
if (parent is GrMethodCall) {
|
||||
if (canBeMethodOf(propCandidate, parent, typeToDelegate)) return true
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
val lValue: Boolean = place is GrReferenceExpression && PsiUtil.isLValue(place);
|
||||
if (!lValue) {
|
||||
val isSetterCandidate = name.startsWith("set")
|
||||
@@ -57,7 +86,7 @@ fun processDeclarations(aClass: PsiClass,
|
||||
if (!processor.execute(method, state)) return false
|
||||
}
|
||||
for (method in aClass.findMethodsByName("set" + propertyName.capitalize(), true)) {
|
||||
if(PsiType.VOID != method.returnType) continue
|
||||
if (PsiType.VOID != method.returnType) continue
|
||||
if (processedSignatures.contains(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText }))) continue
|
||||
processedSignatures.add(method.getSignature(PsiSubstitutor.EMPTY).parameterTypes.map({ it.canonicalText }))
|
||||
place.putUserData(RESOLVED_CODE, true)
|
||||
@@ -88,4 +117,41 @@ fun processDeclarations(aClass: PsiClass,
|
||||
return true
|
||||
}
|
||||
|
||||
fun psiMethodInClass(containingClass: String) = GroovyPatterns.psiMethod().definedInClass(containingClass)
|
||||
fun canBeMethodOf(methodName: String,
|
||||
place: GrMethodCall,
|
||||
type: PsiType): Boolean {
|
||||
val methodCallInfo = GrMethodCallInfo(place)
|
||||
val invoked = methodCallInfo.invokedExpression ?: return false
|
||||
val argumentTypes = methodCallInfo.argumentTypes
|
||||
|
||||
val thisType = TypesUtil.boxPrimitiveType(type, place.manager, place.resolveScope)
|
||||
val processor = MethodResolverProcessor(methodName, invoked, false, thisType, argumentTypes, PsiType.EMPTY_ARRAY, false)
|
||||
val state = ResolveState.initial().let {
|
||||
it.put(ClassHint.RESOLVE_CONTEXT, invoked)
|
||||
it.put(NON_CODE, false)
|
||||
}
|
||||
processAllDeclarations(thisType, processor, state, invoked)
|
||||
val hasApplicableMethods = processor.hasApplicableCandidates()
|
||||
if (hasApplicableMethods) {
|
||||
return true
|
||||
}
|
||||
|
||||
//search for getters
|
||||
for (getterName in GroovyPropertyUtils.suggestGettersName(methodName)) {
|
||||
val getterResolver = AccessorResolverProcessor(getterName, methodName, invoked, true, thisType, PsiType.EMPTY_ARRAY)
|
||||
processAllDeclarations(thisType, getterResolver, state, invoked)
|
||||
if (getterResolver.hasApplicableCandidates()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
//search for setters
|
||||
for (setterName in GroovyPropertyUtils.suggestSettersName(methodName)) {
|
||||
val getterResolver = AccessorResolverProcessor(setterName, methodName, invoked, false, thisType, PsiType.EMPTY_ARRAY)
|
||||
processAllDeclarations(thisType, getterResolver, state, invoked)
|
||||
if (getterResolver.hasApplicableCandidates()) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
return false
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user