Search in sources :

Example 1 with JCLiteral

use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.

the class BadShiftAmount method matchBinary.

@Override
public Description matchBinary(BinaryTree tree, VisitorState state) {
    if (!BINARY_TREE_MATCHER.matches(tree, state)) {
        return Description.NO_MATCH;
    }
    /*
     * For shift amounts in [32, 63], cast the left operand to long.  Otherwise change the shift
     * amount to whatever would actually be used.
     */
    int intValue = ((Number) ((LiteralTree) tree.getRightOperand()).getValue()).intValue();
    Fix fix;
    if (intValue >= 32 && intValue <= 63) {
        if (tree.getLeftOperand().getKind() == Kind.INT_LITERAL) {
            fix = SuggestedFix.postfixWith(tree.getLeftOperand(), "L");
        } else {
            fix = SuggestedFix.prefixWith(tree, "(long) ");
        }
    } else {
        JCLiteral jcLiteral = (JCLiteral) tree.getRightOperand();
        // This is the equivalent shift distance according to JLS 15.19.
        String actualShiftDistance = Integer.toString(intValue & 0x1f);
        int actualStart = ASTHelpers.getActualStartPosition(jcLiteral, state.getSourceCode());
        if (actualStart != jcLiteral.getStartPosition()) {
            fix = SuggestedFix.replace(tree.getRightOperand(), actualShiftDistance, actualStart - jcLiteral.getStartPosition(), 0);
        } else {
            fix = SuggestedFix.replace(tree.getRightOperand(), actualShiftDistance);
        }
    }
    return describeMatch(tree, fix);
}
Also used : SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral)

Example 2 with JCLiteral

use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.

the class LongLiteralLowerCaseSuffix method getLongLiteral.

/**
   * Extracts the long literal corresponding to a given {@link LiteralTree} node from the source
   * code as a string. Returns null if the source code is not available.
   */
private static String getLongLiteral(LiteralTree literalTree, VisitorState state) {
    JCLiteral longLiteral = (JCLiteral) literalTree;
    CharSequence sourceFile = state.getSourceCode();
    if (sourceFile == null) {
        return null;
    }
    int start = longLiteral.getStartPosition();
    java.util.regex.Matcher matcher = LONG_LITERAL_PATTERN.matcher(sourceFile.subSequence(start, sourceFile.length()));
    if (matcher.lookingAt()) {
        return matcher.group();
    }
    return null;
}
Also used : JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral)

Example 3 with JCLiteral

use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.

the class ComparisonOutOfRange method describe.

/**
   * Suggested fixes are as follows.  For the byte case, convert the literal to its byte
   * representation. For example, "255" becomes "-1.  For the character case, replace the
   * comparison with "true"/"false" since it's not clear what was intended and that is
   * semantically equivalent.
   *
   * TODO(eaftan): Suggested fixes don't handle side-effecting expressions, such as
   * (d = reader.read()) == -1.  Maybe add special case handling for assignments.
   */
public Description describe(BinaryTree tree, VisitorState state) {
    List<ExpressionTree> binaryTreeMatches = ASTHelpers.matchBinaryTree(tree, Arrays.asList(Matchers.<ExpressionTree>isInstance(JCLiteral.class), Matchers.<ExpressionTree>anything()), state);
    if (binaryTreeMatches == null) {
        throw new IllegalStateException("Expected one of the operands to be a literal");
    }
    JCLiteral literal = (JCLiteral) binaryTreeMatches.get(0);
    JCTree nonLiteralOperand = (JCTree) binaryTreeMatches.get(1);
    boolean byteMatch = state.getTypes().isSameType(nonLiteralOperand.type, state.getSymtab().byteType);
    boolean willEvaluateTo = (tree.getKind() != Kind.EQUAL_TO);
    Fix fix;
    String customDiagnosticMessage;
    if (byteMatch) {
        String replacement = Byte.toString(((Number) literal.getValue()).byteValue());
        // Correct for poor javac 6 literal parsing.
        int actualStart = ASTHelpers.getActualStartPosition(literal, state.getSourceCode());
        if (actualStart != literal.getStartPosition()) {
            fix = SuggestedFix.replace(literal, replacement, actualStart - literal.getStartPosition(), 0);
        } else {
            fix = SuggestedFix.replace(literal, replacement);
        }
        customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, "byte", (int) Byte.MIN_VALUE, (int) Byte.MAX_VALUE, literal.toString(), Boolean.toString(willEvaluateTo));
    } else {
        fix = SuggestedFix.replace(tree, Boolean.toString(willEvaluateTo));
        customDiagnosticMessage = String.format(MESSAGE_TEMPLATE, "char", (int) Character.MIN_VALUE, (int) Character.MAX_VALUE, literal.toString(), Boolean.toString(willEvaluateTo));
    }
    return buildDescription(tree).addFix(fix).setMessage(customDiagnosticMessage).build();
}
Also used : SuggestedFix(com.google.errorprone.fixes.SuggestedFix) Fix(com.google.errorprone.fixes.Fix) ExpressionTree(com.sun.source.tree.ExpressionTree) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral) JCTree(com.sun.tools.javac.tree.JCTree)

Example 4 with JCLiteral

use of com.sun.tools.javac.tree.JCTree.JCLiteral in project error-prone by google.

the class ASTHelpers method constValue.

/** Returns the compile-time constant value of a tree if it has one, or {@code null}. */
@Nullable
public static Object constValue(Tree tree) {
    if (tree == null) {
        return null;
    }
    tree = TreeInfo.skipParens((JCTree) tree);
    Type type = ASTHelpers.getType(tree);
    Object value;
    if (tree instanceof JCLiteral) {
        value = ((JCLiteral) tree).value;
    } else if (type != null) {
        value = type.constValue();
    } else {
        return null;
    }
    if (type.hasTag(TypeTag.BOOLEAN) && value instanceof Integer) {
        return ((Integer) value) == 1;
    }
    return value;
}
Also used : ClassType(com.sun.tools.javac.code.Type.ClassType) Type(com.sun.tools.javac.code.Type) JCTree(com.sun.tools.javac.tree.JCTree) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral) Nullable(javax.annotation.Nullable)

Example 5 with JCLiteral

use of com.sun.tools.javac.tree.JCTree.JCLiteral in project lombok by rzwitserloot.

the class HandleVal method visitLocal.

@Override
public void visitLocal(JavacNode localNode, JCVariableDecl local) {
    JCTree typeTree = local.vartype;
    if (typeTree == null)
        return;
    String typeTreeToString = typeTree.toString();
    if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var")))
        return;
    boolean isVal = typeMatches(val.class, localNode, typeTree);
    boolean isVar = typeMatches(var.class, localNode, typeTree);
    if (!(isVal || isVar))
        return;
    if (isVal)
        handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
    if (isVar)
        handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var");
    JCTree parentRaw = localNode.directUp().get();
    if (isVal && parentRaw instanceof JCForLoop) {
        localNode.addError("'val' is not allowed in old-style for loops");
        return;
    }
    JCExpression rhsOfEnhancedForLoop = null;
    if (local.init == null) {
        if (parentRaw instanceof JCEnhancedForLoop) {
            JCEnhancedForLoop efl = (JCEnhancedForLoop) parentRaw;
            if (efl.var == local)
                rhsOfEnhancedForLoop = efl.expr;
        }
    }
    final String annotation = typeTreeToString;
    if (rhsOfEnhancedForLoop == null && local.init == null) {
        localNode.addError("'" + annotation + "' on a local variable requires an initializer expression");
        return;
    }
    if (local.init instanceof JCNewArray && ((JCNewArray) local.init).elemtype == null) {
        localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
        return;
    }
    if (localNode.shouldDeleteLombokAnnotations()) {
        JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, val.class.getName());
        JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, var.class.getName());
    }
    if (isVal)
        local.mods.flags |= Flags.FINAL;
    if (!localNode.shouldDeleteLombokAnnotations()) {
        JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext());
        local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation);
    }
    if (JavacResolution.platformHasTargetTyping()) {
        local.vartype = localNode.getAst().getTreeMaker().Ident(localNode.getAst().toName("___Lombok_VAL_Attrib__"));
    } else {
        local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
    }
    Type type;
    try {
        if (rhsOfEnhancedForLoop == null) {
            if (local.init.type == null) {
                if (isVar && local.init instanceof JCLiteral && ((JCLiteral) local.init).value == null) {
                    localNode.addError("variable initializer is 'null'");
                }
                JavacResolution resolver = new JavacResolution(localNode.getContext());
                try {
                    type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
                } catch (RuntimeException e) {
                    System.err.println("Exception while resolving: " + localNode);
                    throw e;
                }
            } else {
                type = local.init.type;
                if (type.isErroneous()) {
                    try {
                        JavacResolution resolver = new JavacResolution(localNode.getContext());
                        local.type = Symtab.instance(localNode.getContext()).unknownType;
                        type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
                    } catch (RuntimeException e) {
                        System.err.println("Exception while resolving: " + localNode);
                        throw e;
                    }
                }
            }
        } else {
            if (rhsOfEnhancedForLoop.type == null) {
                JavacResolution resolver = new JavacResolution(localNode.getContext());
                type = ((JCExpression) resolver.resolveMethodMember(localNode.directUp()).get(rhsOfEnhancedForLoop)).type;
            } else {
                type = rhsOfEnhancedForLoop.type;
            }
        }
        try {
            JCExpression replacement;
            if (rhsOfEnhancedForLoop != null) {
                Type componentType = JavacResolution.ifTypeIsIterableToComponent(type, localNode.getAst());
                if (componentType == null)
                    replacement = JavacResolution.createJavaLangObject(localNode.getAst());
                else
                    replacement = JavacResolution.typeToJCTree(componentType, localNode.getAst(), false);
            } else {
                replacement = JavacResolution.typeToJCTree(type, localNode.getAst(), false);
            }
            if (replacement != null) {
                local.vartype = replacement;
            } else {
                local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
            }
            localNode.getAst().setChanged();
        } catch (JavacResolution.TypeNotConvertibleException e) {
            localNode.addError("Cannot use '" + annotation + "' here because initializer expression does not have a representable type: " + e.getMessage());
            local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
        }
    } catch (RuntimeException e) {
        local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
        throw e;
    } finally {
        recursiveSetGeneratedBy(local.vartype, typeTree, localNode.getContext());
    }
}
Also used : lombok.val(lombok.val) JavacResolution(lombok.javac.JavacResolution) lombok.experimental.var(lombok.experimental.var) JCTree(com.sun.tools.javac.tree.JCTree) JCForLoop(com.sun.tools.javac.tree.JCTree.JCForLoop) Type(com.sun.tools.javac.code.Type) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JCEnhancedForLoop(com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop) JCLiteral(com.sun.tools.javac.tree.JCTree.JCLiteral) JCNewArray(com.sun.tools.javac.tree.JCTree.JCNewArray) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Aggregations

JCLiteral (com.sun.tools.javac.tree.JCTree.JCLiteral)6 JCTree (com.sun.tools.javac.tree.JCTree)4 Fix (com.google.errorprone.fixes.Fix)2 SuggestedFix (com.google.errorprone.fixes.SuggestedFix)2 Type (com.sun.tools.javac.code.Type)2 JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)2 JCEnhancedForLoop (com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop)2 JCForLoop (com.sun.tools.javac.tree.JCTree.JCForLoop)2 JCNewArray (com.sun.tools.javac.tree.JCTree.JCNewArray)2 ExpressionTree (com.sun.source.tree.ExpressionTree)1 ClassType (com.sun.tools.javac.code.Type.ClassType)1 JCArrayAccess (com.sun.tools.javac.tree.JCTree.JCArrayAccess)1 JCArrayTypeTree (com.sun.tools.javac.tree.JCTree.JCArrayTypeTree)1 JCAssert (com.sun.tools.javac.tree.JCTree.JCAssert)1 JCAssign (com.sun.tools.javac.tree.JCTree.JCAssign)1 JCAssignOp (com.sun.tools.javac.tree.JCTree.JCAssignOp)1 JCBinary (com.sun.tools.javac.tree.JCTree.JCBinary)1 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)1 JCBreak (com.sun.tools.javac.tree.JCTree.JCBreak)1 JCCase (com.sun.tools.javac.tree.JCTree.JCCase)1