From 8844ecdbc4e65d823e12f555eb280fcae89e53d9 Mon Sep 17 00:00:00 2001 From: Andrey Breslav Date: Tue, 30 Sep 2014 10:44:11 +0400 Subject: [PATCH] Find Usages extension extracted --- idea/src/META-INF/extensions/common.xml | 3 + .../KotlinFindUsagesHandlerDecorator.kt | 29 ++++++ .../KotlinFindUsagesHandlerFactory.kt | 18 +++- .../DelegatingFindMemberUsagesHandler.kt | 41 +------- .../android-compiler-plugin.iml | 2 +- .../android-idea-plugin.iml | 1 + .../src/META-INF/plugin.xml | 1 + .../android/AndroidFindMemberUsagesHandler.kt | 97 +++++++++++++++++++ 8 files changed, 148 insertions(+), 44 deletions(-) create mode 100644 idea/src/org/jetbrains/jet/plugin/findUsages/handlers/KotlinFindUsagesHandlerDecorator.kt create mode 100644 plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidFindMemberUsagesHandler.kt diff --git a/idea/src/META-INF/extensions/common.xml b/idea/src/META-INF/extensions/common.xml index fa3dc2573fc..1a893f802ce 100644 --- a/idea/src/META-INF/extensions/common.xml +++ b/idea/src/META-INF/extensions/common.xml @@ -14,5 +14,8 @@ + diff --git a/idea/src/org/jetbrains/jet/plugin/findUsages/handlers/KotlinFindUsagesHandlerDecorator.kt b/idea/src/org/jetbrains/jet/plugin/findUsages/handlers/KotlinFindUsagesHandlerDecorator.kt new file mode 100644 index 00000000000..d527f801d74 --- /dev/null +++ b/idea/src/org/jetbrains/jet/plugin/findUsages/handlers/KotlinFindUsagesHandlerDecorator.kt @@ -0,0 +1,29 @@ +/* + * Copyright 2010-2014 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.jet.plugin.findUsages.handlers + +import com.intellij.openapi.extensions.ExtensionPointName +import com.intellij.psi.PsiElement +import com.intellij.find.findUsages.FindUsagesHandler + +public trait KotlinFindUsagesHandlerDecorator { + class object { + public val EP_NAME: ExtensionPointName = ExtensionPointName.create("org.jetbrains.kotlin.findUsagesHandlerDecorator")!! + } + + public fun decorateHandler(element: PsiElement, forHighlightUsages: Boolean, delegate: FindUsagesHandler): FindUsagesHandler +} \ No newline at end of file diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt index bfb450cecff..917622f9ef1 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/KotlinFindUsagesHandlerFactory.kt @@ -33,11 +33,13 @@ import org.jetbrains.kotlin.psi.JetNamedDeclaration import org.jetbrains.kotlin.psi.JetClassOrObject import com.intellij.find.findUsages.JavaFindUsagesHandlerFactory import org.jetbrains.kotlin.idea.findUsages.handlers.DelegatingFindMemberUsagesHandler +import org.jetbrains.jet.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator +import com.intellij.openapi.extensions.Extensions public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactory() { val javaHandlerFactory = JavaFindUsagesHandlerFactory(project) - val findFunctionOptions = KotlinFunctionFindUsagesOptions(project) + public val findFunctionOptions: KotlinFunctionFindUsagesOptions = KotlinFunctionFindUsagesOptions(project) val findPropertyOptions = KotlinPropertyFindUsagesOptions(project) val findClassOptions = KotlinClassFindUsagesOptions(project) val defaultOptions = FindUsagesOptions(project) @@ -50,25 +52,31 @@ public class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandle element is JetTypeParameter public override fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean): FindUsagesHandler? { - when(element) { + val handler = when (element) { is JetClassOrObject -> - return KotlinFindClassUsagesHandler(element, this) + KotlinFindClassUsagesHandler(element, this) is JetNamedFunction, is JetProperty, is JetParameter -> { val declaration = element as JetNamedDeclaration if (forHighlightUsages) return KotlinFindMemberUsagesHandler.getInstance(declaration, this) - return JetRefactoringUtil.checkSuperMethods(declaration, null, "super.methods.action.key.find.usages")?.let { callables -> + JetRefactoringUtil.checkSuperMethods(declaration, null, "super.methods.action.key.find.usages")?.let { callables -> if (callables.empty) FindUsagesHandler.NULL_HANDLER else DelegatingFindMemberUsagesHandler(declaration, callables, this) } } is JetTypeParameter -> - return KotlinTypeParameterFindUsagesHandler(element, this) + KotlinTypeParameterFindUsagesHandler(element, this) else -> throw IllegalArgumentException("unexpected element type: " + element) } + + for (decorator in Extensions.getArea(element.getProject()).getExtensionPoint(KotlinFindUsagesHandlerDecorator.EP_NAME).getExtensions()) { + val decorated = decorator.decorateHandler(element, forHighlightUsages, handler!!) + if (decorated != handler) return decorated + } + return handler } } diff --git a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt b/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt index c260de04ce0..cb3f27935f7 100644 --- a/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt +++ b/idea/src/org/jetbrains/kotlin/idea/findUsages/handlers/DelegatingFindMemberUsagesHandler.kt @@ -48,7 +48,7 @@ class DelegatingFindMemberUsagesHandler( JavaFindUsagesHandler(declaration, elementsToSearch.copyToArray(), factory.javaHandlerFactory) } - fun getHandler(element: PsiElement): FindUsagesHandler? = + private fun getHandler(element: PsiElement): FindUsagesHandler? = when (element) { is JetNamedDeclaration -> KotlinFindMemberUsagesHandler.getInstance(element, elementsToSearch, factory) @@ -60,51 +60,16 @@ class DelegatingFindMemberUsagesHandler( } override fun getPrimaryElements(): Array { - val primaryElements = kotlinHandler.getPrimaryElements() - if (isAndroidSyntheticElement(declaration)) { - val name = (declaration as JetProperty).getName()!! - val parser = ServiceManager.getService(declaration.getProject(), javaClass()) - val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute - if (psiElement != null && psiElement.getValueElement() != null) { - return array(psiElement.getValueElement()!!) - } - } - return primaryElements + return kotlinHandler.getPrimaryElements() } override fun getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions { return kotlinHandler.getFindUsagesOptions(dataContext) } - override fun getSecondaryElements(): Array { - if (isAndroidSyntheticElement(declaration)) { - val name = (declaration as JetProperty).getName()!! - val parser = ServiceManager.getService(declaration.getProject(), javaClass()) - val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute - if (psiElement != null) { - val res = ArrayList() - val fields = AndroidResourceUtil.findIdFields(psiElement) - for (field in fields) { - res.add(field) - } - res.add(declaration) - return res.copyToArray() - } - } - return array() - } - override fun processElementUsages(element: PsiElement, processor: Processor, options: FindUsagesOptions): Boolean { val handler = getHandler(element) - if (handler == null || isAndroidSyntheticElement(element)) { - val findUsagesOptions = JavaVariableFindUsagesOptions(element.getProject()) - findUsagesOptions.isSearchForTextOccurrences = false - findUsagesOptions.isSkipImportStatements = true - findUsagesOptions.isUsages = true - findUsagesOptions.isReadAccess = true - findUsagesOptions.isWriteAccess = true - return super.processElementUsages(element, processor, findUsagesOptions) - } + if (handler == null) return true val handlerOptions = when (handler) { /* Can't have KotlinPropertyFindUsagesOptions here since Kotlin properties do not override java methods, so diff --git a/plugins/android-compiler-plugin/android-compiler-plugin.iml b/plugins/android-compiler-plugin/android-compiler-plugin.iml index f98690d4736..aa254e3cdff 100644 --- a/plugins/android-compiler-plugin/android-compiler-plugin.iml +++ b/plugins/android-compiler-plugin/android-compiler-plugin.iml @@ -8,7 +8,7 @@ - + diff --git a/plugins/android-idea-plugin/android-idea-plugin.iml b/plugins/android-idea-plugin/android-idea-plugin.iml index da72a240ed3..47604f6a9d7 100644 --- a/plugins/android-idea-plugin/android-idea-plugin.iml +++ b/plugins/android-idea-plugin/android-idea-plugin.iml @@ -12,6 +12,7 @@ + diff --git a/plugins/android-idea-plugin/src/META-INF/plugin.xml b/plugins/android-idea-plugin/src/META-INF/plugin.xml index 2bcea2154bc..a2bdb168eea 100644 --- a/plugins/android-idea-plugin/src/META-INF/plugin.xml +++ b/plugins/android-idea-plugin/src/META-INF/plugin.xml @@ -19,5 +19,6 @@ + diff --git a/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidFindMemberUsagesHandler.kt b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidFindMemberUsagesHandler.kt new file mode 100644 index 00000000000..3ea7beac7f0 --- /dev/null +++ b/plugins/android-idea-plugin/src/org/jetbrains/jet/plugin/android/AndroidFindMemberUsagesHandler.kt @@ -0,0 +1,97 @@ +/* + * Copyright 2010-2014 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.jet.plugin.android + +import com.intellij.find.findUsages.FindUsagesHandler +import com.intellij.psi.PsiElement +import com.intellij.usageView.UsageInfo +import com.intellij.util.Processor +import com.intellij.find.findUsages.FindUsagesOptions +import org.jetbrains.jet.lang.psi.JetNamedDeclaration +import com.intellij.openapi.actionSystem.DataContext +import org.jetbrains.jet.lang.resolve.android.isAndroidSyntheticElement +import com.intellij.openapi.components.ServiceManager +import org.jetbrains.jet.lang.resolve.android.AndroidUIXmlProcessor +import com.intellij.psi.xml.XmlAttribute +import org.jetbrains.jet.lang.psi.JetProperty +import org.jetbrains.android.util.AndroidResourceUtil +import java.util.ArrayList +import com.intellij.find.findUsages.JavaVariableFindUsagesOptions +import org.jetbrains.jet.plugin.findUsages.handlers.KotlinFindUsagesHandlerDecorator + +class AndroidFindUsageHandlerDecorator : KotlinFindUsagesHandlerDecorator { + override fun decorateHandler(element: PsiElement, forHighlightUsages: Boolean, delegate: FindUsagesHandler): FindUsagesHandler { + if (element !is JetNamedDeclaration) return delegate + if (!isAndroidSyntheticElement(element)) return delegate + + return AndroidFindMemberUsagesHandler(element, delegate) + } +} + +class AndroidFindMemberUsagesHandler( + private val declaration: JetNamedDeclaration, + private val delegate: FindUsagesHandler? = null +) : FindUsagesHandler(declaration) { + + override fun getPrimaryElements(): Array { + assert(isAndroidSyntheticElement(declaration)) + + val name = (declaration as JetProperty).getName()!! + val parser = ServiceManager.getService(declaration.getProject(), javaClass()) + val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute + if (psiElement != null && psiElement.getValueElement() != null) { + return array(psiElement.getValueElement()!!) + } + + return super.getPrimaryElements() + } + + override fun getFindUsagesOptions(dataContext: DataContext?): FindUsagesOptions { + return delegate?.getFindUsagesOptions(dataContext) ?: super.getFindUsagesOptions(dataContext) + } + + override fun getSecondaryElements(): Array { + assert(isAndroidSyntheticElement(declaration)) + + val name = (declaration as JetProperty).getName()!! + val parser = ServiceManager.getService(declaration.getProject(), javaClass()) + val psiElement = parser?.resourceManager?.idToXmlAttribute(name) as? XmlAttribute + if (psiElement != null) { + val res = ArrayList() + val fields = AndroidResourceUtil.findIdFields(psiElement) + for (field in fields) { + res.add(field) + } + res.add(declaration) + return res.copyToArray() + } + + return super.getSecondaryElements() + } + + override fun processElementUsages(element: PsiElement, processor: Processor, options: FindUsagesOptions): Boolean { + assert(isAndroidSyntheticElement(declaration)) + + val findUsagesOptions = JavaVariableFindUsagesOptions(element.getProject()) + findUsagesOptions.isSearchForTextOccurrences = false + findUsagesOptions.isSkipImportStatements = true + findUsagesOptions.isUsages = true + findUsagesOptions.isReadAccess = true + findUsagesOptions.isWriteAccess = true + return super.processElementUsages(element, processor, findUsagesOptions) + } +}