use of org.sonar.plugins.java.api.semantic.Type 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.plugins.java.api.semantic.Type in project sonar-java by SonarSource.
the class SymbolMetadataResolve method metaAnnotations.
private List<Symbol> metaAnnotations(Set<Type> knownTypes) {
List<Symbol> result = new ArrayList<>();
for (AnnotationInstance annotationInstance : annotations) {
Symbol annotationSymbol = annotationInstance.symbol();
Type annotationType = annotationSymbol.type();
if (!knownTypes.contains(annotationType)) {
knownTypes.add(annotationType);
result.add(annotationSymbol);
result.addAll(((SymbolMetadataResolve) annotationSymbol.metadata()).metaAnnotations(knownTypes));
}
}
return new ArrayList<>(result);
}
use of org.sonar.plugins.java.api.semantic.Type in project sonar-java by SonarSource.
the class TypeAndReferenceSolver method visitTypeCast.
@Override
public void visitTypeCast(TypeCastTree tree) {
resolveAs(tree.type(), JavaSymbol.TYP);
resolveAs(tree.expression(), JavaSymbol.VAR);
JavaType castType = getType(tree.type());
Type expressionType = tree.expression().symbolType();
if (expressionType instanceof DeferredType) {
setInferedType(castType, (DeferredType) expressionType);
}
registerType(tree, castType);
}
use of org.sonar.plugins.java.api.semantic.Type in project sonar-java by SonarSource.
the class TypeAndReferenceSolver method visitReturnStatement.
@Override
public void visitReturnStatement(ReturnStatementTree tree) {
super.visitReturnStatement(tree);
ExpressionTree expression = tree.expression();
if (expression != null && ((JavaType) expression.symbolType()).isTagged(JavaType.DEFERRED)) {
// get owner of return (method or lambda)
Tree parent = tree.parent();
while (!parent.is(Tree.Kind.METHOD, Tree.Kind.LAMBDA_EXPRESSION)) {
parent = parent.parent();
if (parent == null) {
throw new IllegalStateException("Return statement was unexpected here");
}
}
Type infered;
if (parent.is(Tree.Kind.METHOD)) {
infered = ((MethodTree) parent).returnType().symbolType();
} else {
infered = ((LambdaExpressionTree) parent).symbolType();
}
setInferedType(infered, (DeferredType) expression.symbolType());
}
}
use of org.sonar.plugins.java.api.semantic.Type in project sonar-java by SonarSource.
the class TypeAndReferenceSolver method visitMethodInvocation.
@Override
public void visitMethodInvocation(MethodInvocationTree tree) {
MethodInvocationTreeImpl mit = (MethodInvocationTreeImpl) tree;
Resolve.Env methodEnv = semanticModel.getEnv(tree);
if (mit.isTypeSet() && mit.symbol().isMethodSymbol()) {
TypeSubstitution typeSubstitution = inferedSubstitution(mit);
List<JavaType> argTypes = getParameterTypes(tree.arguments());
JavaSymbol.MethodJavaSymbol methodSymbol = (JavaSymbol.MethodJavaSymbol) mit.symbol();
List<JavaType> formals = methodSymbol.parameterTypes().stream().map(t -> (JavaType) t).collect(Collectors.toList());
List<JavaType> inferedArgTypes = resolve.resolveTypeSubstitution(formals, typeSubstitution);
int size = inferedArgTypes.size();
IntStream.range(0, argTypes.size()).forEach(i -> {
JavaType arg = argTypes.get(i);
Type formal = inferedArgTypes.get(Math.min(i, size - 1));
if (formal != arg) {
AbstractTypedTree argTree = (AbstractTypedTree) mit.arguments().get(i);
argTree.setInferedType(formal);
argTree.accept(this);
}
});
List<JavaType> typeParamTypes = getParameterTypes(tree.typeArguments());
JavaType resultType = ((MethodJavaType) mit.symbol().type()).resultType;
// if result type is a type var defined by the method we are solving, use the target type.
if (resultType.symbol.owner == mit.symbol()) {
resultType = (JavaType) mit.symbolType();
}
inferReturnTypeFromInferedArgs(tree, methodEnv, argTypes, typeParamTypes, resultType, typeSubstitution);
return;
}
scan(tree.arguments());
scan(tree.typeArguments());
List<JavaType> argTypes = getParameterTypes(tree.arguments());
List<JavaType> typeParamTypes = getParameterTypes(tree.typeArguments());
Resolve.Resolution resolution = resolveMethodSymbol(tree.methodSelect(), methodEnv, argTypes, typeParamTypes);
JavaSymbol symbol;
JavaType returnType;
if (resolution == null) {
returnType = symbols.deferedType(mit);
symbol = Symbols.unknownSymbol;
} else {
symbol = resolution.symbol();
returnType = resolution.type();
if (symbol.isMethodSymbol()) {
MethodJavaType methodType = (MethodJavaType) resolution.type();
returnType = methodType.resultType;
}
}
mit.setSymbol(symbol);
if (returnType != null && returnType.isTagged(JavaType.DEFERRED)) {
((DeferredType) returnType).setTree(mit);
}
registerType(tree, returnType);
if (resolution != null) {
inferArgumentTypes(argTypes, resolution);
inferReturnTypeFromInferedArgs(tree, methodEnv, argTypes, typeParamTypes, returnType, new TypeSubstitution());
}
}
Aggregations