lombok.core.handlers.InclusionExclusionUtils Maven / Gradle / Ivy
Go to download
Show more of this group Show more artifacts with this name
Show all versions of datacap-shaded-pinot Show documentation
Show all versions of datacap-shaded-pinot Show documentation
DataCap - Shaded for Apache Pinot
/*
* Copyright (C) 2009-2020 The Project Lombok Authors.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
package lombok.core.handlers;
import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
import java.util.Iterator;
import java.util.List;
import lombok.EqualsAndHashCode;
import lombok.ToString;
import lombok.core.AST;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.LombokNode;
public class InclusionExclusionUtils {
private static List createListOfNonExistentFields(List list, LombokNode type, boolean excludeStandard, boolean excludeTransient) {
boolean[] matched = new boolean[list.size()];
for (LombokNode child : type.down()) {
if (list.isEmpty()) break;
if (child.getKind() != Kind.FIELD) continue;
if (excludeStandard) {
if (child.isStatic()) continue;
if (child.getName().startsWith("$")) continue;
}
if (excludeTransient && child.isTransient()) continue;
int idx = list.indexOf(child.getName());
if (idx > -1) matched[idx] = true;
}
List problematic = new ArrayList();
for (int i = 0 ; i < list.size() ; i++) if (!matched[i]) problematic.add(i);
return problematic;
}
public static void checkForBogusFieldNames(LombokNode type, AnnotationValues annotation, List excludes, List includes) {
if (excludes != null && !excludes.isEmpty()) {
for (int i : createListOfNonExistentFields(excludes, type, true, false)) {
if (annotation != null) annotation.setWarning("exclude", "This field does not exist, or would have been excluded anyway.", i);
}
}
if (includes != null && !includes.isEmpty()) {
for (int i : createListOfNonExistentFields(includes, type, false, false)) {
if (annotation != null) annotation.setWarning("of", "This field does not exist.", i);
}
}
}
public static class Included {
private final L node;
private final I inc;
private final boolean defaultInclude;
private final boolean explicitRank;
public Included(L node, I inc, boolean defaultInclude, boolean explicitRank) {
this.node = node;
this.inc = inc;
this.defaultInclude = defaultInclude;
this.explicitRank = explicitRank;
}
public L getNode() {
return node;
}
public I getInc() {
return inc;
}
public boolean isDefaultInclude() {
return defaultInclude;
}
public boolean hasExplicitRank() {
return explicitRank;
}
}
private static String innerAnnName(Class type) {
String name = type.getSimpleName();
Class c = type.getEnclosingClass();
while (c != null) {
name = c.getSimpleName() + "." + name;
c = c.getEnclosingClass();
}
return name;
}
private static , L extends LombokNode, N, I extends Annotation> List> handleIncludeExcludeMarking(Class inclType, String replaceName, Class exclType, LombokNode typeNode, AnnotationValues annotation, LombokNode annotationNode, boolean includeTransient) {
boolean onlyExplicitlyIncluded = annotation != null ? annotation.getAsBoolean("onlyExplicitlyIncluded") : false;
return handleIncludeExcludeMarking(inclType, onlyExplicitlyIncluded, replaceName, exclType, typeNode, annotation, annotationNode, includeTransient);
}
private static , L extends LombokNode, N, I extends Annotation> List> handleIncludeExcludeMarking(Class inclType, boolean onlyExplicitlyIncluded, String replaceName, Class exclType, LombokNode typeNode, AnnotationValues annotation, LombokNode annotationNode, boolean includeTransient) {
List oldExcludes = (annotation != null && annotation.isExplicit("exclude")) ? annotation.getAsStringList("exclude") : null;
List oldIncludes = (annotation != null && annotation.isExplicit("of")) ? annotation.getAsStringList("of") : null;
boolean memberAnnotationMode = onlyExplicitlyIncluded;
List> members = new ArrayList>();
List namesToAutoExclude = new ArrayList();
if (typeNode == null || typeNode.getKind() != Kind.TYPE) return null;
checkForBogusFieldNames(typeNode, annotation, oldExcludes, oldIncludes);
if (oldExcludes != null && oldIncludes != null) {
oldExcludes = null;
if (annotation != null) annotation.setWarning("exclude", "exclude and of are mutually exclusive; the 'exclude' parameter will be ignored.");
}
for (L child : typeNode.down()) {
boolean markExclude = child.getKind() == Kind.FIELD && child.hasAnnotation(exclType);
AnnotationValues markInclude = null;
if (child.getKind() == Kind.FIELD || child.getKind() == Kind.METHOD) markInclude = child.findAnnotation(inclType);
if (markExclude || markInclude != null) memberAnnotationMode = true;
if (markInclude != null && markExclude) {
child.addError("@" + innerAnnName(exclType) + " and @" + innerAnnName(inclType) + " are mutually exclusive; the @Include annotation will be ignored");
markInclude = null;
}
String name = child.getName();
if (markExclude) {
if (onlyExplicitlyIncluded) {
child.addWarning("The @Exclude annotation is not needed; 'onlyExplicitlyIncluded' is set, so this member would be excluded anyway");
} else if (child.isStatic()) {
child.addWarning("The @Exclude annotation is not needed; static fields aren't included anyway");
} else if (name.startsWith("$")) {
child.addWarning("The @Exclude annotation is not needed; fields that start with $ aren't included anyway");
}
continue;
}
if (oldExcludes != null && oldExcludes.contains(name)) continue;
if (markInclude != null) {
I inc = markInclude.getInstance();
if (child.getKind() == Kind.METHOD) {
if (child.countMethodParameters() > 0) {
child.addError("Methods included with @" + innerAnnName(inclType) + " must have no arguments; it will not be included");
continue;
}
String n = replaceName != null ? markInclude.getAsString(replaceName) : "";
if (n.isEmpty()) n = name;
namesToAutoExclude.add(n);
}
members.add(new Included(child, inc, false, markInclude.isExplicit("rank")));
continue;
}
if (onlyExplicitlyIncluded) continue;
if (oldIncludes != null) {
if (child.getKind() == Kind.FIELD && oldIncludes.contains(name)) members.add(new Included(child, null, false, false));
continue;
}
if (child.getKind() != Kind.FIELD) continue;
if (child.isStatic()) continue;
if (child.isTransient() && !includeTransient) continue;
if (name.startsWith("$")) continue;
if (child.isEnumMember()) continue;
members.add(new Included(child, null, true, false));
}
/* delete default-included fields with the same name as an explicit inclusion */ {
Iterator> it = members.iterator();
while (it.hasNext()) {
Included m = it.next();
if (m.isDefaultInclude() && namesToAutoExclude.contains(m.getNode().getName())) it.remove();
}
}
if (annotation == null || !annotation.isExplicit("exclude")) oldExcludes = null;
if (annotation == null || !annotation.isExplicit("of")) oldIncludes = null;
if (memberAnnotationMode && (oldExcludes != null || oldIncludes != null)) {
annotationNode.addError("The old-style 'exclude/of' parameter cannot be used together with the new-style @Include / @Exclude annotations.");
return null;
}
return members;
}
public static , L extends LombokNode, N> List> handleToStringMarking(LombokNode typeNode, boolean onlyExplicitlyIncluded, AnnotationValues annotation, LombokNode annotationNode) {
List> members = handleIncludeExcludeMarking(ToString.Include.class, onlyExplicitlyIncluded, "name", ToString.Exclude.class, typeNode, annotation, annotationNode, true);
Collections.sort(members, new Comparator>() {
@Override public int compare(Included a, Included b) {
int ra = a.getInc() == null ? 0 : a.getInc().rank();
int rb = b.getInc() == null ? 0 : b.getInc().rank();
return compareRankOrPosition(ra, rb, a.getNode(), b.getNode());
}
});
return members;
}
public static , L extends LombokNode, N> List> handleEqualsAndHashCodeMarking(LombokNode typeNode, AnnotationValues annotation, LombokNode annotationNode) {
List> members = handleIncludeExcludeMarking(EqualsAndHashCode.Include.class, "replaces", EqualsAndHashCode.Exclude.class, typeNode, annotation, annotationNode, false);
Collections.sort(members, new Comparator>() {
@Override public int compare(Included a, Included b) {
int ra = a.hasExplicitRank() ? a.getInc().rank() : HandlerUtil.defaultEqualsAndHashcodeIncludeRank(a.node.fieldOrMethodBaseType());
int rb = b.hasExplicitRank() ? b.getInc().rank() : HandlerUtil.defaultEqualsAndHashcodeIncludeRank(b.node.fieldOrMethodBaseType());
return compareRankOrPosition(ra, rb, a.getNode(), b.getNode());
}
});
return members;
}
private static , L extends LombokNode, N> int compareRankOrPosition(int ra, int rb, LombokNode nodeA, LombokNode nodeB) {
if (ra < rb) return +1;
if (ra > rb) return -1;
int pa = nodeA.getStartPos();
int pb = nodeB.getStartPos();
if (pa < pb) return -1;
if (pa > pb) return +1;
return 0;
}
}