More precise value reassignment analysis. #KT-7418 Fixed. #KT-6902 Fixed.
Variable can now be "exactly initialized", "may be initialized" and "not initialized". A set of relevant tests. Some fixed tests.
This commit is contained in:
@@ -372,14 +372,14 @@ public class JetFlowInformationProvider {
|
||||
if (!(element instanceof JetSimpleNameExpression)) return;
|
||||
|
||||
|
||||
boolean isInitialized = ctxt.exitInitState.isInitialized;
|
||||
boolean isDefinitelyInitialized = ctxt.exitInitState.definitelyInitialized();
|
||||
VariableDescriptor variableDescriptor = ctxt.variableDescriptor;
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) {
|
||||
isInitialized = true;
|
||||
isDefinitelyInitialized = true;
|
||||
}
|
||||
}
|
||||
if (!isInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
|
||||
if (!isDefinitelyInitialized && !varWithUninitializedErrorGenerated.contains(variableDescriptor)) {
|
||||
if (!(variableDescriptor instanceof PropertyDescriptor)) {
|
||||
varWithUninitializedErrorGenerated.add(variableDescriptor);
|
||||
}
|
||||
@@ -412,7 +412,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isInitializedNotHere = ctxt.enterInitState.isInitialized;
|
||||
boolean mayBeInitializedNotHere = ctxt.enterInitState.mayBeInitialized();
|
||||
boolean hasBackingField = true;
|
||||
if (variableDescriptor instanceof PropertyDescriptor) {
|
||||
hasBackingField = trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor);
|
||||
@@ -437,7 +437,7 @@ public class JetFlowInformationProvider {
|
||||
}
|
||||
boolean isThisOrNoDispatchReceiver =
|
||||
PseudocodeUtil.isThisOrNoDispatchReceiver(writeValueInstruction, trace.getBindingContext());
|
||||
if ((isInitializedNotHere || !hasBackingField || !isThisOrNoDispatchReceiver) && !variableDescriptor.isVar()) {
|
||||
if ((mayBeInitializedNotHere || !hasBackingField || !isThisOrNoDispatchReceiver) && !variableDescriptor.isVar()) {
|
||||
boolean hasReassignMethodReturningUnit = false;
|
||||
JetSimpleNameExpression operationReference = null;
|
||||
PsiElement parent = expression.getParent();
|
||||
@@ -483,7 +483,7 @@ public class JetFlowInformationProvider {
|
||||
|
||||
private boolean checkAssignmentBeforeDeclaration(@NotNull VariableInitContext ctxt, @NotNull JetExpression expression) {
|
||||
if (!ctxt.enterInitState.isDeclared && !ctxt.exitInitState.isDeclared
|
||||
&& !ctxt.enterInitState.isInitialized && ctxt.exitInitState.isInitialized) {
|
||||
&& !ctxt.enterInitState.mayBeInitialized() && ctxt.exitInitState.mayBeInitialized()) {
|
||||
report(Errors.INITIALIZATION_BEFORE_DECLARATION.on(expression, ctxt.variableDescriptor), ctxt);
|
||||
return true;
|
||||
}
|
||||
@@ -492,7 +492,8 @@ public class JetFlowInformationProvider {
|
||||
|
||||
private boolean checkInitializationUsingBackingField(@NotNull VariableInitContext ctxt, @NotNull JetExpression expression) {
|
||||
VariableDescriptor variableDescriptor = ctxt.variableDescriptor;
|
||||
if (variableDescriptor instanceof PropertyDescriptor && !ctxt.enterInitState.isInitialized && ctxt.exitInitState.isInitialized) {
|
||||
if (variableDescriptor instanceof PropertyDescriptor
|
||||
&& !ctxt.enterInitState.mayBeInitialized() && ctxt.exitInitState.mayBeInitialized()) {
|
||||
if (!variableDescriptor.isVar()) return false;
|
||||
if (!trace.get(BindingContext.BACKING_FIELD_REQUIRED, (PropertyDescriptor) variableDescriptor)) return false;
|
||||
PsiElement property = DescriptorToSourceUtils.descriptorToDeclaration(variableDescriptor);
|
||||
@@ -590,7 +591,7 @@ public class JetFlowInformationProvider {
|
||||
for (VariableDescriptor variable : declaredVariables) {
|
||||
if (variable instanceof PropertyDescriptor) {
|
||||
PseudocodeVariablesData.VariableInitState variableInitState = initializers.getIncoming().get(variable);
|
||||
if (variableInitState != null && variableInitState.isInitialized) continue;
|
||||
if (variableInitState != null && variableInitState.definitelyInitialized()) continue;
|
||||
trace.record(BindingContext.IS_UNINITIALIZED, (PropertyDescriptor) variable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -155,7 +155,7 @@ public class PseudocodeVariablesData {
|
||||
boolean declaredOutsideThisDeclaration =
|
||||
declaredIn == null //declared outside this pseudocode
|
||||
|| declaredIn.getLexicalScopeForContainingDeclaration() != instruction.getLexicalScope().getLexicalScopeForContainingDeclaration();
|
||||
return VariableInitState.create(/*isInitialized=*/declaredOutsideThisDeclaration);
|
||||
return VariableInitState.create(/*initState=*/declaredOutsideThisDeclaration);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@@ -169,20 +169,21 @@ public class PseudocodeVariablesData {
|
||||
|
||||
Map<VariableDescriptor, VariableInitState> enterInstructionData = Maps.newHashMap();
|
||||
for (VariableDescriptor variable : variablesInScope) {
|
||||
boolean isInitialized = true;
|
||||
TriInitState initState = null;
|
||||
boolean isDeclared = true;
|
||||
for (Map<VariableDescriptor, VariableInitState> edgeData : incomingEdgesData) {
|
||||
VariableInitState initState = edgeData.get(variable);
|
||||
if (initState != null) {
|
||||
if (!initState.isInitialized) {
|
||||
isInitialized = false;
|
||||
}
|
||||
if (!initState.isDeclared) {
|
||||
VariableInitState varControlFlowState = edgeData.get(variable);
|
||||
if (varControlFlowState != null) {
|
||||
initState = initState != null ? initState.merge(varControlFlowState.initState) : varControlFlowState.initState;
|
||||
if (!varControlFlowState.isDeclared) {
|
||||
isDeclared = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
enterInstructionData.put(variable, VariableInitState.create(isInitialized, isDeclared));
|
||||
if (initState == null) {
|
||||
throw new AssertionError("An empty set of incoming edges data");
|
||||
}
|
||||
enterInstructionData.put(variable, VariableInitState.create(initState, isDeclared));
|
||||
}
|
||||
return enterInstructionData;
|
||||
}
|
||||
@@ -217,8 +218,8 @@ public class PseudocodeVariablesData {
|
||||
if (enterInitState == null) {
|
||||
enterInitState = getDefaultValueForInitializers(variable, instruction, lexicalScopeVariableInfo);
|
||||
}
|
||||
if (enterInitState == null || !enterInitState.isInitialized || !enterInitState.isDeclared) {
|
||||
boolean isInitialized = enterInitState != null && enterInitState.isInitialized;
|
||||
if (enterInitState == null || !enterInitState.mayBeInitialized() || !enterInitState.isDeclared) {
|
||||
boolean isInitialized = enterInitState != null && enterInitState.mayBeInitialized();
|
||||
VariableInitState variableDeclarationInfo = VariableInitState.create(isInitialized, true);
|
||||
exitInstructionData.put(variable, variableDeclarationInfo);
|
||||
}
|
||||
@@ -279,28 +280,54 @@ public class PseudocodeVariablesData {
|
||||
);
|
||||
}
|
||||
|
||||
private enum TriInitState {
|
||||
INITIALIZED("I"), UNKNOWN("I?"), NOT_INITIALIZED("");
|
||||
|
||||
private final String s;
|
||||
|
||||
TriInitState(String s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
private TriInitState merge(@NotNull TriInitState other) {
|
||||
if (this == other) return this;
|
||||
return UNKNOWN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return s;
|
||||
}
|
||||
}
|
||||
|
||||
public static class VariableInitState {
|
||||
public final boolean isInitialized;
|
||||
|
||||
public final TriInitState initState;
|
||||
public final boolean isDeclared;
|
||||
|
||||
private VariableInitState(boolean isInitialized, boolean isDeclared) {
|
||||
this.isInitialized = isInitialized;
|
||||
private VariableInitState(TriInitState initState, boolean isDeclared) {
|
||||
this.initState = initState;
|
||||
this.isDeclared = isDeclared;
|
||||
}
|
||||
|
||||
private static final VariableInitState VS_TT = new VariableInitState(true, true);
|
||||
private static final VariableInitState VS_TF = new VariableInitState(true, false);
|
||||
private static final VariableInitState VS_FT = new VariableInitState(false, true);
|
||||
private static final VariableInitState VS_FF = new VariableInitState(false, false);
|
||||
private static final VariableInitState VS_IT = new VariableInitState(TriInitState.INITIALIZED, true);
|
||||
private static final VariableInitState VS_IF = new VariableInitState(TriInitState.INITIALIZED, false);
|
||||
private static final VariableInitState VS_UT = new VariableInitState(TriInitState.UNKNOWN, true);
|
||||
private static final VariableInitState VS_UF = new VariableInitState(TriInitState.UNKNOWN, false);
|
||||
private static final VariableInitState VS_NT = new VariableInitState(TriInitState.NOT_INITIALIZED, true);
|
||||
private static final VariableInitState VS_NF = new VariableInitState(TriInitState.NOT_INITIALIZED, false);
|
||||
|
||||
|
||||
private static VariableInitState create(TriInitState initState, boolean isDeclared) {
|
||||
switch (initState) {
|
||||
case INITIALIZED: return isDeclared ? VS_IT : VS_IF;
|
||||
case UNKNOWN: return isDeclared ? VS_UT : VS_UF;
|
||||
default: return isDeclared ? VS_NT : VS_NF;
|
||||
}
|
||||
}
|
||||
|
||||
private static VariableInitState create(boolean isInitialized, boolean isDeclared) {
|
||||
if (isInitialized) {
|
||||
if (isDeclared) return VS_TT;
|
||||
return VS_TF;
|
||||
}
|
||||
if (isDeclared) return VS_FT;
|
||||
return VS_FF;
|
||||
return create(isInitialized ? TriInitState.INITIALIZED : TriInitState.NOT_INITIALIZED, isDeclared);
|
||||
}
|
||||
|
||||
private static VariableInitState create(boolean isInitialized) {
|
||||
@@ -311,14 +338,22 @@ public class PseudocodeVariablesData {
|
||||
return create(true, isDeclaredHere || (mergedEdgesData != null && mergedEdgesData.isDeclared));
|
||||
}
|
||||
|
||||
public boolean definitelyInitialized() {
|
||||
return initState == TriInitState.INITIALIZED;
|
||||
}
|
||||
|
||||
public boolean mayBeInitialized() {
|
||||
return initState != TriInitState.NOT_INITIALIZED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (!isInitialized && !isDeclared) return "-";
|
||||
return (isInitialized ? "I" : "") + (isDeclared ? "D" : "");
|
||||
if (initState == TriInitState.NOT_INITIALIZED && !isDeclared) return "-";
|
||||
return initState + (isDeclared ? "D" : "");
|
||||
}
|
||||
}
|
||||
|
||||
public static enum VariableUseState {
|
||||
public enum VariableUseState {
|
||||
READ(3),
|
||||
WRITTEN_AFTER_READ(2),
|
||||
ONLY_WRITTEN_NEVER_READ(1),
|
||||
|
||||
@@ -10,7 +10,7 @@ fun foo() {
|
||||
}
|
||||
---------------------
|
||||
L0:
|
||||
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
|
||||
1 <START> INIT: in: {} out: {} USE: in: {} out: {}
|
||||
2 mark({ val b: Boolean if (1 < 2) { use(b) } else { b = true } })
|
||||
v(val b: Boolean) INIT: in: {} out: {b=D}
|
||||
mark(if (1 < 2) { use(b) } else { b = true }) INIT: in: {b=D} out: {b=D}
|
||||
@@ -19,23 +19,23 @@ L0:
|
||||
mark(1 < 2)
|
||||
call(1 < 2, compareTo|<v0>, <v1>) -> <v2>
|
||||
jf(L2|<v2>)
|
||||
3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ}
|
||||
r(b) -> <v3> USE: in: {} out: {b=READ}
|
||||
3 mark({ use(b) }) USE: in: {b=READ} out: {b=READ}
|
||||
r(b) -> <v3> USE: in: {} out: {b=READ}
|
||||
mark(use(b))
|
||||
call(use(b), use|<v3>) -> <v4>
|
||||
2 jmp(L3) USE: in: {} out: {}
|
||||
2 jmp(L3) USE: in: {} out: {}
|
||||
L2 [else branch]:
|
||||
3 mark({ b = true })
|
||||
r(true) -> <v5> USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ}
|
||||
w(b|<v5>) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ}
|
||||
r(true) -> <v5> USE: in: {b=ONLY_WRITTEN_NEVER_READ} out: {b=ONLY_WRITTEN_NEVER_READ}
|
||||
w(b|<v5>) INIT: in: {b=D} out: {b=ID} USE: in: {} out: {b=ONLY_WRITTEN_NEVER_READ}
|
||||
L3 ['if' expression result]:
|
||||
2 merge(if (1 < 2) { use(b) } else { b = true }|<v4>, !<v6>) -> <v7> INIT: in: {b=D} out: {b=D}
|
||||
2 merge(if (1 < 2) { use(b) } else { b = true }|<v4>, !<v6>) -> <v7> INIT: in: {b=I?D} out: {b=I?D}
|
||||
L1:
|
||||
1 <END> INIT: in: {} out: {}
|
||||
error:
|
||||
<ERROR>
|
||||
sink:
|
||||
<SINK> USE: in: {} out: {}
|
||||
<SINK> USE: in: {} out: {}
|
||||
=====================
|
||||
== use ==
|
||||
fun use(vararg a: Any?) = a
|
||||
|
||||
+3
-3
@@ -10,7 +10,7 @@ L0:
|
||||
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}
|
||||
d({ (x: Int) -> sum(x - 1) + x }) USE: in: {sum=READ} out: {sum=READ}
|
||||
L2 [after local declaration]:
|
||||
r({ (x: Int) -> sum(x - 1) + x }) -> <v0>
|
||||
w(sum|<v0>) INIT: in: {sum=D} out: {sum=ID}
|
||||
@@ -19,7 +19,7 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {sum=D} out: {sum=D} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {sum=I?D} out: {sum=I?D} USE: in: {} out: {}
|
||||
=====================
|
||||
== anonymous_0 ==
|
||||
{ (x: Int) ->
|
||||
@@ -101,7 +101,7 @@ L1:
|
||||
error:
|
||||
<ERROR> INIT: in: {} out: {}
|
||||
sink:
|
||||
<SINK> INIT: in: {obj=D} out: {obj=D} USE: in: {} out: {}
|
||||
<SINK> INIT: in: {obj=I?D} out: {obj=I?D} USE: in: {} out: {}
|
||||
=====================
|
||||
== foo ==
|
||||
fun foo() {
|
||||
|
||||
+3
-3
@@ -23,9 +23,9 @@ L0:
|
||||
v(i) INIT: in: {numbers=ID} out: {i=D, numbers=ID}
|
||||
L2 [loop entry point]:
|
||||
L6 [condition entry point]:
|
||||
jmp?(L3) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID}
|
||||
jmp?(L3) INIT: in: {i=I?D, numbers=ID} out: {i=I?D, numbers=ID}
|
||||
magic[LOOP_RANGE_ITERATION](numbers|<v1>) -> <v2>
|
||||
w(i|<v2>) INIT: in: {i=D, numbers=ID} out: {i=ID, numbers=ID}
|
||||
w(i|<v2>) INIT: in: {i=I?D, numbers=ID} out: {i=ID, numbers=ID}
|
||||
mark(for (i in numbers) { val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue }) INIT: in: {i=ID, numbers=ID} out: {i=ID, numbers=ID} USE: in: {} out: {}
|
||||
L4 [body entry point]:
|
||||
4 mark({ val b: Boolean if (1 < 2) { b = false } else { b = true } use(b) continue })
|
||||
@@ -53,7 +53,7 @@ L8 ['if' expression result]:
|
||||
- 3 jmp(L2)
|
||||
L3 [loop exit point]:
|
||||
L5 [body exit point]:
|
||||
read (Unit) INIT: in: {i=D, numbers=ID} out: {i=D, numbers=ID}
|
||||
read (Unit) INIT: in: {i=I?D, numbers=ID} out: {i=I?D, numbers=ID}
|
||||
L1:
|
||||
1 <END> INIT: in: {numbers=ID} out: {numbers=ID}
|
||||
error:
|
||||
|
||||
@@ -19,9 +19,9 @@ L0:
|
||||
v(i) INIT: in: {} out: {i=D}
|
||||
L2 [loop entry point]:
|
||||
L6 [condition entry point]:
|
||||
jmp?(L3) INIT: in: {i=D} out: {i=D}
|
||||
jmp?(L3) INIT: in: {i=I?D} out: {i=I?D}
|
||||
magic[LOOP_RANGE_ITERATION](1..10|<v3>) -> <v4>
|
||||
w(i|<v4>) INIT: in: {i=D} out: {i=ID}
|
||||
w(i|<v4>) INIT: in: {i=I?D} out: {i=ID}
|
||||
mark(for (i in 1..10) { val a = i }) INIT: in: {i=ID} out: {i=ID}
|
||||
L4 [body entry point]:
|
||||
4 mark({ val a = i })
|
||||
@@ -31,7 +31,7 @@ L4 [body entry point]:
|
||||
3 jmp(L2) INIT: in: {i=ID} out: {i=ID} USE: in: {i=READ} out: {i=READ}
|
||||
L3 [loop exit point]:
|
||||
L5 [body exit point]:
|
||||
read (Unit) INIT: in: {i=D} out: {i=D}
|
||||
read (Unit) INIT: in: {i=I?D} out: {i=I?D}
|
||||
2 mark("after") INIT: in: {} out: {}
|
||||
r("after") -> <v6>
|
||||
L1:
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(k: Int): Int {
|
||||
val i: Int
|
||||
for (j in 1..k) {
|
||||
<!VAL_REASSIGNMENT!>i<!> = j
|
||||
}
|
||||
i = 6
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ k: kotlin.Int): kotlin.Int
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(): Int {
|
||||
val i: Int
|
||||
var j = 0
|
||||
do {
|
||||
<!VAL_REASSIGNMENT!>i<!> = ++j
|
||||
} while (j < 5)
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Int
|
||||
@@ -0,0 +1,11 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
if (f) {}
|
||||
else {
|
||||
i = 2
|
||||
}
|
||||
<!VAL_REASSIGNMENT!>i<!> = 3
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ f: kotlin.Boolean): kotlin.Int
|
||||
@@ -0,0 +1,9 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(k: Int): Int {
|
||||
val i: Int
|
||||
for (j in 1..k) {
|
||||
<!VAL_REASSIGNMENT!>i<!> = j
|
||||
}
|
||||
return <!UNINITIALIZED_VARIABLE!>i<!>
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ k: kotlin.Int): kotlin.Int
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
if (f) {
|
||||
i = 1
|
||||
}
|
||||
<!VAL_REASSIGNMENT!>i<!> = 3
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ f: kotlin.Boolean): kotlin.Int
|
||||
@@ -0,0 +1,13 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
if (f) {
|
||||
i = 1
|
||||
}
|
||||
else {
|
||||
i = 2
|
||||
}
|
||||
<!VAL_REASSIGNMENT!>i<!> = 3
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ f: kotlin.Boolean): kotlin.Int
|
||||
@@ -0,0 +1,6 @@
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
if (f) {}
|
||||
i = 3
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ f: kotlin.Boolean): kotlin.Int
|
||||
@@ -0,0 +1,10 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(f: Boolean): Int {
|
||||
val i: Int
|
||||
when (f) {
|
||||
true -> i = 1
|
||||
}
|
||||
<!VAL_REASSIGNMENT!>i<!> = 3
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(/*0*/ f: kotlin.Boolean): kotlin.Int
|
||||
@@ -0,0 +1,11 @@
|
||||
// !DIAGNOSTICS: -UNUSED_VALUE
|
||||
|
||||
fun foo(): Int {
|
||||
val i: Int
|
||||
var j = 0
|
||||
while (true) {
|
||||
<!VAL_REASSIGNMENT!>i<!> = ++j
|
||||
if (j > 5) break
|
||||
}
|
||||
return i
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
package
|
||||
|
||||
internal fun foo(): kotlin.Int
|
||||
@@ -10912,6 +10912,69 @@ public class JetDiagnosticsTestGenerated extends AbstractJetDiagnosticsTest {
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/reassignment")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class Reassignment extends AbstractJetDiagnosticsTest {
|
||||
@TestMetadata("afterfor.kt")
|
||||
public void testAfterfor() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/afterfor.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
public void testAllFilesPresentInReassignment() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/diagnostics/tests/reassignment"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("dowhile.kt")
|
||||
public void testDowhile() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/dowhile.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("else.kt")
|
||||
public void testElse() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/else.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("foronly.kt")
|
||||
public void testForonly() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/foronly.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("if.kt")
|
||||
public void testIf() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/if.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("ifelse.kt")
|
||||
public void testIfelse() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/ifelse.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("noifelse.kt")
|
||||
public void testNoifelse() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/noifelse.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("when.kt")
|
||||
public void testWhen() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/when.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("whiletrue.kt")
|
||||
public void testWhiletrue() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/diagnostics/tests/reassignment/whiletrue.kt");
|
||||
doTest(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/diagnostics/tests/recovery")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
+1
-1
@@ -10,7 +10,7 @@ object FileRead {
|
||||
val fstream = FileInputStream()
|
||||
val `in` = DataInputStream(fstream)
|
||||
val br = BufferedReader(InputStreamReader(`in`))
|
||||
val strLine: String
|
||||
var strLine: String
|
||||
while ((strLine = br.readLine()) != null) {
|
||||
println(strLine)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user