use of org.sonar.java.se.constraint.ConstraintManager in project sonar-java by SonarSource.
the class ExplodedGraphWalker method execute.
private void execute(MethodTree tree) {
CFG cfg = CFG.build(tree);
exitBlock = cfg.exitBlock();
checkerDispatcher.init(tree, cfg);
liveVariables = LiveVariables.analyze(cfg);
explodedGraph = new ExplodedGraph();
methodTree = tree;
constraintManager = new ConstraintManager();
workList = new LinkedList<>();
// Linked hashSet is required to guarantee order of yields to be generated
endOfExecutionPath = new LinkedHashSet<>();
if (DEBUG_MODE_ACTIVATED) {
LOG.debug("Exploring Exploded Graph for method " + tree.simpleName().name() + " at line " + ((JavaTree) tree).getLine());
}
programState = ProgramState.EMPTY_STATE;
steps = 0;
for (ProgramState startingState : startingStates(tree, programState)) {
enqueue(new ProgramPoint(cfg.entry()), startingState);
}
while (!workList.isEmpty()) {
steps++;
if (steps > maxSteps()) {
throwMaxSteps(tree);
}
// LIFO:
setNode(workList.removeFirst());
CFG.Block block = (CFG.Block) programPosition.block;
if (block.successors().isEmpty()) {
endOfExecutionPath.add(node);
continue;
}
try {
Tree terminator = block.terminator();
if (programPosition.i < block.elements().size()) {
// process block element
visit(block.elements().get(programPosition.i), terminator);
} else if (terminator == null) {
// process block exit, which is unconditional jump such as goto-statement or return-statement
handleBlockExit(programPosition);
} else if (programPosition.i == block.elements().size()) {
// process block exist, which is conditional jump such as if-statement
checkerDispatcher.executeCheckPostStatement(terminator);
} else {
// process branch
// process block exist, which is conditional jump such as if-statement
checkerDispatcher.executeCheckPreStatement(terminator);
handleBlockExit(programPosition);
}
} catch (TooManyNestedBooleanStatesException e) {
throwTooManyBooleanStates(tree, e);
} catch (RelationalSymbolicValue.TransitiveRelationExceededException e) {
throwTooManyTransitiveRelationsException(tree, e);
}
}
handleEndOfExecutionPath(false);
checkerDispatcher.executeCheckEndOfExecution();
// Cleanup:
workList = null;
node = null;
programState = null;
constraintManager = null;
}
use of org.sonar.java.se.constraint.ConstraintManager in project sonar-java by SonarSource.
the class SymbolicValueFactoryTest method testFactory.
@Test
public void testFactory() {
final IdentifierTree tree = new IdentifierTreeImpl(new InternalSyntaxToken(1, 1, "id", Collections.<SyntaxTrivia>emptyList(), 0, 0, false));
final ConstraintManager manager = new ConstraintManager();
SymbolicValue symbolicValue = manager.createSymbolicValue(tree);
assertThat(symbolicValue.getClass()).as("Created without factory").isSameAs(SymbolicValue.class);
manager.setValueFactory(new TestSymbolicValueFactory());
symbolicValue = manager.createSymbolicValue(tree);
assertThat(symbolicValue.getClass()).as("Created with factory").isSameAs(TestSymbolicValue.class);
assertThat(symbolicValue.references(symbolicValue)).isFalse();
manager.setValueFactory(new TestSymbolicValueFactory());
try {
manager.setValueFactory(new TestSymbolicValueFactory());
fail("Able to add a second factory to the contraints manager");
} catch (IllegalStateException e) {
assertThat(e.getMessage()).as("Exception message").isEqualTo("The symbolic value factory has already been defined by another checker!");
}
symbolicValue = manager.createSymbolicValue(tree);
assertThat(symbolicValue.getClass()).as("Created with first factory").isSameAs(TestSymbolicValue.class);
symbolicValue = manager.createSymbolicValue(tree);
assertThat(symbolicValue.getClass()).as("Created after factory usage").isSameAs(SymbolicValue.class);
}
use of org.sonar.java.se.constraint.ConstraintManager in project sonar-java by SonarSource.
the class ExplodedGraphWalker method executeMethodInvocation.
private void executeMethodInvocation(MethodInvocationTree mit) {
setSymbolicValueOnFields(mit);
// unstack arguments and method identifier
ProgramState.Pop unstack = programState.unstackValue(mit.arguments().size() + 1);
logState(mit);
programState = unstack.state;
// get method behavior for method with known declaration (ie: within the same file)
MethodBehavior methodInvokedBehavior = null;
Symbol methodSymbol = mit.symbol();
if (methodSymbol.isMethodSymbol()) {
methodInvokedBehavior = behaviorCache.get((Symbol.MethodSymbol) methodSymbol);
}
// Enqueue additional exceptional paths corresponding to unchecked exceptions, for instance OutOfMemoryError
enqueueUncheckedExceptionalPaths(methodSymbol);
final SymbolicValue resultValue = constraintManager.createMethodSymbolicValue(mit, unstack.valuesAndSymbols);
if (methodInvokedBehavior != null && methodInvokedBehavior.isComplete() && !EQUALS_METHODS.anyMatch(mit)) {
List<SymbolicValue> invocationArguments = invocationArguments(unstack.values);
List<Type> invocationTypes = mit.arguments().stream().map(ExpressionTree::symbolType).collect(Collectors.toList());
Map<Type, SymbolicValue.ExceptionalSymbolicValue> thrownExceptionsByExceptionType = new HashMap<>();
// Enqueue exceptional paths from exceptional yields
methodInvokedBehavior.exceptionalPathYields().forEach(yield -> yield.statesAfterInvocation(invocationArguments, invocationTypes, programState, () -> thrownExceptionsByExceptionType.computeIfAbsent(yield.exceptionType(semanticModel), constraintManager::createExceptionalSymbolicValue)).forEach(psYield -> enqueueExceptionalPaths(psYield, methodSymbol, yield)));
// Enqueue happy paths
methodInvokedBehavior.happyPathYields().forEach(yield -> yield.statesAfterInvocation(invocationArguments, invocationTypes, programState, () -> resultValue).map(psYield -> handleSpecialMethods(psYield, mit)).forEach(psYield -> enqueueHappyPath(psYield, mit, yield)));
} else {
// Enqueue exceptional paths from thrown exceptions
enqueueThrownExceptionalPaths(methodSymbol);
// Enqueue happy paths
programState = handleSpecialMethods(programState.stackValue(resultValue), mit);
checkerDispatcher.executeCheckPostStatement(mit);
clearStack(mit);
}
}
use of org.sonar.java.se.constraint.ConstraintManager in project sonar-java by SonarSource.
the class NonNullSetToNullCheck method checkEndOfExecutionPath.
@Override
public void checkEndOfExecutionPath(CheckerContext context, ConstraintManager constraintManager) {
if (methodTree.is(Tree.Kind.CONSTRUCTOR) && !isDefaultConstructorForJpa(methodTree) && !callsThisConstructor(methodTree) && !exitingWithException(context)) {
ClassTree classTree = (ClassTree) methodTree.parent();
classTree.members().stream().filter(m -> m.is(Tree.Kind.VARIABLE)).map(m -> (VariableTree) m).filter(v -> v.initializer() == null).forEach(v -> checkVariable(context, methodTree, v.symbol()));
}
}
Aggregations