Search in sources :

Example 31 with JCAnnotation

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

the class HandleVal method visitLocal.

@SuppressWarnings("deprecation")
@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;
    }
    if (parentRaw instanceof JCForLoop && ((JCForLoop) parentRaw).getInitializer().size() > 1) {
        localNode.addError("'var' is not allowed in old-style for loops if there is more than 1 initializer");
        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, lombok.experimental.var.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 + "(" + localNode.getFileName() + ")");
                    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 + "(" + localNode.getFileName() + ")");
                        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.var(lombok.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)

Example 32 with JCAnnotation

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

the class JavacHandlerUtil method findAnnotations.

/**
 * Searches the given field node for annotations and returns each one that matches the provided regular expression pattern.
 *
 * Only the simple name is checked - the package and any containing class are ignored.
 */
public static List<JCAnnotation> findAnnotations(JavacNode fieldNode, Pattern namePattern) {
    ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
    for (JavacNode child : fieldNode.down()) {
        if (child.getKind() == Kind.ANNOTATION) {
            JCAnnotation annotation = (JCAnnotation) child.get();
            String name = annotation.annotationType.toString();
            int idx = name.lastIndexOf(".");
            String suspect = idx == -1 ? name : name.substring(idx + 1);
            if (namePattern.matcher(suspect).matches()) {
                result.append(annotation);
            }
        }
    }
    return result.toList();
}
Also used : JavacNode(lombok.javac.JavacNode) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Example 33 with JCAnnotation

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

the class JavacHandlerUtil method createAnnotation.

/**
 * Creates an instance of {@code AnnotationValues} for the provided AST Node.
 *
 * @param type An annotation class type, such as {@code lombok.Getter.class}.
 * @param node A Lombok AST node representing an annotation in source code.
 */
public static <A extends Annotation> AnnotationValues<A> createAnnotation(Class<A> type, final JavacNode node) {
    Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
    JCAnnotation anno = (JCAnnotation) node.get();
    List<JCExpression> arguments = anno.getArguments();
    for (JCExpression arg : arguments) {
        String mName;
        JCExpression rhs;
        java.util.List<String> raws = new ArrayList<String>();
        java.util.List<Object> guesses = new ArrayList<Object>();
        java.util.List<Object> expressions = new ArrayList<Object>();
        final java.util.List<DiagnosticPosition> positions = new ArrayList<DiagnosticPosition>();
        if (arg instanceof JCAssign) {
            JCAssign assign = (JCAssign) arg;
            mName = assign.lhs.toString();
            rhs = assign.rhs;
        } else {
            rhs = arg;
            mName = "value";
        }
        if (rhs instanceof JCNewArray) {
            List<JCExpression> elems = ((JCNewArray) rhs).elems;
            for (JCExpression inner : elems) {
                raws.add(inner.toString());
                expressions.add(inner);
                guesses.add(calculateGuess(inner));
                positions.add(inner.pos());
            }
        } else {
            raws.add(rhs.toString());
            expressions.add(rhs);
            guesses.add(calculateGuess(rhs));
            positions.add(rhs.pos());
        }
        values.put(mName, new AnnotationValue(node, raws, expressions, guesses, true) {

            @Override
            public void setError(String message, int valueIdx) {
                if (valueIdx < 0)
                    node.addError(message);
                else
                    node.addError(message, positions.get(valueIdx));
            }

            @Override
            public void setWarning(String message, int valueIdx) {
                if (valueIdx < 0)
                    node.addWarning(message);
                else
                    node.addWarning(message, positions.get(valueIdx));
            }
        });
    }
    for (Method m : type.getDeclaredMethods()) {
        if (!Modifier.isPublic(m.getModifiers()))
            continue;
        String name = m.getName();
        if (!values.containsKey(name)) {
            values.put(name, new AnnotationValue(node, new ArrayList<String>(), new ArrayList<Object>(), new ArrayList<Object>(), false) {

                @Override
                public void setError(String message, int valueIdx) {
                    node.addError(message);
                }

                @Override
                public void setWarning(String message, int valueIdx) {
                    node.addWarning(message);
                }
            });
        }
    }
    return new AnnotationValues<A>(type, values, node);
}
Also used : HashMap(java.util.HashMap) JCAssign(com.sun.tools.javac.tree.JCTree.JCAssign) ArrayList(java.util.ArrayList) Method(java.lang.reflect.Method) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) DiagnosticPosition(com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition) AnnotationValues(lombok.core.AnnotationValues) AnnotationValue(lombok.core.AnnotationValues.AnnotationValue) JCNewArray(com.sun.tools.javac.tree.JCTree.JCNewArray) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Example 34 with JCAnnotation

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

the class HandleConstructor method createConstructor.

@SuppressWarnings("deprecation")
public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean allToDefault, JavacNode source) {
    JavacTreeMaker maker = typeNode.getTreeMaker();
    boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0;
    if (isEnum)
        level = AccessLevel.PRIVATE;
    boolean addConstructorProperties;
    if (fields.isEmpty()) {
        addConstructorProperties = false;
    } else {
        Boolean v = typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES);
        addConstructorProperties = v != null ? v.booleanValue() : Boolean.FALSE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
    }
    ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>();
    ListBuffer<JCStatement> assigns = new ListBuffer<JCStatement>();
    ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
    for (JavacNode fieldNode : fields) {
        JCVariableDecl field = (JCVariableDecl) fieldNode.get();
        Name fieldName = removePrefixFromField(fieldNode);
        Name rawName = field.name;
        List<JCAnnotation> nonNulls = findAnnotations(fieldNode, NON_NULL_PATTERN);
        if (!allToDefault) {
            List<JCAnnotation> nullables = findAnnotations(fieldNode, NULLABLE_PATTERN);
            long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
            JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null);
            params.append(param);
            if (!nonNulls.isEmpty()) {
                JCStatement nullCheck = generateNullCheck(maker, fieldNode, param, source);
                if (nullCheck != null)
                    nullChecks.append(nullCheck);
            }
        }
        JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), rawName);
        JCExpression assign = maker.Assign(thisX, allToDefault ? getDefaultExpr(maker, field.vartype) : maker.Ident(fieldName));
        assigns.append(maker.Exec(assign));
    }
    JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
    if (!allToDefault && addConstructorProperties && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
        addConstructorProperties(mods, typeNode, fields);
    }
    if (onConstructor != null)
        mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
    return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"), null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(), maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext());
}
Also used : JCClassDecl(com.sun.tools.javac.tree.JCTree.JCClassDecl) JavacTreeMaker(lombok.javac.JavacTreeMaker) JCFieldAccess(com.sun.tools.javac.tree.JCTree.JCFieldAccess) ListBuffer(com.sun.tools.javac.util.ListBuffer) JCStatement(com.sun.tools.javac.tree.JCTree.JCStatement) JCVariableDecl(com.sun.tools.javac.tree.JCTree.JCVariableDecl) Name(com.sun.tools.javac.util.Name) JCTypeParameter(com.sun.tools.javac.tree.JCTree.JCTypeParameter) JCExpression(com.sun.tools.javac.tree.JCTree.JCExpression) JavacNode(lombok.javac.JavacNode) JCModifiers(com.sun.tools.javac.tree.JCTree.JCModifiers) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Example 35 with JCAnnotation

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

the class EmptySetMultibindingContributions method createReplacementClassModifiers.

private String createReplacementClassModifiers(VisitorState state, JCModifiers enclosingClassModifiers) {
    ImmutableList.Builder<String> classModifierStringsBuilder = ImmutableList.builder();
    for (JCAnnotation annotation : enclosingClassModifiers.annotations) {
        classModifierStringsBuilder.add(state.getSourceForNode(annotation));
    }
    EnumSet<Flag> classFlags = Flags.asFlagSet(enclosingClassModifiers.flags);
    classFlags.remove(Flags.Flag.FINAL);
    classFlags.add(Flags.Flag.ABSTRACT);
    for (Flag flag : classFlags) {
        classModifierStringsBuilder.add(flag.toString());
    }
    return Joiner.on(' ').join(classModifierStringsBuilder.build());
}
Also used : ImmutableList(com.google.common.collect.ImmutableList) Flag(com.sun.tools.javac.code.Flags.Flag) JCAnnotation(com.sun.tools.javac.tree.JCTree.JCAnnotation)

Aggregations

JCAnnotation (com.sun.tools.javac.tree.JCTree.JCAnnotation)53 JCExpression (com.sun.tools.javac.tree.JCTree.JCExpression)32 ListBuffer (com.sun.tools.javac.util.ListBuffer)17 Name (com.sun.tools.javac.util.Name)16 JCTree (com.sun.tools.javac.tree.JCTree)15 JCVariableDecl (com.sun.tools.javac.tree.JCTree.JCVariableDecl)15 JCStatement (com.sun.tools.javac.tree.JCTree.JCStatement)13 JavacNode (lombok.javac.JavacNode)13 JCTypeParameter (com.sun.tools.javac.tree.JCTree.JCTypeParameter)12 JCBlock (com.sun.tools.javac.tree.JCTree.JCBlock)11 JCModifiers (com.sun.tools.javac.tree.JCTree.JCModifiers)10 JCAssign (com.sun.tools.javac.tree.JCTree.JCAssign)8 JavacTreeMaker (lombok.javac.JavacTreeMaker)8 JCPrimitiveTypeTree (com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree)6 Type (com.redhat.ceylon.model.typechecker.model.Type)5 TypeDeclaration (com.redhat.ceylon.model.typechecker.model.TypeDeclaration)5 JCNewArray (com.sun.tools.javac.tree.JCTree.JCNewArray)5 ArrayList (java.util.ArrayList)5 Tree (com.redhat.ceylon.compiler.typechecker.tree.Tree)4 Parameter (com.redhat.ceylon.model.typechecker.model.Parameter)4