search for Kotlin convention usages of Java methods
#KT-5960 Fixed
This commit is contained in:
+8
-47
@@ -17,7 +17,6 @@
|
|||||||
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
package org.jetbrains.kotlin.idea.search.ideaExtensions
|
||||||
|
|
||||||
import com.intellij.openapi.application.QueryExecutorBase
|
import com.intellij.openapi.application.QueryExecutorBase
|
||||||
import com.intellij.openapi.progress.ProgressManager
|
|
||||||
import com.intellij.psi.*
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.impl.cache.CacheManager
|
import com.intellij.psi.impl.cache.CacheManager
|
||||||
import com.intellij.psi.search.*
|
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.KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT
|
||||||
import org.jetbrains.kotlin.idea.search.allScope
|
import org.jetbrains.kotlin.idea.search.allScope
|
||||||
import org.jetbrains.kotlin.idea.search.effectiveSearchScope
|
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.stubindex.KotlinSourceFilterScope
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
@@ -84,7 +85,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
|||||||
|
|
||||||
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
|
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
|
||||||
?: KotlinReferencesSearchOptions.Empty
|
?: KotlinReferencesSearchOptions.Empty
|
||||||
val resultProcessor = MyRequestResultProcessor(unwrappedElement, filter = refFilter, options = kotlinOptions)
|
val resultProcessor = KotlinRequestResultProcessor(unwrappedElement, filter = refFilter, options = kotlinOptions)
|
||||||
|
|
||||||
if (kotlinOptions.anyEnabled()) {
|
if (kotlinOptions.anyEnabled()) {
|
||||||
val name = runReadAction { unwrappedElement.name }
|
val name = runReadAction { unwrappedElement.name }
|
||||||
@@ -123,7 +124,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
|||||||
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
|
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
|
||||||
}
|
}
|
||||||
|
|
||||||
val processor = MyRequestResultProcessor(parameter, filter = { it.isNamedArgumentReference() })
|
val processor = KotlinRequestResultProcessor(parameter, filter = { it.isNamedArgumentReference() })
|
||||||
queryParameters.optimizer.searchWord(parameterName,
|
queryParameters.optimizer.searchWord(parameterName,
|
||||||
namedArgsScope,
|
namedArgsScope,
|
||||||
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
|
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
|
||||||
@@ -136,46 +137,6 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
|||||||
return this is KtSimpleNameReference && expression.parent is KtValueArgumentName
|
return this is KtSimpleNameReference && expression.parent is KtValueArgumentName
|
||||||
}
|
}
|
||||||
|
|
||||||
private class MyRequestResultProcessor(
|
|
||||||
private val unwrappedElement: PsiElement,
|
|
||||||
private val originalElement: PsiElement = unwrappedElement,
|
|
||||||
private val filter: (PsiReference) -> 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<PsiReference>): 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 {
|
companion object {
|
||||||
fun processKtClassOrObject(element: KtClassOrObject, queryParameters: ReferencesSearch.SearchParameters) {
|
fun processKtClassOrObject(element: KtClassOrObject, queryParameters: ReferencesSearch.SearchParameters) {
|
||||||
val className = element.name
|
val className = element.name
|
||||||
@@ -323,9 +284,9 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
|||||||
val context = UsageSearchContext.IN_CODE + UsageSearchContext.IN_FOREIGN_LANGUAGES + UsageSearchContext.IN_COMMENTS
|
val context = UsageSearchContext.IN_CODE + UsageSearchContext.IN_FOREIGN_LANGUAGES + UsageSearchContext.IN_COMMENTS
|
||||||
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
|
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
|
||||||
?: KotlinReferencesSearchOptions.Empty
|
?: KotlinReferencesSearchOptions.Empty
|
||||||
val resultProcessor = MyRequestResultProcessor(element,
|
val resultProcessor = KotlinRequestResultProcessor(element,
|
||||||
queryParameters.elementToSearch.namedUnwrappedElement ?: element,
|
queryParameters.elementToSearch.namedUnwrappedElement ?: element,
|
||||||
options = kotlinOptions)
|
options = kotlinOptions)
|
||||||
queryParameters.optimizer.searchWord(name, scope, context.toShort(), true, element,
|
queryParameters.optimizer.searchWord(name, scope, context.toShort(), true, element,
|
||||||
resultProcessor)
|
resultProcessor)
|
||||||
}
|
}
|
||||||
|
|||||||
+69
@@ -0,0 +1,69 @@
|
|||||||
|
/*
|
||||||
|
* 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.progress.ProgressManager
|
||||||
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiReference
|
||||||
|
import com.intellij.psi.PsiReferenceService
|
||||||
|
import com.intellij.psi.ReferenceRange
|
||||||
|
import com.intellij.psi.search.RequestResultProcessor
|
||||||
|
import com.intellij.util.Processor
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.isCallableOverrideUsage
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.isExtensionOfDeclarationClassUsage
|
||||||
|
import org.jetbrains.kotlin.idea.search.usagesSearch.isUsageInContainingDeclaration
|
||||||
|
import org.jetbrains.kotlin.psi.KtNamedDeclaration
|
||||||
|
|
||||||
|
class KotlinRequestResultProcessor(
|
||||||
|
private val unwrappedElement: PsiElement,
|
||||||
|
private val originalElement: PsiElement = unwrappedElement,
|
||||||
|
private val filter: (PsiReference) -> 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<PsiReference>): 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
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -620,6 +620,7 @@
|
|||||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinPropertyAccessorsReferenceSearcher"/>
|
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinPropertyAccessorsReferenceSearcher"/>
|
||||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinConstructorDelegationCallReferenceSearcher"/>
|
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinConstructorDelegationCallReferenceSearcher"/>
|
||||||
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinOverridingMethodReferenceSearcher"/>
|
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinOverridingMethodReferenceSearcher"/>
|
||||||
|
<methodReferencesSearch implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinConventionMethodReferencesSearcher"/>
|
||||||
|
|
||||||
<readWriteAccessDetector implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReadWriteAccessDetector" id="kotlin"/>
|
<readWriteAccessDetector implementation="org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReadWriteAccessDetector" id="kotlin"/>
|
||||||
|
|
||||||
|
|||||||
+47
@@ -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<PsiReference, MethodReferencesSearch.SearchParameters>(true) {
|
||||||
|
override fun processQuery(queryParameters: MethodReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
// PSI_ELEMENT: com.intellij.psi.PsiMethod
|
||||||
|
// OPTIONS: usages
|
||||||
|
public class Small {
|
||||||
|
public boolean c<caret>ontains(String str) { // Call "Find usages" for this method
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,3 @@
|
|||||||
|
fun some(small: Small) {
|
||||||
|
"asdf" in small
|
||||||
|
}
|
||||||
+1
@@ -0,0 +1 @@
|
|||||||
|
Function call 2 "asdf" in small
|
||||||
@@ -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);
|
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")
|
@TestMetadata("JKMethodOverrides.0.java")
|
||||||
public void testJKMethodOverrides() throws Exception {
|
public void testJKMethodOverrides() throws Exception {
|
||||||
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/JKMethodOverrides.0.java");
|
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/findUsages/java/findJavaMethodUsages/JKMethodOverrides.0.java");
|
||||||
|
|||||||
Reference in New Issue
Block a user