Analyze Data Flow: Initial implementation

#KT-11994 In Progress
This commit is contained in:
Alexey Sedunov
2017-05-18 18:27:21 +03:00
parent 3f104833ba
commit 858b454138
92 changed files with 1450 additions and 8 deletions
@@ -248,13 +248,13 @@ class ControlFlowInstructionsGenerator : ControlFlowBuilderAdapter() {
override fun returnValue(returnExpression: KtExpression, returnValue: PseudoValue, subroutine: KtElement) {
val exitPoint = getSubroutineExitPoint(subroutine) ?: return
handleJumpInsideTryFinally(exitPoint)
add(ReturnValueInstruction(returnExpression, currentScope, exitPoint, returnValue))
add(ReturnValueInstruction(returnExpression, currentScope, exitPoint, returnValue, subroutine))
}
override fun returnNoValue(returnExpression: KtReturnExpression, subroutine: KtElement) {
val exitPoint = getSubroutineExitPoint(subroutine) ?: return
handleJumpInsideTryFinally(exitPoint)
add(ReturnNoValueInstruction(returnExpression, currentScope, exitPoint))
add(ReturnNoValueInstruction(returnExpression, currentScope, exitPoint, subroutine))
}
override fun write(
@@ -19,6 +19,8 @@ package org.jetbrains.kotlin.cfg.pseudocode.instructions.eval
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValue
import org.jetbrains.kotlin.cfg.pseudocode.PseudoValueFactory
import org.jetbrains.kotlin.cfg.pseudocode.instructions.*
import org.jetbrains.kotlin.descriptors.CallableDescriptor
import org.jetbrains.kotlin.descriptors.DeclarationDescriptor
import org.jetbrains.kotlin.descriptors.VariableDescriptor
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtNamedDeclaration
@@ -39,6 +41,13 @@ sealed class AccessTarget {
object BlackBox: AccessTarget()
}
val AccessTarget.accessedDescriptor: CallableDescriptor?
get() = when (this) {
is AccessTarget.Declaration -> descriptor
is AccessTarget.Call -> resolvedCall.resultingDescriptor
is AccessTarget.BlackBox -> null
}
abstract class AccessValueInstruction protected constructor(
element: KtElement,
blockScope: BlockScope,
@@ -25,7 +25,8 @@ import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithRe
class ReturnNoValueInstruction(
element: KtElement,
blockScope: BlockScope,
targetLabel: Label
targetLabel: Label,
val subroutine: KtElement
) : AbstractJumpInstruction(element, targetLabel, blockScope) {
override fun accept(visitor: InstructionVisitor) {
visitor.visitReturnNoValue(this)
@@ -38,5 +39,5 @@ class ReturnNoValueInstruction(
override fun toString(): String = "ret $targetLabel"
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction =
ReturnNoValueInstruction(element, blockScope, newLabel)
ReturnNoValueInstruction(element, blockScope, newLabel, subroutine)
}
@@ -23,13 +23,15 @@ import java.util.Collections
import org.jetbrains.kotlin.cfg.pseudocode.instructions.BlockScope
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitor
import org.jetbrains.kotlin.cfg.pseudocode.instructions.InstructionVisitorWithResult
import org.jetbrains.kotlin.psi.KtElement
import org.jetbrains.kotlin.psi.KtReturnExpression
class ReturnValueInstruction(
returnExpression: KtExpression,
blockScope: BlockScope,
targetLabel: Label,
val returnedValue: PseudoValue
val returnedValue: PseudoValue,
val subroutine: KtElement
) : AbstractJumpInstruction(returnExpression, targetLabel, blockScope) {
override val inputValues: List<PseudoValue> get() = Collections.singletonList(returnedValue)
@@ -46,7 +48,7 @@ class ReturnValueInstruction(
}
override fun createCopy(newLabel: Label, blockScope: BlockScope): AbstractJumpInstruction {
return ReturnValueInstruction((element as KtExpression), blockScope, newLabel, returnedValue)
return ReturnValueInstruction((element as KtExpression), blockScope, newLabel, returnedValue, subroutine)
}
val returnExpressionIfAny: KtReturnExpression? = element as? KtReturnExpression
@@ -130,6 +130,7 @@ import org.jetbrains.kotlin.idea.repl.AbstractIdeReplCompletionTest
import org.jetbrains.kotlin.idea.resolve.*
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationHighlightingTest
import org.jetbrains.kotlin.idea.script.AbstractScriptConfigurationNavigationTest
import org.jetbrains.kotlin.idea.slicer.AbstractSlicerTest
import org.jetbrains.kotlin.idea.structureView.AbstractKotlinFileStructureTest
import org.jetbrains.kotlin.idea.stubs.AbstractMultiFileHighlightingTest
import org.jetbrains.kotlin.idea.stubs.AbstractResolveByStubTest
@@ -1022,6 +1023,10 @@ fun main(args: Array<String>) {
testClass<AbstractNameSuggestionProviderTest> {
model("refactoring/nameSuggestionProvider")
}
testClass<AbstractSlicerTest> {
model("slicer", singleClass = true)
}
}
testGroup("idea/idea-maven/test", "idea/idea-maven/testData") {
+2
View File
@@ -810,6 +810,8 @@
<facetType implementation="org.jetbrains.kotlin.idea.facet.KotlinFacetType"/>
<lang.sliceProvider language="kotlin" implementationClass="org.jetbrains.kotlin.idea.slicer.KotlinSliceProvider"/>
<intentionAction>
<className>org.jetbrains.kotlin.idea.intentions.FoldInitializerAndIfToElvisIntention</className>
<category>Kotlin</category>
@@ -64,7 +64,7 @@ class KotlinFindUsagesHandlerFactory(project: Project) : FindUsagesHandlerFactor
return createFindUsagesHandler(element, forHighlightUsages, canAsk = !forHighlightUsages)
}
private fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean, canAsk: Boolean): FindUsagesHandler {
fun createFindUsagesHandler(element: PsiElement, forHighlightUsages: Boolean, canAsk: Boolean): FindUsagesHandler {
val handler = createFindUsagesHandlerNoDecoration(element, canAsk)
return Extensions.getArea(element.project).getExtensionPoint(KotlinFindUsagesHandlerDecorator.EP_NAME).extensions.fold(handler) {
@@ -0,0 +1,36 @@
/*
* Copyright 2010-2017 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.findUsages
import com.intellij.find.findUsages.FindUsagesOptions
import com.intellij.usageView.UsageInfo
import org.jetbrains.kotlin.psi.KtDeclaration
fun KtDeclaration.processAllUsages(
options: () -> FindUsagesOptions,
processor: (UsageInfo) -> Unit
) {
val findUsagesHandler = KotlinFindUsagesHandlerFactory(project).createFindUsagesHandler(this, false, false)
findUsagesHandler.processElementUsages(
this,
{
processor(it)
true
},
options()
)
}
@@ -65,6 +65,7 @@ class KotlinFunctionFindUsagesOptions(project: Project): KotlinCallableFindUsage
}
class KotlinPropertyFindUsagesOptions(project: Project): KotlinCallableFindUsagesOptions, JavaVariableFindUsagesOptions(project) {
var isReadWriteAccess: Boolean = true
override var searchOverrides: Boolean = false
override fun toJavaOptions(project: Project): JavaVariableFindUsagesOptions {
@@ -112,7 +112,7 @@ abstract class KotlinFindMemberUsagesHandler<T : KtNamedDeclaration>
when (access) {
ReadWriteAccessDetector.Access.Read -> kotlinOptions.isReadAccess
ReadWriteAccessDetector.Access.Write -> kotlinOptions.isWriteAccess
ReadWriteAccessDetector.Access.ReadWrite -> true
ReadWriteAccessDetector.Access.ReadWrite -> kotlinOptions.isReadWriteAccess
}
}
}
@@ -0,0 +1,69 @@
/*
* Copyright 2010-2017 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.slicer
import com.intellij.ide.util.treeView.AbstractTreeStructure
import com.intellij.openapi.actionSystem.DefaultActionGroup
import com.intellij.psi.PsiElement
import com.intellij.slicer.SliceAnalysisParams
import com.intellij.slicer.SliceLanguageSupportProvider
import com.intellij.slicer.SliceTreeBuilder
import org.jetbrains.kotlin.idea.references.mainReference
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.isPlainWithEscapes
import org.jetbrains.kotlin.psi.psiUtil.parentsWithSelf
class KotlinSliceProvider : SliceLanguageSupportProvider {
override fun createRootUsage(element: PsiElement, params: SliceAnalysisParams) = KotlinSliceUsage(element, params)
override fun getExpressionAtCaret(atCaret: PsiElement?, dataFlowToThis: Boolean): KtExpression? {
val element =
atCaret?.parentsWithSelf
?.firstOrNull {
it is KtProperty ||
it is KtParameter ||
it is KtFunction ||
(it is KtExpression && it !is KtDeclaration)
}
?.let { KtPsiUtil.safeDeparenthesize(it as KtExpression) } ?: return null
if (dataFlowToThis) {
if (element is KtConstantExpression) return null
if (element is KtStringTemplateExpression && element.isPlainWithEscapes()) return null
if (element is KtClassLiteralExpression) return null
if (element is KtCallableReferenceExpression) return null
}
return element
}
override fun getElementForDescription(element: PsiElement): PsiElement {
return (element as? KtSimpleNameExpression)?.mainReference?.resolve() ?: element
}
override fun getRenderer() = KotlinSliceUsageCellRenderer
override fun startAnalyzeLeafValues(structure: AbstractTreeStructure, finalRunnable: Runnable) {
}
override fun startAnalyzeNullness(structure: AbstractTreeStructure, finalRunnable: Runnable) {
}
override fun registerExtraPanelActions(group: DefaultActionGroup, builder: SliceTreeBuilder) {
}
}
@@ -0,0 +1,42 @@
/*
* Copyright 2010-2017 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.slicer
import com.intellij.psi.PsiElement
import com.intellij.slicer.SliceAnalysisParams
import com.intellij.slicer.SliceUsage
import com.intellij.util.Processor
import org.jetbrains.kotlin.psi.KtExpression
open class KotlinSliceUsage : SliceUsage {
constructor(element: PsiElement, parent: SliceUsage) : super(element, parent)
constructor(element: PsiElement, params: SliceAnalysisParams) : super(element, params)
override fun copy(): KotlinSliceUsage {
val element = usageInfo.element!!
if (parent == null) return KotlinSliceUsage(element, params)
return KotlinSliceUsage(element, parent)
}
public override fun processUsagesFlownDownTo(element: PsiElement, uniqueProcessor: Processor<SliceUsage>) {
InflowSlicer(element as? KtExpression ?: return, uniqueProcessor, this).processChildren()
}
public override fun processUsagesFlownFromThe(element: PsiElement, uniqueProcessor: Processor<SliceUsage>) {
OutflowSlicer(element as? KtExpression ?: return, uniqueProcessor, this).processChildren()
}
}
@@ -0,0 +1,58 @@
/*
* Copyright 2010-2017 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.slicer
import com.intellij.slicer.SliceUsage
import com.intellij.slicer.SliceUsageCellRendererBase
import com.intellij.ui.SimpleTextAttributes
import com.intellij.util.FontUtil
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.util.IdeDescriptorRenderers
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.parents
import org.jetbrains.kotlin.renderer.ParameterNameRenderingPolicy
// Based on com.intellij.slicer.SliceUsageCellRenderer
object KotlinSliceUsageCellRenderer : SliceUsageCellRendererBase() {
private val descriptorRenderer = IdeDescriptorRenderers.SOURCE_CODE_SHORT_NAMES_IN_TYPES.withOptions {
withDefinedIn = true
withoutTypeParameters = true
parameterNameRenderingPolicy = ParameterNameRenderingPolicy.NONE
includeAdditionalModifiers = false
withoutSuperTypes = true
}
override fun customizeCellRendererFor(sliceUsage: SliceUsage) {
if (sliceUsage !is KotlinSliceUsage) return
for ((i, textChunk) in sliceUsage.getText().withIndex()) {
append(textChunk.text, textChunk.simpleAttributesIgnoreBackground)
if (i == 0) {
append(FontUtil.spaceAndThinSpace())
}
}
val declaration = sliceUsage.element?.parents?.firstOrNull {
it is KtClass ||
it is KtObjectDeclaration && !it.isObjectLiteral() ||
it is KtDeclarationWithBody ||
it is KtProperty && it.isLocal
} as? KtDeclaration ?: return
val descriptor = declaration.resolveToDescriptor()
append(" in ${descriptorRenderer.render(descriptor)}", SimpleTextAttributes.GRAY_ATTRIBUTES)
}
}
@@ -0,0 +1,250 @@
/*
* Copyright 2010-2017 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.slicer
import com.intellij.psi.PsiElement
import com.intellij.psi.search.SearchScope
import com.intellij.slicer.SliceUsage
import com.intellij.usageView.UsageInfo
import com.intellij.util.Processor
import org.jetbrains.kotlin.cfg.pseudocode.Pseudocode
import org.jetbrains.kotlin.cfg.pseudocode.containingDeclarationForPseudocode
import org.jetbrains.kotlin.cfg.pseudocode.getContainingPseudocode
import org.jetbrains.kotlin.cfg.pseudocode.instructions.Instruction
import org.jetbrains.kotlin.cfg.pseudocode.instructions.eval.*
import org.jetbrains.kotlin.cfg.pseudocode.instructions.jumps.ReturnValueInstruction
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.TraversalOrder
import org.jetbrains.kotlin.cfg.pseudocodeTraverser.traverse
import org.jetbrains.kotlin.descriptors.PropertyDescriptor
import org.jetbrains.kotlin.descriptors.ValueParameterDescriptor
import org.jetbrains.kotlin.idea.caches.resolve.analyze
import org.jetbrains.kotlin.idea.caches.resolve.analyzeFully
import org.jetbrains.kotlin.idea.caches.resolve.resolveToDescriptor
import org.jetbrains.kotlin.idea.findUsages.KotlinFunctionFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.KotlinPropertyFindUsagesOptions
import org.jetbrains.kotlin.idea.findUsages.processAllUsages
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.*
import org.jetbrains.kotlin.resolve.calls.callUtil.getResolvedCall
import org.jetbrains.kotlin.resolve.calls.model.DefaultValueArgument
import org.jetbrains.kotlin.resolve.calls.model.ExpressionValueArgument
import org.jetbrains.kotlin.resolve.source.getPsi
import java.util.*
private fun KtFunction.processCalls(scope: SearchScope, processor: (UsageInfo) -> Unit) {
processAllUsages(
{
KotlinFunctionFindUsagesOptions(project).apply {
isSearchForTextOccurrences = false
isSkipImportStatements = true
searchScope = scope.intersectWith(useScope)
}
},
processor
)
}
private fun KtDeclaration.processVariableAccesses(scope: SearchScope, isRead: Boolean, processor: (UsageInfo) -> Unit) {
processAllUsages(
{
KotlinPropertyFindUsagesOptions(project).apply {
isReadAccess = isRead
isWriteAccess = !isRead
isReadWriteAccess = false
isSearchForTextOccurrences = false
isSkipImportStatements = true
searchScope = scope.intersectWith(useScope)
}
},
processor
)
}
private fun KtProperty.canProcess(): Boolean {
if (hasDelegate()) return false
if (isLocal) return true
val descriptor = resolveToDescriptor() as? PropertyDescriptor ?: return false
return descriptor.accessors.all { it.isDefault }
}
private fun KtParameter.canProcess(): Boolean {
return !(isLoopParameter || isVarArg || hasValOrVar())
}
abstract class Slicer(
protected val element: KtExpression,
protected val processor: Processor<SliceUsage>,
protected val parentUsage: SliceUsage
) {
protected class PseudocodeCache {
private val computedPseudocodes = HashMap<KtElement, Pseudocode>()
operator fun get(element: KtElement): Pseudocode? {
val container = element.containingDeclarationForPseudocode ?: return null
return computedPseudocodes.getOrPut(container) {
container.getContainingPseudocode(container.analyzeFully())?.apply { computedPseudocodes[container] = this } ?: return null
}
}
}
protected val pseudocodeCache = PseudocodeCache()
protected fun PsiElement.passToProcessor() {
processor.process(KotlinSliceUsage(this, parentUsage))
}
abstract fun processChildren()
}
class InflowSlicer(
element: KtExpression,
processor: Processor<SliceUsage>,
parentUsage: SliceUsage
) : Slicer(element, processor, parentUsage) {
private fun KtProperty.processProperty() {
if (!canProcess()) return
initializer?.passToProcessor()
processVariableAccesses(parentUsage.scope.toSearchScope(), false) body@ {
val refExpression = it.element as? KtExpression ?: return@body
val rhs = KtPsiUtil.safeDeparenthesize(refExpression).getAssignmentByLHS()?.right ?: return@body
rhs.passToProcessor()
}
}
private fun KtParameter.processParameter() {
if (!canProcess()) return
val function = ownerFunction ?: return
if (function.isOverridable()) return
val parameterDescriptor = resolveToDescriptor() as ValueParameterDescriptor
function.processCalls(parentUsage.scope.toSearchScope()) body@ {
val refExpression = it.element as? KtExpression ?: return@body
val callElement = refExpression.getParentOfTypeAndBranch<KtCallElement> { calleeExpression } ?: return@body
val resolvedCall = callElement.getResolvedCall(callElement.analyze()) ?: return@body
val resolvedArgument = resolvedCall.valueArguments[parameterDescriptor] ?: return@body
val flownExpression = when (resolvedArgument) {
is DefaultValueArgument -> defaultValue
is ExpressionValueArgument -> resolvedArgument.valueArgument?.getArgumentExpression()
else -> null
} ?: return@body
flownExpression.passToProcessor()
}
}
private fun KtFunction.processFunction() {
val pseudocode = pseudocodeCache[bodyExpression ?: return] ?: return
pseudocode.traverse(TraversalOrder.FORWARD) { instr ->
if (instr is ReturnValueInstruction && instr.subroutine == this) {
(instr.returnExpressionIfAny?.returnedExpression ?: instr.element as? KtExpression)?.passToProcessor()
}
}
}
private fun Instruction.passInputsToProcessor() {
inputValues.forEach { it.element?.passToProcessor() }
}
private fun KtExpression.processExpression() {
val pseudocode = pseudocodeCache[this] ?: return
val expressionValue = pseudocode.getElementValue(this) ?: return
val createdAt = expressionValue.createdAt
when (createdAt) {
is ReadValueInstruction -> (createdAt.target.accessedDescriptor?.source?.getPsi() as? KtDeclaration)?.passToProcessor()
is MergeInstruction -> createdAt.passInputsToProcessor()
is MagicInstruction -> when (createdAt.kind) {
MagicKind.NOT_NULL_ASSERTION, MagicKind.CAST -> createdAt.passInputsToProcessor()
else -> return
}
is CallInstruction -> (createdAt.resolvedCall.resultingDescriptor.source.getPsi() as? KtDeclarationWithBody)?.passToProcessor()
}
}
override fun processChildren() {
when (element) {
is KtProperty -> element.processProperty()
is KtParameter -> element.processParameter()
is KtFunction -> element.processFunction()
else -> element.processExpression()
}
}
}
class OutflowSlicer(
element: KtExpression,
processor: Processor<SliceUsage>,
parentUsage: SliceUsage
) : Slicer(element, processor, parentUsage) {
private fun KtDeclaration.processVariable() {
when (this) {
is KtProperty -> if (!canProcess()) return
is KtParameter -> if (!canProcess()) return
else -> return
}
processVariableAccesses(parentUsage.scope.toSearchScope(),true) body@ {
val refExpression = (it.element as? KtExpression)?.let { KtPsiUtil.safeDeparenthesize(it) } ?: return@body
refExpression.processExpression()
}
}
private fun PsiElement.getCallElementForExactCallee(): KtElement? {
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, true)) return parentCall
return null
}
private fun KtFunction.processFunctionCalls() {
processCalls(parentUsage.scope.toSearchScope()) {
it.element?.getCallElementForExactCallee()?.passToProcessor()
}
}
private fun KtExpression.processExpression() {
val pseudocode = pseudocodeCache[this] ?: return
val pseudoValue = pseudocode.getElementValue(this) ?: return
pseudocode.getUsages(pseudoValue).forEach { instr ->
when (instr) {
is WriteValueInstruction -> (instr.target.accessedDescriptor?.source?.getPsi() as? KtDeclaration)?.passToProcessor()
is CallInstruction -> instr.arguments[pseudoValue]?.source?.getPsi()?.passToProcessor()
is ReturnValueInstruction -> (instr.owner.correspondingElement as? KtFunction)?.passToProcessor()
is MagicInstruction -> when (instr.kind) {
MagicKind.NOT_NULL_ASSERTION, MagicKind.CAST -> instr.outputValue.element?.passToProcessor()
else -> return
}
}
}
}
override fun processChildren() {
when (element) {
is KtProperty, is KtParameter -> (element as KtDeclaration).processVariable()
is KtFunction -> element.processFunctionCalls()
else -> element.processExpression()
}
}
}
+5
View File
@@ -0,0 +1,5 @@
// FLOW: IN
fun test(o: Any) {
val <caret>x = o as String
}
+4
View File
@@ -0,0 +1,4 @@
4 val <bold>x = o as String</bold>
4 val x = <bold>o as String</bold>
4 val x = <bold>o</bold> as String
3 fun test(<bold>o: Any</bold>) {
+13
View File
@@ -0,0 +1,13 @@
// FLOW: IN
fun foo(<caret>n: Int, s: String = "???") {
}
fun test() {
foo(1)
foo(1, "2")
foo(1, s = "2")
foo(n = 1, s = "2")
foo(s = "2", n = 1)
}
+6
View File
@@ -0,0 +1,6 @@
3 fun foo(<bold>n: Int</bold>, s: String = "???") {
8 foo(<bold>1</bold>)
9 foo(<bold>1</bold>, "2")
10 foo(<bold>1</bold>, s = "2")
11 foo(n = <bold>1</bold>, s = "2")
12 foo(s = "2", n = <bold>1</bold>)
+13
View File
@@ -0,0 +1,13 @@
// FLOW: IN
fun foo(n: Int, <caret>s: String = "???") {
}
fun test() {
foo(1)
foo(1, "2")
foo(1, s = "2")
foo(n = 1, s = "2")
foo(s = "2", n = 1)
}
@@ -0,0 +1,6 @@
3 fun foo(n: Int, <bold>s: String = "???"</bold>) {
3 fun foo(n: Int, s: String = <bold>"???"</bold>) {
9 foo(1, <bold>"2"</bold>)
10 foo(1, s = <bold>"2"</bold>)
11 foo(n = 1, s = <bold>"2"</bold>)
12 foo(s = <bold>"2"</bold>, n = 1)
+3
View File
@@ -0,0 +1,3 @@
// FLOW: IN
fun <caret>foo(n: Int) = n + 1
@@ -0,0 +1,2 @@
3 fun <bold>foo(n: Int) = n + 1</bold>
3 fun foo(n: Int) = <bold>n + 1</bold>
@@ -0,0 +1,6 @@
// FLOW: IN
fun <caret>foo(n: Int): Int {
if (n > 0) return n
return -n
}
@@ -0,0 +1,4 @@
3 fun <bold>foo(n: Int): Int {</bold>
4 if (n > 0) return <bold>n</bold>
3 fun foo(<bold>n: Int</bold>): Int {
5 return <bold>-n</bold>
+5
View File
@@ -0,0 +1,5 @@
// FLOW: IN
fun test(m: Int, n: Int) {
val <caret>x = if (m > 1) n else 1
}
+5
View File
@@ -0,0 +1,5 @@
4 val <bold>x = if (m > 1) n else 1</bold>
4 val x = <bold>if (m > 1) n else 1</bold>
4 val x = if (m > 1) <bold>n</bold> else 1
3 fun test(m: Int, <bold>n: Int</bold>) {
4 val x = if (m > 1) n else <bold>1</bold>
+6
View File
@@ -0,0 +1,6 @@
// FLOW: IN
fun test(n: Int) {
val <caret>x = n
val y = x
}
+3
View File
@@ -0,0 +1,3 @@
4 val <bold>x = n</bold>
4 val x = <bold>n</bold>
3 fun test(<bold>n: Int</bold>) {
+7
View File
@@ -0,0 +1,7 @@
// FLOW: IN
fun test(n: Int) {
var <caret>x = n
val y = x
x = 0
}
+4
View File
@@ -0,0 +1,4 @@
4 var <bold>x = n</bold>
4 var x = <bold>n</bold>
3 fun test(<bold>n: Int</bold>) {
6 x = <bold>0</bold>
+10
View File
@@ -0,0 +1,10 @@
// FLOW: IN
class A {
val <caret>x: Int = 1
val y = x
fun test() {
val y = x
}
}
@@ -0,0 +1,2 @@
4 val <bold>x: Int = 1</bold>
4 val x: Int = <bold>1</bold>
@@ -0,0 +1,15 @@
// FLOW: IN
class A {
val <caret>x: Int
init {
x = 1
}
val y = x
fun test() {
val y = x
}
}
@@ -0,0 +1,2 @@
4 val <bold>x: Int</bold>
7 x = <bold>1</bold>
+11
View File
@@ -0,0 +1,11 @@
// FLOW: IN
class A {
var <caret>x: Int = 1
val y = x
fun test() {
val y = x
x = 2
}
}
@@ -0,0 +1,3 @@
4 var <bold>x: Int = 1</bold>
4 var x: Int = <bold>1</bold>
9 x = <bold>2</bold>
@@ -0,0 +1,16 @@
// FLOW: IN
class A {
var <caret>x: Int
init {
x = 1
}
val y = x
fun test() {
val y = x
x = 2
}
}
@@ -0,0 +1,3 @@
4 var <bold>x: Int</bold>
7 x = <bold>1</bold>
14 x = <bold>2</bold>
+5
View File
@@ -0,0 +1,5 @@
// FLOW: IN
fun test(s: String?) {
val <caret>x = s!!
}
@@ -0,0 +1,4 @@
4 val <bold>x = s!!</bold>
4 val x = <bold>s!!</bold>
4 val x = <bold>s</bold>!!
3 fun test(<bold>s: String?</bold>) {
@@ -0,0 +1,17 @@
// FLOW: IN
open class A(<caret>n: Int, s: String = "???")
class B1: A(1)
class B2: A(1, "2")
class B3: A(1, s = "2")
class B4: A(n = 1, s = "2")
class B5: A(s = "2", n = 1)
fun test() {
A(1)
A(1, "2")
A(1, s = "2")
A(n = 1, s = "2")
A(s = "2", n = 1)
}
@@ -0,0 +1,11 @@
3 open class A(<bold>n: Int</bold>, s: String = "???")
5 class B1: A(<bold>1</bold>)
6 class B2: A(<bold>1</bold>, "2")
7 class B3: A(<bold>1</bold>, s = "2")
8 class B4: A(n = <bold>1</bold>, s = "2")
9 class B5: A(s = "2", n = <bold>1</bold>)
12 A(<bold>1</bold>)
13 A(<bold>1</bold>, "2")
14 A(<bold>1</bold>, s = "2")
15 A(n = <bold>1</bold>, s = "2")
16 A(s = "2", n = <bold>1</bold>)
@@ -0,0 +1,17 @@
// FLOW: IN
open class A(n: Int, <caret>s: String = "???")
class B1: A(1)
class B2: A(1, "2")
class B3: A(1, s = "2")
class B4: A(n = 1, s = "2")
class B5: A(s = "2", n = 1)
fun test() {
A(1)
A(1, "2")
A(1, s = "2")
A(n = 1, s = "2")
A(s = "2", n = 1)
}
@@ -0,0 +1,10 @@
3 open class A(n: Int, <bold>s: String = "???"</bold>)
3 open class A(n: Int, s: String = <bold>"???"</bold>)
6 class B2: A(1, <bold>"2"</bold>)
7 class B3: A(1, s = <bold>"2"</bold>)
8 class B4: A(n = 1, s = <bold>"2"</bold>)
9 class B5: A(s = <bold>"2"</bold>, n = 1)
13 A(1, <bold>"2"</bold>)
14 A(1, s = <bold>"2"</bold>)
15 A(n = 1, s = <bold>"2"</bold>)
16 A(s = <bold>"2"</bold>, n = 1)
+5
View File
@@ -0,0 +1,5 @@
// FLOW: IN
fun test(o: Any) {
val <caret>x = o as? String
}
+4
View File
@@ -0,0 +1,4 @@
4 val <bold>x = o as? String</bold>
4 val x = <bold>o as? String</bold>
4 val x = <bold>o</bold> as? String
3 fun test(<bold>o: Any</bold>) {
@@ -0,0 +1,19 @@
// FLOW: IN
open class A {
constructor(<caret>n: Int, s: String = "???")
}
class B1: A(1)
class B2: A(1, "2")
class B3: A(1, s = "2")
class B4: A(n = 1, s = "2")
class B5: A(s = "2", n = 1)
fun test() {
A(1)
A(1, "2")
A(1, s = "2")
A(n = 1, s = "2")
A(s = "2", n = 1)
}
@@ -0,0 +1,11 @@
4 constructor(<bold>n: Int</bold>, s: String = "???")
7 class B1: A(<bold>1</bold>)
8 class B2: A(<bold>1</bold>, "2")
9 class B3: A(<bold>1</bold>, s = "2")
10 class B4: A(n = <bold>1</bold>, s = "2")
11 class B5: A(s = "2", n = <bold>1</bold>)
14 A(<bold>1</bold>)
15 A(<bold>1</bold>, "2")
16 A(<bold>1</bold>, s = "2")
17 A(n = <bold>1</bold>, s = "2")
18 A(s = "2", n = <bold>1</bold>)
@@ -0,0 +1,19 @@
// FLOW: IN
open class A {
constructor(n: Int, <caret>s: String = "???")
}
class B1: A(1)
class B2: A(1, "2")
class B3: A(1, s = "2")
class B4: A(n = 1, s = "2")
class B5: A(s = "2", n = 1)
fun test() {
A(1)
A(1, "2")
A(1, s = "2")
A(n = 1, s = "2")
A(s = "2", n = 1)
}
@@ -0,0 +1,10 @@
4 constructor(n: Int, <bold>s: String = "???"</bold>)
4 constructor(n: Int, s: String = <bold>"???"</bold>)
8 class B2: A(1, <bold>"2"</bold>)
9 class B3: A(1, s = <bold>"2"</bold>)
10 class B4: A(n = 1, s = <bold>"2"</bold>)
11 class B5: A(s = <bold>"2"</bold>, n = 1)
15 A(1, <bold>"2"</bold>)
16 A(1, s = <bold>"2"</bold>)
17 A(n = 1, s = <bold>"2"</bold>)
18 A(s = <bold>"2"</bold>, n = 1)
+7
View File
@@ -0,0 +1,7 @@
// FLOW: IN
val <caret>foo: Int = 1
fun test() {
val x = foo
}
+2
View File
@@ -0,0 +1,2 @@
3 val <bold>foo: Int = 1</bold>
3 val foo: Int = <bold>1</bold>
+8
View File
@@ -0,0 +1,8 @@
// FLOW: IN
var <caret>foo: Int = 1
fun test() {
val x = foo
foo = 2
}
+3
View File
@@ -0,0 +1,3 @@
3 var <bold>foo: Int = 1</bold>
3 var foo: Int = <bold>1</bold>
7 foo = <bold>2</bold>
+9
View File
@@ -0,0 +1,9 @@
// FLOW: IN
fun test(m: Int, n: Int) {
val <caret>x = when (m) {
1 -> 1
2 -> n
else -> 0
}
}
@@ -0,0 +1,6 @@
4 val <bold>x = when (m) {</bold>
4 val x = <bold>when (m) {</bold>
5 1 -> <bold>1</bold>
6 2 -> <bold>n</bold>
3 fun test(m: Int, <bold>n: Int</bold>) {
7 else -> <bold>0</bold>
+10
View File
@@ -0,0 +1,10 @@
// FLOW: OUT
fun foo(n: Int) {
val y = n
}
fun test() {
val x = <caret>1
foo(x)
}
+4
View File
@@ -0,0 +1,4 @@
7 val x = <bold>1</bold>
7 val <bold>x = 1</bold>
2 fun foo(<bold>n: Int</bold>) {
3 val <bold>y = n</bold>
+6
View File
@@ -0,0 +1,6 @@
// FLOW: OUT
fun test(<caret>o: Any) {
val x = o as String
val y = o as? String
}
+5
View File
@@ -0,0 +1,5 @@
3 fun test(<bold>o: Any</bold>) {
4 val x = <bold>o as String</bold>
4 val <bold>x = o as String</bold>
5 val y = <bold>o as? String</bold>
5 val <bold>y = o as? String</bold>
+7
View File
@@ -0,0 +1,7 @@
// FLOW: OUT
fun foo(n: Int): Int = <caret>n
fun test() {
val x = foo(1)
}
@@ -0,0 +1,4 @@
3 fun foo(n: Int): Int = <bold>n</bold>
3 fun <bold>foo(n: Int): Int = n</bold>
6 val x = <bold>foo(1)</bold>
6 val <bold>x = foo(1)</bold>
+14
View File
@@ -0,0 +1,14 @@
// FLOW: OUT
fun foo(<caret>n: Int) {
val x = n
val y: Int
y = n
bar(n)
}
fun bar(m: Int) {
}
@@ -0,0 +1,4 @@
3 fun foo(<bold>n: Int</bold>) {
4 val <bold>x = n</bold>
6 val <bold>y: Int</bold>
12 fun bar(<bold>m: Int</bold>) {
+9
View File
@@ -0,0 +1,9 @@
// FLOW: OUT
fun foo(n: Int): Int {
return <caret>n
}
fun test() {
val x = foo(1)
}
@@ -0,0 +1,4 @@
4 return <bold>n</bold>
3 fun <bold>foo(n: Int): Int {</bold>
8 val x = <bold>foo(1)</bold>
8 val <bold>x = foo(1)</bold>
+9
View File
@@ -0,0 +1,9 @@
// FLOW: OUT
fun <caret>foo(n: Int) {
}
fun test(m: Int) {
val x = foo(1)
}
@@ -0,0 +1,3 @@
3 fun <bold>foo(n: Int) {</bold>
8 val x = <bold>foo(1)</bold>
8 val <bold>x = foo(1)</bold>
+9
View File
@@ -0,0 +1,9 @@
// FLOW: OUT
class A {
operator fun <caret>get(n: Int) = this
}
fun test() {
val x = A()[2]
}
+3
View File
@@ -0,0 +1,3 @@
4 operator fun <bold>get(n: Int) = this</bold>
8 val x = <bold>A()[2]</bold>
8 val <bold>x = A()[2]</bold>
+5
View File
@@ -0,0 +1,5 @@
// FLOW: OUT
fun test(m: Int, <caret>n: Int) {
val x = if (m > 1) n else 1
}
+2
View File
@@ -0,0 +1,2 @@
3 fun test(m: Int, <bold>n: Int</bold>) {
4 val <bold>x = if (m > 1) n else 1</bold>
+14
View File
@@ -0,0 +1,14 @@
// FLOW: OUT
fun foo(n: Int) {
}
fun test() {
val <caret>x = 1
val y = x
val z: Int
z = x
foo(x)
}
@@ -0,0 +1,4 @@
6 val <bold>x = 1</bold>
8 val <bold>y = x</bold>
10 val <bold>z: Int</bold>
2 fun foo(<bold>n: Int</bold>) {
+19
View File
@@ -0,0 +1,19 @@
// FLOW: OUT
class A {
val <caret>x = 1
val y = x
val z: Int
init {
z = x
bar(x)
}
fun bar(m: Int) {
}
}
@@ -0,0 +1,4 @@
4 val <bold>x = 1</bold>
6 val <bold>y = x</bold>
8 val <bold>z: Int</bold>
16 fun bar(<bold>m: Int</bold>) {
+5
View File
@@ -0,0 +1,5 @@
// FLOW: OUT
fun test(<caret>s: String?) {
val x = s!!
}
@@ -0,0 +1,3 @@
3 fun test(<bold>s: String?</bold>) {
4 val x = <bold>s!!</bold>
4 val <bold>x = s!!</bold>
+9
View File
@@ -0,0 +1,9 @@
// FLOW: OUT
class A {
operator fun <caret>plus(n: Int) = this
}
fun test() {
val x = A() + 2
}
@@ -0,0 +1,3 @@
4 operator fun <bold>plus(n: Int) = this</bold>
8 val x = <bold>A() + 2</bold>
8 val <bold>x = A() + 2</bold>
+15
View File
@@ -0,0 +1,15 @@
// FLOW: OUT
open class A<caret>(n: Int) {
constructor() : this(1)
}
class B : A(1)
class C : A {
constructor() : super(1)
}
fun test() {
val x = A(1)
}
@@ -0,0 +1,6 @@
3 open class A<bold>(n: Int)</bold> {
7 class B : <bold>A(1)</bold>
14 val x = <bold>A(1)</bold>
14 val <bold>x = A(1)</bold>
4 constructor() : <bold>this(1)</bold>
10 constructor() : <bold>super(1)</bold>
@@ -0,0 +1,17 @@
// FLOW: OUT
class A(<caret>n: Int) {
val x = n
val y: Int
init {
y = n
bar(n)
}
fun bar(m: Int) {
}
}
@@ -0,0 +1,4 @@
3 class A(<bold>n: Int</bold>) {
4 val <bold>x = n</bold>
6 val <bold>y: Int</bold>
14 fun bar(<bold>m: Int</bold>) {
@@ -0,0 +1,17 @@
// FLOW: OUT
open class A {
<caret>constructor(n: Int)
constructor() : this(1)
}
class B : A(1)
class C : A {
constructor() : super(1)
}
fun test() {
val x = A(1)
}
@@ -0,0 +1,6 @@
4 <bold>constructor(n: Int)</bold>
9 class B : <bold>A(1)</bold>
16 val x = <bold>A(1)</bold>
16 val <bold>x = A(1)</bold>
6 constructor() : <bold>this(1)</bold>
12 constructor() : <bold>super(1)</bold>
+21
View File
@@ -0,0 +1,21 @@
// FLOW: OUT
val <caret>x = 1
val y = x
fun test() {
val y = x
val z: Int
init {
z = x
bar(x)
}
}
fun bar(m: Int) {
}
@@ -0,0 +1,5 @@
3 val <bold>x = 1</bold>
5 val <bold>y = x</bold>
8 val <bold>y = x</bold>
10 val <bold>z: Int</bold>
19 fun bar(<bold>m: Int</bold>) {
+9
View File
@@ -0,0 +1,9 @@
// FLOW: OUT
fun test(m: Int, <caret>n: Int) {
val x = when (m) {
1 -> 1
2 -> n
else -> 0
}
}
@@ -0,0 +1,2 @@
3 fun test(m: Int, <bold>n: Int</bold>) {
4 val <bold>x = when (m) {</bold>
@@ -0,0 +1,119 @@
/*
* Copyright 2010-2017 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.slicer
import com.intellij.analysis.AnalysisScope
import com.intellij.openapi.util.io.FileUtil
import com.intellij.psi.PsiElement
import com.intellij.slicer.SliceAnalysisParams
import com.intellij.slicer.SliceUsage
import com.intellij.usages.TextChunk
import com.intellij.util.CommonProcessors
import gnu.trove.TObjectHashingStrategy
import org.jetbrains.kotlin.idea.test.KotlinLightCodeInsightFixtureTestCase
import org.jetbrains.kotlin.idea.util.application.runReadAction
import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.test.InTextDirectivesUtils
import org.jetbrains.kotlin.test.KotlinTestUtils
import java.awt.Font
import java.io.File
abstract class AbstractSlicerTest : KotlinLightCodeInsightFixtureTestCase() {
object SliceUsageHashingStrategy : TObjectHashingStrategy<SliceUsage> {
override fun computeHashCode(`object`: SliceUsage) = `object`.usageInfo.hashCode()
override fun equals(o1: SliceUsage, o2: SliceUsage) = o1.usageInfo == o2.usageInfo
}
// Based on SliceUsage.processChildren
private fun KotlinSliceUsage.processChildrenWithoutProgress(processor: (KotlinSliceUsage) -> Unit) {
val element = runReadAction { element }
val uniqueProcessor = CommonProcessors.UniqueProcessor(
{
processor(it as KotlinSliceUsage)
true
},
SliceUsageHashingStrategy
)
runReadAction {
if (params.dataFlowToThis) {
processUsagesFlownDownTo(element, uniqueProcessor)
}
else {
processUsagesFlownFromThe(element, uniqueProcessor)
}
}
}
private fun buildTreeRepresentation(rootUsage: KotlinSliceUsage): String {
val visitedElements = HashSet<PsiElement>()
fun TextChunk.render(): String {
var text = text
if (attributes.fontType == Font.BOLD) {
text = "<bold>$text</bold>"
}
return text
}
fun process(usage: KotlinSliceUsage, indent: Int): String {
val isDuplicated = !visitedElements.add(usage.element)
return buildString {
val chunks = usage.text
append(chunks.first().render() + " ")
append("\t".repeat(indent))
chunks.slice(1..chunks.size - 1).joinTo(
this,
separator = "",
prefix = if (isDuplicated) "DUPLICATE: " else "",
postfix = "\n"
) { it.render() }
if (!isDuplicated) {
usage.processChildrenWithoutProgress { append(process(it, indent + 1)) }
}
}.replace(Regex("</bold><bold>"), "")
}
return process(rootUsage, 0)
}
protected fun doTest(path: String) {
val mainFile = File(path)
myFixture.testDataPath = "${KotlinTestUtils.getHomeDirectory()}/${mainFile.parent}"
val fileText = FileUtil.loadFile(mainFile, true)
val flowKind = InTextDirectivesUtils.findStringWithPrefixes(fileText, "// FLOW: ")
val analysisParams = SliceAnalysisParams().apply {
dataFlowToThis = when (flowKind) {
"IN" -> true
"OUT" -> false
else -> throw AssertionError("Invalid flow kind: $flowKind")
}
scope = AnalysisScope(project)
}
val file = myFixture.configureByFile(mainFile.name) as KtFile
val elementAtCaret = file.findElementAt(editor.caretModel.offset)
val sliceProvider = KotlinSliceProvider()
val expression = sliceProvider.getExpressionAtCaret(elementAtCaret, analysisParams.dataFlowToThis)!!
val rootUsage = sliceProvider.createRootUsage(expression, analysisParams)
KotlinTestUtils.assertEqualsToFile(File(path.replace(".kt", ".results.txt")), buildTreeRepresentation(rootUsage))
}
}
@@ -0,0 +1,266 @@
/*
* Copyright 2010-2017 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.slicer;
import com.intellij.testFramework.TestDataPath;
import org.jetbrains.kotlin.test.JUnit3RunnerWithInners;
import org.jetbrains.kotlin.test.KotlinTestUtils;
import org.jetbrains.kotlin.test.TargetBackend;
import org.jetbrains.kotlin.test.TestMetadata;
import org.junit.runner.RunWith;
import java.io.File;
import java.util.regex.Pattern;
/** This class is generated by {@link org.jetbrains.kotlin.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("idea/testData/slicer")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public class SlicerTestGenerated extends AbstractSlicerTest {
public void testAllFilesPresentInSlicer() throws Exception {
KotlinTestUtils.assertAllTestsPresentInSingleGeneratedClass(this.getClass(), new File("idea/testData/slicer"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY);
}
@TestMetadata("inflow/cast.kt")
public void testInflow_Cast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/cast.kt");
doTest(fileName);
}
@TestMetadata("inflow/funParamerer.kt")
public void testInflow_FunParamerer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funParamerer.kt");
doTest(fileName);
}
@TestMetadata("inflow/funParamererWithDefault.kt")
public void testInflow_FunParamererWithDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funParamererWithDefault.kt");
doTest(fileName);
}
@TestMetadata("inflow/funWithExpressionBody.kt")
public void testInflow_FunWithExpressionBody() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funWithExpressionBody.kt");
doTest(fileName);
}
@TestMetadata("inflow/funWithReturnExpressions.kt")
public void testInflow_FunWithReturnExpressions() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/funWithReturnExpressions.kt");
doTest(fileName);
}
@TestMetadata("inflow/ifExpression.kt")
public void testInflow_IfExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/ifExpression.kt");
doTest(fileName);
}
@TestMetadata("inflow/localVal.kt")
public void testInflow_LocalVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/localVal.kt");
doTest(fileName);
}
@TestMetadata("inflow/localVar.kt")
public void testInflow_LocalVar() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/localVar.kt");
doTest(fileName);
}
@TestMetadata("inflow/memberValWithInitializer.kt")
public void testInflow_MemberValWithInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberValWithInitializer.kt");
doTest(fileName);
}
@TestMetadata("inflow/memberValWithSplitInitializer.kt")
public void testInflow_MemberValWithSplitInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberValWithSplitInitializer.kt");
doTest(fileName);
}
@TestMetadata("inflow/memberVarWithInitializer.kt")
public void testInflow_MemberVarWithInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberVarWithInitializer.kt");
doTest(fileName);
}
@TestMetadata("inflow/memberVarWithSplitInitializer.kt")
public void testInflow_MemberVarWithSplitInitializer() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/memberVarWithSplitInitializer.kt");
doTest(fileName);
}
@TestMetadata("inflow/notNullAssertion.kt")
public void testInflow_NotNullAssertion() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/notNullAssertion.kt");
doTest(fileName);
}
@TestMetadata("inflow/primaryConstructorParameter.kt")
public void testInflow_PrimaryConstructorParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/primaryConstructorParameter.kt");
doTest(fileName);
}
@TestMetadata("inflow/primaryConstructorParameterWithDefault.kt")
public void testInflow_PrimaryConstructorParameterWithDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/primaryConstructorParameterWithDefault.kt");
doTest(fileName);
}
@TestMetadata("inflow/safeCast.kt")
public void testInflow_SafeCast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/safeCast.kt");
doTest(fileName);
}
@TestMetadata("inflow/secondaryConstructorParameter.kt")
public void testInflow_SecondaryConstructorParameter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/secondaryConstructorParameter.kt");
doTest(fileName);
}
@TestMetadata("inflow/secondaryConstructorParameterWithDefault.kt")
public void testInflow_SecondaryConstructorParameterWithDefault() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/secondaryConstructorParameterWithDefault.kt");
doTest(fileName);
}
@TestMetadata("inflow/topLevelVal.kt")
public void testInflow_TopLevelVal() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/topLevelVal.kt");
doTest(fileName);
}
@TestMetadata("inflow/topLevelVar.kt")
public void testInflow_TopLevelVar() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/topLevelVar.kt");
doTest(fileName);
}
@TestMetadata("inflow/whenExpression.kt")
public void testInflow_WhenExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/inflow/whenExpression.kt");
doTest(fileName);
}
@TestMetadata("outflow/callArgument.kt")
public void testOutflow_CallArgument() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/callArgument.kt");
doTest(fileName);
}
@TestMetadata("outflow/cast.kt")
public void testOutflow_Cast() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/cast.kt");
doTest(fileName);
}
@TestMetadata("outflow/funBodyExpression.kt")
public void testOutflow_FunBodyExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/funBodyExpression.kt");
doTest(fileName);
}
@TestMetadata("outflow/functionCalls.kt")
public void testOutflow_FunctionCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/functionCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/funParameterUsages.kt")
public void testOutflow_FunParameterUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/funParameterUsages.kt");
doTest(fileName);
}
@TestMetadata("outflow/funReturnExpression.kt")
public void testOutflow_FunReturnExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/funReturnExpression.kt");
doTest(fileName);
}
@TestMetadata("outflow/getFunCalls.kt")
public void testOutflow_GetFunCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/getFunCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/ifExpression.kt")
public void testOutflow_IfExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/ifExpression.kt");
doTest(fileName);
}
@TestMetadata("outflow/localVariableUsages.kt")
public void testOutflow_LocalVariableUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/localVariableUsages.kt");
doTest(fileName);
}
@TestMetadata("outflow/memberPropertyUsages.kt")
public void testOutflow_MemberPropertyUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/memberPropertyUsages.kt");
doTest(fileName);
}
@TestMetadata("outflow/notNullAssertion.kt")
public void testOutflow_NotNullAssertion() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/notNullAssertion.kt");
doTest(fileName);
}
@TestMetadata("outflow/operatorFunCalls.kt")
public void testOutflow_OperatorFunCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/operatorFunCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/primaryConstructorCalls.kt")
public void testOutflow_PrimaryConstructorCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/primaryConstructorCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/primaryConstructorParameterUsages.kt")
public void testOutflow_PrimaryConstructorParameterUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/primaryConstructorParameterUsages.kt");
doTest(fileName);
}
@TestMetadata("outflow/secondaryConstructorCalls.kt")
public void testOutflow_SecondaryConstructorCalls() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/secondaryConstructorCalls.kt");
doTest(fileName);
}
@TestMetadata("outflow/topLevelPropertyUsages.kt")
public void testOutflow_TopLevelPropertyUsages() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/topLevelPropertyUsages.kt");
doTest(fileName);
}
@TestMetadata("outflow/whenExpression.kt")
public void testOutflow_WhenExpression() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("idea/testData/slicer/outflow/whenExpression.kt");
doTest(fileName);
}
}