private static Optional<String> lookupMatchingStandardInterface(MethodSymbol functionalMethod) { MethodTree declaration = functionalMethod.declaration(); if (!functionalMethod.thrownTypes().isEmpty() || (declaration != null && !declaration.typeParameters().isEmpty())) { return Optional.empty(); } Type returnType = declaration != null ? declaration.returnType().symbolType() : functionalMethod.returnType().type(); return STD_INTERFACE_BY_PARAMETER_COUNT.getOrDefault(functionalMethod.parameterTypes().size(), Collections.emptyList()).stream() .map(standardInterface -> standardInterface.matchingSpecialization(functionalMethod, returnType)) .filter(Objects::nonNull) .findFirst(); }
private static Optional<String> lookupMatchingStandardInterface(MethodSymbol functionalMethod) { MethodTree declaration = functionalMethod.declaration(); if (!functionalMethod.thrownTypes().isEmpty() || (declaration != null && !declaration.typeParameters().isEmpty())) { return Optional.empty(); } Type returnType = declaration != null ? declaration.returnType().symbolType() : functionalMethod.returnType().type(); return STD_INTERFACE_BY_PARAMETER_COUNT.getOrDefault(functionalMethod.parameterTypes().size(), Collections.emptyList()).stream() .map(standardInterface -> standardInterface.matchingSpecialization(functionalMethod, returnType)) .filter(Objects::nonNull) .findFirst(); }
private static Optional<String> isSetterLike(Symbol.MethodSymbol methodSymbol) { if (methodSymbol.parameterTypes().size() != 1 || isPrivateStaticOrAbstract(methodSymbol)) { return Optional.empty(); } String methodName = methodSymbol.name(); if (methodName.length() > 3 && methodName.startsWith("set") && methodSymbol.returnType().type().isVoid()) { return Optional.of(lowerCaseFirstLetter(methodName.substring(3))); } return Optional.empty(); }
@Override public void visitNode(Tree tree) { // Cast the node to the correct type : // in this case we registered only to one kind so we will only receive MethodTree see Tree.Kind enum to know about which type you can // cast depending on Kind. MethodTree methodTree = (MethodTree) tree; // Retrieve symbol of method. MethodSymbol methodSymbol = methodTree.symbol(); Type returnType = methodSymbol.returnType().type(); // Check method has only one argument. if (methodSymbol.parameterTypes().size() == 1) { Type argType = methodSymbol.parameterTypes().get(0); // Verify argument type is same as return type. if (argType.is(returnType.fullyQualifiedName())) { // raise an issue on this node of the SyntaxTree reportIssue(tree, "message"); } } } }
@Override public void visitMethod(MethodTree tree) { List<IdentifierTree> usages = tree.symbol().usages(); if (tree.symbol().returnType() == null) { if (tree.symbol().owner().isEnum()) { // as long as SONAR-5894 is not fixed, do not provide references to enum constructors createSymbol(tree.simpleName(), Lists.<IdentifierTree>newArrayList()); } else { // as long as SONAR-5894 is not fixed, only provides references to constructors using direct call (with same name), and consequently // discard usages of this()/super() String constructorName = tree.simpleName().name(); ArrayList<IdentifierTree> filteredUsages = Lists.newArrayList(Iterables.filter(usages, new SameNameFilter(constructorName))); createSymbol(tree.simpleName(), filteredUsages); } } else { createSymbol(tree.simpleName(), usages); } super.visitMethod(tree); }
private static boolean requiredForMemberAccess(TypeCastTree typeCastTree) { ExpressionTree expression = typeCastTree.expression(); if (!expression.is(Tree.Kind.METHOD_INVOCATION)) { Tree parent = typeCastTree.parent(); return expression.is(Tree.Kind.METHOD_REFERENCE) && parent != null && skipParentheses(parent).is(Tree.Kind.MEMBER_SELECT); } Symbol symbol = ((MethodInvocationTree) expression).symbol(); if (!symbol.isMethodSymbol()) { return false; } Type returnType = ((Symbol.MethodSymbol) symbol).returnType().type(); if (!(returnType instanceof TypeVariableJavaType) || ((TypeVariableJavaType) returnType).bounds().get(0).is("java.lang.Object")) { return false; } // consider REQUIRED as soon as the parent expression is a member access (killing the noise), without checking if cast could have been avoided // as the member accessed could have also been part of initial type return skipParentheses(typeCastTree.parent()).is(Tree.Kind.MEMBER_SELECT); }
@Override public void visitMethodInvocation(MethodInvocationTree tree) { if (tree.symbol().isMethodSymbol() && tree.symbol().declaration() == null) { String fqn = tree.symbol().owner().type().fullyQualifiedName(); if (isMethodFromJavaPackage(fqn)) { Symbol.MethodSymbol methodSymbol = (Symbol.MethodSymbol) tree.symbol(); List<Type> types = new ArrayList<>(methodSymbol.parameterTypes()); Symbol.TypeSymbol returnType = methodSymbol.returnType(); if (returnType != null) { types.add(returnType.type()); } types.forEach(t -> exclusions.addAll(REPLACEMENTS.keySet().stream().filter(t::isSubtypeOf).collect(Collectors.toSet()))); } } super.visitMethodInvocation(tree); }
private static boolean requiredForMemberAccess(TypeCastTree typeCastTree) { ExpressionTree expression = typeCastTree.expression(); if (!expression.is(Tree.Kind.METHOD_INVOCATION)) { Tree parent = typeCastTree.parent(); return expression.is(Tree.Kind.METHOD_REFERENCE) && parent != null && skipParentheses(parent).is(Tree.Kind.MEMBER_SELECT); } Symbol symbol = ((MethodInvocationTree) expression).symbol(); if (!symbol.isMethodSymbol()) { return false; } Type returnType = ((Symbol.MethodSymbol) symbol).returnType().type(); if (!(returnType instanceof TypeVariableJavaType) || ((TypeVariableJavaType) returnType).bounds().get(0).is("java.lang.Object")) { return false; } // consider REQUIRED as soon as the parent expression is a member access (killing the noise), without checking if cast could have been avoided // as the member accessed could have also been part of initial type return skipParentheses(typeCastTree.parent()).is(Tree.Kind.MEMBER_SELECT); }
@Override public void visitMethodInvocation(MethodInvocationTree tree) { if (tree.symbol().isMethodSymbol() && tree.symbol().declaration() == null) { String fqn = tree.symbol().owner().type().fullyQualifiedName(); if (isMethodFromJavaPackage(fqn)) { Symbol.MethodSymbol methodSymbol = (Symbol.MethodSymbol) tree.symbol(); List<Type> types = new ArrayList<>(methodSymbol.parameterTypes()); Symbol.TypeSymbol returnType = methodSymbol.returnType(); if (returnType != null) { types.add(returnType.type()); } types.forEach(t -> exclusions.addAll(REPLACEMENTS.keySet().stream().filter(t::isSubtypeOf).collect(Collectors.toSet()))); } } super.visitMethodInvocation(tree); }
private void checkGetter(String fieldName, MethodTree methodTree) { Symbol.TypeSymbol getterOwner = ((Symbol.TypeSymbol) methodTree.symbol().owner()); if (hasNoPrivateFieldMatchingNameAndType(fieldName, methodTree.symbol().returnType().type(), getterOwner)) { return; } firstAndOnlyStatement(methodTree) .filter(statementTree -> statementTree.is(Tree.Kind.RETURN_STATEMENT)) .map(statementTree -> ((ReturnStatementTree) statementTree).expression()) .flatMap(GettersSettersOnRightFieldCheck::symbolFromExpression) .filter(returnSymbol -> !fieldName.equals(returnSymbol.name())) .ifPresent(returnedSymbol -> context.reportIssue(this, methodTree.simpleName(), "Refactor this getter so that it actually refers to the field \"" + fieldName + "\".")); }
private void checkGetter(String fieldName, MethodTree methodTree) { Symbol.TypeSymbol getterOwner = ((Symbol.TypeSymbol) methodTree.symbol().owner()); if (hasNoPrivateFieldMatchingNameAndType(fieldName, methodTree.symbol().returnType().type(), getterOwner)) { return; } firstAndOnlyStatement(methodTree) .filter(statementTree -> statementTree.is(Tree.Kind.RETURN_STATEMENT)) .map(statementTree -> ((ReturnStatementTree) statementTree).expression()) .flatMap(GettersSettersOnRightFieldCheck::symbolFromExpression) .filter(returnSymbol -> !fieldName.equals(returnSymbol.name())) .ifPresent(returnedSymbol -> context.reportIssue(this, methodTree.simpleName(), "Refactor this getter so that it actually refers to the field \"" + fieldName + "\".")); }
private void checkTestNGmembers(IdentifierTree className, Stream<Symbol.MethodSymbol> members) { if (members.noneMatch(member -> member.isPublic() && !member.isStatic() && member.returnType() != null)) { reportClass(className); } }
private static Optional<String> isSetterLike(Symbol.MethodSymbol methodSymbol) { if (methodSymbol.parameterTypes().size() != 1 || isPrivateStaticOrAbstract(methodSymbol)) { return Optional.empty(); } String methodName = methodSymbol.name(); if (methodName.length() > 3 && methodName.startsWith("set") && methodSymbol.returnType().type().isVoid()) { return Optional.of(lowerCaseFirstLetter(methodName.substring(3))); } return Optional.empty(); }
@Override public void visitMethod(MethodTree tree) { //as long as SONAR-5894 is not fixed, do not provide references to enum constructors if(tree.symbol().returnType() == null && tree.symbol().owner().isEnum()) { createSymbol(tree.simpleName(), Lists.<IdentifierTree>newArrayList()); } else { createSymbol(tree.simpleName(), tree.symbol().usages()); } super.visitMethod(tree); }
private void checkTestNGmembers(IdentifierTree className, Stream<Symbol.MethodSymbol> members) { if (members.noneMatch(member -> member.isPublic() && !member.isStatic() && member.returnType() != null)) { reportClass(className); } }
private static boolean isIntermediateOperation(MethodInvocationTree mit) { if (BASE_STREAM_INTERMEDIATE_OPERATIONS.anyMatch(mit)) { return true; } Symbol method = mit.symbol(); return method.isMethodSymbol() && !method.isStatic() && STREAM_TYPES.contains(method.owner().type().fullyQualifiedName()) && STREAM_TYPES.contains(((Symbol.MethodSymbol) method).returnType().type().fullyQualifiedName()); }
private static boolean isIntermediateOperation(MethodInvocationTree mit) { if (BASE_STREAM_INTERMEDIATE_OPERATIONS.anyMatch(mit)) { return true; } Symbol method = mit.symbol(); return method.isMethodSymbol() && !method.isStatic() && STREAM_TYPES.contains(method.owner().type().fullyQualifiedName()) && STREAM_TYPES.contains(((Symbol.MethodSymbol) method).returnType().type().fullyQualifiedName()); }
private void checkReturnType(MethodTree methodTree, String requiredReturnType) { Symbol.MethodSymbol methodSymbol = methodTree.symbol(); if (!methodSymbol.returnType().type().is(requiredReturnType)) { reportIssue(methodTree.simpleName(), "\"" + methodSymbol.name() + "\" should return \"" + requiredReturnType + "\"."); } }
private void checkReturnType(MethodTree methodTree, String requiredReturnType) { Symbol.MethodSymbol methodSymbol = methodTree.symbol(); if (!methodSymbol.returnType().type().is(requiredReturnType)) { addIssue(methodTree, "\"" + methodSymbol.name() + "\" should return \"" + requiredReturnType + "\"."); } }
private void checkReturnType(MethodTree methodTree, String requiredReturnType) { Symbol.MethodSymbol methodSymbol = methodTree.symbol(); if (!methodSymbol.returnType().type().is(requiredReturnType)) { reportIssue(methodTree.simpleName(), "\"" + methodSymbol.name() + "\" should return \"" + requiredReturnType + "\"."); } }