Code refactoring + better handling of incoming data flow to java super methods
This commit is contained in:
@@ -7,6 +7,7 @@ package org.jetbrains.kotlin.idea.slicer
|
|||||||
|
|
||||||
import com.intellij.psi.PsiCall
|
import com.intellij.psi.PsiCall
|
||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.search.LocalSearchScope
|
import com.intellij.psi.search.LocalSearchScope
|
||||||
import com.intellij.psi.search.SearchScope
|
import com.intellij.psi.search.SearchScope
|
||||||
import com.intellij.psi.search.searches.ReferencesSearch
|
import com.intellij.psi.search.searches.ReferencesSearch
|
||||||
@@ -33,7 +34,6 @@ import org.jetbrains.kotlin.idea.search.declarationsSearch.HierarchySearchReques
|
|||||||
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
|
import org.jetbrains.kotlin.idea.search.declarationsSearch.searchOverriders
|
||||||
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
import org.jetbrains.kotlin.idea.util.actualsForExpected
|
||||||
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
import org.jetbrains.kotlin.idea.util.isExpectDeclaration
|
||||||
import org.jetbrains.kotlin.js.resolve.diagnostics.findPsi
|
|
||||||
import org.jetbrains.kotlin.lexer.KtTokens
|
import org.jetbrains.kotlin.lexer.KtTokens
|
||||||
import org.jetbrains.kotlin.psi.*
|
import org.jetbrains.kotlin.psi.*
|
||||||
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
import org.jetbrains.kotlin.psi.psiUtil.forEachDescendantOfType
|
||||||
@@ -129,25 +129,7 @@ class InflowSlicer(
|
|||||||
val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
|
val parameterDescriptor = parameter.resolveToParameterDescriptorIfAny(BodyResolveMode.FULL) ?: return
|
||||||
|
|
||||||
if (function is KtFunction) {
|
if (function is KtFunction) {
|
||||||
val sliceTransformer = ArgumentExpressionTransformer(parameterDescriptor)
|
processCalls(function, includeOverriders, ArgumentSliceProducer(parameterDescriptor))
|
||||||
|
|
||||||
when {
|
|
||||||
function is KtFunctionLiteral -> {
|
|
||||||
processFunctionLiteralCalls(function, sliceTransformer)
|
|
||||||
}
|
|
||||||
|
|
||||||
function is KtNamedFunction && function.name == null -> {
|
|
||||||
processAnonymousFunctionCalls(function, sliceTransformer)
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
processCalls(function, analysisScope, includeOverriders) { usageInfo ->
|
|
||||||
usageInfo.element?.let {
|
|
||||||
sliceTransformer.extractArgumentExpression(it)?.passToProcessorAsValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parameter.valOrVarKeyword.toValVar() == KotlinValVar.Var) {
|
if (parameter.valOrVarKeyword.toValVar() == KotlinValVar.Var) {
|
||||||
@@ -156,33 +138,7 @@ class InflowSlicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private fun processExtensionReceiver(declaration: KtCallableDeclaration, includeOverriders: Boolean) {
|
private fun processExtensionReceiver(declaration: KtCallableDeclaration, includeOverriders: Boolean) {
|
||||||
fun processReceiver(refElement: PsiElement) {
|
processCalls(declaration, includeOverriders, ReceiverSliceProducer)
|
||||||
when (refElement) {
|
|
||||||
is KtExpression -> {
|
|
||||||
val resolvedCall = refElement.resolveToCall() ?: return
|
|
||||||
when (val receiver = resolvedCall.extensionReceiver) {
|
|
||||||
is ExpressionReceiver -> {
|
|
||||||
receiver.expression.passToProcessorAsValue()
|
|
||||||
}
|
|
||||||
|
|
||||||
is ImplicitReceiver -> {
|
|
||||||
val callableDeclaration = (receiver.declarationDescriptor as? CallableDescriptor)?.originalSource?.getPsi()
|
|
||||||
(callableDeclaration as? KtCallableDeclaration)?.receiverTypeReference?.passToProcessor()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
else -> {
|
|
||||||
(refElement.parent as? PsiCall)?.argumentList?.expressions?.getOrNull(0)?.passToProcessorAsValue()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
processCalls(declaration, analysisScope, includeOverriders) { usageInfo ->
|
|
||||||
usageInfo.element?.let {
|
|
||||||
processReceiver(it)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun processExpression(expression: KtExpression) {
|
private fun processExpression(expression: KtExpression) {
|
||||||
@@ -234,8 +190,8 @@ class InflowSlicer(
|
|||||||
val anonymousFunction = accessedDescriptor.containingDeclaration as? AnonymousFunctionDescriptor
|
val anonymousFunction = accessedDescriptor.containingDeclaration as? AnonymousFunctionDescriptor
|
||||||
if (anonymousFunction != null && accessedDescriptor.name.asString() == "it") {
|
if (anonymousFunction != null && accessedDescriptor.name.asString() == "it") {
|
||||||
val functionLiteral = anonymousFunction.source.getPsi() as KtFunctionLiteral
|
val functionLiteral = anonymousFunction.source.getPsi() as KtFunctionLiteral
|
||||||
val sliceTransformer = ArgumentExpressionTransformer(anonymousFunction.valueParameters.first())
|
val sliceTransformer = ArgumentSliceProducer(anonymousFunction.valueParameters.first())
|
||||||
processFunctionLiteralCalls(functionLiteral, sliceTransformer)
|
processCalls(functionLiteral, false, sliceTransformer)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
accessedDeclaration.passDeclarationToProcessorWithOverriders()
|
accessedDeclaration.passDeclarationToProcessorWithOverriders()
|
||||||
@@ -366,23 +322,27 @@ class InflowSlicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
@Suppress("DataClassPrivateConstructor") // we have modifier data to get equals&hashCode only
|
@Suppress("DataClassPrivateConstructor") // we have modifier data to get equals&hashCode only
|
||||||
private data class ArgumentExpressionTransformer private constructor(
|
private data class ArgumentSliceProducer private constructor(
|
||||||
private val parameterIndex: Int,
|
private val parameterIndex: Int,
|
||||||
private val isExtension: Boolean
|
private val isExtension: Boolean
|
||||||
) : KotlinSliceUsageTransformer
|
) : SliceProducer
|
||||||
{
|
{
|
||||||
constructor(parameterDescriptor: ValueParameterDescriptor) : this(
|
constructor(parameterDescriptor: ValueParameterDescriptor) : this(
|
||||||
parameterDescriptor.index,
|
parameterDescriptor.index,
|
||||||
parameterDescriptor.containingDeclaration.isExtension
|
parameterDescriptor.containingDeclaration.isExtension
|
||||||
)
|
)
|
||||||
|
|
||||||
override fun transform(usage: KotlinSliceUsage): SliceUsage? {
|
override fun produce(
|
||||||
val element = usage.element ?: return null
|
usage: UsageInfo,
|
||||||
val argumentExpression = extractArgumentExpression(element) ?: return null
|
behaviour: KotlinSliceUsage.SpecialBehaviour?,
|
||||||
return KotlinSliceUsage(argumentExpression, usage.parent, usage.behaviour?.originalBehaviour, forcedExpressionMode = true)
|
parent: SliceUsage
|
||||||
|
): Collection<SliceUsage>? {
|
||||||
|
val element = usage.element ?: return emptyList()
|
||||||
|
val argumentExpression = extractArgumentExpression(element) ?: return emptyList()
|
||||||
|
return listOf(KotlinSliceUsage(argumentExpression, parent, behaviour, forcedExpressionMode = true))
|
||||||
}
|
}
|
||||||
|
|
||||||
fun extractArgumentExpression(refElement: PsiElement): PsiElement? {
|
private fun extractArgumentExpression(refElement: PsiElement): PsiElement? {
|
||||||
val refParent = refElement.parent
|
val refParent = refElement.parent
|
||||||
return when {
|
return when {
|
||||||
refElement is KtExpression -> {
|
refElement is KtExpression -> {
|
||||||
@@ -404,8 +364,47 @@ class InflowSlicer(
|
|||||||
|
|
||||||
refParent is PsiCall -> refParent.argumentList?.expressions?.getOrNull(parameterIndex + (if (isExtension) 1 else 0))
|
refParent is PsiCall -> refParent.argumentList?.expressions?.getOrNull(parameterIndex + (if (isExtension) 1 else 0))
|
||||||
|
|
||||||
|
refElement is PsiMethod -> refElement.parameterList.parameters.getOrNull(parameterIndex + (if (isExtension) 1 else 0))
|
||||||
|
|
||||||
else -> null
|
else -> null
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object ReceiverSliceProducer : SliceProducer {
|
||||||
|
override fun produce(
|
||||||
|
usage: UsageInfo,
|
||||||
|
behaviour: KotlinSliceUsage.SpecialBehaviour?,
|
||||||
|
parent: SliceUsage
|
||||||
|
): Collection<SliceUsage>? {
|
||||||
|
val refElement = usage.element ?: return emptyList()
|
||||||
|
when (refElement) {
|
||||||
|
is KtExpression -> {
|
||||||
|
val resolvedCall = refElement.resolveToCall() ?: return emptyList()
|
||||||
|
when (val receiver = resolvedCall.extensionReceiver) {
|
||||||
|
is ExpressionReceiver -> {
|
||||||
|
return listOf(KotlinSliceUsage(receiver.expression, parent, behaviour, true))
|
||||||
|
}
|
||||||
|
|
||||||
|
is ImplicitReceiver -> {
|
||||||
|
val callableDeclaration = (receiver.declarationDescriptor as? CallableDescriptor)?.originalSource?.getPsi()
|
||||||
|
val receiverTypeReference = (callableDeclaration as? KtCallableDeclaration)?.receiverTypeReference
|
||||||
|
?: return emptyList()
|
||||||
|
return listOf(KotlinSliceUsage(receiverTypeReference, parent, behaviour, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> return emptyList()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
val argument = (refElement.parent as? PsiCall)?.argumentList?.expressions?.getOrNull(0) ?: return emptyList()
|
||||||
|
return listOf(KotlinSliceUsage(argument, parent, behaviour, true))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = other === this
|
||||||
|
override fun hashCode() = 0
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -11,17 +11,9 @@ import org.jetbrains.kotlin.idea.caches.resolve.resolveToCall
|
|||||||
import org.jetbrains.kotlin.idea.findUsages.handlers.SliceUsageProcessor
|
import org.jetbrains.kotlin.idea.findUsages.handlers.SliceUsageProcessor
|
||||||
import org.jetbrains.kotlin.psi.Call
|
import org.jetbrains.kotlin.psi.Call
|
||||||
import org.jetbrains.kotlin.psi.KtElement
|
import org.jetbrains.kotlin.psi.KtElement
|
||||||
import org.jetbrains.kotlin.resolve.scopes.receivers.ExpressionReceiver
|
|
||||||
|
|
||||||
interface KotlinSliceUsageTransformer {
|
|
||||||
fun transform(usage: KotlinSliceUsage): SliceUsage?
|
|
||||||
|
|
||||||
override fun equals(other: Any?): Boolean
|
|
||||||
override fun hashCode(): Int
|
|
||||||
}
|
|
||||||
|
|
||||||
data class LambdaCallsBehaviour(
|
data class LambdaCallsBehaviour(
|
||||||
val usageTransformer: KotlinSliceUsageTransformer,
|
val sliceProducer: SliceProducer,
|
||||||
override val originalBehaviour: KotlinSliceUsage.SpecialBehaviour?
|
override val originalBehaviour: KotlinSliceUsage.SpecialBehaviour?
|
||||||
) : KotlinSliceUsage.SpecialBehaviour {
|
) : KotlinSliceUsage.SpecialBehaviour {
|
||||||
|
|
||||||
@@ -32,7 +24,7 @@ data class LambdaCallsBehaviour(
|
|||||||
val sliceElement = sliceUsage.element ?: return true
|
val sliceElement = sliceUsage.element ?: return true
|
||||||
val resolvedCall = (sliceElement as? KtElement)?.resolveToCall()
|
val resolvedCall = (sliceElement as? KtElement)?.resolveToCall()
|
||||||
if (resolvedCall?.call?.callType == Call.CallType.INVOKE) {
|
if (resolvedCall?.call?.callType == Call.CallType.INVOKE) {
|
||||||
return usageTransformer.transform(sliceUsage)?.let { uniqueProcessor.process(it) } ?: true
|
return sliceProducer.produceAndProcess(sliceUsage, originalBehaviour, parent, uniqueProcessor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return uniqueProcessor.process(sliceUsage)
|
return uniqueProcessor.process(sliceUsage)
|
||||||
|
|||||||
@@ -9,6 +9,7 @@ import com.intellij.codeInsight.highlighting.ReadWriteAccessDetector.Access
|
|||||||
import com.intellij.psi.PsiElement
|
import com.intellij.psi.PsiElement
|
||||||
import com.intellij.psi.PsiMethod
|
import com.intellij.psi.PsiMethod
|
||||||
import com.intellij.psi.impl.light.LightMemberReference
|
import com.intellij.psi.impl.light.LightMemberReference
|
||||||
|
import com.intellij.slicer.SliceUsage
|
||||||
import com.intellij.usageView.UsageInfo
|
import com.intellij.usageView.UsageInfo
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
|
||||||
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
|
||||||
@@ -150,17 +151,7 @@ class OutflowSlicer(
|
|||||||
|
|
||||||
private fun processFunction(function: KtFunction) {
|
private fun processFunction(function: KtFunction) {
|
||||||
if (function is KtConstructor<*> || function is KtNamedFunction && function.name != null) {
|
if (function is KtConstructor<*> || function is KtNamedFunction && function.name != null) {
|
||||||
processCalls(function, analysisScope, includeOverriders = false) { usageInfo ->
|
processCalls(function, includeOverriders = false, sliceProducer = CallSliceProducer)
|
||||||
when (val refElement = usageInfo.element) {
|
|
||||||
null -> (usageInfo.reference as? LightMemberReference)?.element?.passToProcessor()
|
|
||||||
is KtExpression -> {
|
|
||||||
refElement.getCallElementForExactCallee()?.passToProcessor()
|
|
||||||
refElement.getCallableReferenceForExactCallee()
|
|
||||||
?.passToProcessor(LambdaResultOutflowBehaviour(behaviour))
|
|
||||||
}
|
|
||||||
else -> refElement.passToProcessor()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -249,25 +240,6 @@ class OutflowSlicer(
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun PsiElement.getCallElementForExactCallee(): PsiElement? {
|
|
||||||
if (this is KtArrayAccessExpression) return this
|
|
||||||
|
|
||||||
val operationRefExpr = getNonStrictParentOfType<KtOperationReferenceExpression>()
|
|
||||||
if (operationRefExpr != null) return operationRefExpr.parent as? KtOperationExpression
|
|
||||||
|
|
||||||
val parentCall = getParentOfTypeAndBranch<KtCallElement> { calleeExpression } ?: return null
|
|
||||||
val callee = parentCall.calleeExpression?.let { KtPsiUtil.safeDeparenthesize(it) }
|
|
||||||
if (callee == this || callee is KtConstructorCalleeExpression && callee.isAncestor(this, strict = true)) return parentCall
|
|
||||||
|
|
||||||
return null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun PsiElement.getCallableReferenceForExactCallee(): KtCallableReferenceExpression? {
|
|
||||||
val callableRef = getParentOfTypeAndBranch<KtCallableReferenceExpression> { callableReference } ?: return null
|
|
||||||
val callee = KtPsiUtil.safeDeparenthesize(callableRef.callableReference)
|
|
||||||
return if (callee == this) callableRef else null
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun processDereferenceIfNeeded(
|
private fun processDereferenceIfNeeded(
|
||||||
expression: KtExpression,
|
expression: KtExpression,
|
||||||
pseudoValue: PseudoValue,
|
pseudoValue: PseudoValue,
|
||||||
@@ -301,4 +273,54 @@ class OutflowSlicer(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private object CallSliceProducer : SliceProducer {
|
||||||
|
override fun produce(
|
||||||
|
usage: UsageInfo,
|
||||||
|
behaviour: KotlinSliceUsage.SpecialBehaviour?,
|
||||||
|
parent: SliceUsage
|
||||||
|
): Collection<SliceUsage>? {
|
||||||
|
when (val refElement = usage.element) {
|
||||||
|
null -> {
|
||||||
|
val element = (usage.reference as? LightMemberReference)?.element ?: return emptyList()
|
||||||
|
return listOf(KotlinSliceUsage(element, parent, behaviour, false))
|
||||||
|
}
|
||||||
|
|
||||||
|
is KtExpression -> {
|
||||||
|
return mutableListOf<SliceUsage>().apply {
|
||||||
|
refElement.getCallElementForExactCallee()
|
||||||
|
?.let { this += KotlinSliceUsage(it, parent, behaviour, false) }
|
||||||
|
refElement.getCallableReferenceForExactCallee()
|
||||||
|
?.let { this += KotlinSliceUsage(it, parent, LambdaResultOutflowBehaviour(behaviour), false) }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
else -> {
|
||||||
|
return null // unknown type of usage - return null to process it "as is"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun equals(other: Any?) = other === this
|
||||||
|
override fun hashCode() = 0
|
||||||
|
|
||||||
|
private fun PsiElement.getCallElementForExactCallee(): PsiElement? {
|
||||||
|
if (this is KtArrayAccessExpression) return this
|
||||||
|
|
||||||
|
val operationRefExpr = getNonStrictParentOfType<KtOperationReferenceExpression>()
|
||||||
|
if (operationRefExpr != null) return operationRefExpr.parent as? KtOperationExpression
|
||||||
|
|
||||||
|
val parentCall = getParentOfTypeAndBranch<KtCallElement> { calleeExpression } ?: return null
|
||||||
|
val callee = parentCall.calleeExpression?.let { KtPsiUtil.safeDeparenthesize(it) }
|
||||||
|
if (callee == this || callee is KtConstructorCalleeExpression && callee.isAncestor(this, strict = true)) return parentCall
|
||||||
|
|
||||||
|
return null
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun PsiElement.getCallableReferenceForExactCallee(): KtCallableReferenceExpression? {
|
||||||
|
val callableRef = getParentOfTypeAndBranch<KtCallableReferenceExpression> { callableReference } ?: return null
|
||||||
|
val callee = KtPsiUtil.safeDeparenthesize(callableRef.callableReference)
|
||||||
|
return if (callee == this) callableRef else null
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,30 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||||
|
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package org.jetbrains.kotlin.idea.slicer
|
||||||
|
|
||||||
|
import com.intellij.slicer.SliceUsage
|
||||||
|
import com.intellij.usageView.UsageInfo
|
||||||
|
import org.jetbrains.kotlin.idea.findUsages.handlers.SliceUsageProcessor
|
||||||
|
|
||||||
|
interface SliceProducer {
|
||||||
|
fun produce(usage: UsageInfo, behaviour: KotlinSliceUsage.SpecialBehaviour?, parent: SliceUsage): Collection<SliceUsage>?
|
||||||
|
|
||||||
|
override fun equals(other: Any?): Boolean
|
||||||
|
override fun hashCode(): Int
|
||||||
|
}
|
||||||
|
|
||||||
|
fun SliceProducer.produceAndProcess(
|
||||||
|
sliceUsage: SliceUsage,
|
||||||
|
behaviour: KotlinSliceUsage.SpecialBehaviour?,
|
||||||
|
parentUsage: SliceUsage,
|
||||||
|
processor: SliceUsageProcessor
|
||||||
|
): Boolean {
|
||||||
|
val result = produce(sliceUsage.usageInfo, behaviour, parentUsage) ?: listOf(sliceUsage)
|
||||||
|
for (usage in result) {
|
||||||
|
if (!processor.process(usage)) return false
|
||||||
|
}
|
||||||
|
return true
|
||||||
|
}
|
||||||
@@ -68,29 +68,18 @@ abstract class Slicer(
|
|||||||
passToProcessor(behaviour, forcedExpressionMode = true)
|
passToProcessor(behaviour, forcedExpressionMode = true)
|
||||||
}
|
}
|
||||||
|
|
||||||
protected fun processFunctionLiteralCalls(
|
|
||||||
functionLiteral: KtFunctionLiteral,
|
|
||||||
sliceTransformer: KotlinSliceUsageTransformer,
|
|
||||||
) {
|
|
||||||
(functionLiteral.parent as KtLambdaExpression).passToProcessorAsValue(LambdaCallsBehaviour(sliceTransformer, behaviour))
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun processAnonymousFunctionCalls(
|
|
||||||
function: KtNamedFunction,
|
|
||||||
sliceTransformer: KotlinSliceUsageTransformer,
|
|
||||||
) {
|
|
||||||
require(function.name == null)
|
|
||||||
function.passToProcessorAsValue(LambdaCallsBehaviour(sliceTransformer, behaviour))
|
|
||||||
}
|
|
||||||
|
|
||||||
protected fun processCalls(
|
protected fun processCalls(
|
||||||
callable: KtCallableDeclaration,
|
callable: KtCallableDeclaration,
|
||||||
scope: SearchScope,
|
|
||||||
includeOverriders: Boolean,
|
includeOverriders: Boolean,
|
||||||
usageProcessor: (UsageInfo) -> Unit
|
sliceProducer: SliceProducer
|
||||||
) {
|
) {
|
||||||
if (callable is KtFunctionLiteral) {
|
if (callable is KtFunctionLiteral) {
|
||||||
//TODO
|
(callable.parent as KtLambdaExpression).passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if (callable is KtFunction && callable.name == null) {
|
||||||
|
callable.passToProcessorAsValue(LambdaCallsBehaviour(sliceProducer, behaviour))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -99,7 +88,7 @@ abstract class Slicer(
|
|||||||
KotlinFunctionFindUsagesOptions(project).apply {
|
KotlinFunctionFindUsagesOptions(project).apply {
|
||||||
isSearchForTextOccurrences = false
|
isSearchForTextOccurrences = false
|
||||||
isSkipImportStatements = true
|
isSkipImportStatements = true
|
||||||
searchScope = scope
|
searchScope = analysisScope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,7 +96,7 @@ abstract class Slicer(
|
|||||||
KotlinPropertyFindUsagesOptions(project).apply {
|
KotlinPropertyFindUsagesOptions(project).apply {
|
||||||
isSearchForTextOccurrences = false
|
isSearchForTextOccurrences = false
|
||||||
isSkipImportStatements = true
|
isSkipImportStatements = true
|
||||||
searchScope = scope
|
searchScope = analysisScope
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -131,6 +120,11 @@ abstract class Slicer(
|
|||||||
val declaration = superDescriptor.originalSource.getPsi() ?: continue
|
val declaration = superDescriptor.originalSource.getPsi() ?: continue
|
||||||
when (declaration) {
|
when (declaration) {
|
||||||
is KtDeclaration -> {
|
is KtDeclaration -> {
|
||||||
|
val usageProcessor: (UsageInfo) -> Unit = processor@ { usageInfo ->
|
||||||
|
val element = usageInfo.element ?: return@processor
|
||||||
|
val sliceUsage = KotlinSliceUsage(element, parentUsage, behaviour, false)
|
||||||
|
sliceProducer.produceAndProcess(sliceUsage, behaviour, parentUsage, processor)
|
||||||
|
}
|
||||||
if (includeOverriders) {
|
if (includeOverriders) {
|
||||||
declaration.processAllUsages(options, usageProcessor)
|
declaration.processAllUsages(options, usageProcessor)
|
||||||
} else {
|
} else {
|
||||||
@@ -139,12 +133,13 @@ abstract class Slicer(
|
|||||||
}
|
}
|
||||||
|
|
||||||
is PsiMethod -> {
|
is PsiMethod -> {
|
||||||
// todo: work around the bug in JavaSliceProvider.transform()
|
val sliceUsage = JavaSliceUsage.createRootUsage(declaration, parentUsage.params)
|
||||||
processor.process(JavaSliceUsage.createRootUsage(declaration, parentUsage.params))
|
sliceProducer.produceAndProcess(sliceUsage, behaviour, parentUsage, processor)
|
||||||
}
|
}
|
||||||
|
|
||||||
else -> {
|
else -> {
|
||||||
declaration.passToProcessor()
|
val sliceUsage = KotlinSliceUsage(declaration, parentUsage, behaviour, false)
|
||||||
|
sliceProducer.produceAndProcess(sliceUsage, behaviour, parentUsage, processor)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -189,12 +184,14 @@ abstract class Slicer(
|
|||||||
|
|
||||||
protected fun canProcessParameter(parameter: KtParameter) = !parameter.isVarArg
|
protected fun canProcessParameter(parameter: KtParameter) = !parameter.isVarArg
|
||||||
|
|
||||||
protected val DeclarationDescriptorWithSource.originalSource: SourceElement
|
protected companion object {
|
||||||
get() {
|
val DeclarationDescriptorWithSource.originalSource: SourceElement
|
||||||
var descriptor = this
|
get() {
|
||||||
while (descriptor.original != descriptor) {
|
var descriptor = this
|
||||||
descriptor = descriptor.original
|
while (descriptor.original != descriptor) {
|
||||||
|
descriptor = descriptor.original
|
||||||
|
}
|
||||||
|
return descriptor.source
|
||||||
}
|
}
|
||||||
return descriptor.source
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
+3
-2
@@ -1,7 +1,8 @@
|
|||||||
2 void <bold>foo(int p);</bold>
|
22 i.<bold>foo</bold>(3)
|
||||||
9 val v = <bold>p</bold>
|
9 val v = <bold>p</bold>
|
||||||
8 override fun foo(<bold>p: Int</bold>) {
|
8 override fun foo(<bold>p: Int</bold>) {
|
||||||
2 void <bold>foo(int p);</bold>
|
2 void foo(int <bold>p</bold>);
|
||||||
|
22 i.<bold>foo</bold>(3)
|
||||||
|
|
||||||
13 foo(<bold>1</bold>)
|
13 foo(<bold>1</bold>)
|
||||||
9 val v = <bold>p</bold>
|
9 val v = <bold>p</bold>
|
||||||
|
|||||||
+3
-1
@@ -1,5 +1,7 @@
|
|||||||
9 val v = <bold>p</bold>
|
9 val v = <bold>p</bold>
|
||||||
8 override fun foo(<bold>p: Int</bold>) {
|
8 override fun foo(<bold>p: Int</bold>) {
|
||||||
2 void <bold>foo(int p);</bold>
|
2 void foo(int <bold>p</bold>);
|
||||||
|
13 <bold>foo</bold>(1)
|
||||||
|
22 i.<bold>foo</bold>(3)
|
||||||
13 foo(<bold>1</bold>)
|
13 foo(<bold>1</bold>)
|
||||||
18 i.foo(<bold>2</bold>)
|
18 i.foo(<bold>2</bold>)
|
||||||
|
|||||||
Reference in New Issue
Block a user