use of org.sonar.plugins.java.api.tree.MethodInvocationTree in project sonar-java by SonarSource.
the class TypeAndReferenceSolver method inferReturnTypeFromInferedArgs.
private void inferReturnTypeFromInferedArgs(MethodInvocationTree tree, Resolve.Env methodEnv, List<JavaType> argTypes, List<JavaType> typeParamTypes, JavaType returnType, TypeSubstitution typeSubstitution) {
List<JavaType> parameterTypes = getParameterTypes(tree.arguments());
if (!parameterTypes.equals(argTypes)) {
IdentifierTree identifier = null;
Resolution resolution = null;
Tree methodSelect = tree.methodSelect();
if (methodSelect.is(Tree.Kind.MEMBER_SELECT)) {
MemberSelectExpressionTree mset = (MemberSelectExpressionTree) methodSelect;
JavaType type = getType(mset.expression());
if (type.isTagged(JavaType.DEFERRED)) {
throw new IllegalStateException("type of arg should not be defered anymore ??");
}
identifier = mset.identifier();
resolution = resolve.findMethod(methodEnv, type, identifier.name(), parameterTypes, typeParamTypes);
} else if (methodSelect.is(Tree.Kind.IDENTIFIER)) {
identifier = (IdentifierTree) methodSelect;
resolution = resolve.findMethod(methodEnv, identifier.name(), parameterTypes, typeParamTypes);
}
if (resolution != null && returnType != resolution.type() && resolution.symbol().isMethodSymbol()) {
MethodJavaType methodType = (MethodJavaType) resolution.type();
if (!methodType.resultType.isTagged(JavaType.DEFERRED)) {
registerType(tree, resolve.applySubstitution(methodType.resultType, typeSubstitution));
// update type associated to identifier as it may have been inferred deeper when re-resolving method with new parameter types
registerType(identifier, methodType);
}
}
} else {
registerType(tree, resolve.applySubstitution(returnType, typeSubstitution));
}
}
use of org.sonar.plugins.java.api.tree.MethodInvocationTree in project sonar-java by SonarSource.
the class MapComputeIfAbsentOrPresentCheck method checkPostStatement.
@Override
public ProgramState checkPostStatement(CheckerContext context, Tree syntaxNode) {
if (syntaxNode.is(Tree.Kind.METHOD_INVOCATION)) {
MethodInvocationTree mit = (MethodInvocationTree) syntaxNode;
if (MAP_GET.matches(mit)) {
ProgramState psBeforeInvocation = context.getNode().programState;
ProgramState psAfterInvocation = context.getState();
SymbolicValue keySV = psBeforeInvocation.peekValue(0);
SymbolicValue mapSV = psBeforeInvocation.peekValue(1);
SymbolicValue valueSV = psAfterInvocation.peekValue();
mapGetInvocations.put(mapSV, new MapGetInvocation(valueSV, keySV, mit));
}
}
return super.checkPostStatement(context, syntaxNode);
}
use of org.sonar.plugins.java.api.tree.MethodInvocationTree in project sonar-java by SonarSource.
the class NonNullSetToNullCheck method callsThisConstructor.
private static boolean callsThisConstructor(MethodTree constructor) {
List<StatementTree> body = constructor.block().body();
if (body.isEmpty()) {
return false;
}
StatementTree firstStatement = body.get(0);
if (!firstStatement.is(Tree.Kind.EXPRESSION_STATEMENT)) {
return false;
}
ExpressionTree expression = ((ExpressionStatementTree) firstStatement).expression();
if (!expression.is(Tree.Kind.METHOD_INVOCATION)) {
return false;
}
ExpressionTree methodSelect = ((MethodInvocationTree) expression).methodSelect();
return methodSelect.is(Tree.Kind.IDENTIFIER) && "this".equals(((IdentifierTree) methodSelect).name());
}
use of org.sonar.plugins.java.api.tree.MethodInvocationTree in project sonar-java by SonarSource.
the class ExceptionalYieldChecker method reportIssue.
private void reportIssue(ExplodedGraph.Node node, ExceptionalCheckBasedYield yield, SECheck check) {
MethodInvocationTree mit = (MethodInvocationTree) node.programPoint.syntaxTree();
ExpressionTree methodSelect = mit.methodSelect();
String methodName = mit.symbol().name();
Tree reportTree = methodSelect;
if (methodSelect.is(Tree.Kind.MEMBER_SELECT)) {
reportTree = ((MemberSelectExpressionTree) methodSelect).identifier();
}
JavaFileScannerContext.Location methodInvocationMessage;
int parameterCausingExceptionIndex = yield.parameterCausingExceptionIndex();
IdentifierTree identifierTree = FlowComputation.getArgumentIdentifier(mit, parameterCausingExceptionIndex);
if (identifierTree != null) {
methodInvocationMessage = new JavaFileScannerContext.Location(String.format("'%s' is passed to '%s()'.", identifierTree.name(), methodName), identifierTree);
} else {
methodInvocationMessage = new JavaFileScannerContext.Location(String.format("'%s()' is invoked.", methodName), reportTree);
}
Flow argumentChangingNameFlows = flowsForArgumentsChangingName(yield, mit);
Set<Flow> argumentsFlows = flowsForMethodArguments(node, mit, parameterCausingExceptionIndex);
Set<Flow> exceptionFlows = yield.exceptionFlows();
ImmutableSet.Builder<Flow> flows = ImmutableSet.builder();
for (Flow argumentFlow : argumentsFlows) {
for (Flow exceptionFlow : exceptionFlows) {
flows.add(Flow.builder().addAll(exceptionFlow).addAll(argumentChangingNameFlows).add(methodInvocationMessage).addAll(argumentFlow).build());
}
}
check.reportIssue(reportTree, String.format(message, methodName), flows.build());
}
use of org.sonar.plugins.java.api.tree.MethodInvocationTree in project sonar-java by SonarSource.
the class ExceptionalYieldChecker method flowsForMethodArguments.
private static Set<Flow> flowsForMethodArguments(ExplodedGraph.Node node, MethodInvocationTree mit, int parameterCausingExceptionIndex) {
ProgramState programState = node.programState;
List<ProgramState.SymbolicValueSymbol> arguments = Lists.reverse(programState.peekValuesAndSymbols(mit.arguments().size()));
SymbolicValue parameterCausingExceptionSV = arguments.get(parameterCausingExceptionIndex).symbolicValue();
Set<SymbolicValue> argSymbolicValues = new LinkedHashSet<>();
Set<Symbol> argSymbols = new LinkedHashSet<>();
arguments.stream().filter(svs -> parameterCausingExceptionSV == svs.symbolicValue() || hasConstraintOtherThanNonNull(svs, programState)).forEach(svs -> {
argSymbolicValues.add(svs.symbolicValue());
Symbol symbol = svs.symbol();
if (symbol != null) {
argSymbols.add(symbol);
}
});
List<Class<? extends Constraint>> domains = domainsFromArguments(programState, argSymbolicValues);
return FlowComputation.flow(node, argSymbolicValues, c -> true, c -> false, domains, argSymbols);
}
Aggregations