/*
 * Copyright (C) 2009-2018 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;

import java.lang.annotation.Annotation;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;

import lombok.core.AST.Kind;

An instance of this class wraps an Eclipse/javac internal node object.
Params:
  • A – Type of our owning AST.
  • L – self-type.
  • N – The common type of all AST nodes in the internal representation of the target platform. For example, JCTree for javac, and ASTNode for Eclipse.
/** * An instance of this class wraps an Eclipse/javac internal node object. * * @param A Type of our owning AST. * @param L self-type. * @param N The common type of all AST nodes in the internal representation of the target platform. * For example, JCTree for javac, and ASTNode for Eclipse. */
public abstract class LombokNode<A extends AST<A, L, N>, L extends LombokNode<A, L, N>, N> implements DiagnosticsReceiver { protected final Kind kind; protected final N node; protected LombokImmutableList<L> children; protected L parent;
structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels, so fields, local declarations, method arguments, methods, types, the Compilation Unit itself, and initializers.
/** structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels, * so fields, local declarations, method arguments, methods, types, the Compilation Unit itself, and initializers. */
protected boolean isStructurallySignificant;
Creates a new Node object that represents the provided node.
Params:
  • ast – The owning AST - this node is part of this AST's tree of nodes.
  • node – The AST object in the target parser's own internal AST tree that this node object will represent.
  • children – A list of child nodes. Passing in null results in the children list being empty, not null.
  • kind – The kind of node represented by this object.
/** * Creates a new Node object that represents the provided node. * * @param ast The owning AST - this node is part of this AST's tree of nodes. * @param node The AST object in the target parser's own internal AST tree that this node object will represent. * @param children A list of child nodes. Passing in null results in the children list being empty, not null. * @param kind The kind of node represented by this object. */
@SuppressWarnings("unchecked") protected LombokNode(N node, List<L> children, Kind kind) { this.kind = kind; this.node = node; this.children = children != null ? LombokImmutableList.copyOf(children) : LombokImmutableList.<L>of(); for (L child : this.children) { child.parent = (L) this; if (!child.isStructurallySignificant) child.isStructurallySignificant = calculateIsStructurallySignificant(node); } this.isStructurallySignificant = calculateIsStructurallySignificant(null); } public abstract A getAst();
{@inheritDoc}
/** {@inheritDoc} */
@Override public String toString() { return String.format("NODE %s (%s) %s", kind, node == null ? "(NULL)" : node.getClass(), node == null ? "" : node); }
Convenient shortcut to the owning ast object's getPackageDeclaration method.
See Also:
/** * Convenient shortcut to the owning ast object's {@code getPackageDeclaration} method. * * @see AST#getPackageDeclaration() */
public String getPackageDeclaration() { return getAst().getPackageDeclaration(); }
Convenient shortcut to the owning ast object's getImportList method.
See Also:
/** * Convenient shortcut to the owning ast object's {@code getImportList} method. * * @see AST#getImportList() */
public ImportList getImportList() { return getAst().getImportList(); } /** * See {@link #isStructurallySignificant}. */ protected abstract boolean calculateIsStructurallySignificant(N parent);
Convenient shortcut to the owning ast object's get method.
See Also:
  • get.get(Object)
/** * Convenient shortcut to the owning ast object's get method. * * @see AST#get(Object) */
public L getNodeFor(N obj) { return getAst().get(obj); }
Returns:The javac/Eclipse internal AST object wrapped by this LombokNode object.
/** * @return The javac/Eclipse internal AST object wrapped by this LombokNode object. */
public N get() { return node; } public Kind getKind() { return kind; }
Return the name of your type (simple name), method, field, or local variable. Return null if this node doesn't really have a name, such as initializers, while statements, etc.
/** * Return the name of your type (simple name), method, field, or local variable. Return null if this * node doesn't really have a name, such as initializers, while statements, etc. */
public abstract String getName();
Returns the structurally significant node that encloses this one.
See Also:
  • isStructurallySignificant()
/** Returns the structurally significant node that encloses this one. * * @see #isStructurallySignificant() */
public L up() { L result = parent; while (result != null && !result.isStructurallySignificant) result = result.parent; return result; }
@Foo int x, y; is stored in both javac and ecj as 2 FieldDeclarations, both with the same annotation as child. The normal up() method can't handle having multiple parents, but this one can.
/** * {@code @Foo int x, y;} is stored in both javac and ecj as 2 FieldDeclarations, both with the same annotation as child. * The normal {@code up()} method can't handle having multiple parents, but this one can. */
public Collection<L> upFromAnnotationToFields() { if (getKind() != Kind.ANNOTATION) return Collections.emptyList(); L field = up(); if (field == null || field.getKind() != Kind.FIELD) return Collections.emptyList(); L type = field.up(); if (type == null || type.getKind() != Kind.TYPE) return Collections.emptyList(); List<L> fields = new ArrayList<L>(); for (L potentialField : type.down()) { if (potentialField.getKind() != Kind.FIELD) continue; if (fieldContainsAnnotation(potentialField.get(), get())) fields.add(potentialField); } return fields; }
Return true if the annotation is attached to the field.
/** * Return {@code true} if the annotation is attached to the field. */
protected abstract boolean fieldContainsAnnotation(N field, N annotation);
Returns the direct parent node in the AST tree of this node. For example, a local variable declaration's direct parent can be e.g. an If block, but its up() LombokNode is the Method that contains it.
/** * Returns the direct parent node in the AST tree of this node. For example, a local variable declaration's * direct parent can be e.g. an If block, but its {@code up()} {@code LombokNode} is the {@code Method} that contains it. */
public L directUp() { return parent; }
Returns all children nodes.
/** * Returns all children nodes. */
public LombokImmutableList<L> down() { return children; }
Convenient shortcut to the owning ast object's getLatestJavaSpecSupported method.
See Also:
  • getLatestJavaSpecSupported.getLatestJavaSpecSupported()
/** * Convenient shortcut to the owning ast object's getLatestJavaSpecSupported method. * * @see AST#getLatestJavaSpecSupported() */
public int getLatestJavaSpecSupported() { return getAst().getLatestJavaSpecSupported(); }
Convenient shortcut to the owning ast object's getSourceVersion method.
See Also:
  • getSourceVersion.getSourceVersion()
/** * Convenient shortcut to the owning ast object's getSourceVersion method. * * @see AST#getSourceVersion() */
public int getSourceVersion() { return getAst().getSourceVersion(); }
Convenient shortcut to the owning ast object's top method.
See Also:
  • top.top()
/** * Convenient shortcut to the owning ast object's top method. * * @see AST#top() */
public L top() { return getAst().top(); }
Convenient shortcut to the owning ast object's getFileName method.
See Also:
  • getFileName.getFileName()
/** * Convenient shortcut to the owning ast object's getFileName method. * * @see AST#getFileName() */
public String getFileName() { return getAst().getFileName(); }
Adds the stated node as a direct child of this node. Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
/** * Adds the stated node as a direct child of this node. * * Does not change the underlying (javac/Eclipse) AST, only the wrapped view. */
@SuppressWarnings({"unchecked"}) public L add(N newChild, Kind newChildKind) { getAst().setChanged(); L n = getAst().buildTree(newChild, newChildKind); if (n == null) return null; n.parent = (L) this; children = children.append(n); return n; }
Reparses the AST node represented by this node. Any existing nodes that occupy a different space in the AST are rehomed, any nodes that no longer exist are removed, and new nodes are created. Careful - the node you call this on must not itself have been removed or rehomed - it rebuilds all children.
/** * Reparses the AST node represented by this node. Any existing nodes that occupy a different space in the AST are rehomed, any * nodes that no longer exist are removed, and new nodes are created. * * Careful - the node you call this on must not itself have been removed or rehomed - it rebuilds <i>all children</i>. */
public void rebuild() { Map<N, L> oldNodes = new IdentityHashMap<N, L>(); gatherAndRemoveChildren(oldNodes); L newNode = getAst().buildTree(get(), kind); getAst().setChanged(); getAst().replaceNewWithExistingOld(oldNodes, newNode); } @SuppressWarnings({"unchecked", "rawtypes"}) private void gatherAndRemoveChildren(Map<N, L> map) { for (LombokNode child : children) child.gatherAndRemoveChildren(map); getAst().identityDetector.remove(get()); map.put(get(), (L) this); children = LombokImmutableList.of(); getAst().getNodeMap().remove(get()); }
Removes the stated node, which must be a direct child of this node, from the AST. Does not change the underlying (javac/Eclipse) AST, only the wrapped view.
/** * Removes the stated node, which must be a direct child of this node, from the AST. * * Does not change the underlying (javac/Eclipse) AST, only the wrapped view. */
public void removeChild(L child) { getAst().setChanged(); children = children.removeElement(child); }
Structurally significant means: LocalDeclaration, TypeDeclaration, MethodDeclaration, ConstructorDeclaration, FieldDeclaration, Initializer, and CompilationUnitDeclaration. The rest is e.g. if statements, while loops, etc.
/** * Structurally significant means: LocalDeclaration, TypeDeclaration, MethodDeclaration, ConstructorDeclaration, * FieldDeclaration, Initializer, and CompilationUnitDeclaration. * The rest is e.g. if statements, while loops, etc. */
public boolean isStructurallySignificant() { return isStructurallySignificant; } public abstract boolean hasAnnotation(Class<? extends Annotation> type); public abstract <Z extends Annotation> AnnotationValues<Z> findAnnotation(Class<Z> type); public abstract boolean isStatic(); public abstract boolean isTransient(); public abstract boolean isEnumMember(); public abstract boolean isEnumType(); public abstract int countMethodParameters(); public abstract int getStartPos(); }