diff --git a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt index 2f77107ad78..072ffcf7fa0 100644 --- a/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt +++ b/idea/idea-analysis/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinReferencesSearcher.kt @@ -17,7 +17,6 @@ package org.jetbrains.kotlin.idea.search.ideaExtensions import com.intellij.openapi.application.QueryExecutorBase -import com.intellij.openapi.progress.ProgressManager import com.intellij.psi.* import com.intellij.psi.impl.cache.CacheManager import com.intellij.psi.search.* @@ -30,7 +29,9 @@ import org.jetbrains.kotlin.idea.references.KtSimpleNameReference import org.jetbrains.kotlin.idea.search.KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT import org.jetbrains.kotlin.idea.search.allScope import org.jetbrains.kotlin.idea.search.effectiveSearchScope -import org.jetbrains.kotlin.idea.search.usagesSearch.* +import org.jetbrains.kotlin.idea.search.usagesSearch.dataClassComponentFunction +import org.jetbrains.kotlin.idea.search.usagesSearch.getClassNameForCompanionObject +import org.jetbrains.kotlin.idea.search.usagesSearch.getSpecialNamesToSearch import org.jetbrains.kotlin.idea.stubindex.KotlinSourceFilterScope import org.jetbrains.kotlin.idea.util.application.runReadAction import org.jetbrains.kotlin.psi.* @@ -84,7 +85,7 @@ class KotlinReferencesSearcher : QueryExecutorBase Boolean = { true }, - private val options: KotlinReferencesSearchOptions = KotlinReferencesSearchOptions.Empty - ) : RequestResultProcessor(unwrappedElement, originalElement, filter, options) { - private val referenceService = PsiReferenceService.getService() - - override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: Processor): Boolean { - return referenceService.getReferences(element, PsiReferenceService.Hints.NO_HINTS).all { ref -> - ProgressManager.checkCanceled() - - when { - !filter(ref) -> true - !ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true - !ref.isReferenceToTarget(unwrappedElement) -> true - else -> consumer.process(ref) - } - } - } - - private fun PsiReference.isReferenceToTarget(element: PsiElement): Boolean { - if (isReferenceTo(element)) { - return true - } - if (originalElement is KtNamedDeclaration) { - if (options.acceptCallableOverrides && isCallableOverrideUsage(originalElement)) { - return true - } - if (options.acceptOverloads && isUsageInContainingDeclaration(originalElement)) { - return true - } - if (options.acceptExtensionsOfDeclarationClass && isExtensionOfDeclarationClassUsage(originalElement)) { - return true - } - } - return false - } - } - companion object { fun processKtClassOrObject(element: KtClassOrObject, queryParameters: ReferencesSearch.SearchParameters) { val className = element.name @@ -323,9 +284,9 @@ class KotlinReferencesSearcher : QueryExecutorBase Boolean = { true }, + private val options: KotlinReferencesSearchOptions = KotlinReferencesSearchOptions.Empty +) : RequestResultProcessor(unwrappedElement, originalElement, filter, options) { + private val referenceService = PsiReferenceService.getService() + + override fun processTextOccurrence(element: PsiElement, offsetInElement: Int, consumer: Processor): Boolean { + return referenceService.getReferences(element, PsiReferenceService.Hints.NO_HINTS).all { ref -> + ProgressManager.checkCanceled() + + when { + !filter(ref) -> true + !ReferenceRange.containsOffsetInElement(ref, offsetInElement) -> true + !ref.isReferenceToTarget(unwrappedElement) -> true + else -> consumer.process(ref) + } + } + } + + private fun PsiReference.isReferenceToTarget(element: PsiElement): Boolean { + if (isReferenceTo(element)) { + return true + } + if (originalElement is KtNamedDeclaration) { + if (options.acceptCallableOverrides && isCallableOverrideUsage(originalElement)) { + return true + } + if (options.acceptOverloads && isUsageInContainingDeclaration(originalElement)) { + return true + } + if (options.acceptExtensionsOfDeclarationClass && isExtensionOfDeclarationClassUsage(originalElement)) { + return true + } + } + return false + } +} \ No newline at end of file diff --git a/idea/src/META-INF/plugin.xml b/idea/src/META-INF/plugin.xml index 61fb023ad44..f786d03f5e0 100644 --- a/idea/src/META-INF/plugin.xml +++ b/idea/src/META-INF/plugin.xml @@ -620,6 +620,7 @@ + diff --git a/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinConventionMethodReferencesSearcher.kt b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinConventionMethodReferencesSearcher.kt new file mode 100644 index 00000000000..927574c8cb4 --- /dev/null +++ b/idea/src/org/jetbrains/kotlin/idea/search/ideaExtensions/KotlinConventionMethodReferencesSearcher.kt @@ -0,0 +1,47 @@ +/* + * Copyright 2010-2016 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.kotlin.idea.search.ideaExtensions + +import com.intellij.openapi.application.QueryExecutorBase +import com.intellij.psi.PsiReference +import com.intellij.psi.search.UsageSearchContext +import com.intellij.psi.search.searches.MethodReferencesSearch +import com.intellij.util.Processor +import org.jetbrains.kotlin.idea.search.restrictToKotlinSources +import org.jetbrains.kotlin.idea.search.usagesSearch.getOperationSymbolsToSearch +import org.jetbrains.kotlin.idea.util.application.runReadAction +import org.jetbrains.kotlin.lexer.KtSingleValueToken +import org.jetbrains.kotlin.name.Name + +class KotlinConventionMethodReferencesSearcher() : QueryExecutorBase(true) { + override fun processQuery(queryParameters: MethodReferencesSearch.SearchParameters, consumer: Processor) { + val method = queryParameters.method + val name = runReadAction { method.name } + if (!Name.isValidIdentifier(name)) return + val operationSymbolsToSearch = Name.identifier(name).getOperationSymbolsToSearch() + val wordsToSearch = operationSymbolsToSearch.first.map { (it as KtSingleValueToken).value } + if (wordsToSearch.isEmpty()) return + val resultProcessor = KotlinRequestResultProcessor(method, + filter = { ref -> ref.javaClass == operationSymbolsToSearch.second }) + + wordsToSearch.forEach { word -> + queryParameters.optimizer.searchWord(word, queryParameters.effectiveSearchScope.restrictToKotlinSources(), + UsageSearchContext.IN_CODE, true, method, + resultProcessor) + } + } +} diff --git a/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.0.java b/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.0.java new file mode 100644 index 00000000000..b209e937fd0 --- /dev/null +++ b/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.0.java @@ -0,0 +1,7 @@ +// PSI_ELEMENT: com.intellij.psi.PsiMethod +// OPTIONS: usages +public class Small { + public boolean contains(String str) { // Call "Find usages" for this method + return true; + } +} diff --git a/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.1.kt b/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.1.kt new file mode 100644 index 00000000000..1e54489518c --- /dev/null +++ b/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.1.kt @@ -0,0 +1,3 @@ +fun some(small: Small) { + "asdf" in small +} \ No newline at end of file diff --git a/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.results.txt b/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.results.txt new file mode 100644 index 00000000000..a2f3bd194b8 --- /dev/null +++ b/idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.results.txt @@ -0,0 +1 @@ +Function call 2 "asdf" in small diff --git a/idea/tests/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java b/idea/tests/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java index abf846656de..72bd3a1bdfb 100644 --- a/idea/tests/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java +++ b/idea/tests/org/jetbrains/kotlin/findUsages/FindUsagesTestGenerated.java @@ -1422,6 +1422,12 @@ public class FindUsagesTestGenerated extends AbstractFindUsagesTest { KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("idea/testData/findUsages/java/findJavaMethodUsages"), Pattern.compile("^(.+)\\.0\\.java$"), true); } + @TestMetadata("ConventionUsages.0.java") + public void testConventionUsages() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/ConventionUsages.0.java"); + doTest(fileName); + } + @TestMetadata("JKMethodOverrides.0.java") public void testJKMethodOverrides() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/JKMethodOverrides.0.java");