added 'mergeDataWithLocalDeclarations' option

for collecting variable data for pseudocode

  removed using data from outer context
  for local declarations for 'variable initializers' analysis
This commit is contained in:
Svetlana Isakova
2014-03-05 19:42:05 +04:00
parent eed3dec539
commit fbbfb95861
19 changed files with 332 additions and 103 deletions
@@ -261,6 +261,7 @@ public class JetFlowInformationProvider {
PseudocodeVariablesData pseudocodeVariablesData = getPseudocodeVariablesData();
Map<Instruction, Edges<Map<VariableDescriptor,VariableInitState>>> initializers = pseudocodeVariablesData.getVariableInitializers();
final Set<VariableDescriptor> declaredVariables = pseudocodeVariablesData.getDeclaredVariables(pseudocode, true);
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariablesData.getLexicalScopeVariableInfo();
final Map<Instruction, DiagnosticFactory> reportedDiagnosticMap = Maps.newHashMap();
@@ -272,7 +273,7 @@ public class JetFlowInformationProvider {
@Nullable Map<VariableDescriptor, VariableInitState> in,
@Nullable Map<VariableDescriptor, VariableInitState> out) {
assert in != null && out != null;
VariableInitContext ctxt = new VariableInitContext(instruction, reportedDiagnosticMap, in, out, declaredVariables);
VariableInitContext ctxt = new VariableInitContext(instruction, reportedDiagnosticMap, in, out, lexicalScopeVariableInfo);
if (ctxt.variableDescriptor == null) return;
if (instruction instanceof ReadValueInstruction) {
JetElement element = ((ReadValueInstruction) instruction).getElement();
@@ -847,22 +848,22 @@ public class JetFlowInformationProvider {
@NotNull Map<Instruction, DiagnosticFactory> map,
@NotNull Map<VariableDescriptor, VariableInitState> in,
@NotNull Map<VariableDescriptor, VariableInitState> out,
@NotNull Set<VariableDescriptor> declaredVariables
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
) {
super(instruction, map);
enterInitState = initialize(variableDescriptor, declaredVariables, in);
exitInitState = initialize(variableDescriptor, declaredVariables, out);
enterInitState = initialize(variableDescriptor, lexicalScopeVariableInfo, in);
exitInitState = initialize(variableDescriptor, lexicalScopeVariableInfo, out);
}
private VariableInitState initialize(
VariableDescriptor variableDescriptor,
Set<VariableDescriptor> declaredVariables,
LexicalScopeVariableInfo lexicalScopeVariableInfo,
Map<VariableDescriptor, VariableInitState> map
) {
if (variableDescriptor == null) return null;
VariableInitState state = map.get(variableDescriptor);
if (state != null) return state;
return PseudocodeVariablesData.getDefaultValueForInitializers(declaredVariables, variableDescriptor);
return PseudocodeVariablesData.getDefaultValueForInitializers(variableDescriptor, instruction, lexicalScopeVariableInfo);
}
}
@@ -44,15 +44,6 @@ fun Instruction.getPreviousInstructions(traversalOrder: TraversalOrder): Collect
fun Instruction.isStartInstruction(traversalOrder: TraversalOrder): Boolean =
if (traversalOrder == FORWARD) this is SubroutineEnterInstruction else this is SubroutineSinkInstruction
enum class LookInsideStrategy {
ANALYSE_LOCAL_DECLARATIONS
SKIP_LOCAL_DECLARATIONS
}
fun Instruction.shouldLookInside(lookInside: LookInsideStrategy): Boolean =
lookInside == LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS && this is LocalFunctionDeclarationInstruction
fun Pseudocode.traverse(
traversalOrder: TraversalOrder,
analyzeInstruction: (Instruction) -> Unit
@@ -29,6 +29,7 @@ import org.jetbrains.jet.utils.addToStdlib.*
import kotlin.properties.Delegates
import java.util.*
import org.jetbrains.jet.lang.psi.JetDeclaration
public class PseudocodeVariableDataCollector(
private val bindingContext: BindingContext,
@@ -39,16 +40,19 @@ public class PseudocodeVariableDataCollector(
suppress("UNCHECKED_CAST")
public fun <D> collectDataJ(
traversalOrder: TraversalOrder,
mergeDataWithLocalDeclarations: Boolean,
instructionDataMergeStrategy: InstructionDataMergeStrategy<MutableMap<VariableDescriptor, D>>
): MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>> {
//see KT-4605
return collectData(
traversalOrder, instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
traversalOrder, mergeDataWithLocalDeclarations,
instructionDataMergeStrategy as InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
) as MutableMap<Instruction, Edges<MutableMap<VariableDescriptor, D>>>
}
public fun <D> collectData(
traversalOrder: TraversalOrder,
mergeDataWithLocalDeclarations: Boolean,
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>
): Map<Instruction, Edges<Map<VariableDescriptor, D>>> {
val initialDataValue : Map<VariableDescriptor, D> = Collections.emptyMap<VariableDescriptor, D>()
@@ -61,7 +65,7 @@ public class PseudocodeVariableDataCollector(
while (changed[0]) {
changed[0] = false
collectDataFromSubgraph(
pseudocode, traversalOrder, LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS, edgesMap,
pseudocode, traversalOrder, mergeDataWithLocalDeclarations, edgesMap,
instructionDataMergeStrategy, Collections.emptyList<Instruction>(), changed, false)
}
return edgesMap
@@ -76,8 +80,8 @@ public class PseudocodeVariableDataCollector(
val initialEdge = Edges(initialDataValue, initialDataValue)
for (instruction in instructions) {
edgesMap.put(instruction, initialEdge)
if (instruction.shouldLookInside(LookInsideStrategy.ANALYSE_LOCAL_DECLARATIONS)) {
initializeEdgesMap((instruction as LocalFunctionDeclarationInstruction).getBody(), edgesMap, initialDataValue)
if (instruction is LocalFunctionDeclarationInstruction) {
initializeEdgesMap(instruction.getBody(), edgesMap, initialDataValue)
}
}
}
@@ -85,7 +89,7 @@ public class PseudocodeVariableDataCollector(
private fun <D> collectDataFromSubgraph(
pseudocode: Pseudocode,
traversalOrder: TraversalOrder,
lookInside: LookInsideStrategy,
mergeDataWithLocalDeclarations: Boolean,
edgesMap: MutableMap<Instruction, Edges<Map<VariableDescriptor, D>>>,
instructionDataMergeStrategy: InstructionDataMergeStrategy<Map<VariableDescriptor, D>>,
previousSubGraphInstructions: Collection<Instruction>,
@@ -121,20 +125,22 @@ public class PseudocodeVariableDataCollector(
}
}
if (instruction.shouldLookInside(lookInside)) {
val functionInstruction = (instruction as LocalFunctionDeclarationInstruction)
val subroutinePseudocode = functionInstruction.getBody()
if (instruction is LocalFunctionDeclarationInstruction) {
val subroutinePseudocode = instruction.getBody()
val previous = if (mergeDataWithLocalDeclarations) previousInstructions else Collections.emptyList()
collectDataFromSubgraph(
subroutinePseudocode, traversalOrder, lookInside, edgesMap, instructionDataMergeStrategy,
previousInstructions, changed, true)
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
val previousValue = edgesMap.get(instruction)
val newValue = edgesMap.get(lastInstruction)
val updatedValue = if (newValue == null) null else
Edges(filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`),
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out))
updateEdgeDataForInstruction(previousValue, updatedValue)
continue
subroutinePseudocode, traversalOrder, mergeDataWithLocalDeclarations,
edgesMap, instructionDataMergeStrategy, previous, changed, true)
if (mergeDataWithLocalDeclarations) {
val lastInstruction = subroutinePseudocode.getLastInstruction(traversalOrder)
val previousValue = edgesMap.get(instruction)
val newValue = edgesMap.get(lastInstruction)
val updatedValue = if (newValue == null) null else
Edges(filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.`in`),
filterOutVariablesOutOfScope(lastInstruction, instruction, newValue.out))
updateEdgeDataForInstruction(previousValue, updatedValue)
continue
}
}
val previousDataValue = edgesMap.get(instruction)
@@ -62,6 +62,11 @@ public class PseudocodeVariablesData {
return pseudocode;
}
@NotNull
public LexicalScopeVariableInfo getLexicalScopeVariableInfo() {
return pseudocodeVariableDataCollector.getLexicalScopeVariableInfo();
}
@NotNull
public Set<VariableDescriptor> getUsedVariables(@NotNull Pseudocode pseudocode) {
Set<VariableDescriptor> usedVariables = usedVariablesForDeclaration.get(pseudocode);
@@ -139,10 +144,10 @@ public class PseudocodeVariablesData {
@NotNull
private Map<Instruction, Edges<Map<VariableDescriptor, VariableInitState>>> computeVariableInitializers() {
final Set<VariableDescriptor> declaredVariables = getDeclaredVariables(pseudocode, true);
final LexicalScopeVariableInfo lexicalScopeVariableInfo = pseudocodeVariableDataCollector.getLexicalScopeVariableInfo();
return pseudocodeVariableDataCollector.collectDataJ(
FORWARD,
FORWARD, /*mergeDataWithLocalDeclarations=*/ false,
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableInitState>>() {
@NotNull
@Override
@@ -153,8 +158,8 @@ public class PseudocodeVariablesData {
Map<VariableDescriptor, VariableInitState> enterInstructionData =
mergeIncomingEdgesDataForInitializers(incomingEdgesData);
Map<VariableDescriptor, VariableInitState> exitInstructionData =
addVariableInitStateFromCurrentInstructionIfAny(instruction, enterInstructionData, declaredVariables);
Map<VariableDescriptor, VariableInitState> exitInstructionData = addVariableInitStateFromCurrentInstructionIfAny(
instruction, enterInstructionData, lexicalScopeVariableInfo);
return createEdges(enterInstructionData, exitInstructionData);
}
}
@@ -162,12 +167,16 @@ public class PseudocodeVariablesData {
}
public static VariableInitState getDefaultValueForInitializers(
@NotNull Set<VariableDescriptor> declaredVariables,
@NotNull VariableDescriptor variable
@NotNull VariableDescriptor variable,
@NotNull Instruction instruction,
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
) {
//todo: think of replacing it with "MapWithDefaultValue"
boolean isInitialized = !declaredVariables.contains(variable);
return VariableInitState.create(isInitialized);
LexicalScope declaredIn = lexicalScopeVariableInfo.getDeclaredIn().get(variable);
boolean declaredOutsideThisDeclaration =
declaredIn == null //declared outside this pseudocode
|| declaredIn.getLexicalScopeForContainingDeclaration() != instruction.getLexicalScope().getLexicalScopeForContainingDeclaration();
return VariableInitState.create(/*isInitialized=*/declaredOutsideThisDeclaration);
}
@NotNull
@@ -203,7 +212,7 @@ public class PseudocodeVariablesData {
private Map<VariableDescriptor, VariableInitState> addVariableInitStateFromCurrentInstructionIfAny(
@NotNull Instruction instruction,
@NotNull Map<VariableDescriptor, VariableInitState> enterInstructionData,
@NotNull Set<VariableDescriptor> declaredVariables
@NotNull LexicalScopeVariableInfo lexicalScopeVariableInfo
) {
if (!(instruction instanceof WriteValueInstruction) && !(instruction instanceof VariableDeclarationInstruction)) {
return enterInstructionData;
@@ -222,7 +231,7 @@ public class PseudocodeVariablesData {
else { // instruction instanceof VariableDeclarationInstruction
VariableInitState enterInitState = enterInstructionData.get(variable);
if (enterInitState == null) {
enterInitState = getDefaultValueForInitializers(declaredVariables, variable);
enterInitState = getDefaultValueForInitializers(variable, instruction, lexicalScopeVariableInfo);
}
if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) {
boolean isInitialized = enterInitState != null && enterInitState.isInitialized;
@@ -238,7 +247,7 @@ public class PseudocodeVariablesData {
@NotNull
public Map<Instruction, Edges<Map<VariableDescriptor, VariableUseState>>> getVariableUseStatusData() {
return pseudocodeVariableDataCollector.collectDataJ(
BACKWARD,
BACKWARD, /*mergeDataWithLocalDeclarations=*/ true,
new InstructionDataMergeStrategy<Map<VariableDescriptor, VariableUseState>>() {
@NotNull
@Override
@@ -17,9 +17,23 @@
package org.jetbrains.jet.lang.cfg.pseudocode
import org.jetbrains.jet.lang.psi.JetElement
import org.jetbrains.jet.lang.psi.JetDeclaration
import kotlin.properties.Delegates
public class LexicalScope(val parentScope: LexicalScope?, val element: JetElement) {
//todo remove after KT-4126
private val _d = (parentScope?.depth ?: 0) + 1
val depth: Int get() = _d
val lexicalScopeForContainingDeclaration: LexicalScope? by Delegates.lazy { computeLexicalScopeForContainingDeclaration() }
private fun computeLexicalScopeForContainingDeclaration(): LexicalScope? {
var scope: LexicalScope? = this
while (scope != null) {
if (scope?.element is JetDeclaration) {
return scope
}
scope = scope?.parentScope
}
return null
}
}
@@ -34,25 +34,25 @@ sink:
}
---------------------
L3:
3 <START> INIT: in: {a=ID, f=D} out: {a=ID, f=D}
v(x: Int) INIT: in: {a=ID, f=D} out: {a=ID, f=D, x=D}
w(x) INIT: in: {a=ID, f=D, x=D} out: {a=ID, f=D, x=ID}
4 mark(val y = x + a use(a)) INIT: in: {a=ID, f=D, x=ID} out: {a=ID, f=D, x=ID}
v(val y = x + a) INIT: in: {a=ID, f=D, x=ID} out: {a=ID, f=D, x=ID, y=D}
mark(x + a) INIT: in: {a=ID, f=D, x=ID, y=D} out: {a=ID, f=D, x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ}
r(x) USE: in: {a=READ} out: {a=READ, x=READ}
3 <START> INIT: in: {} out: {}
v(x: Int) INIT: in: {} out: {x=D}
w(x) INIT: in: {x=D} out: {x=ID}
4 mark(val y = x + a use(a)) INIT: in: {x=ID} out: {x=ID}
v(val y = x + a) INIT: in: {x=ID} out: {x=ID, y=D}
mark(x + a) INIT: in: {x=ID, y=D} out: {x=ID, y=D} USE: in: {a=READ, x=READ} out: {a=READ, x=READ}
r(x) USE: in: {a=READ} out: {a=READ, x=READ}
r(a)
call(+, plus)
w(y) INIT: in: {a=ID, f=D, x=ID, y=D} out: {a=ID, f=D, x=ID, y=ID}
mark(use(a)) INIT: in: {a=ID, f=D, x=ID, y=ID} out: {a=ID, f=D, x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
r(a) USE: in: {} out: {a=READ}
w(y) INIT: in: {x=ID, y=D} out: {x=ID, y=ID}
mark(use(a)) INIT: in: {x=ID, y=ID} out: {x=ID, y=ID} USE: in: {a=READ} out: {a=READ}
r(a) USE: in: {} out: {a=READ}
call(use, use)
L4:
3 <END> INIT: in: {a=ID, f=D, x=ID} out: {a=ID, f=D, x=ID}
3 <END> INIT: in: {x=ID} out: {x=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {a=ID, f=D, x=ID} out: {a=ID, f=D, x=ID} USE: in: {} out: {}
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
=====================
== use ==
fun use(vararg a: Any?) = a
@@ -0,0 +1,135 @@
== TestFunctionLiteral ==
class TestFunctionLiteral {
val sum: (Int)->Int = { (x: Int) ->
sum(x - 1) + x
}
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(val sum: (Int)->Int = { (x: Int) -> sum(x - 1) + x }) INIT: in: {} out: {sum=D}
mark({ (x: Int) -> sum(x - 1) + x }) INIT: in: {sum=D} out: {sum=D}
jmp?(L2)
d({ (x: Int) -> sum(x - 1) + x }) USE: in: {sum=READ} out: {sum=READ}
L2:
r({ (x: Int) -> sum(x - 1) + x })
w(sum) INIT: in: {sum=D} out: {sum=ID}
L1:
<END> INIT: in: {sum=ID} out: {sum=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {sum=D} out: {sum=D} USE: in: {} out: {}
=====================
== anonymous_0 ==
{ (x: Int) ->
sum(x - 1) + x
}
---------------------
L3:
2 <START> INIT: in: {} out: {}
v(x: Int) INIT: in: {} out: {x=D}
w(x) INIT: in: {x=D} out: {x=ID}
3 mark(sum(x - 1) + x) INIT: in: {x=ID} out: {x=ID}
mark(sum(x - 1) + x)
mark(sum(x - 1)) USE: in: {sum=READ, x=READ} out: {sum=READ, x=READ}
r(sum) USE: in: {x=READ} out: {sum=READ, x=READ}
mark(x - 1)
r(x)
r(1)
call(-, minus)
call(sum, invoke) USE: in: {x=READ} out: {x=READ}
r(x) USE: in: {} out: {x=READ}
call(+, plus)
L4:
2 <END>
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
=====================
== A ==
open class A(val a: A)
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(val a: A) INIT: in: {} out: {a=D}
w(a) INIT: in: {a=D} out: {a=ID}
L1:
<END> INIT: in: {a=ID} out: {a=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {a=ID} out: {a=ID} USE: in: {} out: {}
=====================
== TestObjectLiteral ==
class TestObjectLiteral {
val obj: A = object: A(obj) {
{
val x = obj
}
fun foo() {
val y = obj
}
}
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(val obj: A = object: A(obj) { { val x = obj } fun foo() { val y = obj } }) INIT: in: {} out: {obj=D}
mark(object: A(obj) { { val x = obj } fun foo() { val y = obj } }) INIT: in: {obj=D} out: {obj=D}
r(obj)
2 mark({ val x = obj })
v(val x = obj) INIT: in: {obj=D} out: {obj=D, x=D}
r(obj) INIT: in: {obj=D, x=D} out: {obj=D, x=D}
w(x) INIT: in: {obj=D, x=D} out: {obj=D, x=ID}
1 jmp?(L2) INIT: in: {obj=D} out: {obj=D}
d(fun foo() { val y = obj }) USE: in: {obj=READ} out: {obj=READ}
L2:
r(object: A(obj) { { val x = obj } fun foo() { val y = obj } })
w(obj) INIT: in: {obj=D} out: {obj=ID}
L1:
<END> INIT: in: {obj=ID} out: {obj=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {obj=D} out: {obj=D} USE: in: {} out: {}
=====================
== foo ==
fun foo() {
val y = obj
}
---------------------
L3:
2 <START> INIT: in: {} out: {}
3 mark({ val y = obj })
v(val y = obj) INIT: in: {} out: {y=D} USE: in: {obj=READ} out: {obj=READ}
r(obj) INIT: in: {y=D} out: {y=D} USE: in: {} out: {obj=READ}
w(y) INIT: in: {y=D} out: {y=ID}
L4:
2 <END> INIT: in: {} out: {}
error:
<ERROR>
sink:
<SINK> USE: in: {} out: {}
=====================
== TestOther ==
class TestOther {
val x: Int = x + 1
}
---------------------
L0:
1 <START> INIT: in: {} out: {}
v(val x: Int = x + 1) INIT: in: {} out: {x=D}
mark(x + 1) INIT: in: {x=D} out: {x=D} USE: in: {x=READ} out: {x=READ}
r(x) USE: in: {} out: {x=READ}
r(1)
call(+, plus)
w(x) INIT: in: {x=D} out: {x=ID}
L1:
<END> INIT: in: {x=ID} out: {x=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
=====================
@@ -0,0 +1,22 @@
class TestFunctionLiteral {
val sum: (Int)->Int = { (x: Int) ->
sum(x - 1) + x
}
}
open class A(val a: A)
class TestObjectLiteral {
val obj: A = object: A(obj) {
{
val x = obj
}
fun foo() {
val y = obj
}
}
}
class TestOther {
val x: Int = x + 1
}
@@ -38,20 +38,20 @@ sink:
}
---------------------
L3:
3 <START> INIT: in: {b=ID, f=D} out: {b=ID, f=D}
v(x: Int) INIT: in: {b=ID, f=D} out: {b=ID, f=D, x=D}
w(x) INIT: in: {b=ID, f=D, x=D} out: {b=ID, f=D, x=ID}
4 mark(val a = x + b) INIT: in: {b=ID, f=D, x=ID} out: {b=ID, f=D, x=ID}
v(val a = x + b) INIT: in: {b=ID, f=D, x=ID} out: {a=D, b=ID, f=D, x=ID}
mark(x + b) INIT: in: {a=D, b=ID, f=D, x=ID} out: {a=D, b=ID, f=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ}
r(x) USE: in: {b=READ} out: {b=READ, x=READ}
r(b) USE: in: {} out: {b=READ}
3 <START> INIT: in: {} out: {}
v(x: Int) INIT: in: {} out: {x=D}
w(x) INIT: in: {x=D} out: {x=ID}
4 mark(val a = x + b) INIT: in: {x=ID} out: {x=ID}
v(val a = x + b) INIT: in: {x=ID} out: {a=D, x=ID}
mark(x + b) INIT: in: {a=D, x=ID} out: {a=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ}
r(x) USE: in: {b=READ} out: {b=READ, x=READ}
r(b) USE: in: {} out: {b=READ}
call(+, plus)
w(a) INIT: in: {a=D, b=ID, f=D, x=ID} out: {a=ID, b=ID, f=D, x=ID}
w(a) INIT: in: {a=D, x=ID} out: {a=ID, x=ID}
L4:
3 <END> INIT: in: {b=ID, f=D, x=ID} out: {b=ID, f=D, x=ID}
3 <END> INIT: in: {x=ID} out: {x=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {b=ID, f=D, x=ID} out: {b=ID, f=D, x=ID} USE: in: {} out: {}
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
=====================
@@ -41,15 +41,15 @@ fun foo() {
}
---------------------
L3:
3 <START> INIT: in: {x=ID} out: {x=ID}
3 <START> INIT: in: {} out: {}
4 mark({ val b = x })
v(val b = x) INIT: in: {x=ID} out: {b=D, x=ID} USE: in: {x=READ} out: {x=READ}
r(x) INIT: in: {b=D, x=ID} out: {b=D, x=ID} USE: in: {} out: {x=READ}
w(b) INIT: in: {b=D, x=ID} out: {b=ID, x=ID}
v(val b = x) INIT: in: {} out: {b=D} USE: in: {x=READ} out: {x=READ}
r(x) INIT: in: {b=D} out: {b=D} USE: in: {} out: {x=READ}
w(b) INIT: in: {b=D} out: {b=ID}
L4:
3 <END> INIT: in: {x=ID} out: {x=ID}
3 <END> INIT: in: {} out: {}
error:
<ERROR> INIT: in: {} out: {}
<ERROR>
sink:
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
<SINK> USE: in: {} out: {}
=====================
@@ -34,20 +34,20 @@ fun local(x: Int) {
}
---------------------
L3:
3 <START> INIT: in: {b=ID} out: {b=ID}
v(x: Int) INIT: in: {b=ID} out: {b=ID, x=D}
w(x) INIT: in: {b=ID, x=D} out: {b=ID, x=ID}
4 mark({ val a = x + b }) INIT: in: {b=ID, x=ID} out: {b=ID, x=ID}
v(val a = x + b) INIT: in: {b=ID, x=ID} out: {a=D, b=ID, x=ID}
mark(x + b) INIT: in: {a=D, b=ID, x=ID} out: {a=D, b=ID, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ}
r(x) USE: in: {b=READ} out: {b=READ, x=READ}
r(b) USE: in: {} out: {b=READ}
3 <START> INIT: in: {} out: {}
v(x: Int) INIT: in: {} out: {x=D}
w(x) INIT: in: {x=D} out: {x=ID}
4 mark({ val a = x + b }) INIT: in: {x=ID} out: {x=ID}
v(val a = x + b) INIT: in: {x=ID} out: {a=D, x=ID}
mark(x + b) INIT: in: {a=D, x=ID} out: {a=D, x=ID} USE: in: {b=READ, x=READ} out: {b=READ, x=READ}
r(x) USE: in: {b=READ} out: {b=READ, x=READ}
r(b) USE: in: {} out: {b=READ}
call(+, plus)
w(a) INIT: in: {a=D, b=ID, x=ID} out: {a=ID, b=ID, x=ID}
w(a) INIT: in: {a=D, x=ID} out: {a=ID, x=ID}
L4:
3 <END> INIT: in: {b=ID, x=ID} out: {b=ID, x=ID}
3 <END> INIT: in: {x=ID} out: {x=ID}
error:
<ERROR> INIT: in: {} out: {}
sink:
<SINK> INIT: in: {b=ID, x=ID} out: {b=ID, x=ID} USE: in: {} out: {}
<SINK> INIT: in: {x=ID} out: {x=ID} USE: in: {} out: {}
=====================
@@ -43,15 +43,15 @@ fun foo() {
}
---------------------
L3:
3 <START> INIT: in: {bar=D} out: {bar=D}
3 <START> INIT: in: {} out: {}
4 mark({ val a = 2 })
v(val a = 2) INIT: in: {bar=D} out: {a=D, bar=D}
r(2) INIT: in: {a=D, bar=D} out: {a=D, bar=D}
w(a) INIT: in: {a=D, bar=D} out: {a=ID, bar=D}
v(val a = 2) INIT: in: {} out: {a=D}
r(2) INIT: in: {a=D} out: {a=D}
w(a) INIT: in: {a=D} out: {a=ID}
L4:
3 <END> INIT: in: {bar=D} out: {bar=D}
3 <END> INIT: in: {} out: {}
error:
<ERROR> INIT: in: {} out: {}
<ERROR>
sink:
<SINK> INIT: in: {bar=D} out: {bar=D} USE: in: {} out: {}
<SINK> USE: in: {} out: {}
=====================
@@ -0,0 +1,32 @@
// !DIAGNOSTICS: -UNUSED_VARIABLE
package o
class TestFunctionLiteral {
val sum: (Int) -> Int = { (x: Int) ->
sum(x - 1) + x
}
val foo: () -> Unit = @l ({ foo() })
}
open class A(val a: A)
class TestObjectLiteral {
val obj: A = object: A(<!UNINITIALIZED_VARIABLE!>obj<!>) {
{
val x = <!UNINITIALIZED_VARIABLE!>obj<!>
}
fun foo() {
val y = obj
}
}
val obj1: A = @l ( object: A(<!UNINITIALIZED_VARIABLE!>obj1<!>) {
{
val x = <!UNINITIALIZED_VARIABLE!>obj1<!>
}
fun foo() = obj1
})
}
class TestOther {
val x: Int = <!UNINITIALIZED_VARIABLE!>x<!> + 1
}
@@ -31,7 +31,7 @@ import org.jetbrains.jet.cfg.AbstractDataFlowTest;
/** This class is generated by {@link org.jetbrains.jet.generators.tests.TestsPackage}. DO NOT MODIFY MANUALLY */
@SuppressWarnings("all")
@TestMetadata("compiler/testData/cfg-variables")
@InnerTestClasses({DataFlowTestGenerated.Basic.class, DataFlowTestGenerated.LexicalScopes.class})
@InnerTestClasses({DataFlowTestGenerated.Basic.class, DataFlowTestGenerated.Bugs.class, DataFlowTestGenerated.LexicalScopes.class})
public class DataFlowTestGenerated extends AbstractDataFlowTest {
public void testAllFilesPresentInCfg_variables() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg-variables"), Pattern.compile("^(.+)\\.kt$"), true);
@@ -58,16 +58,6 @@ public class DataFlowTestGenerated extends AbstractDataFlowTest {
doTest("compiler/testData/cfg-variables/basic/UsageInFunctionLiteral.kt");
}
@TestMetadata("varInitializationInIf.kt")
public void testVarInitializationInIf() throws Exception {
doTest("compiler/testData/cfg-variables/basic/varInitializationInIf.kt");
}
@TestMetadata("varInitializationInIfInCycle.kt")
public void testVarInitializationInIfInCycle() throws Exception {
doTest("compiler/testData/cfg-variables/basic/varInitializationInIfInCycle.kt");
}
@TestMetadata("VariablesInitialization.kt")
public void testVariablesInitialization() throws Exception {
doTest("compiler/testData/cfg-variables/basic/VariablesInitialization.kt");
@@ -80,6 +70,29 @@ public class DataFlowTestGenerated extends AbstractDataFlowTest {
}
@TestMetadata("compiler/testData/cfg-variables/bugs")
public static class Bugs extends AbstractDataFlowTest {
public void testAllFilesPresentInBugs() throws Exception {
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), "org.jetbrains.jet.generators.tests.TestsPackage", new File("compiler/testData/cfg-variables/bugs"), Pattern.compile("^(.+)\\.kt$"), true);
}
@TestMetadata("referenceToPropertyInitializer.kt")
public void testReferenceToPropertyInitializer() throws Exception {
doTest("compiler/testData/cfg-variables/bugs/referenceToPropertyInitializer.kt");
}
@TestMetadata("varInitializationInIf.kt")
public void testVarInitializationInIf() throws Exception {
doTest("compiler/testData/cfg-variables/bugs/varInitializationInIf.kt");
}
@TestMetadata("varInitializationInIfInCycle.kt")
public void testVarInitializationInIfInCycle() throws Exception {
doTest("compiler/testData/cfg-variables/bugs/varInitializationInIfInCycle.kt");
}
}
@TestMetadata("compiler/testData/cfg-variables/lexicalScopes")
public static class LexicalScopes extends AbstractDataFlowTest {
public void testAllFilesPresentInLexicalScopes() throws Exception {
@@ -152,6 +165,7 @@ public class DataFlowTestGenerated extends AbstractDataFlowTest {
TestSuite suite = new TestSuite("DataFlowTestGenerated");
suite.addTestSuite(DataFlowTestGenerated.class);
suite.addTestSuite(Basic.class);
suite.addTestSuite(Bugs.class);
suite.addTestSuite(LexicalScopes.class);
return suite;
}
@@ -1673,6 +1673,11 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/propertiesOrderInPackage.kt");
}
@TestMetadata("referenceToPropertyInitializer.kt")
public void testReferenceToPropertyInitializer() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/referenceToPropertyInitializer.kt");
}
@TestMetadata("repeatUnitializedErrorOnlyForLocalVars.kt")
public void testRepeatUnitializedErrorOnlyForLocalVars() throws Exception {
doTest("compiler/testData/diagnostics/tests/controlFlowAnalysis/repeatUnitializedErrorOnlyForLocalVars.kt");