Implemented fast search for binary operators
This commit is contained in:
+19
-19
@@ -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.allScope
|
||||||
import org.jetbrains.kotlin.idea.search.effectiveSearchScope
|
import org.jetbrains.kotlin.idea.search.effectiveSearchScope
|
||||||
import org.jetbrains.kotlin.idea.search.unionSafe
|
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.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.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
import org.jetbrains.kotlin.psi.psiUtil.getStrictParentOfType
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.parents
|
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,
|
data class KotlinReferencesSearchOptions(val acceptCallableOverrides: Boolean = false,
|
||||||
val acceptOverloads: Boolean = false,
|
val acceptOverloads: Boolean = false,
|
||||||
val acceptExtensionsOfDeclarationClass: Boolean = false,
|
val acceptExtensionsOfDeclarationClass: Boolean = false,
|
||||||
val acceptCompanionObjectMembers: Boolean = false,
|
val acceptCompanionObjectMembers: Boolean = false,
|
||||||
val searchForComponentConventions: Boolean = true,
|
val searchForComponentConventions: Boolean = true,
|
||||||
val searchInvokeOperator: Boolean = true,
|
val searchForOperatorConventions: Boolean = true,
|
||||||
val searchNamedArguments: Boolean = true) {
|
val searchNamedArguments: Boolean = true) {
|
||||||
fun anyEnabled(): Boolean = acceptCallableOverrides || acceptOverloads || acceptExtensionsOfDeclarationClass
|
fun anyEnabled(): Boolean = acceptCallableOverrides || acceptOverloads || acceptExtensionsOfDeclarationClass
|
||||||
|
|
||||||
@@ -119,35 +120,31 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
|||||||
searchLightElements(queryParameters, element, consumer)
|
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) {
|
if (kotlinOptions.searchForComponentConventions) {
|
||||||
when (element) {
|
when (element) {
|
||||||
is KtFunction -> {
|
|
||||||
if (name != null && isComponentLike(name)) {
|
|
||||||
DestructuringDeclarationReferenceSearcher(element, effectiveSearchScope, consumer, queryParameters.optimizer).run()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
is KtParameter -> {
|
is KtParameter -> {
|
||||||
val componentFunctionDescriptor = runReadAction { element.dataClassComponentFunction() }
|
val componentFunctionDescriptor = runReadAction { element.dataClassComponentFunction() }
|
||||||
if (componentFunctionDescriptor != null) {
|
if (componentFunctionDescriptor != null) {
|
||||||
val containingClass = element.getStrictParentOfType<KtClassOrObject>()?.toLightClass()
|
val containingClass = element.getStrictParentOfType<KtClassOrObject>()?.toLightClass()
|
||||||
searchDataClassComponentUsages(queryParameters, containingClass, componentFunctionDescriptor, consumer)
|
searchDataClassComponentUsages(queryParameters, containingClass, componentFunctionDescriptor, consumer, kotlinOptions)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
is KtLightParameter -> {
|
is KtLightParameter -> {
|
||||||
val componentFunctionDescriptor = runReadAction { element.kotlinOrigin?.dataClassComponentFunction() }
|
val componentFunctionDescriptor = runReadAction { element.kotlinOrigin?.dataClassComponentFunction() }
|
||||||
if (componentFunctionDescriptor != null) {
|
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) {
|
private fun searchNamedArguments(parameter: KtParameter, queryParameters: ReferencesSearch.SearchParameters) {
|
||||||
@@ -242,14 +239,17 @@ class KotlinReferencesSearcher : QueryExecutorBase<PsiReference, ReferencesSearc
|
|||||||
private fun searchDataClassComponentUsages(queryParameters: ReferencesSearch.SearchParameters,
|
private fun searchDataClassComponentUsages(queryParameters: ReferencesSearch.SearchParameters,
|
||||||
containingClass: PsiClass?,
|
containingClass: PsiClass?,
|
||||||
componentFunctionDescriptor: FunctionDescriptor,
|
componentFunctionDescriptor: FunctionDescriptor,
|
||||||
consumer: Processor<PsiReference>
|
consumer: Processor<PsiReference>,
|
||||||
|
kotlinOptions: KotlinReferencesSearchOptions
|
||||||
) {
|
) {
|
||||||
val componentFunction = containingClass?.methods?.find {
|
val componentFunction = containingClass?.methods?.find {
|
||||||
it.name == componentFunctionDescriptor.name.asString() && it.parameterList.parametersCount == 0
|
it.name == componentFunctionDescriptor.name.asString() && it.parameterList.parametersCount == 0
|
||||||
}
|
}
|
||||||
if (componentFunction != null) {
|
if (componentFunction != null) {
|
||||||
searchNamedElement(queryParameters, componentFunction)
|
searchNamedElement(queryParameters, componentFunction)
|
||||||
DestructuringDeclarationReferenceSearcher.runForPsiMethod(componentFunction, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer)
|
val searcher = OperatorReferenceSearcher.createForPsiMethod(
|
||||||
|
componentFunction, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer, kotlinOptions)
|
||||||
|
searcher!!.run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+55
@@ -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>()
|
||||||
|
}
|
||||||
|
}
|
||||||
+1
-18
@@ -17,16 +17,12 @@
|
|||||||
package org.jetbrains.kotlin.idea.search.usagesSearch
|
package org.jetbrains.kotlin.idea.search.usagesSearch
|
||||||
|
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
|
||||||
import com.intellij.psi.PsiReference
|
import com.intellij.psi.PsiReference
|
||||||
import com.intellij.psi.search.SearchRequestCollector
|
import com.intellij.psi.search.SearchRequestCollector
|
||||||
import com.intellij.psi.search.SearchScope
|
import com.intellij.psi.search.SearchScope
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
|
||||||
import org.jetbrains.kotlin.idea.references.KtDestructuringDeclarationReference
|
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.psi.*
|
||||||
import org.jetbrains.kotlin.resolve.dataClassUtils.getComponentIndex
|
import org.jetbrains.kotlin.resolve.dataClassUtils.getComponentIndex
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
@@ -36,20 +32,7 @@ class DestructuringDeclarationReferenceSearcher(
|
|||||||
searchScope: SearchScope,
|
searchScope: SearchScope,
|
||||||
consumer: Processor<PsiReference>,
|
consumer: Processor<PsiReference>,
|
||||||
optimizer: SearchRequestCollector
|
optimizer: SearchRequestCollector
|
||||||
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(targetDeclaration, searchScope, consumer, optimizer, wordToSearch = "(") {
|
) : OperatorReferenceSearcher<KtDestructuringDeclaration>(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = listOf("(")) {
|
||||||
|
|
||||||
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()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private val componentIndex = when (targetDeclaration) {
|
private val componentIndex = when (targetDeclaration) {
|
||||||
is KtParameter -> targetDeclaration.dataClassComponentFunction()?.name?.asString()?.let { getComponentIndex(it) }
|
is KtParameter -> targetDeclaration.dataClassComponentFunction()?.name?.asString()?.let { getComponentIndex(it) }
|
||||||
|
|||||||
+3
-4
@@ -28,10 +28,8 @@ import com.intellij.psi.search.searches.ReferencesSearch
|
|||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.KtNodeTypes
|
import org.jetbrains.kotlin.KtNodeTypes
|
||||||
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
import org.jetbrains.kotlin.asJava.classes.KtLightClass
|
||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
|
||||||
import org.jetbrains.kotlin.asJava.toLightClass
|
import org.jetbrains.kotlin.asJava.toLightClass
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
|
||||||
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
|
||||||
import org.jetbrains.kotlin.idea.KotlinLanguage
|
import org.jetbrains.kotlin.idea.KotlinLanguage
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
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.FuzzyType
|
||||||
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
import org.jetbrains.kotlin.idea.util.ProjectRootsUtil
|
||||||
import org.jetbrains.kotlin.kdoc.psi.impl.KDocName
|
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.load.java.sam.SingleAbstractMethodUtils
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.*
|
import org.jetbrains.kotlin.psi.psiUtil.*
|
||||||
import org.jetbrains.kotlin.types.KotlinType
|
import org.jetbrains.kotlin.types.KotlinType
|
||||||
import org.jetbrains.kotlin.util.OperatorNameConventions
|
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
//TODO: check if smart search is too expensive
|
//TODO: check if smart search is too expensive
|
||||||
@@ -592,6 +588,8 @@ class ExpressionsOfTypeProcessor(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiElement.isOperatorExpensiveToSearch(): Boolean {
|
private fun PsiElement.isOperatorExpensiveToSearch(): Boolean {
|
||||||
|
return false //TODO
|
||||||
|
/*
|
||||||
when (this) {
|
when (this) {
|
||||||
is KtFunction -> {
|
is KtFunction -> {
|
||||||
if (name?.startsWith("component") == true || name == OperatorNameConventions.INVOKE.asString()) return false
|
if (name?.startsWith("component") == true || name == OperatorNameConventions.INVOKE.asString()) return false
|
||||||
@@ -607,6 +605,7 @@ class ExpressionsOfTypeProcessor(
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
|
private fun KotlinType.containsTypeOrDerivedInside(type: FuzzyType): Boolean {
|
||||||
|
|||||||
+5
-5
@@ -25,16 +25,16 @@ import com.intellij.util.Processor
|
|||||||
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
|
import org.jetbrains.kotlin.idea.references.KtInvokeFunctionReference
|
||||||
import org.jetbrains.kotlin.psi.KtCallExpression
|
import org.jetbrains.kotlin.psi.KtCallExpression
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.psi.KtExpression
|
||||||
|
import org.jetbrains.kotlin.psi.KtFunction
|
||||||
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstance
|
||||||
|
|
||||||
class InvokeOperatorReferenceSearcher(
|
class InvokeOperatorReferenceSearcher(
|
||||||
targetDeclaration: KtDeclaration,
|
targetDeclaration: KtFunction,
|
||||||
searchScope: SearchScope,
|
searchScope: SearchScope,
|
||||||
consumer: Processor<PsiReference>,
|
consumer: Processor<PsiReference>,
|
||||||
optimizer: SearchRequestCollector
|
optimizer: SearchRequestCollector
|
||||||
) : OperatorReferenceSearcher<KtCallExpression>(targetDeclaration, searchScope, consumer, optimizer, wordToSearch = null) {
|
) : OperatorReferenceSearcher<KtCallExpression>(targetDeclaration, searchScope, consumer, optimizer, wordsToSearch = emptyList()) {
|
||||||
|
|
||||||
companion object {
|
companion object {
|
||||||
fun runForPsiMethod(
|
fun runForPsiMethod(
|
||||||
@@ -44,8 +44,8 @@ class InvokeOperatorReferenceSearcher(
|
|||||||
optimizer: SearchRequestCollector
|
optimizer: SearchRequestCollector
|
||||||
) {
|
) {
|
||||||
if (invokeFunction !is KtLightMethod) return //TODO
|
if (invokeFunction !is KtLightMethod) return //TODO
|
||||||
val ktDeclarationTarget = invokeFunction.kotlinOrigin as? KtDeclaration ?: return //TODO?
|
val ktFunction = invokeFunction.kotlinOrigin as? KtFunction ?: return //TODO?
|
||||||
InvokeOperatorReferenceSearcher(ktDeclarationTarget, scope, consumer, optimizer).run()
|
InvokeOperatorReferenceSearcher(ktFunction, scope, consumer, optimizer).run()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+71
-13
@@ -17,29 +17,29 @@
|
|||||||
package org.jetbrains.kotlin.idea.search.usagesSearch
|
package org.jetbrains.kotlin.idea.search.usagesSearch
|
||||||
|
|
||||||
import com.intellij.openapi.roots.ProjectRootManager
|
import com.intellij.openapi.roots.ProjectRootManager
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.*
|
||||||
import com.intellij.psi.PsiManager
|
|
||||||
import com.intellij.psi.PsiRecursiveElementWalkingVisitor
|
|
||||||
import com.intellij.psi.PsiReference
|
|
||||||
import com.intellij.psi.search.*
|
import com.intellij.psi.search.*
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
|
import org.jetbrains.kotlin.asJava.elements.KtLightMethod
|
||||||
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
import org.jetbrains.kotlin.asJava.namedUnwrappedElement
|
||||||
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
import org.jetbrains.kotlin.descriptors.CallableDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
import org.jetbrains.kotlin.descriptors.ClassDescriptor
|
||||||
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
import org.jetbrains.kotlin.descriptors.FunctionDescriptor
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade
|
||||||
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
|
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.ideaExtensions.KotlinRequestResultProcessor
|
||||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
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.logPresentation
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.testLog
|
import org.jetbrains.kotlin.idea.search.usagesSearch.ExpressionsOfTypeProcessor.Companion.testLog
|
||||||
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
import org.jetbrains.kotlin.idea.util.fuzzyExtensionReceiverType
|
||||||
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
import org.jetbrains.kotlin.idea.util.toFuzzyType
|
||||||
import org.jetbrains.kotlin.psi.KtDeclaration
|
import org.jetbrains.kotlin.name.Name
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.KtExpression
|
import org.jetbrains.kotlin.resolve.dataClassUtils.isComponentLike
|
||||||
import org.jetbrains.kotlin.psi.KtFile
|
|
||||||
import org.jetbrains.kotlin.resolve.descriptorUtil.isExtension
|
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 org.jetbrains.kotlin.util.isValidOperator
|
||||||
import java.util.*
|
import java.util.*
|
||||||
|
|
||||||
@@ -48,7 +48,7 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
|||||||
private val searchScope: SearchScope,
|
private val searchScope: SearchScope,
|
||||||
private val consumer: Processor<PsiReference>,
|
private val consumer: Processor<PsiReference>,
|
||||||
private val optimizer: SearchRequestCollector,
|
private val optimizer: SearchRequestCollector,
|
||||||
private val wordToSearch: String?
|
private val wordsToSearch: List<String>
|
||||||
) {
|
) {
|
||||||
private val project = targetDeclaration.project
|
private val project = targetDeclaration.project
|
||||||
|
|
||||||
@@ -70,6 +70,62 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
|||||||
}
|
}
|
||||||
|
|
||||||
companion object {
|
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>>() {
|
private object SearchesInProgress : ThreadLocal<HashSet<KtDeclaration>>() {
|
||||||
override fun initialValue() = HashSet<KtDeclaration>()
|
override fun initialValue() = HashSet<KtDeclaration>()
|
||||||
}
|
}
|
||||||
@@ -77,9 +133,9 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
|||||||
|
|
||||||
open fun run() {
|
open fun run() {
|
||||||
val inProgress = SearchesInProgress.get()
|
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) {
|
val usePlainSearch = when (ExpressionsOfTypeProcessor.mode) {
|
||||||
ExpressionsOfTypeProcessor.Mode.ALWAYS_SMART -> false
|
ExpressionsOfTypeProcessor.Mode.ALWAYS_SMART -> false
|
||||||
ExpressionsOfTypeProcessor.Mode.ALWAYS_PLAIN -> true
|
ExpressionsOfTypeProcessor.Mode.ALWAYS_PLAIN -> true
|
||||||
@@ -131,11 +187,13 @@ abstract class OperatorReferenceSearcher<TReferenceElement : KtElement>(
|
|||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
scope as GlobalSearchScope
|
scope as GlobalSearchScope
|
||||||
if (wordToSearch != null) {
|
if (wordsToSearch.isNotEmpty()) {
|
||||||
val unwrappedElement = targetDeclaration.namedUnwrappedElement ?: return
|
val unwrappedElement = targetDeclaration.namedUnwrappedElement ?: return
|
||||||
val resultProcessor = KotlinRequestResultProcessor(unwrappedElement,
|
val resultProcessor = KotlinRequestResultProcessor(unwrappedElement,
|
||||||
filter = { ref -> isReferenceToCheck(ref) })
|
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 {
|
else {
|
||||||
val psiManager = PsiManager.getInstance(project)
|
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]
|
val unaryOp = UNARY_OPERATION_NAMES_WITH_DEPRECATED_INVERTED[this]
|
||||||
if (unaryOp != null) return setOf(unaryOp) to KtSimpleNameReference::class.java
|
if (unaryOp != null) return setOf(unaryOp) to KtSimpleNameReference::class.java
|
||||||
|
|
||||||
|
/*
|
||||||
val binaryOp = BINARY_OPERATION_NAMES.inverse()[this]
|
val binaryOp = BINARY_OPERATION_NAMES.inverse()[this]
|
||||||
if (binaryOp != null) {
|
if (binaryOp != null) {
|
||||||
val assignmentOp = ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp]
|
val assignmentOp = ASSIGNMENT_OPERATION_COUNTERPARTS.inverse()[binaryOp]
|
||||||
return (if (assignmentOp != null) setOf(binaryOp, assignmentOp) else setOf(binaryOp)) to KtSimpleNameReference::class.java
|
return (if (assignmentOp != null) setOf(binaryOp, assignmentOp) else setOf(binaryOp)) to KtSimpleNameReference::class.java
|
||||||
}
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
val assignmentOp = ASSIGNMENT_OPERATIONS.inverse()[this]
|
val assignmentOp = ASSIGNMENT_OPERATIONS.inverse()[this]
|
||||||
if (assignmentOp != null) return setOf(assignmentOp) to KtSimpleNameReference::class.java
|
if (assignmentOp != null) return setOf(assignmentOp) to KtSimpleNameReference::class.java
|
||||||
|
|||||||
+2
-2
@@ -131,9 +131,9 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
|
|||||||
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
|
val uniqueProcessor = CommonProcessors.UniqueProcessor(processor)
|
||||||
|
|
||||||
if (options.isUsages) {
|
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)
|
val kotlinSearchOptions = createKotlinReferencesSearchOptions(options)
|
||||||
.copy(searchForComponentConventions = false, searchInvokeOperator = false)
|
.copy(searchForComponentConventions = false, searchForOperatorConventions = false)
|
||||||
val searchParameters = KotlinReferencesSearchParameters(element, options.searchScope, kotlinOptions = kotlinSearchOptions)
|
val searchParameters = KotlinReferencesSearchParameters(element, options.searchScope, kotlinOptions = kotlinSearchOptions)
|
||||||
|
|
||||||
with(applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))) {
|
with(applyQueryFilters(element, options, ReferencesSearch.search(searchParameters))) {
|
||||||
|
|||||||
+5
-9
@@ -22,14 +22,11 @@ import com.intellij.psi.search.UsageSearchContext
|
|||||||
import com.intellij.psi.search.searches.MethodReferencesSearch
|
import com.intellij.psi.search.searches.MethodReferencesSearch
|
||||||
import com.intellij.util.Processor
|
import com.intellij.util.Processor
|
||||||
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
import org.jetbrains.kotlin.idea.search.restrictToKotlinSources
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.DestructuringDeclarationReferenceSearcher
|
import org.jetbrains.kotlin.idea.search.usagesSearch.OperatorReferenceSearcher
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.InvokeOperatorReferenceSearcher
|
|
||||||
import org.jetbrains.kotlin.idea.search.usagesSearch.getOperationSymbolsToSearch
|
import org.jetbrains.kotlin.idea.search.usagesSearch.getOperationSymbolsToSearch
|
||||||
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
import org.jetbrains.kotlin.idea.util.application.runReadAction
|
||||||
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
import org.jetbrains.kotlin.lexer.KtSingleValueToken
|
||||||
import org.jetbrains.kotlin.name.Name
|
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) {
|
class KotlinConventionMethodReferencesSearcher() : QueryExecutorBase<PsiReference, MethodReferencesSearch.SearchParameters>(true) {
|
||||||
override fun processQuery(queryParameters: MethodReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
|
override fun processQuery(queryParameters: MethodReferencesSearch.SearchParameters, consumer: Processor<PsiReference>) {
|
||||||
@@ -38,11 +35,10 @@ class KotlinConventionMethodReferencesSearcher() : QueryExecutorBase<PsiReferenc
|
|||||||
if (!Name.isValidIdentifier(name)) return
|
if (!Name.isValidIdentifier(name)) return
|
||||||
val identifier = Name.identifier(name)
|
val identifier = Name.identifier(name)
|
||||||
|
|
||||||
if (isComponentLike(identifier)) {
|
val operatorSearcher = OperatorReferenceSearcher.createForPsiMethod(
|
||||||
DestructuringDeclarationReferenceSearcher.runForPsiMethod(method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer)
|
method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer, KotlinReferencesSearchOptions.Empty)
|
||||||
}
|
if (operatorSearcher != null) {
|
||||||
else if (identifier == OperatorNameConventions.INVOKE) {
|
operatorSearcher.run()
|
||||||
InvokeOperatorReferenceSearcher.runForPsiMethod(method, queryParameters.effectiveSearchScope, consumer, queryParameters.optimizer)
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
val operationSymbolsToSearch = identifier.getOperationSymbolsToSearch()
|
val operationSymbolsToSearch = identifier.getOperationSymbolsToSearch()
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
// OPTIONS: usages
|
// OPTIONS: usages
|
||||||
|
|
||||||
class A(val n: Int) {
|
class A(val n: Int) {
|
||||||
fun <caret>compareTo(other: A): Int = compareTo(other.n)
|
infix operator fun <caret>compareTo(other: A): Int = compareTo(other.n)
|
||||||
fun compareTo(m: Int): Int = n.compareTo(m)
|
infix operator fun compareTo(m: Int): Int = n.compareTo(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
@@ -1,4 +1,13 @@
|
|||||||
|
Resolved (x, y)
|
||||||
|
Resolved b1 + b2
|
||||||
Searched references to A
|
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:
|
Used plain search in LocalSearchScope:
|
||||||
CLASS:A
|
CLASS:A
|
||||||
Used plain search in whole search scope
|
Used plain search in LocalSearchScope:
|
||||||
|
CLASS:B
|
||||||
|
FUN:plus
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
// OPTIONS: usages
|
// OPTIONS: usages
|
||||||
|
|
||||||
class A(val n: Int) {
|
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() {
|
fun test() {
|
||||||
|
|||||||
+1
-1
@@ -3,7 +3,7 @@
|
|||||||
// FIND_BY_REF
|
// FIND_BY_REF
|
||||||
|
|
||||||
class A(val n: Int) {
|
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() {
|
fun test() {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
Function call 10 A(0) == A(1)
|
Function call 10 A(0) == A(1)
|
||||||
Function call 11 A(0) != A(1)
|
Function call 11 A(0) != A(1)
|
||||||
Function call 12 A(0) equals 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
|
// OPTIONS: usages
|
||||||
|
|
||||||
class A<T: Any> {
|
class A<T: Any> {
|
||||||
public fun <caret>iterator(): Iterator<T> = throw IllegalStateException("")
|
operator fun <caret>iterator(): Iterator<T> = throw IllegalStateException("")
|
||||||
}
|
}
|
||||||
|
|
||||||
class B<T: Any> {
|
class B<T: Any> {
|
||||||
public fun iterator(): Iterator<T> = throw IllegalStateException("")
|
operator fun iterator(): Iterator<T> = throw IllegalStateException("")
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
// OPTIONS: usages
|
// OPTIONS: usages
|
||||||
|
|
||||||
class B(val n: Int) {
|
class B(val n: Int) {
|
||||||
fun <caret>get(i: Int): B = B(i)
|
operator fun <caret>get(i: Int): B = B(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Delegate() {
|
class Delegate() {
|
||||||
fun <caret>getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
|
operator fun <caret>getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
|
||||||
}
|
}
|
||||||
|
|
||||||
val p: String by Delegate()
|
val p: String by Delegate()
|
||||||
|
|||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
// OPTIONS: usages
|
// OPTIONS: usages
|
||||||
|
|
||||||
class A(val n: Int) {
|
class A(val n: Int) {
|
||||||
fun <caret>inc(): A = A(n + 1)
|
operator fun <caret>inc(): A = A(n + 1)
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
+2
-2
@@ -2,8 +2,8 @@
|
|||||||
// OPTIONS: usages
|
// OPTIONS: usages
|
||||||
|
|
||||||
class A(val n: Int) {
|
class A(val n: Int) {
|
||||||
fun <caret>plus(m: Int): A = A(n + m)
|
operator fun <caret>plus(m: Int): A = A(n + m)
|
||||||
fun plus(a: A): A = this + a.n
|
operator fun plus(a: A): A = this + a.n
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
@@ -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 11 A(0) plus A(1) plus 2
|
||||||
Function call 12 A(0).plus(A(1).plus(2))
|
Function call 12 A(0).plus(A(1).plus(2))
|
||||||
Function call 15 a += 1
|
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
|
// OPTIONS: usages
|
||||||
|
|
||||||
class A(var n: Int) {
|
class A(var n: Int) {
|
||||||
fun <caret>plusAssign(m: Int) {
|
operator fun <caret>plusAssign(m: Int) {
|
||||||
n += m
|
n += m
|
||||||
}
|
}
|
||||||
|
|
||||||
fun plusAssign(a: A) {
|
operator fun plusAssign(a: A) {
|
||||||
this += a.n
|
this += a.n
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Delegate() {
|
class Delegate() {
|
||||||
fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
|
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
|
||||||
fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
|
|
||||||
|
operator fun setValue(thisRef: Any?, property: KProperty<*>, value: String) {
|
||||||
}
|
}
|
||||||
|
|
||||||
fun <caret>propertyDelegated(property: KProperty<*>) {
|
fun <caret>propertyDelegated(property: KProperty<*>) {
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
Property delegation 15 var p: String by Delegate()
|
Property delegation 16 var p: String by Delegate()
|
||||||
+1
-1
@@ -2,7 +2,7 @@
|
|||||||
// OPTIONS: usages
|
// OPTIONS: usages
|
||||||
|
|
||||||
class B(val n: Int) {
|
class B(val n: Int) {
|
||||||
fun <caret>set(i: Int, a: B) {}
|
operator fun <caret>set(i: Int, a: B) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
fun test() {
|
fun test() {
|
||||||
|
|||||||
@@ -4,8 +4,9 @@
|
|||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
|
|
||||||
class Delegate() {
|
class Delegate() {
|
||||||
fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
|
operator fun getValue(thisRef: Any?, property: KProperty<*>): String = ":)"
|
||||||
fun <caret>setValue(thisRef: Any?, property: KProperty<*>, value: String) {
|
|
||||||
|
operator fun <caret>setValue(thisRef: Any?, property: KProperty<*>, value: String) {
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -1 +1 @@
|
|||||||
Property delegation 13 var p: String by Delegate()
|
Property delegation 14 var p: String by Delegate()
|
||||||
Reference in New Issue
Block a user