KotlinDefinitionsSearcher: J2K
This commit is contained in:
+111
-141
@@ -14,166 +14,136 @@
|
|||||||
* limitations under the License.
|
* limitations under the License.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
package org.jetbrains.kotlin.idea.search.ideaExtensions;
|
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||||
|
|
||||||
import com.intellij.codeInsight.navigation.MethodImplementationsSearch;
|
import com.intellij.codeInsight.navigation.MethodImplementationsSearch
|
||||||
import com.intellij.openapi.application.ApplicationManager;
|
import com.intellij.openapi.application.ApplicationManager
|
||||||
import com.intellij.openapi.util.Computable;
|
import com.intellij.openapi.util.Computable
|
||||||
import com.intellij.psi.PsiClass;
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiElement;
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.PsiMethod;
|
import com.intellij.psi.search.SearchScope
|
||||||
import com.intellij.psi.search.SearchScope;
|
import com.intellij.psi.search.searches.ClassInheritorsSearch
|
||||||
import com.intellij.psi.search.searches.ClassInheritorsSearch;
|
import com.intellij.psi.search.searches.DefinitionsScopedSearch
|
||||||
import com.intellij.psi.search.searches.DefinitionsScopedSearch;
|
import com.intellij.util.Processor
|
||||||
import com.intellij.util.Processor;
|
import com.intellij.util.QueryExecutor
|
||||||
import com.intellij.util.QueryExecutor;
|
import com.intellij.util.containers.ContainerUtil
|
||||||
import com.intellij.util.containers.ContainerUtil;
|
import org.jetbrains.kotlin.asJava.LightClassUtil
|
||||||
import org.jetbrains.annotations.NotNull;
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.LightClassUtil;
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod;
|
|
||||||
import org.jetbrains.kotlin.psi.*;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList
|
||||||
import java.util.List;
|
|
||||||
|
|
||||||
import static org.jetbrains.kotlin.asJava.LightClassUtilsKt.toLightClass;
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
|
|
||||||
public class KotlinDefinitionsSearcher implements QueryExecutor<PsiElement, DefinitionsScopedSearch.SearchParameters> {
|
class KotlinDefinitionsSearcher : QueryExecutor<PsiElement, DefinitionsScopedSearch.SearchParameters> {
|
||||||
@Override
|
override fun execute(queryParameters: DefinitionsScopedSearch.SearchParameters, consumer: Processor<PsiElement>): Boolean {
|
||||||
public boolean execute(@NotNull DefinitionsScopedSearch.SearchParameters queryParameters, @NotNull Processor<PsiElement> consumer) {
|
var consumer = consumer
|
||||||
PsiElement element = queryParameters.getElement();
|
val element = queryParameters.element
|
||||||
SearchScope scope = queryParameters.getScope();
|
val scope = queryParameters.scope
|
||||||
consumer = skipDelegatedMethodsConsumer(consumer);
|
consumer = skipDelegatedMethodsConsumer(consumer)
|
||||||
|
|
||||||
if (element instanceof KtClass) {
|
if (element is KtClass) {
|
||||||
return processClassImplementations((KtClass) element, consumer);
|
return processClassImplementations(element, consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof KtNamedFunction || element instanceof KtSecondaryConstructor) {
|
if (element is KtNamedFunction || element is KtSecondaryConstructor) {
|
||||||
return processFunctionImplementations((KtFunction) element, scope, consumer);
|
return processFunctionImplementations(element as KtFunction, scope, consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof KtProperty) {
|
if (element is KtProperty) {
|
||||||
return processPropertyImplementations((KtProperty) element, scope, consumer);
|
return processPropertyImplementations(element, scope, consumer)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (element instanceof KtParameter) {
|
if (element is KtParameter) {
|
||||||
KtParameter parameter = (KtParameter) element;
|
|
||||||
|
|
||||||
if (isFieldParameter(parameter)) {
|
if (isFieldParameter(element)) {
|
||||||
return processPropertyImplementations((KtParameter) element, scope, consumer);
|
return processPropertyImplementations(element, scope, consumer)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
companion object {
|
||||||
private static Processor<PsiElement> skipDelegatedMethodsConsumer(@NotNull final Processor<PsiElement> baseConsumer) {
|
|
||||||
return new Processor<PsiElement>() {
|
private fun skipDelegatedMethodsConsumer(baseConsumer: Processor<PsiElement>): Processor<PsiElement> {
|
||||||
@Override
|
return Processor { element ->
|
||||||
public boolean process(PsiElement element) {
|
|
||||||
if (isDelegated(element)) {
|
if (isDelegated(element)) {
|
||||||
return true;
|
return@Processor true
|
||||||
}
|
|
||||||
return baseConsumer.process(element);
|
|
||||||
}
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isDelegated(@NotNull PsiElement element) {
|
|
||||||
return element instanceof KtLightMethod && ((KtLightMethod) element).isDelegated();
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean isFieldParameter(final KtParameter parameter) {
|
|
||||||
return ApplicationManager.getApplication().runReadAction(
|
|
||||||
new Computable<Boolean>() {
|
|
||||||
@Override
|
|
||||||
public Boolean compute() {
|
|
||||||
return KtPsiUtil.getClassIfParameterIsProperty(parameter) != null;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean processClassImplementations(@NotNull final KtClass klass, Processor<PsiElement> consumer) {
|
|
||||||
PsiClass psiClass = ApplicationManager.getApplication().runReadAction(new Computable<PsiClass>() {
|
|
||||||
@Override
|
|
||||||
public PsiClass compute() {
|
|
||||||
return toLightClass(klass);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
if (psiClass != null) {
|
|
||||||
return ContainerUtil.process(ClassInheritorsSearch.search(psiClass, true), consumer);
|
|
||||||
}
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean processFunctionImplementations(final KtFunction function, SearchScope scope, Processor<PsiElement> consumer) {
|
|
||||||
PsiMethod psiMethod = ApplicationManager.getApplication().runReadAction(new Computable<PsiMethod>() {
|
|
||||||
@Override
|
|
||||||
public PsiMethod compute() {
|
|
||||||
return LightClassUtil.INSTANCE.getLightClassMethod(function);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
if (psiMethod != null) {
|
|
||||||
MethodImplementationsSearch.processImplementations(psiMethod, consumer, scope);
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean processPropertyImplementations(@NotNull final KtParameter parameter, @NotNull SearchScope scope, @NotNull Processor<PsiElement> consumer) {
|
|
||||||
LightClassUtil.PropertyAccessorsPsiMethods accessorsPsiMethods = ApplicationManager.getApplication().runReadAction(
|
|
||||||
new Computable<LightClassUtil.PropertyAccessorsPsiMethods>() {
|
|
||||||
@Override
|
|
||||||
public LightClassUtil.PropertyAccessorsPsiMethods compute() {
|
|
||||||
return LightClassUtil.INSTANCE.getLightClassPropertyMethods(parameter);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
private static boolean processPropertyImplementations(@NotNull final KtProperty property, @NotNull SearchScope scope, @NotNull Processor<PsiElement> consumer) {
|
|
||||||
LightClassUtil.PropertyAccessorsPsiMethods accessorsPsiMethods = ApplicationManager.getApplication().runReadAction(
|
|
||||||
new Computable<LightClassUtil.PropertyAccessorsPsiMethods>() {
|
|
||||||
@Override
|
|
||||||
public LightClassUtil.PropertyAccessorsPsiMethods compute() {
|
|
||||||
return LightClassUtil.INSTANCE.getLightClassPropertyMethods(property);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer);
|
|
||||||
}
|
|
||||||
|
|
||||||
public static boolean processPropertyImplementationsMethods(LightClassUtil.PropertyAccessorsPsiMethods accessors, @NotNull SearchScope scope, @NotNull Processor<PsiElement> consumer) {
|
|
||||||
for (PsiMethod method : accessors) {
|
|
||||||
List<PsiMethod> implementations = new ArrayList<PsiMethod>();
|
|
||||||
MethodImplementationsSearch.getOverridingMethods(method, implementations, scope);
|
|
||||||
|
|
||||||
for (PsiMethod implementation : implementations) {
|
|
||||||
if (isDelegated(implementation)) continue;
|
|
||||||
|
|
||||||
PsiElement mirrorElement = implementation instanceof KtLightMethod
|
|
||||||
? ((KtLightMethod) implementation).getKotlinOrigin() : null;
|
|
||||||
if (mirrorElement instanceof KtProperty || mirrorElement instanceof KtParameter) {
|
|
||||||
if (!consumer.process(mirrorElement)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (mirrorElement instanceof KtPropertyAccessor && mirrorElement.getParent() instanceof KtProperty) {
|
|
||||||
if (!consumer.process(mirrorElement.getParent())) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else {
|
|
||||||
if (!consumer.process(implementation)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
baseConsumer.process(element)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true;
|
|
||||||
|
private fun isDelegated(element: PsiElement): Boolean {
|
||||||
|
return element is KtLightMethod && element.isDelegated
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun isFieldParameter(parameter: KtParameter): Boolean {
|
||||||
|
return ApplicationManager.getApplication().runReadAction(
|
||||||
|
Computable { KtPsiUtil.getClassIfParameterIsProperty(parameter) != null })
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processClassImplementations(klass: KtClass, consumer: Processor<PsiElement>): Boolean {
|
||||||
|
val psiClass = ApplicationManager.getApplication().runReadAction(Computable<com.intellij.psi.PsiClass> { klass.toLightClass() })
|
||||||
|
if (psiClass != null) {
|
||||||
|
return ContainerUtil.process(ClassInheritorsSearch.search(psiClass, true), consumer)
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processFunctionImplementations(function: KtFunction, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
|
val psiMethod = ApplicationManager.getApplication().runReadAction(Computable<com.intellij.psi.PsiMethod> { LightClassUtil.getLightClassMethod(function) })
|
||||||
|
|
||||||
|
if (psiMethod != null) {
|
||||||
|
MethodImplementationsSearch.processImplementations(psiMethod, consumer, scope)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processPropertyImplementations(parameter: KtParameter, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
|
val accessorsPsiMethods = ApplicationManager.getApplication().runReadAction<LightClassUtil.PropertyAccessorsPsiMethods> { LightClassUtil.getLightClassPropertyMethods(parameter) }
|
||||||
|
|
||||||
|
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun processPropertyImplementations(property: KtProperty, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
|
val accessorsPsiMethods = ApplicationManager.getApplication().runReadAction<LightClassUtil.PropertyAccessorsPsiMethods> { LightClassUtil.getLightClassPropertyMethods(property) }
|
||||||
|
|
||||||
|
return processPropertyImplementationsMethods(accessorsPsiMethods, scope, consumer)
|
||||||
|
}
|
||||||
|
|
||||||
|
fun processPropertyImplementationsMethods(accessors: LightClassUtil.PropertyAccessorsPsiMethods, scope: SearchScope, consumer: Processor<PsiElement>): Boolean {
|
||||||
|
for (method in accessors) {
|
||||||
|
val implementations = ArrayList<PsiMethod>()
|
||||||
|
MethodImplementationsSearch.getOverridingMethods(method, implementations, scope)
|
||||||
|
|
||||||
|
for (implementation in implementations) {
|
||||||
|
if (isDelegated(implementation)) continue
|
||||||
|
|
||||||
|
val mirrorElement = if (implementation is KtLightMethod)
|
||||||
|
implementation.kotlinOrigin
|
||||||
|
else
|
||||||
|
null
|
||||||
|
if (mirrorElement is KtProperty || mirrorElement is KtParameter) {
|
||||||
|
if (!consumer.process(mirrorElement)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mirrorElement is KtPropertyAccessor && mirrorElement.parent is KtProperty) {
|
||||||
|
if (!consumer.process(mirrorElement.parent)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (!consumer.process(implementation)) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user