Java control flow: Detecting redundant assignment when the control flow includes a try-finally statement, fixed handling calls, tests added (IDEA-155836)

This commit is contained in:
Pavel Dolgov
2016-08-09 18:20:57 +03:00
parent 5775c66e61
commit aa51cac5c5
18 changed files with 893 additions and 57 deletions
@@ -23,13 +23,13 @@ import com.intellij.psi.util.PsiUtil;
import com.intellij.psi.util.PsiUtilCore;
import com.intellij.util.containers.IntArrayList;
import com.intellij.util.containers.Queue;
import com.intellij.util.containers.Stack;
import gnu.trove.THashMap;
import gnu.trove.THashSet;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.*;
/**
* @author max
@@ -64,67 +64,71 @@ public class DefUseUtil {
}
}
private static class InstructionState {
private Set<PsiVariable> myVariablesUseArmed;
private final int myInstructionIdx;
private final IntArrayList myBackwardTraces;
private static class InstructionState implements Comparable<InstructionState> {
private Set<PsiVariable> myUsed;
private final InstructionKey myInstructionKey;
private final List<InstructionKey> myBackwardTraces;
private boolean myIsVisited;
public InstructionState(int instructionIdx) {
myInstructionIdx = instructionIdx;
myBackwardTraces = new IntArrayList();
myVariablesUseArmed = null;
public InstructionState(@NotNull InstructionKey instructionKey) {
myInstructionKey = instructionKey;
myBackwardTraces = new ArrayList<InstructionKey>(2);
myUsed = null;
}
public void addBackwardTrace(int i) {
myBackwardTraces.add(i);
public void addBackwardTrace(InstructionKey key) {
myBackwardTraces.add(key);
}
public IntArrayList getBackwardTraces() {
public List<InstructionKey> getBackwardTraces() {
return myBackwardTraces;
}
public int getInstructionIdx() {
return myInstructionIdx;
public InstructionKey getInstructionKey() {
return myInstructionKey;
}
void mergeUseArmed(PsiVariable psiVariable) {
void addUsed(PsiVariable psiVariable) {
touch();
myVariablesUseArmed.add(psiVariable);
myUsed.add(psiVariable);
}
boolean mergeUseDisarmed(PsiVariable psiVariable) {
boolean removeUsed(PsiVariable psiVariable) {
touch();
boolean result = myVariablesUseArmed.contains(psiVariable);
myVariablesUseArmed.remove(psiVariable);
return result;
return myUsed.remove(psiVariable);
}
private void touch() {
if (myVariablesUseArmed == null) myVariablesUseArmed = new THashSet<PsiVariable>();
if (myUsed == null) myUsed = new THashSet<PsiVariable>();
}
public void merge(InstructionState state) {
public void addUsedFrom(InstructionState state) {
touch();
myVariablesUseArmed.addAll(state.myVariablesUseArmed);
myUsed.addAll(state.myUsed);
}
public boolean contains(InstructionState state) {
return myVariablesUseArmed != null && state.myVariablesUseArmed != null &&
myVariablesUseArmed.containsAll(state.myVariablesUseArmed);
return myUsed != null && state.myUsed != null &&
myUsed.containsAll(state.myUsed);
}
public boolean markVisited() {
boolean old = myIsVisited;
public void markVisited() {
myIsVisited = true;
return old;
}
public boolean isVisited() {
return myIsVisited;
}
@Override
public int compareTo(@NotNull InstructionState other) {
return myInstructionKey.compareTo(other.myInstructionKey);
}
@Override
public String toString() {
return myInstructionKey + " " + myBackwardTraces + (myIsVisited ? "(v)" : "(n)") + " " + (myUsed != null ? myUsed : "-");
}
}
@Nullable
@@ -165,9 +169,11 @@ public class DefUseUtil {
}
}
InstructionState[] states = getStates(instructions);
Map<InstructionKey, InstructionState> stateMap = getStates(instructions);
InstructionState[] states = stateMap.values().toArray(new InstructionState[0]);
Arrays.sort(states);
boolean[] defsArmed = new boolean[instructions.size()];
BitSet usefulWrites = new BitSet(instructions.size());
Queue<InstructionState> queue = new Queue<InstructionState>(8);
@@ -178,7 +184,7 @@ public class DefUseUtil {
for (PsiVariable psiVariable : assignedVariables) {
if (psiVariable instanceof PsiField) {
outerState.mergeUseArmed(psiVariable);
outerState.addUsed(psiVariable);
}
}
queue.addLast(outerState);
@@ -188,21 +194,21 @@ public class DefUseUtil {
InstructionState state = queue.pullFirst();
state.markVisited();
int idx = state.getInstructionIdx();
if (idx < instructions.size()) {
Instruction instruction = instructions.get(idx);
InstructionKey key = state.getInstructionKey();
if (key.getOffset() < instructions.size()) {
Instruction instruction = instructions.get(key.getOffset());
if (instruction instanceof WriteVariableInstruction) {
WriteVariableInstruction writeInstruction = (WriteVariableInstruction)instruction;
PsiVariable psiVariable = writeInstruction.variable;
outUsedVariables.add(psiVariable);
if (state.mergeUseDisarmed(psiVariable)) {
defsArmed[idx] = true;
if (state.removeUsed(psiVariable)) {
usefulWrites.set(key.getOffset());
}
}
else if (instruction instanceof ReadVariableInstruction) {
ReadVariableInstruction readInstruction = (ReadVariableInstruction)instruction;
state.mergeUseArmed(readInstruction.variable);
state.addUsed(readInstruction.variable);
outUsedVariables.add(readInstruction.variable);
}
else {
@@ -210,12 +216,11 @@ public class DefUseUtil {
}
}
IntArrayList backwardTraces = state.getBackwardTraces();
for (int j = 0; j < backwardTraces.size(); j++) {
int prevIdx = backwardTraces.get(j);
InstructionState prevState = states[prevIdx];
if (!prevState.contains(state)) {
prevState.merge(state);
List<InstructionKey> backwardTraces = state.getBackwardTraces();
for (InstructionKey prevKeys : backwardTraces) {
InstructionState prevState = stateMap.get(prevKeys);
if (prevState != null && !prevState.contains(state)) {
prevState.addUsedFrom(state);
queue.addLast(prevState);
}
}
@@ -228,7 +233,7 @@ public class DefUseUtil {
Instruction instruction = instructions.get(i);
if (instruction instanceof WriteVariableInstruction) {
WriteVariableInstruction writeInstruction = (WriteVariableInstruction)instruction;
if (!defsArmed[i]) {
if (!usefulWrites.get(i)) {
PsiElement context = PsiTreeUtil.getNonStrictParentOfType(flow.getElement(i),
PsiStatement.class, PsiAssignmentExpression.class,
PsiPostfixExpression.class, PsiPrefixExpression.class);
@@ -254,16 +259,16 @@ public class DefUseUtil {
public static PsiElement[] getDefs(PsiCodeBlock body, final PsiVariable def, PsiElement ref) {
try {
RefsDefs refsDefs = new RefsDefs(body) {
private final InstructionState[] states = getStates(instructions);
private final IntArrayList[] myBackwardTraces = getBackwardTraces(instructions);
@Override
protected int nNext(int index) {
return states[index].getBackwardTraces().size();
return myBackwardTraces[index].size();
}
@Override
protected int getNext(int index, int no) {
return states[index].getBackwardTraces().get(no);
return myBackwardTraces[index].get(no);
}
@Override
@@ -407,7 +412,7 @@ public class DefUseUtil {
}
}
// hack: ControlFlow doesnn't contains parameters initialization
// hack: ControlFlow doesn't contains parameters initialization
if (index == 0 && def instanceof PsiParameter) {
res.add(def.getNameIdentifier());
}
@@ -442,10 +447,10 @@ public class DefUseUtil {
}
private static InstructionState[] getStates(final List<Instruction> instructions) {
final InstructionState[] states = new InstructionState[instructions.size()];
private static IntArrayList[] getBackwardTraces(final List<Instruction> instructions) {
final IntArrayList[] states = new IntArrayList[instructions.size()];
for (int i = 0; i < states.length; i++) {
states[i] = new InstructionState(i);
states[i] = new IntArrayList();
}
for (int i = 0; i < instructions.size(); i++) {
@@ -453,13 +458,106 @@ public class DefUseUtil {
for (int j = 0; j != instruction.nNext(); ++ j) {
final int next = instruction.getNext(i, j);
if (next < states.length) {
states[next].addBackwardTrace(i);
states[next].add(i);
}
}
}
return states;
}
private static Map<InstructionKey, InstructionState> getStates(final List<Instruction> instructions) {
class WalkThroughStack {
private final com.intellij.util.containers.Stack<InstructionKey> myFrom;
private final com.intellij.util.containers.Stack<InstructionKey> myNext;
WalkThroughStack(int size) {
if (size < 2) size = 2;
myFrom = new Stack<InstructionKey>(size);
myNext = new Stack<InstructionKey>(size);
}
void push(InstructionKey fromKey, InstructionKey nextKey) {
myFrom.push(fromKey);
myNext.push(nextKey);
}
InstructionKey peekFrom() {
return myFrom.peek();
}
InstructionKey popNext() {
myFrom.pop();
return myNext.pop();
}
boolean isEmpty() {
return myFrom.isEmpty();
}
}
class Walker {
private final Map<InstructionKey, InstructionState> myStates;
private final WalkThroughStack myWalkThroughStack;
Walker() {
myStates = new THashMap<InstructionKey, InstructionState>(instructions.size());
myWalkThroughStack = new WalkThroughStack(instructions.size() / 2);
}
Map<InstructionKey, InstructionState> walk() {
InstructionKey startKey = InstructionKey.create(0);
myStates.put(startKey, new InstructionState(startKey));
myWalkThroughStack.push(InstructionKey.create(-1), startKey);
Set<InstructionKey> visited = new THashSet<InstructionKey>(instructions.size());
while (!myWalkThroughStack.isEmpty()) {
InstructionKey fromKey = myWalkThroughStack.peekFrom();
InstructionKey nextKey = myWalkThroughStack.popNext();
addBackwardTrace(fromKey, nextKey);
if (!visited.contains(nextKey)) {
visit(nextKey);
visited.add(nextKey);
}
}
return myStates;
}
private void visit(InstructionKey fromKey) {
if (fromKey.getOffset() >= instructions.size()) return;
final Instruction instruction = instructions.get(fromKey.getOffset());
if (instruction instanceof CallInstruction) {
int nextOffset = ((CallInstruction)instruction).offset;
LOG.assertTrue(nextOffset != 0);
int returnOffset = fromKey.getOffset() + 1;
InstructionKey nextKey = fromKey.push(nextOffset, returnOffset);
myWalkThroughStack.push(fromKey, nextKey);
}
else if (instruction instanceof ReturnInstruction) {
int overriddenOffset = ((ReturnInstruction)instruction).offset;
InstructionKey nextKey = fromKey.pop(overriddenOffset);
myWalkThroughStack.push(fromKey, nextKey);
}
else {
for (int no = 0; no != instruction.nNext(); no++) {
final int nextOffset = instruction.getNext(fromKey.getOffset(), no);
InstructionKey nextKey = fromKey.next(nextOffset);
myWalkThroughStack.push(fromKey, nextKey);
}
}
}
private void addBackwardTrace(InstructionKey fromKey, InstructionKey nextKey) {
if (fromKey.getOffset() >= 0 && nextKey.getOffset() < instructions.size()) {
InstructionState state = myStates.get(nextKey);
if (state == null) myStates.put(nextKey, state = new InstructionState(nextKey));
state.addBackwardTrace(fromKey);
}
}
}
return new Walker().walk();
}
private static final ControlFlowPolicy ourPolicy = new ControlFlowPolicy() {
@Override
public PsiVariable getUsedVariable(@NotNull PsiReferenceExpression refExpr) {
@@ -0,0 +1,108 @@
/*
* Copyright 2000-2016 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.intellij.psi.controlFlow;
import com.intellij.util.ArrayUtil;
import org.jetbrains.annotations.NotNull;
import java.util.Arrays;
/**
* @author Pavel.Dolgov
*/
class InstructionKey implements Comparable<InstructionKey> {
private final int myOffset;
private final int[] myCallStack; // shared between instructions on the same stack level
private InstructionKey(int offset, @NotNull int[] callStack) {
myOffset = offset;
myCallStack = callStack;
}
@NotNull
static InstructionKey create(int offset) {
return new InstructionKey(offset, ArrayUtil.EMPTY_INT_ARRAY);
}
InstructionKey next(int nextOffset) {
return new InstructionKey(nextOffset, myCallStack);
}
InstructionKey push(int nextOffset, int returnOffset) {
int[] nextStack = ArrayUtil.append(myCallStack, returnOffset);
return new InstructionKey(nextOffset, nextStack);
}
InstructionKey pop(int overriddenOffset) {
int returnOffset = myCallStack[myCallStack.length - 1];
int[] nextStack = ArrayUtil.realloc(myCallStack, myCallStack.length - 1);
int nextOffset = overriddenOffset != 0 ? overriddenOffset : returnOffset;
return new InstructionKey(nextOffset, nextStack);
}
int getOffset() {
return myOffset;
}
int[] getCallStack() {
return myCallStack;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
InstructionKey key = (InstructionKey)o;
if (myOffset != key.myOffset) return false;
if (!Arrays.equals(myCallStack, key.myCallStack)) return false;
return true;
}
@Override
public int hashCode() {
int result = myOffset;
result = 31 * result + Arrays.hashCode(myCallStack);
return result;
}
@Override
public String toString() {
if (myCallStack.length == 0) {
return String.valueOf(myOffset);
}
StringBuilder s = new StringBuilder();
for (int offset : myCallStack) {
if (s.length() != 0) s.append(',');
s.append(offset);
}
return myOffset + "(" + s + ")";
}
@Override
public int compareTo(@NotNull InstructionKey key) {
int c = myOffset - key.myOffset;
if (c != 0) return c;
for (int i = 0, len = Math.min(myCallStack.length, key.myCallStack.length); i < len; i++) {
c = myCallStack[i] - key.myCallStack[i];
if (c != 0) return c;
}
c = myCallStack.length - key.myCallStack.length;
return c;
}
}
@@ -0,0 +1,307 @@
import java.io.File;
import java.io.IOException;
import java.util.*;
class Z {
private float f1;
private float f2;
private static class R {
public static final R N = new R();
}
private static class J {
}
private static class E {
public static final E E1 = new E();
public static final E E2 = new E();
public static final E E3 = new E();
public static final E E4 = new E();
}
private static class G {
public static final G G1 = new G();
public static G[] gs() {
return new G[]{new G()};
}
}
private static class C {
public void c() {
}
public D d() {
return new D();
}
}
private static class B {
public B(C c) {
}
public int n() {
return 0;
}
public void c() {
}
public void f() {
}
}
private static class L {
public void s(C c, M m) {
}
public E b(C c, M m, H<J, N> h, B b) {
return new E();
}
public String s() {
return "";
}
public void f(C c, M m) {
}
}
private static class Q<J, M> {
}
private static class N {
}
private static class H<J, M> {
public void p(Q<J, M> q) throws IOException {
}
}
private static class HB<J, M> extends H<J, M> {
public HB(C c) {
}
}
private static class T {
public int s() {
return 0;
}
}
private static class M {
public T t() {
return new T();
}
public List<N> ns() {
return new ArrayList<N>();
}
public String s() {
return "";
}
}
private static class F {
public void b(C c, M m) {
}
public void c(C c) {
}
}
private static class S {
public void s(String s, List<String> ls) {
}
}
private static class DM {
public S s(N n) {
return new S();
}
}
private static class D {
public F f = new F();
public DM dm;
}
private D d = new D();
private static class K {
public List<L> ls(G g) {
return new ArrayList<L>();
}
}
private K k = new K();
private static class Ex extends Exception {
public Ex(String s) {
super(s);
}
public Ex(Exception e) {
super(e);
}
}
private boolean foo(final C c, final M m) throws Ex, IOException {
for (G g : G.gs()) {
for (L l : k.ls(g)) {
l.s(c, m);
}
}
boolean b1 = false;
boolean b2 = false;
float c1 = f1;
final int s = m.t().s();
int p = 0;
boolean b3;
B b = new B(c);
try {
do {
b3 = false;
d.f.b(c, m);
H<J, N> h = new HB<J, N>(c) {
@Override
public void p(Q<J, N> q) throws IOException {
m5(c, m, q);
}
};
if (!m4(c)) {
final Map<N, Set<File>> map = m2(c, h);
for (Map.Entry<N, Set<File>> e : map.entrySet()) {
final N n = e.getKey();
final Set<File> files = e.getValue();
if (!files.isEmpty()) {
final S mapping = c.d().dm.s(n);
for (File srcFile : files) {
mapping.s(srcFile.getPath(), new ArrayList<String>());
}
}
}
}
L:
for (G g : G.gs()) {
final List<L> ls = k.ls(g);
if (g == G.G1) {
m9(b);
}
if (ls.isEmpty()) {
continue;
}
try {
for (L l : ls) {
m8(c, m.ns());
long l1 = System.nanoTime();
int n1 = b.n();
final E e = l.b(c, m, h, b);
m7(l, System.nanoTime() - l1, b.n() - n1);
b1 |= (e != E.E1);
if (e == E.E2) {
throw new Ex("Fail " + l.s());
}
c.c();
if (e == E.E3) {
b3 = true;
}
else if (e == E.E4) {
if (!b2 && !m4(c)) {
System.out.println("1 " + l.s() + ":" + m.s());
b2 = true;
try {
c.d().f.c(c);
m1(c, R.N, m, null);
f2 -= (p * s) / c1;
c1 = f1;
p = 0;
b3 = true;
b.c();
break L;
}
catch (Exception ex) {
throw new Ex(ex);
}
}
else {
System.out.println("2 " + l.s());
}
}
p++;
m6(c, s / (c1));
}
}
finally {
final boolean b4 = m3(c, h, m);
if (b4) {
b3 = true;
}
if (b3 && !b2) {
f2 -= (p * s) / c1;
c1 += f1;
f2 += (p * s) / c1;
}
}
}
}
while (b3);
}
finally {
m9(b);
b.f();
b.c();
for (G g : G.gs()) {
for (L l : k.ls(g)) {
l.f(c, m);
}
}
}
return b1;
}
private void m1(C c, R r, M m, Object o) {
}
private static Map<N, Set<File>> m2(C c, H<J, N> h) {
return new HashMap<N, Set<File>>();
}
private static boolean m3(C c, H<J, N> h, M m) {
return c != null && h != null && m != null;
}
private boolean m4(C c) {
return c != null && f1>1;
}
private void m5(C c, M m, Q<J, N> q) {
}
private void m6(C c, float v) {
}
private void m7(L l1, long l, int i) {
}
private void m8(C c, List<N> ns) {
}
private void m9(B b) {
}
}
@@ -0,0 +1,143 @@
import java.io.IOException;
class Y {
private static class Ex extends Exception {
public Ex(Exception e) {
super(e);
}
}
private static class P {
}
private static class T {
}
private static class R {
public T[] ts() {
return new T[]{new T()};
}
}
private static class M {
public S s() {
return new S();
}
}
private static class S {
public void c() throws IOException {
}
}
private static class F {
public void c() {
}
}
private static class D {
public M m;
public S s;
public F f;
public R r() {
return new R();
}
public P p() {
return new P();
}
}
private static class C {
public D d() {
return new D();
}
public void c() {
}
public Q q() {
return new Q();
}
}
private static class Q {
public boolean a(T t) {
return false;
}
}
private static class J {
public boolean c() {
return false;
}
}
private void foo(C c) throws Ex {
final D d = c.d();
Ex ex = null;
try {
final J j = m2(d.p());
final boolean b = j.c();
if (b) {
m3(c);
}
else {
for (T t : d.r().ts()) {
c.c();
if (c.q().a(t)) {
m1(c, t);
}
}
}
}
catch (Ex e) {
ex = e;
}
finally {
try {
d.m.s().c();
}
catch (IOException e) {
if (ex == null) {
ex = new Ex(e);
}
else {
System.out.println("1" + e);
}
}
finally {
try {
d.s.c();
}
catch (IOException e) {
if (ex == null) {
ex = new Ex(e);
}
else {
System.out.println("2 " + e);
}
}
finally {
d.f.c();
if (ex != null) {
throw ex;
}
}
}
}
}
private void m1(C c, T t) throws Ex {
}
private static J m2(P p) throws Ex {
return new J();
}
private void m3(C c) throws Ex {
}
}
@@ -0,0 +1,12 @@
class C {
int f(boolean b) {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
if (b) {
i = 1;
}
else {
i = 2;
}
return i;
}
}
@@ -0,0 +1,13 @@
class C {
int f(boolean b) {
int i;
if (b) {
<warning descr="The value 1 assigned to 'i' is never used">i</warning> = 1;
}
else {
<warning descr="The value 2 assigned to 'i' is never used">i</warning> = 2;
}
i = 3;
return i;
}
}
@@ -0,0 +1,10 @@
class C {
int f() {
int i = 0;
for (int j = 0; j < 2; j++) {
if (j == 2) return 1;
i = 1;
}
return i;
}
}
@@ -0,0 +1,17 @@
class C {
int f(boolean b, boolean c) {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
if (b) {
if (c) {
i = 1;
}
else {
i = 2;
}
}
else {
i = 3;
}
return i;
}
}
@@ -0,0 +1,9 @@
class C {
int f() {
int i = 0;
for (int j = 0; j < 2; j++) {
i = 1;
}
return i;
}
}
@@ -0,0 +1,19 @@
class C {
int f() {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
try {
<warning descr="The value 1 assigned to 'i' is never used">i</warning> = 1;
}
finally {
<warning descr="The value 2 assigned to 'i' is never used">i</warning> = 2;
try {
<warning descr="The value 3 assigned to 'i' is never used">i</warning> = 3;
}
finally {
<warning descr="The value 4 assigned to 'i' is never used">i</warning> = 4;
}
i = 5;
}
return i;
}
}
@@ -0,0 +1,14 @@
class C {
int f() {
int i;
try {
} finally {
<warning descr="The value 1 assigned to 'i' is never used">i</warning> = 1;
try {
i = 2;
} finally {
}
}
return i;
}
}
@@ -0,0 +1,8 @@
class C {
int f() {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
<warning descr="The value 1 assigned to 'i' is never used">i</warning> = 1;
i = 2;
return i;
}
}
@@ -0,0 +1,12 @@
class C {
int f(boolean b) {
int i;
try {
<warning descr="The value 0 assigned to 'i' is never used">i</warning> = 0;
} finally {
if (b) throw new RuntimeException();
i = 1;
}
return i;
}
}
@@ -0,0 +1,11 @@
class C {
int f(boolean b) {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
try {
if (b) throw new RuntimeException();
} finally {
i = 1;
}
return i;
}
}
@@ -0,0 +1,12 @@
class C {
int f(boolean b) {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
try {
<warning descr="The value 1 assigned to 'i' is never used">i</warning> = 1;
}
finally {
i = 2;
}
return i;
}
}
@@ -0,0 +1,13 @@
class C {
int f(boolean b) {
int i = <warning descr="Variable 'i' initializer '0' is redundant">0</warning>;
try {
<warning descr="The value 1 assigned to 'i' is never used">i</warning> = 1;
if (b) throw new RuntimeException();
}
finally {
i = 2;
}
return i;
}
}
@@ -0,0 +1,15 @@
class C {
boolean test(boolean b) {
boolean f = <warning descr="Variable 'f' initializer 'false' is redundant">false</warning>;
try {
if (b) throw new RuntimeException();
f = true;
}
catch (RuntimeException e) {
throw e;
}
finally {
}
return f;
}
}
@@ -38,9 +38,24 @@ public class DefUseTest extends LightCodeInsightFixtureTestCase {
public void testUsedInArrayInitializer() { doTest(); }
public void testHang() { doTest(); }
public void testOperatorAssignment() { doTest(); }
@Bombed(user="roman.shevchenko@jetbrains.com", day=1, month=Calendar.AUGUST, year=2017) public void testTryWithFinally() { doTest(); }
public void testTryWithFinally() { doTest(); }
public void testTryWithoutFinally() { doTest(); }
public void testSequence() { doTest(); }
public void testIfAfter() { doTest(); }
public void testIfBefore() { doTest(); }
public void testIfNested() { doTest(); }
public void testInLoop() { doTest(); }
public void testIfInLoop() { doTest(); }
public void testThrowInTry() { doTest(); }
public void testThrowInFinally() { doTest(); }
public void testTryThrowFinally() { doTest(); }
public void testNestedTryFinally() { doTest(); }
public void testNestedBigTryFinally() { doTest(); }
public void testTryWithFinallyRethrow() { doTest(); }
public void testComplexDoubleTryFinally() { doTest(); }
public void testComplexTripleTryFinally() { doTest(); }
private void doTest() {
myFixture.enableInspections(new DefUseInspection());
myFixture.testHighlighting(getTestName(false) + ".java");