mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-09-27 10:03:11 +07:00
lite analyzers for methods without JSR instructions
This commit is contained in:
+21
-9
@@ -103,15 +103,25 @@ public class ClassDataIndexer implements DataIndexer<HKey, HResult, FileContent>
|
||||
public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
|
||||
final MethodNode node = new MethodNode(Opcodes.ASM5, access, name, desc, signature, exceptions);
|
||||
return new MethodVisitor(Opcodes.ASM5, node) {
|
||||
private boolean jsr;
|
||||
|
||||
@Override
|
||||
public void visitJumpInsn(int opcode, Label label) {
|
||||
if (opcode == Opcodes.JSR) {
|
||||
jsr = true;
|
||||
}
|
||||
super.visitJumpInsn(opcode, label);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitEnd() {
|
||||
super.visitEnd();
|
||||
processMethod(node);
|
||||
processMethod(node, jsr);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private void processMethod(final MethodNode methodNode) {
|
||||
private void processMethod(final MethodNode methodNode, boolean jsr) {
|
||||
ProgressManager.checkCanceled();
|
||||
final Type[] argumentTypes = Type.getArgumentTypes(methodNode.desc);
|
||||
final Type resultType = Type.getReturnType(methodNode.desc);
|
||||
@@ -127,7 +137,7 @@ public class ClassDataIndexer implements DataIndexer<HKey, HResult, FileContent>
|
||||
final boolean stable = stableClass || (methodNode.access & STABLE_FLAGS) != 0 || "<init>".equals(methodNode.name);
|
||||
|
||||
try {
|
||||
final ControlFlowGraph graph = ControlFlowGraph.build(className, methodNode);
|
||||
final ControlFlowGraph graph = ControlFlowGraph.build(className, methodNode, jsr);
|
||||
if (graph.transitions.length > 0) {
|
||||
final DFSTree dfs = DFSTree.build(graph.transitions, graph.edgeCount);
|
||||
boolean complex = !dfs.back.isEmpty();
|
||||
@@ -143,7 +153,7 @@ public class ClassDataIndexer implements DataIndexer<HKey, HResult, FileContent>
|
||||
if (complex) {
|
||||
RichControlFlow richControlFlow = new RichControlFlow(graph, dfs);
|
||||
if (richControlFlow.reducible()) {
|
||||
processBranchingMethod(method, methodNode, richControlFlow, argumentTypes, isReferenceResult, isInterestingResult, stable);
|
||||
processBranchingMethod(method, methodNode, richControlFlow, argumentTypes, isReferenceResult, isInterestingResult, stable, jsr);
|
||||
return;
|
||||
}
|
||||
LOG.debug(method + ": CFG is not reducible");
|
||||
@@ -172,7 +182,8 @@ public class ClassDataIndexer implements DataIndexer<HKey, HResult, FileContent>
|
||||
Type[] argumentTypes,
|
||||
boolean isReferenceResult,
|
||||
boolean isInterestingResult,
|
||||
final boolean stable) throws AnalyzerException {
|
||||
final boolean stable,
|
||||
boolean jsr) throws AnalyzerException {
|
||||
|
||||
boolean maybeLeakingParameter = isInterestingResult;
|
||||
for (Type argType : argumentTypes) {
|
||||
@@ -183,7 +194,7 @@ public class ClassDataIndexer implements DataIndexer<HKey, HResult, FileContent>
|
||||
}
|
||||
|
||||
final Pair<boolean[], Frame<org.jetbrains.org.objectweb.asm.tree.analysis.Value>[]> leakingParametersAndFrames =
|
||||
maybeLeakingParameter ? leakingParametersAndFrames(method, methodNode, argumentTypes) : null;
|
||||
maybeLeakingParameter ? leakingParametersAndFrames(method, methodNode, argumentTypes, jsr) : null;
|
||||
boolean[] leakingParameters =
|
||||
leakingParametersAndFrames != null ? leakingParametersAndFrames.first : null;
|
||||
|
||||
@@ -339,11 +350,12 @@ public class ClassDataIndexer implements DataIndexer<HKey, HResult, FileContent>
|
||||
|
||||
private Pair<boolean[], Frame<org.jetbrains.org.objectweb.asm.tree.analysis.Value>[]> leakingParametersAndFrames(Method method,
|
||||
MethodNode methodNode,
|
||||
Type[] argumentTypes)
|
||||
Type[] argumentTypes,
|
||||
boolean jsr)
|
||||
throws AnalyzerException {
|
||||
return argumentTypes.length < 32 ?
|
||||
LeakingParametersAnalysis.fastLeakingParameters(method.internalClassName, methodNode) :
|
||||
LeakingParametersAnalysis.leakingParameters(method.internalClassName, methodNode);
|
||||
LeakingParametersAnalysis.fastLeakingParameters(method.internalClassName, methodNode, jsr) :
|
||||
LeakingParametersAnalysis.leakingParameters(method.internalClassName, methodNode, jsr);
|
||||
}
|
||||
}, ClassReader.SKIP_DEBUG | ClassReader.SKIP_FRAMES);
|
||||
|
||||
|
||||
+52
-2
@@ -67,8 +67,8 @@ public final class ControlFlowGraph {
|
||||
this.errorTransitions = errorTransitions;
|
||||
}
|
||||
|
||||
public static ControlFlowGraph build(String className, MethodNode methodNode) throws AnalyzerException {
|
||||
return new ControlFlowBuilder(className, methodNode).buildCFG();
|
||||
public static ControlFlowGraph build(String className, MethodNode methodNode, boolean jsr) throws AnalyzerException {
|
||||
return jsr ? new ControlFlowBuilder(className, methodNode).buildCFG() : new LiteControlFlowBuilder(className, methodNode).buildCFG();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -122,3 +122,53 @@ final class ControlFlowBuilder extends FramelessAnalyzer {
|
||||
}
|
||||
}
|
||||
|
||||
final class LiteControlFlowBuilder extends LiteFramelessAnalyzer {
|
||||
final String className;
|
||||
final MethodNode methodNode;
|
||||
final TIntArrayList[] transitions;
|
||||
final Set<ControlFlowGraph.Edge> errorTransitions;
|
||||
private final boolean[] errors;
|
||||
private int edgeCount;
|
||||
|
||||
LiteControlFlowBuilder(String className, MethodNode methodNode) {
|
||||
this.className = className;
|
||||
this.methodNode = methodNode;
|
||||
transitions = new TIntArrayList[methodNode.instructions.size()];
|
||||
errors = new boolean[methodNode.instructions.size()];
|
||||
for (int i = 0; i < transitions.length; i++) {
|
||||
transitions[i] = new TIntArrayList();
|
||||
}
|
||||
errorTransitions = new HashSet<Edge>();
|
||||
}
|
||||
|
||||
final ControlFlowGraph buildCFG() throws AnalyzerException {
|
||||
if ((methodNode.access & (ACC_ABSTRACT | ACC_NATIVE)) == 0) {
|
||||
analyze(methodNode);
|
||||
}
|
||||
int[][] resultTransitions = new int[transitions.length][];
|
||||
for (int i = 0; i < resultTransitions.length; i++) {
|
||||
resultTransitions[i] = transitions[i].toNativeArray();
|
||||
}
|
||||
return new ControlFlowGraph(className, methodNode, resultTransitions, edgeCount, errors, errorTransitions);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final void newControlFlowEdge(int insn, int successor) {
|
||||
if (!transitions[insn].contains(successor)) {
|
||||
transitions[insn].add(successor);
|
||||
edgeCount++;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected final boolean newControlFlowExceptionEdge(int insn, int successor) {
|
||||
if (!transitions[insn].contains(successor)) {
|
||||
transitions[insn].add(successor);
|
||||
edgeCount++;
|
||||
errorTransitions.add(new Edge(insn, successor));
|
||||
errors[successor] = true;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
+8
-8
@@ -26,7 +26,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Specialized lite version of {@link org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer}.
|
||||
* Specialized version of {@link org.jetbrains.org.objectweb.asm.tree.analysis.Analyzer}.
|
||||
* Calculation of fix-point of frames is removed, since frames are not needed to build control flow graph.
|
||||
* So, the main point here is handling of subroutines (jsr) and try-catch-finally blocks.
|
||||
*/
|
||||
@@ -81,10 +81,10 @@ public class FramelessAnalyzer implements Opcodes {
|
||||
private InsnList insns;
|
||||
private List<TryCatchBlockNode>[] handlers;
|
||||
private Subroutine[] subroutines;
|
||||
private boolean[] wasQueued;
|
||||
private boolean[] queued;
|
||||
private int[] queue;
|
||||
private int top;
|
||||
protected boolean[] wasQueued;
|
||||
protected boolean[] queued;
|
||||
protected int[] queue;
|
||||
protected int top;
|
||||
|
||||
public void analyze(final MethodNode m) throws AnalyzerException {
|
||||
n = m.instructions.size();
|
||||
@@ -240,7 +240,7 @@ public class FramelessAnalyzer implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
private void findSubroutine(int insn, final Subroutine sub,
|
||||
protected void findSubroutine(int insn, final Subroutine sub,
|
||||
final List<AbstractInsnNode> calls) throws AnalyzerException {
|
||||
while (true) {
|
||||
if (insn < 0 || insn >= n) {
|
||||
@@ -317,7 +317,7 @@ public class FramelessAnalyzer implements Opcodes {
|
||||
|
||||
// -------------------------------------------------------------------------
|
||||
|
||||
private void merge(final int insn, @Nullable final Subroutine subroutine) throws AnalyzerException {
|
||||
protected void merge(final int insn, @Nullable final Subroutine subroutine) throws AnalyzerException {
|
||||
Subroutine oldSubroutine = subroutines[insn];
|
||||
boolean changes = false;
|
||||
|
||||
@@ -342,7 +342,7 @@ public class FramelessAnalyzer implements Opcodes {
|
||||
}
|
||||
}
|
||||
|
||||
private void merge(final int insn, final Subroutine subroutineBeforeJSR, final boolean[] access) throws AnalyzerException {
|
||||
protected void merge(final int insn, final Subroutine subroutineBeforeJSR, final boolean[] access) throws AnalyzerException {
|
||||
Subroutine oldSubroutine = subroutines[insn];
|
||||
boolean changes = false;
|
||||
|
||||
|
||||
+8
-4
@@ -30,8 +30,10 @@ import static org.jetbrains.org.objectweb.asm.Opcodes.*;
|
||||
* @author lambdamix
|
||||
*/
|
||||
public class LeakingParametersAnalysis {
|
||||
public static Pair<boolean[], Frame<Value>[]> leakingParameters(String className, MethodNode methodNode) throws AnalyzerException {
|
||||
Frame<ParamsValue>[] frames = new Analyzer<ParamsValue>(new ParametersUsage(methodNode)).analyze(className, methodNode);
|
||||
public static Pair<boolean[], Frame<Value>[]> leakingParameters(String className, MethodNode methodNode, boolean jsr) throws AnalyzerException {
|
||||
Frame<ParamsValue>[] frames = jsr ?
|
||||
new Analyzer<ParamsValue>(new ParametersUsage(methodNode)).analyze(className, methodNode) :
|
||||
new LiteAnalyzer<ParamsValue>(new ParametersUsage(methodNode)).analyze(className, methodNode);
|
||||
InsnList insns = methodNode.instructions;
|
||||
LeakingParametersCollector collector = new LeakingParametersCollector(methodNode);
|
||||
for (int i = 0; i < frames.length; i++) {
|
||||
@@ -51,9 +53,11 @@ public class LeakingParametersAnalysis {
|
||||
return Pair.create(collector.leaking, (Frame<Value>[])(Frame<?>[])frames);
|
||||
}
|
||||
|
||||
public static Pair<boolean[], Frame<Value>[]> fastLeakingParameters(String className, MethodNode methodNode) throws AnalyzerException {
|
||||
public static Pair<boolean[], Frame<Value>[]> fastLeakingParameters(String className, MethodNode methodNode, boolean jsr) throws AnalyzerException {
|
||||
IParametersUsage parametersUsage = new IParametersUsage(methodNode);
|
||||
Frame<?>[] frames = new Analyzer<IParamsValue>(parametersUsage).analyze(className, methodNode);
|
||||
Frame<?>[] frames = jsr ?
|
||||
new Analyzer<IParamsValue>(parametersUsage).analyze(className, methodNode) :
|
||||
new LiteAnalyzer<IParamsValue>(parametersUsage).analyze(className, methodNode);
|
||||
int leakingMask = parametersUsage.leaking;
|
||||
boolean[] result = new boolean[parametersUsage.arity];
|
||||
for (int i = 0; i < result.length; i++) {
|
||||
|
||||
+189
@@ -0,0 +1,189 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInspection.bytecodeAnalysis.asm;
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.Opcodes;
|
||||
import org.jetbrains.org.objectweb.asm.Type;
|
||||
import org.jetbrains.org.objectweb.asm.tree.*;
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame;
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Interpreter;
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.Value;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Specialized lite version of {@link org.objectweb.asm.tree.analysis.Analyzer}.
|
||||
* No processing of Subroutines. May be used for methods without JSR/RET instructions.
|
||||
*
|
||||
* @author lambdamix
|
||||
*/
|
||||
public class LiteAnalyzer<V extends Value> implements Opcodes {
|
||||
|
||||
private final Interpreter<V> interpreter;
|
||||
|
||||
private Frame<V>[] frames;
|
||||
|
||||
private boolean[] queued;
|
||||
|
||||
private int[] queue;
|
||||
|
||||
private int top;
|
||||
|
||||
public LiteAnalyzer(final Interpreter<V> interpreter) {
|
||||
this.interpreter = interpreter;
|
||||
}
|
||||
|
||||
public Frame<V>[] analyze(final String owner, final MethodNode m) throws AnalyzerException {
|
||||
if ((m.access & (ACC_ABSTRACT | ACC_NATIVE)) != 0 || m.instructions.size() == 0) {
|
||||
frames = (Frame<V>[]) new Frame<?>[0];
|
||||
return frames;
|
||||
}
|
||||
int n = m.instructions.size();
|
||||
InsnList insns = m.instructions;
|
||||
List<TryCatchBlockNode>[] handlers = (List<TryCatchBlockNode>[]) new List<?>[n];
|
||||
frames = (Frame<V>[]) new Frame<?>[n];
|
||||
queued = new boolean[n];
|
||||
queue = new int[n];
|
||||
top = 0;
|
||||
|
||||
// computes exception handlers for each instruction
|
||||
for (int i = 0; i < m.tryCatchBlocks.size(); ++i) {
|
||||
TryCatchBlockNode tcb = m.tryCatchBlocks.get(i);
|
||||
int begin = insns.indexOf(tcb.start);
|
||||
int end = insns.indexOf(tcb.end);
|
||||
for (int j = begin; j < end; ++j) {
|
||||
List<TryCatchBlockNode> insnHandlers = handlers[j];
|
||||
if (insnHandlers == null) {
|
||||
insnHandlers = new ArrayList<TryCatchBlockNode>();
|
||||
handlers[j] = insnHandlers;
|
||||
}
|
||||
insnHandlers.add(tcb);
|
||||
}
|
||||
}
|
||||
|
||||
// initializes the data structures for the control flow analysis
|
||||
Frame<V> current = new Frame<V>(m.maxLocals, m.maxStack);
|
||||
Frame<V> handler = new Frame<V>(m.maxLocals, m.maxStack);
|
||||
current.setReturn(interpreter.newValue(Type.getReturnType(m.desc)));
|
||||
Type[] args = Type.getArgumentTypes(m.desc);
|
||||
int local = 0;
|
||||
if ((m.access & ACC_STATIC) == 0) {
|
||||
Type ctype = Type.getObjectType(owner);
|
||||
current.setLocal(local++, interpreter.newValue(ctype));
|
||||
}
|
||||
for (int i = 0; i < args.length; ++i) {
|
||||
current.setLocal(local++, interpreter.newValue(args[i]));
|
||||
if (args[i].getSize() == 2) {
|
||||
current.setLocal(local++, interpreter.newValue(null));
|
||||
}
|
||||
}
|
||||
while (local < m.maxLocals) {
|
||||
current.setLocal(local++, interpreter.newValue(null));
|
||||
}
|
||||
merge(0, current);
|
||||
|
||||
// control flow analysis
|
||||
while (top > 0) {
|
||||
int insn = queue[--top];
|
||||
Frame<V> f = frames[insn];
|
||||
queued[insn] = false;
|
||||
|
||||
AbstractInsnNode insnNode = null;
|
||||
try {
|
||||
insnNode = m.instructions.get(insn);
|
||||
int insnOpcode = insnNode.getOpcode();
|
||||
int insnType = insnNode.getType();
|
||||
|
||||
if (insnType == AbstractInsnNode.LABEL || insnType == AbstractInsnNode.LINE || insnType == AbstractInsnNode.FRAME) {
|
||||
merge(insn + 1, f);
|
||||
} else {
|
||||
current.init(f).execute(insnNode, interpreter);
|
||||
|
||||
if (insnNode instanceof JumpInsnNode) {
|
||||
JumpInsnNode j = (JumpInsnNode) insnNode;
|
||||
if (insnOpcode != GOTO && insnOpcode != JSR) {
|
||||
merge(insn + 1, current);
|
||||
}
|
||||
int jump = insns.indexOf(j.label);
|
||||
merge(jump, current);
|
||||
} else if (insnNode instanceof LookupSwitchInsnNode) {
|
||||
LookupSwitchInsnNode lsi = (LookupSwitchInsnNode) insnNode;
|
||||
int jump = insns.indexOf(lsi.dflt);
|
||||
merge(jump, current);
|
||||
for (int j = 0; j < lsi.labels.size(); ++j) {
|
||||
LabelNode label = lsi.labels.get(j);
|
||||
jump = insns.indexOf(label);
|
||||
merge(jump, current);
|
||||
}
|
||||
} else if (insnNode instanceof TableSwitchInsnNode) {
|
||||
TableSwitchInsnNode tsi = (TableSwitchInsnNode) insnNode;
|
||||
int jump = insns.indexOf(tsi.dflt);
|
||||
merge(jump, current);
|
||||
for (int j = 0; j < tsi.labels.size(); ++j) {
|
||||
LabelNode label = tsi.labels.get(j);
|
||||
jump = insns.indexOf(label);
|
||||
merge(jump, current);
|
||||
}
|
||||
} else if (insnOpcode != ATHROW && (insnOpcode < IRETURN || insnOpcode > RETURN)) {
|
||||
merge(insn + 1, current);
|
||||
}
|
||||
}
|
||||
|
||||
List<TryCatchBlockNode> insnHandlers = handlers[insn];
|
||||
if (insnHandlers != null) {
|
||||
for (int i = 0; i < insnHandlers.size(); ++i) {
|
||||
TryCatchBlockNode tcb = insnHandlers.get(i);
|
||||
int jump = insns.indexOf(tcb.handler);
|
||||
handler.init(f);
|
||||
handler.clearStack();
|
||||
handler.push(interpreter.newValue(ASMUtils.THROWABLE_TYPE));
|
||||
merge(jump, handler);
|
||||
}
|
||||
}
|
||||
} catch (AnalyzerException e) {
|
||||
throw new AnalyzerException(e.node, "Error at instruction " + insn + ": " + e.getMessage(), e);
|
||||
} catch (Exception e) {
|
||||
throw new AnalyzerException(insnNode, "Error at instruction " + insn + ": " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
|
||||
return frames;
|
||||
}
|
||||
|
||||
public Frame<V>[] getFrames() {
|
||||
return frames;
|
||||
}
|
||||
|
||||
private void merge(final int insn, final Frame<V> frame) throws AnalyzerException {
|
||||
Frame<V> oldFrame = frames[insn];
|
||||
boolean changes;
|
||||
|
||||
if (oldFrame == null) {
|
||||
frames[insn] = new Frame<V>(frame);
|
||||
changes = true;
|
||||
} else {
|
||||
changes = oldFrame.merge(frame, interpreter);
|
||||
}
|
||||
if (changes && !queued[insn]) {
|
||||
queued[insn] = true;
|
||||
queue[top++] = insn;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
+56
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* Copyright 2000-2014 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.codeInspection.bytecodeAnalysis.asm;
|
||||
|
||||
import org.jetbrains.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import org.jetbrains.org.objectweb.asm.tree.analysis.AnalyzerException;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Specialized lite version of {@link FramelessAnalyzer}.
|
||||
* No processing of Subroutines. May be used for methods without JSR/RET instructions.
|
||||
*
|
||||
* @author lambdamix
|
||||
*/
|
||||
public class LiteFramelessAnalyzer extends FramelessAnalyzer {
|
||||
|
||||
@Override
|
||||
protected void findSubroutine(int insn, FramelessAnalyzer.Subroutine sub, List<AbstractInsnNode> calls) throws AnalyzerException {
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void merge(final int insn, final FramelessAnalyzer.Subroutine subroutine) throws AnalyzerException {
|
||||
if (!wasQueued[insn]) {
|
||||
wasQueued[insn] = true;
|
||||
if (!queued[insn]) {
|
||||
queued[insn] = true;
|
||||
queue[top++] = insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void merge(final int insn, final FramelessAnalyzer.Subroutine subroutineBeforeJSR, final boolean[] access) throws AnalyzerException {
|
||||
if (!wasQueued[insn]) {
|
||||
wasQueued[insn] = true;
|
||||
if (!queued[insn]) {
|
||||
queued[insn] = true;
|
||||
queue[top++] = insn;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -95,7 +95,7 @@ public class BytecodeAnalysisTest extends JavaCodeInsightFixtureTestCase {
|
||||
public void visitEnd() {
|
||||
super.visitEnd();
|
||||
try {
|
||||
map.put(method, LeakingParametersAnalysis.leakingParameters(classReader.getClassName(), node).first);
|
||||
map.put(method, LeakingParametersAnalysis.leakingParameters(classReader.getClassName(), node, false).first);
|
||||
}
|
||||
catch (AnalyzerException ignore) {}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user