private void checkExtends( ClassDeclaration classDeclaration, PackageDeclaration packageDeclaration) { String scName = classDeclaration.getSuperclass().toString(); int lt = scName.indexOf('<'); if (lt != -1) { scName = scName.substring(0, lt); } int dot = scName.lastIndexOf('.'); if (dot != -1) { String superClassPackageName = scName.substring(0, dot); if (!superClassPackageName.equals(packageDeclaration.getQualifiedName())) { scName = ""; // force error below } else { scName = scName.substring(dot + 1); } } if (!scName.equals(classDeclaration.getSimpleName() + "Gen")) { error( classDeclaration, classDeclaration.getQualifiedName() + " must extend " + classDeclaration.getQualifiedName() + "Gen for @Bean to work properly"); } }
private boolean checkInheritedMethod( Thing data, String methodName, String returnType, ClassDeclaration superclass, boolean finalOk, InheritCheck inheritCheck) { if (inheritCheck != null) { if (inheritCheck.isInherited(data, superclass)) { return true; } } for (MethodDeclaration methodDeclaration : superclass.getMethods()) { if (methodName.equals(methodDeclaration.getSimpleName()) && methodDeclaration.getParameters().isEmpty() && returnType.equals(methodDeclaration.getReturnType().toString())) { data.put(methodName + "Inherited", true); Collection<Modifier> modifiers = methodDeclaration.getModifiers(); if ((modifiers.contains(Modifier.FINAL) || modifiers.contains(Modifier.PRIVATE)) && !finalOk) { // TBD TBD TBD - ERROR!!! cannot extend class with superclass method like this - how to // report? } else if (modifiers.contains(Modifier.PROTECTED)) { data.put(methodName + "Modifiers", "protected"); } else if (modifiers.contains(Modifier.PUBLIC)) { data.put(methodName + "Modifiers", "public"); } else { data.put(methodName + "Modifiers", ""); } return true; } } if (superclass.getSuperclass() != null) { if (superclass.getSuperclass().getDeclaration() != null) { if (checkInheritedMethod( data, methodName, returnType, superclass.getSuperclass().getDeclaration(), finalOk, inheritCheck)) { return true; } } } return false; }
/** * Visits a class declaration. * * @param d the declaration to visit */ public void visitClassDeclaration(ClassDeclaration d) { d.accept(pre); SortedSet<Declaration> decls = new TreeSet<Declaration>(SourceOrderDeclScanner.comparator); for (TypeParameterDeclaration tpDecl : d.getFormalTypeParameters()) { decls.add(tpDecl); } for (FieldDeclaration fieldDecl : d.getFields()) { decls.add(fieldDecl); } for (MethodDeclaration methodDecl : d.getMethods()) { decls.add(methodDecl); } for (TypeDeclaration typeDecl : d.getNestedTypes()) { decls.add(typeDecl); } for (ConstructorDeclaration ctorDecl : d.getConstructors()) { decls.add(ctorDecl); } for (Declaration decl : decls) decl.accept(this); d.accept(post); }
public static boolean checkIfAnnotationValueAttributeIsEntity( AnnotationMirror mirror, String attributeName, EclipseMessager messager) { Map<AnnotationTypeElementDeclaration, AnnotationValue> valueMap = mirror.getElementValues(); Set<Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue>> valueSet = valueMap.entrySet(); for (Map.Entry<AnnotationTypeElementDeclaration, AnnotationValue> annoKeyValue : valueSet) { if (annoKeyValue.getKey().getSimpleName().equals(attributeName)) { ClassDeclaration annoValue = (ClassDeclaration) annoKeyValue.getValue().getValue(); Entity entityAnnotation = annoValue.getAnnotation(Entity.class); if (entityAnnotation == null) { SourcePosition pos = annoKeyValue.getValue().getPosition(); messager.printError( pos, "'" + attributeName + "' attribute value class should be annotated with 'javax.persistence.Entity'"); return false; } } } return true; }
@Test(result = "T") Collection<TypeParameterDeclaration> getFormalTypeParameters2() { return nested.getFormalTypeParameters(); }
@Test(result = {"m1()", "m2()", "m2(int)"}) Collection<MethodDeclaration> getMethods() { return nested.getMethods(); }
@Test(result = {"null"}) ClassType objectHasNoSuperclass() { return object.getSuperclass(); }
@Test(result = "java.io.Serializable") Collection<InterfaceType> getSuperinterfaces() { return nested.getSuperinterfaces(); }
// Check for default constructor. // 4997614: visitConstructionDeclaration reports info when there is no ctor @Test(result = {"NestedClass()"}) Collection<ConstructorDeclaration> getConstructors2() { return nested.getConstructors(); }
@Test(result = "ClassDecl.NestedClass") String getQualifiedName2() { return nested.getQualifiedName(); }
@Test(result = "java.lang.Object") String getQualifiedName3() { return object.getQualifiedName(); }
@Override public void process() { final AnnotationTypeDeclaration beanAnn = (AnnotationTypeDeclaration) env_.getTypeDeclaration(Bean.class.getName()); for (Declaration declaration : env_.getDeclarationsAnnotatedWith(beanAnn)) { try { if (!(declaration instanceof ClassDeclaration)) { error(declaration, "You can only annotate class declarations with @Bean"); return; } Thing data = new Thing("data"); ClassDeclaration classDeclaration = (ClassDeclaration) declaration; PackageDeclaration packageDeclaration = classDeclaration.getPackage(); Map<String, AnnotationValue> beanValues = getAnnotationValues(classDeclaration, "com.javadude.annotation.Bean"); checkExtends(classDeclaration, packageDeclaration); // check that the class extends XXXGen processSuperclass(data, beanValues); // process the superclass attribute processProperties(data, beanValues); processObservers(data, beanValues); processNullObjects(data, beanValues); processDelegates(data, beanValues); processDefaultMethods(data, classDeclaration); setValue(data, beanValues, "cloneable", false); setValue(data, beanValues, "defineEqualsAndHashCode", false); setValue(data, beanValues, "equalsAndHashCodeCallSuper", false); setValue(data, beanValues, "definePropertyNameConstants", false); setValue(data, beanValues, "defineCreatePropertyMap", false); data.put("date", new Date()); data.put("year", Calendar.getInstance().get(Calendar.YEAR)); data.put("className", classDeclaration.getSimpleName()); data.put("packageName", packageDeclaration.getQualifiedName()); data.checkAllValuesSet(declaration, this); Filer f = env_.getFiler(); PrintWriter pw = f.createSourceFile(classDeclaration.getQualifiedName() + "Gen"); if (nestedEclipse) { // debugging in eclipse -- reread the template each time FileReader fileReader = new FileReader( workspace + "/com.javadude.annotation/template/$packageName$/$className$Gen.java"); template = new TemplateReader().readTemplate(fileReader); } int spacesForLeadingTabs = i(beanValues, "spacesForLeadingTabs", -1); String padding = null; if (spacesForLeadingTabs != -1) { padding = ""; for (int i = 0; i < spacesForLeadingTabs; i++) { padding += ' '; } } template.process(new Symbols(data), pw, -1, padding); pw.close(); } catch (ThreadDeath e) { throw e; } catch (ExpressionException e) { error(declaration, "@Bean generator error: " + e.getMessage()); } catch (Throwable t) { StringWriter stringWriter = new StringWriter(); PrintWriter printWriter = new PrintWriter(stringWriter); t.printStackTrace(printWriter); printWriter.close(); error(declaration, "Unexpected exception: " + stringWriter.toString()); } } }
@Test(result = "java.lang") PackageDeclaration getPackage2() { return object.getPackage(); }
@Test(result = "ClassDecl") TypeDeclaration getDeclaringType2() { return nested.getDeclaringType(); }
@Test(result = "NestedClass") String getSimpleName2() { return nested.getSimpleName(); }
// Check that static nested class has "static" modifier, even though // the VM doesn't set that bit. @Test(result = {"private", "static", "strictfp"}) Collection<Modifier> getModifiers2() { return nested.getModifiers(); }
private void processSuperclass(Thing data, Map<String, AnnotationValue> beanValues) { AnnotationValue value = beanValues.get("superclass"); data.put("superclass", null); data.put("genericDecls", ""); data.put("classModifiers", ""); data.put("propertyNameConstantsInherited", false); data.put("getPropertyChangeSupportInherited", false); data.put("getPropertyChangeSupportModifiers", "protected"); data.put("paramStringInherited", false); data.put("paramStringModifiers", "protected"); data.put("createPropertyMapInherited", false); data.put("createPropertyMapModifiers", "public"); data.put("atLeastOneDouble", false); data.put("atLeastOneBound", false); data.put("atLeastOneObject", false); data.put("atLeastOneDefault", false); if (value == null) { data.setEmpty("superclassConstructors"); } else { if (!(value.getValue() instanceof ClassDeclaration)) { error(value, "superclass must be a class"); return; } ClassDeclaration superclass = (ClassDeclaration) value.getValue(); data.put("superclass", superclass.getQualifiedName()); boolean hasProperties = !l(beanValues, "properties").isEmpty(); // check if getPropertyChangeSupport or some superclass defines bound properties in @Bean checkInheritedMethod( data, "getPropertyChangeSupport", "java.beans.PropertyChangeSupport", superclass, true, new InheritCheck() { @Override public boolean isInherited(Thing d, ClassDeclaration classDeclaration) { Bean beanAnn = classDeclaration.getAnnotation(Bean.class); if (beanAnn != null) { Property[] properties = beanAnn.properties(); for (Property property : properties) { if (property.bound()) { d.put("getPropertyChangeSupportInherited", true); d.put("getPropertyChangeSupportModifiers", "protected"); return true; } } } return false; } }); // check if paramString inherited or some superclass has @Bean checkInheritedMethod( data, "paramString", "java.lang.String", superclass, !hasProperties, new InheritCheck() { @Override public boolean isInherited(Thing d, ClassDeclaration classDeclaration) { if (classDeclaration.getAnnotation(Bean.class) != null) { d.put("paramStringInherited", true); d.put("paramStringModifiers", "protected"); return true; } return false; } }); // check if createPropertyMap inherited or some superclass has @Bean with // defineCreatePropertyMap checkInheritedMethod( data, "createPropertyMap", "java.lang.String", superclass, !hasProperties, new InheritCheck() { @Override public boolean isInherited(Thing d, ClassDeclaration classDeclaration) { Bean beanAnn = classDeclaration.getAnnotation(Bean.class); if (beanAnn != null && beanAnn.defineCreatePropertyMap()) { d.put("createPropertyMapInherited", true); d.put("createPropertyMapModifiers", "public"); return true; } return false; } }); String genericDecls = null; Collection<TypeParameterDeclaration> formalTypeParameters2 = superclass.getFormalTypeParameters(); for (TypeParameterDeclaration typeParameterDeclaration : formalTypeParameters2) { genericDecls = addWithCommasBetween(genericDecls, typeParameterDeclaration); } if (genericDecls == null) { genericDecls = ""; } else { genericDecls = '<' + genericDecls + '>'; } data.put("genericDecls", genericDecls); String classModifiers = ""; for (Modifier modifier : superclass.getModifiers()) { if (!"abstract".equals(modifier.toString())) { classModifiers += modifier.toString() + ' '; } } data.put("classModifiers", classModifiers); Collection<ConstructorDeclaration> constructors = superclass.getConstructors(); if (constructors.isEmpty()) { data.setEmpty("superclassConstructors"); } else { for (ConstructorDeclaration constructorDeclaration : constructors) { data.add("superclassConstructors", setupMethod(constructorDeclaration, false)); } } boolean extendPropertyNameConstants = false; if (b(beanValues, "definePropertyNameConstants")) { // if superclass has a PropertyNameConstants interface or a Bean annotation with // definePropertyNameConstants=true, we need to have our PropertyNameConstants // extend it Collection<TypeDeclaration> nestedTypes = superclass.getNestedTypes(); for (TypeDeclaration typeDeclaration : nestedTypes) { if ("PropertyNames".equals(typeDeclaration.getSimpleName()) && (typeDeclaration instanceof InterfaceDeclaration)) { extendPropertyNameConstants = true; } } if (!extendPropertyNameConstants) { // check if the superclass is annotated with Bean Bean annotation = superclass.getAnnotation(Bean.class); if (annotation != null) { extendPropertyNameConstants = annotation.definePropertyNameConstants(); } } } data.put("propertyNameConstantsInherited", extendPropertyNameConstants); } }
private void processDefaultMethods(Thing data, ClassDeclaration classDeclaration) { // find any methods that have default parameters boolean error = false; for (ConstructorDeclaration constructorDeclaration : classDeclaration.getConstructors()) { Collection<ParameterDeclaration> parameters = constructorDeclaration.getParameters(); for (ParameterDeclaration parameterDeclaration : parameters) { Default annotation = parameterDeclaration.getAnnotation(Default.class); if (annotation != null) { error(parameterDeclaration, "@Default is not legal in constructor parameters"); error = true; } } } if (error) { return; } boolean atLeastOneDefault = false; methods: for (MethodDeclaration methodDeclaration : classDeclaration.getMethods()) { Collection<ParameterDeclaration> parameters = methodDeclaration.getParameters(); boolean seenDefault = false; String[] names = new String[parameters.size()]; String[] types = new String[parameters.size()]; String[] defaults = new String[parameters.size()]; int n = 0; for (ParameterDeclaration parameterDeclaration : parameters) { Default annotation = parameterDeclaration.getAnnotation(Default.class); names[n] = parameterDeclaration.getSimpleName(); types[n] = parameterDeclaration.getType().toString(); if (annotation != null) { seenDefault = true; if ("java.lang.String".equals(types[n])) { defaults[n] = '"' + annotation.value() + '"'; } else { defaults[n] = annotation.value(); } } else if (seenDefault) { error( parameterDeclaration, "All parameters after a parameter annotated with @Default must be annotated with @Default"); continue methods; } n++; } if (seenDefault) { atLeastOneDefault = true; if (methodDeclaration.getModifiers().contains(Modifier.PRIVATE)) { error(methodDeclaration, "Private methods cannot use @Default parameters"); } if (methodDeclaration.getModifiers().contains(Modifier.STATIC)) { error(methodDeclaration, "Static methods cannot use @Default parameters"); } String modifiers3 = ""; if (methodDeclaration.getModifiers().contains(Modifier.PUBLIC)) { modifiers3 = "public "; } else if (methodDeclaration.getModifiers().contains(Modifier.PROTECTED)) { modifiers3 = "protected "; } String throwsClause = getThrowsClause(methodDeclaration); String returnType = methodDeclaration.getReturnType().toString(); String methodName = methodDeclaration.getSimpleName(); String argDecl = ""; String callArgs = ""; for (int i = 0; i < n; i++) { if (defaults[i] != null) { String callArgsWithDefaults = callArgs; for (int j = i; j < n; j++) { if (j > 0) { callArgsWithDefaults += ", "; } callArgsWithDefaults += defaults[j]; } Thing method = new Thing("method"); method.put("name", methodName); method.put("returnType", returnType); method.put("throwsClause", throwsClause); method.put("argDecls", argDecl); method.put("modifiers", modifiers3); method.put("args", callArgsWithDefaults); data.add("defaultMethods", method); } if (i > 0) { argDecl += ", "; callArgs += ", "; } argDecl += types[i] + ' ' + names[i]; callArgs += names[i]; } Thing method = new Thing("method"); method.put("name", methodName); method.put("returnType", returnType); method.put("throwsClause", throwsClause); method.put("modifiers", modifiers3); method.put("abstract", true); method.put("argDecls", argDecl); data.add("defaultMethods", method); } } data.put("atLeastOneDefault", atLeastOneDefault); if (!atLeastOneDefault) { data.setEmpty("defaultMethods"); } }