Skip to content

Commit

Permalink
#379 refined warnings for inner builder
Browse files Browse the repository at this point in the history
  • Loading branch information
elucash committed Jun 28, 2016
1 parent 28a0931 commit e906b23
Show file tree
Hide file tree
Showing 2 changed files with 72 additions and 39 deletions.
@@ -0,0 +1,10 @@
package org.immutables.fixture;

import org.immutables.value.Value;

@Value.Immutable(builder = false)
class NoWarningInnerBuilderEnum {
// inner builder is enum, but it is ignored
// with no warning as the builder is disabled
enum Builder {}
}
Expand Up @@ -636,11 +636,30 @@ public final class InnerBuilderDefinition {

InnerBuilderDefinition() {
@Nullable TypeElement builderElement = findBuilderElement();
// The following series of checks designed
// to not validate inner builder if it's disabled,
// but at the same time we need such validation
// if we are using "extending" builder which is still allowed
// on demand even if builder feature is disabled
boolean extending = false;

if (builderElement != null) {
extending = isExtending(builderElement);
}

if (builderElement != null && !protoclass().features().builder() && !extending) {
builderElement = null;
}

if (builderElement != null && !isValidInnerBuilder(builderElement)) {
builderElement = null;
}

if (builderElement != null) {
this.isPresent = true;
this.isInterface = builderElement.getKind() == ElementKind.INTERFACE;
this.isExtending = isExtending(builderElement);
this.isSuper = !isExtending;
this.isExtending = extending;
this.isSuper = !extending;
this.simpleName = builderElement.getSimpleName().toString();
this.visibility = Visibility.of(builderElement);
this.generics = new Generics(protoclass(), builderElement);
Expand Down Expand Up @@ -725,50 +744,54 @@ private TypeElement findBuilderElement() {
Naming typeInnerBuilderNaming = names().namings.typeInnerBuilder;

if (!typeInnerBuilderNaming.detect(simpleName).isEmpty()) {

if (kind != ElementKind.CLASS
&& kind != ElementKind.INTERFACE) {
protoclass
.report()
.withElement(t)
.warning("Inner type %s is %s - not supported as Builder extend/super type",
t.getSimpleName(),
kind.name().toLowerCase());

return null;
}

Set<Modifier> modifiers = t.getModifiers();

if (!modifiers.contains(Modifier.STATIC)
|| modifiers.contains(Modifier.PRIVATE)) {
protoclass
.report()
.withElement(t)
.warning("Inner type %s should be static non-private to be supported as Builder extend/super type",
t.getSimpleName());

return null;
}

if (kind == ElementKind.CLASS
&& !hasAccessibleConstructor(t)) {
protoclass()
.report()
.withElement(t)
.warning("%s should have non-private no-argument constructor to be supported as Builder extend/super type",
t.getSimpleName());

return null;
}

return (TypeElement) t;
}
}
}
return null;
}

private boolean isValidInnerBuilder(Element t) {
ElementKind kind = t.getKind();
if (kind != ElementKind.CLASS
&& kind != ElementKind.INTERFACE) {
protoclass()
.report()
.withElement(t)
.warning("Inner type %s is %s - not supported as Builder extend/super type",
t.getSimpleName(),
kind.name().toLowerCase());

return false;
}

Set<Modifier> modifiers = t.getModifiers();

if (!modifiers.contains(Modifier.STATIC)
|| modifiers.contains(Modifier.PRIVATE)) {
protoclass()
.report()
.withElement(t)
.warning("Inner type %s should be static non-private to be supported as Builder extend/super type",
t.getSimpleName());

return false;
}

if (kind == ElementKind.CLASS
&& !hasAccessibleConstructor(t)) {
protoclass()
.report()
.withElement(t)
.warning("%s should have non-private no-argument constructor to be supported as Builder extend/super type",
t.getSimpleName());

return false;
}

return true;
}

private boolean hasAccessibleConstructor(Element type) {
List<ExecutableElement> constructors = ElementFilter.constructorsIn(type.getEnclosedElements());

Expand Down

0 comments on commit e906b23

Please sign in to comment.