Implemented fast search for binary operators

This commit is contained in:
Valentin Kipyatkov
2016-09-02 14:07:21 +03:00
parent f2c0d131e4
commit 1ca698cfc4
27 changed files with 225 additions and 93 deletions
@@ -37,21 +37,22 @@ 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.unionSafe
import org.jetbrains.kotlin.idea.search.usagesSearch.*
import org.jetbrains.kotlin.idea.search.usagesSearch.OperatorReferenceSearcher
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.*
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.util.OperatorNameConventions
data class KotlinReferencesSearchOptions(val acceptCallableOverrides: Boolean = false,
val acceptOverloads: Boolean = false,
val acceptExtensionsOfDeclarationClass: Boolean = false,
val acceptCompanionObjectMembers: Boolean = false,
val searchForComponentConventions: Boolean = true,
val searchInvokeOperator: Boolean = true,
val searchForOperatorConventions: Boolean = true,
val searchNamedArguments: Boolean = true) {
fun anyEnabled(): Boolean = acceptCallableOverrides || acceptOverloads || acceptExtensionsOfDeclarationClass
@@ -119,35 +120,31 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
searchLightElements(queryParameters, element, consumer)
}
//TODO: operator functions from Java
if (element is KtFunction) {
val referenceSearcher = OperatorReferenceSearcher.createForKtFunction(
element, effectiveSearchScope, consumer, queryParameters.optimizer, kotlinOptions)
referenceSearcher?.run()
}
if (kotlinOptions.searchForComponentConventions) {
when (element) {
is KtFunction -> {
if (name != null && isComponentLike(name)) {
DestructuringDeclarationReferenceSearcher(element, effectiveSearchScope, consumer, queryParameters.optimizer).run()
}
}
is KtParameter -> {
val componentFunctionDescriptor = runReadAction { element.dataClassComponentFunction() }
if (componentFunctionDescriptor != null) {
val containingClass = element.getStrictParentOfType<KtClassOrObject>()?.toLightClass()
searchDataClassComponentUsages(queryParameters, containingClass, componentFunctionDescriptor, consumer)
searchDataClassComponentUsages(queryParameters, containingClass, componentFunctionDescriptor, consumer, kotlinOptions)
}
}
is KtLightParameter -> {
val componentFunctionDescriptor = runReadAction { element.kotlinOrigin?.dataClassComponentFunction() }
if (componentFunctionDescriptor != null) {
searchDataClassComponentUsages(queryParameters, element.method.containingClass, componentFunctionDescriptor, consumer)
searchDataClassComponentUsages(queryParameters, element.method.containingClass, componentFunctionDescriptor, consumer, kotlinOptions)
}
}
}
}
//TODO: Java invoke's
if (kotlinOptions.searchInvokeOperator && element is KtFunction && name == OperatorNameConventions.INVOKE.asString()) {
InvokeOperatorReferenceSearcher(element, effectiveSearchScope, consumer, queryParameters.optimizer).run()
}
}
private fun searchNamedArguments(parameter: KtParameter, queryParameters: ReferencesSearch.SearchParameters) {
@@ -242,14 +239,17 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
private fun searchDataClassComponentUsages(queryParameters: ReferencesSearch.SearchParameters,
containingClass: PsiClass?,
componentFunctionDescriptor: FunctionDescriptor,
consumer: Processor<PsiReference>
consumer: Processor<PsiReference>,
kotlinOptions: KotlinReferencesSearchOptions
) {
val componentFunction = containingClass?.methods?.find {
it.name == componentFunctionDescriptor.name.asString() && it.parameterList.parametersCount == 0
}
if (componentFunction != null) {
searchNamedElement(queryParameters, componentFunction)
DestructuringDeclarationReferenceSearcher.runForPsiMethod(componentFunction, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer)
val searcher = OperatorReferenceSearcher.createForPsiMethod(
componentFunction, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer, kotlinOptions)
searcher!!.run()
}
}
@@ -0,0 +1,55 @@
/*
* 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.usagesSearch
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiReference
import com.intellij.psi.search.SearchRequestCollector
import com.intellij.psi.search.SearchScope
import com.intellij.util.Processor
import org.jetbrains.kotlin.idea.references.KtSimpleNameReference
import org.jetbrains.kotlin.lexer.KtSingleValueToken
import org.jetbrains.kotlin.psi.KtBinaryExpression
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class BinaryOperatorReferenceSearcher(
targetDeclaration: KtDeclaration,
private val operationTokens: List<KtSingleValueToken>,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) : OperatorReferenceSearcher<KtBinaryExpression>(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = operationTokens.map { it.value }) {
override fun processSuspiciousExpression(expression: KtExpression) {
val binaryExpression = expression.parent as? KtBinaryExpression ?: return
if (binaryExpression.operationToken !in operationTokens) return
if (expression != binaryExpression.left) return
processReferenceElement(binaryExpression)
}
override fun isReferenceToCheck(ref: PsiReference): Boolean {
return ref is KtSimpleNameReference && ref.element.getReferencedNameElementType() in operationTokens
}
override fun extractReference(element: PsiElement): PsiReference? {
val binaryExpression = element as? KtBinaryExpression ?: return null
if (binaryExpression.operationToken !in operationTokens) return null
return binaryExpression.operationReference.references.firstIsInstance<KtSimpleNameReference>()
}
}
@@ -17,16 +17,12 @@
package org.jetbrains.kotlin.idea.search.usagesSearch
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiMethod
import com.intellij.psi.PsiReference
import com.intellij.psi.search.SearchRequestCollector
import com.intellij.psi.search.SearchScope
import com.intellij.util.Processor
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.logPresentation
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.testLog
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.dataClassUtils.getComponentIndex
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
@@ -36,20 +32,7 @@ class DestructuringDeclarationReferenceSearcher(
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(targetDeclaration, searchScope, consumer, optimizer, wordToSearch = "(") {
companion object {
fun runForPsiMethod(
componentFunction: PsiMethod,
scope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) {
if (componentFunction !is KtLightMethod) return //TODO
val ktDeclarationTarget = componentFunction.kotlinOrigin as? KtDeclaration ?: return //TODO?
DestructuringDeclarationReferenceSearcher(ktDeclarationTarget, scope, consumer, optimizer).run()
}
}
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = listOf("(")) {
private val componentIndex = when (targetDeclaration) {
is KtParameter -> targetDeclaration.dataClassComponentFunction()?.name?.asString()?.let { getComponentIndex(it) }
@@ -28,10 +28,8 @@ import com.intellij.psi.search.searches.ReferencesSearch
import com.intellij.util.Processor
import org.jetbrains.kotlin.KtNodeTypes
import org.jetbrains.kotlin.asJava.classes.KtLightClass
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.toLightClass
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.idea.KotlinLanguage
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
@@ -46,12 +44,10 @@ import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
import org.jetbrains.kotlin.idea.util.FuzzyType
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
import org.jetbrains.kotlin.lexer.KtTokens
import org.jetbrains.kotlin.load.java.sam.SingleAbstractMethodUtils
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.types.KotlinType
import org.jetbrains.kotlin.util.OperatorNameConventions
import java.util.*
//TODO: check if smart search is too expensive
@@ -592,6 +588,8 @@ class ExpressionsOfTypeProcessor(
}
private fun PsiElement.isOperatorExpensiveToSearch(): Boolean {
return false //TODO
/*
when (this) {
is KtFunction -> {
if (name?.startsWith("component") == true || name == OperatorNameConventions.INVOKE.asString()) return false
@@ -607,6 +605,7 @@ class ExpressionsOfTypeProcessor(
return false
}
}
*/
}
private fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
@@ -25,16 +25,16 @@ import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
import org.jetbrains.kotlin.psi.KtCallExpression
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFunction
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
class InvokeOperatorReferenceSearcher(
targetDeclaration: KtDeclaration,
targetDeclaration: KtFunction,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector
) : OperatorReferenceSearcher<KtCallExpression>(targetDeclaration, searchScope, consumer, optimizer, wordToSearch = null) {
) : OperatorReferenceSearcher<KtCallExpression>(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = emptyList()) {
companion object {
fun runForPsiMethod(
@@ -44,8 +44,8 @@ class InvokeOperatorReferenceSearcher(
optimizer: SearchRequestCollector
) {
if (invokeFunction !is KtLightMethod) return //TODO
val ktDeclarationTarget = invokeFunction.kotlinOrigin as? KtDeclaration ?: return //TODO?
InvokeOperatorReferenceSearcher(ktDeclarationTarget, scope, consumer, optimizer).run()
val ktFunction = invokeFunction.kotlinOrigin as? KtFunction ?: return //TODO?
InvokeOperatorReferenceSearcher(ktFunction, scope, consumer, optimizer).run()
}
}
@@ -17,29 +17,29 @@
package org.jetbrains.kotlin.idea.search.usagesSearch
import com.intellij.openapi.roots.ProjectRootManager
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiManager
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
import com.intellij.psi.PsiReference
import com.intellij.psi.*
import com.intellij.psi.search.*
import com.intellij.util.Processor
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.ClassDescriptor
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinReferencesSearchOptions
import org.jetbrains.kotlin.idea.search.ideaExtensions.KotlinRequestResultProcessor
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.logPresentation
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.testLog
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
import org.jetbrains.kotlin.idea.util.toFuzzyType
import org.jetbrains.kotlin.psi.KtDeclaration
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtExpression
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
import org.jetbrains.kotlin.types.expressions.OperatorConventions
import org.jetbrains.kotlin.util.OperatorNameConventions
import org.jetbrains.kotlin.util.isValidOperator
import java.util.*
@@ -48,7 +48,7 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
private val searchScope: SearchScope,
private val consumer: Processor<PsiReference>,
private val optimizer: SearchRequestCollector,
private val wordToSearch: String?
private val wordsToSearch: List<String>
) {
private val project = targetDeclaration.project
@@ -70,6 +70,62 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
}
companion object {
fun createForKtFunction(
function: KtFunction,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
val name = function.name ?: return null
return create(function, name, searchScope, consumer, optimizer, options)
}
fun createForPsiMethod(
psiMethod: PsiMethod,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
if (psiMethod !is KtLightMethod) return null //TODO?
val ktDeclaration = psiMethod.kotlinOrigin as? KtDeclaration ?: return null //TODO?
return create(ktDeclaration, psiMethod.name, searchScope, consumer, optimizer, options)
}
private fun create(
declaration: KtDeclaration,
functionName: String,
searchScope: SearchScope,
consumer: Processor<PsiReference>,
optimizer: SearchRequestCollector,
options: KotlinReferencesSearchOptions
): OperatorReferenceSearcher<*>? {
if (!Name.isValidIdentifier(functionName)) return null
val name = Name.identifier(functionName)
if (isComponentLike(name)) {
if (!options.searchForComponentConventions) return null
return DestructuringDeclarationReferenceSearcher(declaration, searchScope, consumer, optimizer)
}
if (!options.searchForOperatorConventions) return null
if (declaration !is KtFunction) return null
if (name == OperatorNameConventions.INVOKE) {
return InvokeOperatorReferenceSearcher(declaration, searchScope, consumer, optimizer)
}
val binaryOp = OperatorConventions.BINARY_OPERATION_NAMES.inverse()[name]
if (binaryOp != null) {
val assignmentOp = OperatorConventions.ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp]
val operationTokens = listOf(binaryOp, assignmentOp).filterNotNull()
return BinaryOperatorReferenceSearcher(declaration, operationTokens, searchScope, consumer, optimizer)
}
return null
}
private object SearchesInProgress : ThreadLocal<HashSet<KtDeclaration>>() {
override fun initialValue() = HashSet<KtDeclaration>()
}
@@ -77,9 +133,9 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
open fun run() {
val inProgress = SearchesInProgress.get()
try {
if (!inProgress.add(targetDeclaration)) return //TODO: it's not quite correct
if (!inProgress.add(targetDeclaration)) return //TODO: it's not quite correct
try {
val usePlainSearch = when (ExpressionsOfTypeProcessor.mode) {
ExpressionsOfTypeProcessor.Mode.ALWAYS_SMART -> false
ExpressionsOfTypeProcessor.Mode.ALWAYS_PLAIN -> true
@@ -131,11 +187,13 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
}
else {
scope as GlobalSearchScope
if (wordToSearch != null) {
if (wordsToSearch.isNotEmpty()) {
val unwrappedElement = targetDeclaration.namedUnwrappedElement ?: return
val resultProcessor = KotlinRequestResultProcessor(unwrappedElement,
filter = { ref -> isReferenceToCheck(ref) })
optimizer.searchWord(wordToSearch, scope.restrictToKotlinSources(), UsageSearchContext.IN_CODE, true, unwrappedElement, resultProcessor)
wordsToSearch.forEach {
optimizer.searchWord(it, scope.restrictToKotlinSources(), UsageSearchContext.IN_CODE, true, unwrappedElement, resultProcessor)
}
}
else {
val psiManager = PsiManager.getInstance(project)
@@ -62,11 +62,13 @@ fun Name.getOperationSymbolsToSearch(): Pair<Set<KtToken>, Class<*>?> {
val unaryOp = UNARY_OPERATION_NAMES_WITH_DEPRECATED_INVERTED[this]
if (unaryOp != null) return setOf(unaryOp) to KtSimpleNameReference::class.java
/*
val binaryOp = BINARY_OPERATION_NAMES.inverse()[this]
if (binaryOp != null) {
val assignmentOp = ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp]
return (if (assignmentOp != null) setOf(binaryOp, assignmentOp) else setOf(binaryOp)) to KtSimpleNameReference::class.java
}
*/
val assignmentOp = ASSIGNMENT_OPERATIONS.inverse()[this]
if (assignmentOp != null) return setOf(assignmentOp) to KtSimpleNameReference::class.java
@@ -131,9 +131,9 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
if (options.isUsages) {
// we disable searchForComponentConventions and searchInvokeOperator for ReferencesSearch because they will be searched by MethodReferencesSearch
// we disable searchForComponentConventions and searchForOperatorConventions for ReferencesSearch because they will be searched by MethodReferencesSearch
val kotlinSearchOptions = createKotlinReferencesSearchOptions(options)
.copy(searchForComponentConventions = false, searchInvokeOperator = false)
.copy(searchForComponentConventions = false, searchForOperatorConventions = false)
val searchParameters = KotlinReferencesSearchParameters(element, options.searchScope, kotlinOptions = kotlinSearchOptions)
with(applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))) {
@@ -22,14 +22,11 @@ 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.DestructuringDeclarationReferenceSearcher
import org.jetbrains.kotlin.idea.search.usagesSearch.InvokeOperatorReferenceSearcher
import org.jetbrains.kotlin.idea.search.usagesSearch.OperatorReferenceSearcher
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
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
import org.jetbrains.kotlin.util.OperatorNameConventions
class KotlinConventionMethodReferencesSearcher() : QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters>(true) {
override fun processQuery(queryParameters: MethodReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
@@ -38,11 +35,10 @@ class KotlinConventionMethodReferencesSearcher() : QueryExecutorBase<PsiReferenc
if (!Name.isValidIdentifier(name)) return
val identifier = Name.identifier(name)
if (isComponentLike(identifier)) {
DestructuringDeclarationReferenceSearcher.runForPsiMethod(method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer)
}
else if (identifier == OperatorNameConventions.INVOKE) {
InvokeOperatorReferenceSearcher.runForPsiMethod(method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer)
val operatorSearcher = OperatorReferenceSearcher.createForPsiMethod(
method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer, KotlinReferencesSearchOptions.Empty)
if (operatorSearcher != null) {
operatorSearcher.run()
}
else {
val operationSymbolsToSearch = identifier.getOperationSymbolsToSearch()
+2 -2
View File
@@ -2,8 +2,8 @@
// OPTIONS: usages
class A(val n: Int) {
fun <caret>compareTo(other: A): Int = compareTo(other.n)
fun compareTo(m: Int): Int = n.compareTo(m)
infix operator fun <caret>compareTo(other: A): Int = compareTo(other.n)
infix operator fun compareTo(m: Int): Int = n.compareTo(m)
}
fun test() {
@@ -1,4 +1,13 @@
Resolved (x, y)
Resolved b1 + b2
Searched references to A
Searched references to B
Searched references to parameter b1 in f() in Kotlin files
Searched references to parameter b2 in f() in Kotlin files
Searched references to parameter other in plus() in Kotlin files
Searched references to plus() in Kotlin files
Used plain search in LocalSearchScope:
CLASS:A
Used plain search in whole search scope
Used plain search in LocalSearchScope:
CLASS:B
FUN:plus
+1 -1
View File
@@ -2,7 +2,7 @@
// OPTIONS: usages
class A(val n: Int) {
fun <caret>contains(k: Int): Boolean = k <= n
infix operator fun <caret>contains(k: Int): Boolean = k <= n
}
fun test() {
+1 -1
View File
@@ -3,7 +3,7 @@
// FIND_BY_REF
class A(val n: Int) {
override fun equals(other: Any?): Boolean = other is A && other.n <caret>== n
infix override fun equals(other: Any?): Boolean = other is A && other.n <caret>== n
}
fun test() {
@@ -1,4 +1,4 @@
Function call 10 A(0) == A(1)
Function call 11 A(0) != A(1)
Function call 12 A(0) equals A(1)
Function call 6 override fun equals(other: Any?): Boolean = other is A && other.n == n
Function call 6 infix override fun equals(other: Any?): Boolean = other is A && other.n == n
@@ -2,11 +2,11 @@
// OPTIONS: usages
class A<T: Any> {
public fun <caret>iterator(): Iterator<T> = throw IllegalStateException("")
operator fun <caret>iterator(): Iterator<T> = throw IllegalStateException("")
}
class B<T: Any> {
public fun iterator(): Iterator<T> = throw IllegalStateException("")
operator fun iterator(): Iterator<T> = throw IllegalStateException("")
}
fun test() {
+1 -1
View File
@@ -2,7 +2,7 @@
// OPTIONS: usages
class B(val n: Int) {
fun <caret>get(i: Int): B = B(i)
operator fun <caret>get(i: Int): B = B(i)
}
fun test() {
@@ -4,7 +4,7 @@
import kotlin.reflect.KProperty
class Delegate() {
fun <caret>getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
operator fun <caret>getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
}
val p: String by Delegate()
+1 -1
View File
@@ -2,7 +2,7 @@
// OPTIONS: usages
class A(val n: Int) {
fun <caret>inc(): A = A(n + 1)
operator fun <caret>inc(): A = A(n + 1)
}
fun test() {
+2 -2
View File
@@ -2,8 +2,8 @@
// OPTIONS: usages
class A(val n: Int) {
fun <caret>plus(m: Int): A = A(n + m)
fun plus(a: A): A = this + a.n
operator fun <caret>plus(m: Int): A = A(n + m)
operator fun plus(a: A): A = this + a.n
}
fun test() {
+28
View File
@@ -0,0 +1,28 @@
Checked type of a
Checked type of a
Resolved A(0) + A(1)
Resolved A(0) + A(1)
Resolved A(0) + A(1) + 2
Resolved A(0) + A(1) + 2
Resolved A(0) + A(1) + 2
Resolved A(0) + A(1) + 2
Resolved A(0) + A(1) + 2
Resolved A(0) + A(1) + 2
Resolved a += 1
Resolved a += 1
Resolved a += A(1)
Resolved a += A(1)
Searched references to A
Searched references to A
Searched references to A.plus() in Kotlin files
Searched references to A.plus() in Kotlin files
Searched references to A.plus() in Kotlin files
Searched references to A.plus() in Kotlin files
Searched references to a in Kotlin files
Searched references to a in Kotlin files
Searched references to parameter a in A.plus() in Kotlin files
Searched references to parameter a in A.plus() in Kotlin files
Used plain search in LocalSearchScope:
CLASS:A
Used plain search in LocalSearchScope:
CLASS:A
@@ -2,4 +2,4 @@ Function call 10 A(0) + A(1) + 2
Function call 11 A(0) plus A(1) plus 2
Function call 12 A(0).plus(A(1).plus(2))
Function call 15 a += 1
Function call 6 fun plus(a: A): A = this + a.n
Function call 6 operator fun plus(a: A): A = this + a.n
@@ -2,11 +2,11 @@
// OPTIONS: usages
class A(var n: Int) {
fun <caret>plusAssign(m: Int) {
operator fun <caret>plusAssign(m: Int) {
n += m
}
fun plusAssign(a: A) {
operator fun plusAssign(a: A) {
this += a.n
}
}
@@ -4,8 +4,9 @@
import kotlin.reflect.KProperty
class Delegate() {
fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
}
fun <caret>propertyDelegated(property: KProperty<*>) {
@@ -1 +1 @@
Property delegation 15 var p: String by Delegate()
Property delegation 16 var p: String by Delegate()
+1 -1
View File
@@ -2,7 +2,7 @@
// OPTIONS: usages
class B(val n: Int) {
fun <caret>set(i: Int, a: B) {}
operator fun <caret>set(i: Int, a: B) {}
}
fun test() {
@@ -4,8 +4,9 @@
import kotlin.reflect.KProperty
class Delegate() {
fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
fun <caret>setValue(thisRef: Any?, property: KProperty<*>, value: String) {
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
operator fun <caret>setValue(thisRef: Any?, property: KProperty<*>, value: String) {
}
}
@@ -1 +1 @@
Property delegation 13 var p: String by Delegate()
Property delegation 14 var p: String by Delegate()