mirror of
https://gitflic.ru/project/openide/openide.git
synced 2026-01-04 00:20:55 +07:00
DFA: make CFG independent on assertion status
GitOrigin-RevId: 4c81f96bb7d6108d4e74898bfc5f014e753132e1
This commit is contained in:
committed by
intellij-monorepo-bot
parent
ebde07d923
commit
546d12c3f8
@@ -47,7 +47,6 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
static final int MAX_UNROLL_SIZE = 3;
|
||||
private static final int MAX_ARRAY_INDEX_FOR_INITIALIZER = 32;
|
||||
private final PsiElement myCodeFragment;
|
||||
private final boolean myIgnoreAssertions;
|
||||
private final boolean myInlining;
|
||||
private final Project myProject;
|
||||
|
||||
@@ -60,12 +59,11 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
private final Map<String, ExceptionTransfer> myExceptionCache;
|
||||
private ExpressionBlockContext myExpressionBlockContext;
|
||||
|
||||
ControlFlowAnalyzer(final DfaValueFactory valueFactory, @NotNull PsiElement codeFragment, boolean ignoreAssertions, boolean inlining) {
|
||||
ControlFlowAnalyzer(final DfaValueFactory valueFactory, @NotNull PsiElement codeFragment, boolean inlining) {
|
||||
myInlining = inlining;
|
||||
myFactory = valueFactory;
|
||||
myCodeFragment = codeFragment;
|
||||
myProject = codeFragment.getProject();
|
||||
myIgnoreAssertions = ignoreAssertions;
|
||||
GlobalSearchScope scope = codeFragment.getResolveScope();
|
||||
myExceptionCache = FactoryMap.create(fqn -> new ExceptionTransfer(myFactory.createDfaType(createClassType(scope, fqn))));
|
||||
}
|
||||
@@ -233,11 +231,10 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
}
|
||||
|
||||
@Override public void visitAssertStatement(PsiAssertStatement statement) {
|
||||
if (myIgnoreAssertions) {
|
||||
return;
|
||||
}
|
||||
|
||||
startElement(statement);
|
||||
addInstruction(new PushInstruction(myFactory.getExpressionFactory().getAssertionsDisabledVariable(), null));
|
||||
ConditionalGotoInstruction jump = new ConditionalGotoInstruction(null, false, null);
|
||||
addInstruction(jump);
|
||||
final PsiExpression condition = statement.getAssertCondition();
|
||||
final PsiExpression description = statement.getAssertDescription();
|
||||
if (condition != null) {
|
||||
@@ -250,6 +247,7 @@ public class ControlFlowAnalyzer extends JavaElementVisitor {
|
||||
|
||||
throwException(myExceptionCache.get(JAVA_LANG_ASSERTION_ERROR), statement);
|
||||
}
|
||||
jump.setOffset(getInstructionCount());
|
||||
finishElement(statement);
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ import java.lang.management.ThreadMXBean;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class DataFlowRunner {
|
||||
private static final Logger LOG = Logger.getInstance(DataFlowRunner.class);
|
||||
@@ -178,7 +179,7 @@ public class DataFlowRunner {
|
||||
ControlFlow flow = null;
|
||||
try {
|
||||
myStats.reset();
|
||||
flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, myIgnoreAssertions, myInlining).buildControlFlow();
|
||||
flow = new ControlFlowAnalyzer(myValueFactory, psiBlock, myInlining).buildControlFlow();
|
||||
myStats.endFlow();
|
||||
|
||||
if (flow != null) {
|
||||
@@ -435,6 +436,14 @@ public class DataFlowRunner {
|
||||
private void initializeVariables(@NotNull PsiElement psiBlock,
|
||||
@NotNull Collection<? extends DfaMemoryState> initialStates,
|
||||
@NotNull ControlFlow flow) {
|
||||
List<DfaVariableValue> vars = flow.accessedVariables().collect(Collectors.toList());
|
||||
DfaVariableValue assertionStatus =
|
||||
ContainerUtil.find(vars, v -> v.getDescriptor() instanceof DfaExpressionFactory.AssertionDisabledDescriptor);
|
||||
if (assertionStatus != null) {
|
||||
for (DfaMemoryState state : initialStates) {
|
||||
state.applyCondition(assertionStatus.eq(myValueFactory.getBoolean(myIgnoreAssertions)));
|
||||
}
|
||||
}
|
||||
if (psiBlock instanceof PsiClass) {
|
||||
DfaVariableValue thisValue = getFactory().getVarFactory().createThisValue((PsiClass)psiBlock);
|
||||
// In class initializer this variable is local until escaped
|
||||
@@ -445,7 +454,7 @@ public class DataFlowRunner {
|
||||
}
|
||||
PsiElement parent = psiBlock.getParent();
|
||||
if (parent instanceof PsiMethod && !(((PsiMethod)parent).isConstructor())) {
|
||||
Map<DfaVariableValue, DfaValue> initialValues = StreamEx.of(flow.accessedVariables()).mapToEntry(
|
||||
Map<DfaVariableValue, DfaValue> initialValues = StreamEx.of(vars).mapToEntry(
|
||||
var -> makeInitialValue(var, (PsiMethod)parent)).nonNullValues().toMap();
|
||||
for (DfaMemoryState state : initialStates) {
|
||||
initialValues.forEach(state::setVarValue);
|
||||
|
||||
@@ -299,6 +299,32 @@ public class DfaExpressionFactory {
|
||||
}
|
||||
return PsiSubstitutor.EMPTY;
|
||||
}
|
||||
|
||||
public DfaVariableValue getAssertionsDisabledVariable() {
|
||||
return myFactory.getVarFactory().createVariableValue(AssertionDisabledDescriptor.INSTANCE);
|
||||
}
|
||||
|
||||
public static final class AssertionDisabledDescriptor implements VariableDescriptor {
|
||||
static final AssertionDisabledDescriptor INSTANCE = new AssertionDisabledDescriptor();
|
||||
|
||||
private AssertionDisabledDescriptor() {}
|
||||
|
||||
@Override
|
||||
public boolean isStable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
@Override
|
||||
public PsiType getType(@Nullable DfaVariableValue qualifier) {
|
||||
return PsiType.BOOLEAN;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "$assertionsDisabled";
|
||||
}
|
||||
}
|
||||
|
||||
static final class PlainDescriptor implements VariableDescriptor {
|
||||
private final @NotNull PsiVariable myVariable;
|
||||
|
||||
Reference in New Issue
Block a user