@Override public void visitMethodReference(MethodReferenceTree methodReferenceTree) { MethodReferenceTreeImpl methodRefTree = (MethodReferenceTreeImpl) methodReferenceTree; if (methodRefTree.isTypeSet() && methodReferenceTree.typeArguments() == null) { resolve.getSamMethod((JavaType) methodRefTree.symbolType()).ifPresent(samMethod -> resolveMethodReference(samMethod, methodRefTree)); } else { // TODO : SONARJAVA-1663 : consider type arguments for method resolution and substitution scan(methodReferenceTree.typeArguments()); resolveAs(methodReferenceTree.expression(), JavaSymbol.VAR | JavaSymbol.TYP); registerType(methodRefTree, symbols.deferedType(methodRefTree)); } }
@Override public void visitMethodReference(MethodReferenceTree methodReferenceTree) { MethodReferenceTreeImpl methodRefTree = (MethodReferenceTreeImpl) methodReferenceTree; if (methodRefTree.isTypeSet() && methodReferenceTree.typeArguments() == null) { resolve.getSamMethod((JavaType) methodRefTree.symbolType()).ifPresent(samMethod -> resolveMethodReference(samMethod, methodRefTree)); } else { // TODO : SONARJAVA-1663 : consider type arguments for method resolution and substitution scan(methodReferenceTree.typeArguments()); resolveAs(methodReferenceTree.expression(), JavaSymbol.VAR | JavaSymbol.TYP); registerType(methodRefTree, symbols.deferedType(methodRefTree)); } }
JavaType getReturnType(@Nullable JavaType returnType, JavaType defSite, JavaType callSite, TypeSubstitution substitution, JavaSymbol.MethodJavaSymbol method) { JavaType resultType = returnType; if (method.isConstructor()) { if (constructParametrizedTypeWithoutSubstitution(method, defSite)) { resultType = applySubstitution(defSite, substitution); } else { return defSite; } } // As per getClass javadoc: // The actual result type [of getClass] is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. if(defSite == symbols.objectType && "getClass".equals(method.name())) { TypeJavaSymbol classSymbol = symbols.classType.symbol; JavaType wildcardType = parametrizedTypeCache.getWildcardType(callSite.erasure(), WildCardType.BoundType.EXTENDS); resultType = parametrizedTypeCache.getParametrizedTypeType(classSymbol, new TypeSubstitution().add(classSymbol.typeVariableTypes.get(0), wildcardType)); } resultType = applySiteSubstitution(resultType, defSite); if (callSite != defSite) { resultType = applySiteSubstitution(resultType, callSite); } resultType = applySubstitution(resultType, substitution); if (!isReturnTypeCompletelySubstituted(resultType, method.typeVariableTypes) || (method.isConstructor() && !isReturnTypeCompletelySubstituted(resultType, defSite.symbol.typeVariableTypes))) { resultType = symbols.deferedType(resultType); } return resultType; }
@Override public void visitLambdaExpression(LambdaExpressionTree tree) { LambdaExpressionTreeImpl lambdaExpressionTree = (LambdaExpressionTreeImpl) tree; if (lambdaExpressionTree.isTypeSet()) { // type should be tied to a SAM interface JavaType lambdaType = (JavaType) lambdaExpressionTree.symbolType(); List<JavaType> samMethodArgs = resolve.findSamMethodArgs(lambdaType); for (int i = 0; i < samMethodArgs.size(); i++) { VariableTree param = lambdaExpressionTree.parameters().get(i); if (param.type().is(Tree.Kind.INFERED_TYPE)) { JavaType inferedType = samMethodArgs.get(i); if(inferedType.isTagged(JavaType.WILDCARD)) { // JLS8 18.5.3 inferedType = ((WildCardType) inferedType).bound; } ((AbstractTypedTree) param.type()).setInferedType(inferedType); ((JavaSymbol.VariableJavaSymbol) param.symbol()).type = inferedType; } } super.visitLambdaExpression(tree); if(lambdaType.isUnknown() || lambdaType.isTagged(JavaType.DEFERRED)) { return; } refineLambdaType(lambdaExpressionTree, lambdaType); } else { registerType(tree, symbols.deferedType(lambdaExpressionTree)); } }
JavaType getReturnType(@Nullable JavaType returnType, JavaType defSite, JavaType callSite, TypeSubstitution substitution, JavaSymbol.MethodJavaSymbol method) { JavaType resultType = returnType; if (method.isConstructor()) { if (constructParametrizedTypeWithoutSubstitution(method, defSite)) { resultType = applySubstitution(defSite, substitution); } else { return defSite; } } // As per getClass javadoc: // The actual result type [of getClass] is Class<? extends |X|> where |X| is the erasure of the static type of the expression on which getClass is called. if(defSite == symbols.objectType && "getClass".equals(method.name())) { TypeJavaSymbol classSymbol = symbols.classType.symbol; JavaType wildcardType = parametrizedTypeCache.getWildcardType(callSite.erasure(), WildCardType.BoundType.EXTENDS); resultType = parametrizedTypeCache.getParametrizedTypeType(classSymbol, new TypeSubstitution().add(classSymbol.typeVariableTypes.get(0), wildcardType)); } resultType = applySiteSubstitution(resultType, defSite); if (callSite != defSite) { resultType = applySiteSubstitution(resultType, callSite); } resultType = applySubstitution(resultType, substitution); if (!isReturnTypeCompletelySubstituted(resultType, method.typeVariableTypes) || (method.isConstructor() && !isReturnTypeCompletelySubstituted(resultType, defSite.symbol.typeVariableTypes))) { resultType = symbols.deferedType(resultType); } return resultType; }
@Override public void visitLambdaExpression(LambdaExpressionTree tree) { LambdaExpressionTreeImpl lambdaExpressionTree = (LambdaExpressionTreeImpl) tree; if (lambdaExpressionTree.isTypeSet()) { // type should be tied to a SAM interface JavaType lambdaType = (JavaType) lambdaExpressionTree.symbolType(); List<JavaType> samMethodArgs = resolve.findSamMethodArgs(lambdaType); for (int i = 0; i < samMethodArgs.size(); i++) { VariableTree param = lambdaExpressionTree.parameters().get(i); if (param.type().is(Tree.Kind.INFERED_TYPE)) { JavaType inferedType = samMethodArgs.get(i); if(inferedType.isTagged(JavaType.WILDCARD)) { // JLS8 18.5.3 inferedType = ((WildCardType) inferedType).bound; } ((AbstractTypedTree) param.type()).setInferedType(inferedType); ((JavaSymbol.VariableJavaSymbol) param.symbol()).type = inferedType; } } super.visitLambdaExpression(tree); if(lambdaType.isUnknown() || lambdaType.isTagged(JavaType.DEFERRED)) { return; } refineLambdaType(lambdaExpressionTree, lambdaType); } else { registerType(tree, symbols.deferedType(lambdaExpressionTree)); } }
@Override public void visitParenthesized(ParenthesizedTree tree) { if(((ParenthesizedTreeImpl) tree).isTypeSet()) { JavaType expType = getType(tree.expression()); if(expType.isTagged(JavaType.DEFERRED)) { setInferedType(tree.symbolType(), (DeferredType) expType); } } else { resolveAs(tree.expression(), JavaSymbol.VAR); JavaType parenthesizedExpressionType = getType(tree.expression()); if(parenthesizedExpressionType.isTagged(JavaType.DEFERRED)) { parenthesizedExpressionType = symbols.deferedType((AbstractTypedTree) tree); } registerType(tree, parenthesizedExpressionType); } }
JavaType returnType; if(resolution == null) { returnType = symbols.deferedType(mit); symbol = Symbols.unknownSymbol; } else {
JavaType returnType; if(resolution == null) { returnType = symbols.deferedType(mit); symbol = Symbols.unknownSymbol; } else {
@Override public void visitParenthesized(ParenthesizedTree tree) { if(((ParenthesizedTreeImpl) tree).isTypeSet()) { JavaType expType = getType(tree.expression()); if(expType.isTagged(JavaType.DEFERRED)) { setInferedType(tree.symbolType(), (DeferredType) expType); } } else { resolveAs(tree.expression(), JavaSymbol.VAR); JavaType parenthesizedExpressionType = getType(tree.expression()); if(parenthesizedExpressionType.isTagged(JavaType.DEFERRED)) { parenthesizedExpressionType = symbols.deferedType((AbstractTypedTree) tree); } registerType(tree, parenthesizedExpressionType); } }
public JavaType conditionalExpressionType(ConditionalExpressionTree tree, JavaType trueType, JavaType falseType) { if (trueType.isTagged(JavaType.DEFERRED)) { return falseType.isTagged(JavaType.DEFERRED) ? symbols.deferedType((ConditionalExpressionTreeImpl) tree) : falseType; } if (falseType.isTagged(JavaType.DEFERRED)) { return trueType; } if (trueType == falseType) { return trueType; } if (trueType.isTagged(JavaType.BOT)) { return falseType.isPrimitive() ? falseType.primitiveWrapperType() : falseType; } if (falseType.isTagged(JavaType.BOT)) { return trueType.isPrimitive() ? trueType.primitiveWrapperType() : trueType; } JavaType secondOperand = getPrimitive(trueType); JavaType thirdOperand = getPrimitive(falseType); if (secondOperand != null && thirdOperand != null && isNumericalConditionalExpression(secondOperand, thirdOperand)) { // If operand is a constant int that can fits a narrow type it should be narrowed. We always narrow to approximate things properly for // method resolution. if ((secondOperand.tag < thirdOperand.tag || secondOperand.isTagged(JavaType.INT)) && !thirdOperand.isTagged(JavaType.INT)) { return thirdOperand; } else { return secondOperand; } } return (JavaType) leastUpperBound(Sets.<Type>newHashSet(trueType, falseType)); }
public JavaType conditionalExpressionType(ConditionalExpressionTree tree, JavaType trueType, JavaType falseType) { if (trueType.isTagged(JavaType.DEFERRED)) { return falseType.isTagged(JavaType.DEFERRED) ? symbols.deferedType((ConditionalExpressionTreeImpl) tree) : falseType; } if (falseType.isTagged(JavaType.DEFERRED)) { return trueType; } if (trueType == falseType) { return trueType; } if (trueType.isTagged(JavaType.BOT)) { return falseType.isPrimitive() ? falseType.primitiveWrapperType() : falseType; } if (falseType.isTagged(JavaType.BOT)) { return trueType.isPrimitive() ? trueType.primitiveWrapperType() : trueType; } JavaType secondOperand = getPrimitive(trueType); JavaType thirdOperand = getPrimitive(falseType); if (secondOperand != null && thirdOperand != null && isNumericalConditionalExpression(secondOperand, thirdOperand)) { // If operand is a constant int that can fits a narrow type it should be narrowed. We always narrow to approximate things properly for // method resolution. if ((secondOperand.tag < thirdOperand.tag || secondOperand.isTagged(JavaType.INT)) && !thirdOperand.isTagged(JavaType.INT)) { return thirdOperand; } else { return secondOperand; } } return (JavaType) leastUpperBound(Sets.<Type>newHashSet(trueType, falseType)); }
@Override public void visitNewArray(NewArrayTree tree) { resolveAs(tree.type(), JavaSymbol.TYP); scan(tree.dimensions()); resolveAs((List<? extends Tree>) tree.initializers(), JavaSymbol.VAR); JavaType type = getType(tree.type()); if (tree.type() == null) { if (((NewArrayTreeImpl) tree).isTypeSet() && tree.symbolType().isArray()) { type = ((ArrayJavaType) tree.symbolType()).elementType; } else { registerType(tree, symbols.deferedType((AbstractTypedTree) tree)); return; } } int dimensions = tree.dimensions().size(); // TODO why? type = new ArrayJavaType(type, symbols.arrayClass); for (int i = 1; i < dimensions; i++) { type = new ArrayJavaType(type, symbols.arrayClass); } registerType(tree, type); for (ExpressionTree expressionTree : tree.initializers()) { if(((JavaType) expressionTree.symbolType()).isTagged(JavaType.DEFERRED)) { setInferedType(((ArrayJavaType) type).elementType, (DeferredType) expressionTree.symbolType()); } } }
@Override public void visitNewArray(NewArrayTree tree) { resolveAs(tree.type(), JavaSymbol.TYP); scan(tree.dimensions()); resolveAs((List<? extends Tree>) tree.initializers(), JavaSymbol.VAR); JavaType type = getType(tree.type()); if (tree.type() == null) { if (((NewArrayTreeImpl) tree).isTypeSet() && tree.symbolType().isArray()) { type = ((ArrayJavaType) tree.symbolType()).elementType; } else { registerType(tree, symbols.deferedType((AbstractTypedTree) tree)); return; } } int dimensions = tree.dimensions().size(); // TODO why? type = new ArrayJavaType(type, symbols.arrayClass); for (int i = 1; i < dimensions; i++) { type = new ArrayJavaType(type, symbols.arrayClass); } registerType(tree, type); for (ExpressionTree expressionTree : tree.initializers()) { if(((JavaType) expressionTree.symbolType()).isTagged(JavaType.DEFERRED)) { setInferedType(((ArrayJavaType) type).elementType, (DeferredType) expressionTree.symbolType()); } } }
JavaType type = getType(tree); if (tree.is(Tree.Kind.INFERED_TYPE, Tree.Kind.VAR_TYPE)) { type = symbols.deferedType((AbstractTypedTree) tree); registerType(tree, type);
JavaType type = getType(tree); if (tree.is(Tree.Kind.INFERED_TYPE, Tree.Kind.VAR_TYPE)) { type = symbols.deferedType((AbstractTypedTree) tree); registerType(tree, type);