[java-analysis] Combined: avoid stream API; some simplifications

GitOrigin-RevId: e084277028abe134613f7579b317c15d86d20f25
This commit is contained in:
Tagir Valeev
2021-02-04 17:35:18 +07:00
committed by intellij-monorepo-bot
parent 21c6697128
commit d3944cbd37
3 changed files with 44 additions and 42 deletions

View File

@@ -29,8 +29,6 @@ import java.util.concurrent.atomic.AtomicLong;
import java.util.function.BiFunction;
import java.util.function.BinaryOperator;
import java.util.function.Function;
import java.util.function.IntFunction;
import java.util.stream.Stream;
import static com.intellij.codeInspection.bytecodeAnalysis.Direction.*;
import static com.intellij.codeInspection.bytecodeAnalysis.Effects.VOLATILE_EFFECTS;
@@ -502,31 +500,6 @@ public class ClassDataIndexer implements VirtualFileGist.GistCalculator<Map<HMem
return;
}
final IntFunction<Function<Value, Stream<Equation>>> inOuts =
index -> val -> {
if (isBooleanResult && negatedAnalysis != null) {
return Stream.of(negatedAnalysis.contractEquation(index, val, stable));
}
Stream.Builder<Equation> builder = Stream.builder();
try {
if (isInterestingResult) {
builder.add(new InOutAnalysis(richControlFlow, new InOut(index, val), origins, stable, mySharedPendingStates).analyze());
}
if (shouldInferNonTrivialFailingContracts) {
InThrow direction = new InThrow(index, val);
if (throwEquation.result.equals(Value.Fail)) {
builder.add(new Equation(new EKey(method, direction, stable), Value.Fail));
}
else {
builder.add(new InThrowAnalysis(richControlFlow, direction, origins, stable, mySharedPendingStates).analyze());
}
}
}
catch (AnalyzerException e) {
throw new RuntimeException("Analyzer error", e);
}
return builder.build();
};
// arguments and contract clauses
for (int i = 0; i < argumentTypes.length; i++) {
boolean notNullParam = false;
@@ -573,7 +546,27 @@ public class ClassDataIndexer implements VirtualFileGist.GistCalculator<Map<HMem
}
}
}
Value.typeValues(argumentTypes[i]).flatMap(inOuts.apply(i)).forEach(result::add);
for (Value val : Value.typeValues(argumentTypes[i])) {
if (isBooleanResult && negatedAnalysis != null) {
result.add(negatedAnalysis.contractEquation(i, val, stable));
continue;
}
try {
if (isInterestingResult) {
result.add(new InOutAnalysis(richControlFlow, new InOut(i, val), origins, stable, mySharedPendingStates).analyze());
}
if (shouldInferNonTrivialFailingContracts) {
InThrow direction = new InThrow(i, val);
Equation failEquation = throwEquation.result.equals(Value.Fail)
? new Equation(new EKey(method, direction, stable), Value.Fail)
: new InThrowAnalysis(richControlFlow, direction, origins, stable, mySharedPendingStates).analyze();
result.add(failEquation);
}
}
catch (AnalyzerException e) {
throw new RuntimeException("Analyzer error", e);
}
}
}
}
@@ -592,16 +585,22 @@ public class ClassDataIndexer implements VirtualFileGist.GistCalculator<Map<HMem
if (ASMUtils.isReferenceType(returnType)) {
result.add(analyzer.nullableResultEquation(stable));
}
EntryStream.of(argumentTypes).forKeyValue((i, argType) -> {
for (int i = 0; i < argumentTypes.length; i++) {
Type argType = argumentTypes[i];
if (ASMUtils.isReferenceType(argType)) {
result.add(analyzer.notNullParamEquation(i, stable));
result.add(analyzer.nullableParamEquation(i, stable));
for (Value val : Value.OBJECT) {
ContainerUtil.addIfNotNull(result, analyzer.contractEquation(i, val, stable));
ContainerUtil.addIfNotNull(result, analyzer.failEquation(i, val, stable));
}
} else if (ASMUtils.isBooleanType(argType)) {
for (Value val : Value.BOOLEAN) {
ContainerUtil.addIfNotNull(result, analyzer.contractEquation(i, val, stable));
ContainerUtil.addIfNotNull(result, analyzer.failEquation(i, val, stable));
}
}
Value.typeValues(argType)
.flatMap(val -> Stream.of(analyzer.contractEquation(i, val, stable), analyzer.failEquation(i, val, stable)))
.filter(Objects::nonNull)
.forEach(result::add);
});
}
}
private void storeStaticFieldEquations(CombinedAnalysis analyzer) {

View File

@@ -17,7 +17,6 @@ import org.jetbrains.org.objectweb.asm.tree.analysis.BasicValue;
import org.jetbrains.org.objectweb.asm.tree.analysis.Frame;
import java.util.*;
import java.util.stream.Collectors;
import static com.intellij.codeInspection.bytecodeAnalysis.AbstractValues.*;
import static com.intellij.codeInspection.bytecodeAnalysis.CombinedData.*;
@@ -279,8 +278,10 @@ final class CombinedAnalysis {
result = Value.Fail;
}
else if (!interpreter.calls.isEmpty()) {
Set<EKey> keys =
interpreter.calls.stream().map(call -> new EKey(call.method, Throw, call.stableCall)).collect(Collectors.toSet());
Set<EKey> keys = new HashSet<>();
for (TrackableCallValue call : interpreter.calls) {
keys.add(new EKey(call.method, Throw, call.stableCall));
}
result = new Pending(Collections.singleton(new Component(Value.Top, keys)));
}
else {

View File

@@ -6,15 +6,17 @@ import com.intellij.codeInspection.dataFlow.ContractReturnValue;
import com.intellij.codeInspection.dataFlow.StandardMethodContract;
import org.jetbrains.org.objectweb.asm.Type;
import java.util.stream.Stream;
import java.util.List;
enum Value implements Result {
Bot, NotNull, Null, True, False, Fail, Pure, Top;
static final List<Value> BOOLEAN = List.of(True, False);
static final List<Value> OBJECT = List.of(Null, NotNull);
static Stream<Value> typeValues(Type type) {
if (ASMUtils.isReferenceType(type)) return Stream.of(Null, NotNull);
if (ASMUtils.isBooleanType(type)) return Stream.of(True, False);
return Stream.empty();
static List<Value> typeValues(Type type) {
if (ASMUtils.isReferenceType(type)) return OBJECT;
if (ASMUtils.isBooleanType(type)) return BOOLEAN;
return List.of();
}
ContractReturnValue toReturnValue() {