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
|
||||
|
||||
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<PsiReference, ReferencesSearc
|
||||
|
||||
val kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
|
||||
?: KotlinReferencesSearchOptions.Empty
|
||||
val resultProcessor = MyRequestResultProcessor(unwrappedElement, filter = refFilter, options = kotlinOptions)
|
||||
val resultProcessor = KotlinRequestResultProcessor(unwrappedElement, filter = refFilter, options = kotlinOptions)
|
||||
|
||||
if (kotlinOptions.anyEnabled()) {
|
||||
val name = runReadAction { unwrappedElement.name }
|
||||
@@ -123,7 +124,7 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
namedArgsScope = GlobalSearchScope.filesScope(project, filesWithFunctionName.asList())
|
||||
}
|
||||
|
||||
val processor = MyRequestResultProcessor(parameter, filter = { it.isNamedArgumentReference() })
|
||||
val processor = KotlinRequestResultProcessor(parameter, filter = { it.isNamedArgumentReference() })
|
||||
queryParameters.optimizer.searchWord(parameterName,
|
||||
namedArgsScope,
|
||||
KOTLIN_NAMED_ARGUMENT_SEARCH_CONTEXT,
|
||||
@@ -136,46 +137,6 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
||||
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 {
|
||||
fun processKtClassOrObject(element: KtClassOrObject, queryParameters: ReferencesSearch.SearchParameters) {
|
||||
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 kotlinOptions = (queryParameters as? KotlinReferencesSearchParameters)?.kotlinOptions
|
||||
?: KotlinReferencesSearchOptions.Empty
|
||||
val resultProcessor = MyRequestResultProcessor(element,
|
||||
queryParameters.elementToSearch.namedUnwrappedElement ?: element,
|
||||
options = kotlinOptions)
|
||||
val resultProcessor = KotlinRequestResultProcessor(element,
|
||||
queryParameters.elementToSearch.namedUnwrappedElement ?: element,
|
||||
options = kotlinOptions)
|
||||
queryParameters.optimizer.searchWord(name, scope, context.toShort(), true, element,
|
||||
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.KotlinConstructorDelegationCallReferenceSearcher"/>
|
||||
<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"/>
|
||||
|
||||
|
||||
+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);
|
||||
}
|
||||
|
||||
@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");
|
||||
|
||||
Reference in New Issue
Block a user