(TypeElement subject)
| 58 | } |
| 59 | |
| 60 | public ValidationReport<TypeElement> validate(TypeElement subject) { |
| 61 | ValidationReport.Builder<TypeElement> builder = ValidationReport.about(subject); |
| 62 | |
| 63 | ComponentDescriptor.Kind componentKind = |
| 64 | ComponentDescriptor.Kind.forAnnotatedBuilderElement(subject).get(); |
| 65 | |
| 66 | Element componentElement = subject.getEnclosingElement(); |
| 67 | ErrorMessages.ComponentBuilderMessages msgs = ErrorMessages.builderMsgsFor(componentKind); |
| 68 | Class<? extends Annotation> componentAnnotation = componentKind.annotationType(); |
| 69 | Class<? extends Annotation> builderAnnotation = componentKind.builderAnnotationType(); |
| 70 | checkArgument(subject.getAnnotation(builderAnnotation) != null); |
| 71 | |
| 72 | if (!isAnnotationPresent(componentElement, componentAnnotation)) { |
| 73 | builder.addError(msgs.mustBeInComponent(), subject); |
| 74 | } |
| 75 | |
| 76 | switch (subject.getKind()) { |
| 77 | case CLASS: |
| 78 | List<? extends Element> allElements = subject.getEnclosedElements(); |
| 79 | List<ExecutableElement> cxtors = ElementFilter.constructorsIn(allElements); |
| 80 | if (cxtors.size() != 1 || getOnlyElement(cxtors).getParameters().size() != 0) { |
| 81 | builder.addError(msgs.cxtorOnlyOneAndNoArgs(), subject); |
| 82 | } |
| 83 | break; |
| 84 | case INTERFACE: |
| 85 | break; |
| 86 | default: |
| 87 | // If not the correct type, exit early since the rest of the messages will be bogus. |
| 88 | builder.addError(msgs.mustBeClassOrInterface(), subject); |
| 89 | return builder.build(); |
| 90 | } |
| 91 | |
| 92 | if (!subject.getTypeParameters().isEmpty()) { |
| 93 | builder.addError(msgs.generics(), subject); |
| 94 | } |
| 95 | |
| 96 | Set<Modifier> modifiers = subject.getModifiers(); |
| 97 | if (modifiers.contains(PRIVATE)) { |
| 98 | builder.addError(msgs.isPrivate(), subject); |
| 99 | } |
| 100 | if (!modifiers.contains(STATIC)) { |
| 101 | builder.addError(msgs.mustBeStatic(), subject); |
| 102 | } |
| 103 | // Note: Must be abstract, so no need to check for final. |
| 104 | if (!modifiers.contains(ABSTRACT)) { |
| 105 | builder.addError(msgs.mustBeAbstract(), subject); |
| 106 | } |
| 107 | |
| 108 | ExecutableElement buildMethod = null; |
| 109 | for (ExecutableElement method : elements.getUnimplementedMethods(subject)) { |
| 110 | ExecutableType resolvedMethodType = |
| 111 | MoreTypes.asExecutable(types.asMemberOf(MoreTypes.asDeclared(subject.asType()), method)); |
| 112 | TypeMirror returnType = resolvedMethodType.getReturnType(); |
| 113 | if (method.getParameters().size() == 0) { |
| 114 | // If this is potentially a build() method, validate it returns the correct type. |
| 115 | if (types.isSubtype(componentElement.asType(), returnType)) { |
| 116 | validateBuildMethodReturnType( |
| 117 | builder, |
no test coverage detected