/* * Copyright (C) 2009-2012 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.eclipse; import java.util.List; import lombok.core.AST.Kind; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Clinit; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.Initializer; import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration; import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; /** * Eclipse specific version of the LombokNode class. */ public class EclipseNode extends lombok.core.LombokNode { /** {@inheritDoc} */ EclipseNode(EclipseAST ast, ASTNode node, List children, Kind kind) { super(ast, node, children, kind); } /** * Visits this node and all child nodes depth-first, calling the provided visitor's visit methods. */ public void traverse(EclipseASTVisitor visitor) { if (!this.isCompleteParse() && visitor.getClass().isAnnotationPresent(DeferUntilPostDiet.class)) return; switch (getKind()) { case COMPILATION_UNIT: visitor.visitCompilationUnit(this, (CompilationUnitDeclaration)get()); ast.traverseChildren(visitor, this); visitor.endVisitCompilationUnit(this, (CompilationUnitDeclaration)get()); break; case TYPE: visitor.visitType(this, (TypeDeclaration)get()); ast.traverseChildren(visitor, this); visitor.endVisitType(this, (TypeDeclaration)get()); break; case FIELD: visitor.visitField(this, (FieldDeclaration)get()); ast.traverseChildren(visitor, this); visitor.endVisitField(this, (FieldDeclaration)get()); break; case INITIALIZER: visitor.visitInitializer(this, (Initializer)get()); ast.traverseChildren(visitor, this); visitor.endVisitInitializer(this, (Initializer)get()); break; case METHOD: if (get() instanceof Clinit) return; visitor.visitMethod(this, (AbstractMethodDeclaration)get()); ast.traverseChildren(visitor, this); visitor.endVisitMethod(this, (AbstractMethodDeclaration)get()); break; case ARGUMENT: AbstractMethodDeclaration method = (AbstractMethodDeclaration)up().get(); visitor.visitMethodArgument(this, (Argument)get(), method); ast.traverseChildren(visitor, this); visitor.endVisitMethodArgument(this, (Argument)get(), method); break; case LOCAL: visitor.visitLocal(this, (LocalDeclaration)get()); ast.traverseChildren(visitor, this); visitor.endVisitLocal(this, (LocalDeclaration)get()); break; case ANNOTATION: switch (up().getKind()) { case TYPE: visitor.visitAnnotationOnType((TypeDeclaration)up().get(), this, (Annotation)get()); break; case FIELD: visitor.visitAnnotationOnField((FieldDeclaration)up().get(), this, (Annotation)get()); break; case METHOD: visitor.visitAnnotationOnMethod((AbstractMethodDeclaration)up().get(), this, (Annotation)get()); break; case ARGUMENT: visitor.visitAnnotationOnMethodArgument( (Argument)parent.get(), (AbstractMethodDeclaration)parent.directUp().get(), this, (Annotation)get()); break; case LOCAL: visitor.visitAnnotationOnLocal((LocalDeclaration)parent.get(), this, (Annotation)get()); break; default: throw new AssertionError("Annotation not expected as child of a " + up().getKind()); } break; case STATEMENT: visitor.visitStatement(this, (Statement)get()); ast.traverseChildren(visitor, this); visitor.endVisitStatement(this, (Statement)get()); break; default: throw new AssertionError("Unexpected kind during node traversal: " + getKind()); } } @Override protected boolean fieldContainsAnnotation(ASTNode field, ASTNode annotation) { if (!(field instanceof FieldDeclaration)) return false; FieldDeclaration f = (FieldDeclaration) field; if (f.annotations == null) return false; for (Annotation childAnnotation : f.annotations) { if (childAnnotation == annotation) return true; } return false; } /** {@inheritDoc} */ @Override public String getName() { final char[] n; if (node instanceof TypeDeclaration) n = ((TypeDeclaration)node).name; else if (node instanceof FieldDeclaration) n = ((FieldDeclaration)node).name; else if (node instanceof AbstractMethodDeclaration) n = ((AbstractMethodDeclaration)node).selector; else if (node instanceof LocalDeclaration) n = ((LocalDeclaration)node).name; else n = null; return n == null ? null : new String(n); } /** {@inheritDoc} */ @Override public void addError(String message) { this.addError(message, this.get().sourceStart, this.get().sourceEnd); } /** Generate a compiler error that shows the wavy underline from-to the stated character positions. */ public void addError(String message, int sourceStart, int sourceEnd) { ast.addProblem(ast.new ParseProblem(false, message, sourceStart, sourceEnd)); } /** {@inheritDoc} */ @Override public void addWarning(String message) { this.addWarning(message, this.get().sourceStart, this.get().sourceEnd); } /** Generate a compiler warning that shows the wavy underline from-to the stated character positions. */ public void addWarning(String message, int sourceStart, int sourceEnd) { ast.addProblem(ast.new ParseProblem(true, message, sourceStart, sourceEnd)); } /** {@inheritDoc} */ @Override protected boolean calculateIsStructurallySignificant(ASTNode parent) { if (node instanceof TypeDeclaration) return true; if (node instanceof AbstractMethodDeclaration) return true; if (node instanceof FieldDeclaration) return true; if (node instanceof LocalDeclaration) return true; if (node instanceof CompilationUnitDeclaration) return true; return false; } /** * Convenient shortcut to the owning EclipseAST object's isCompleteParse method. * * @see EclipseAST#isCompleteParse() */ public boolean isCompleteParse() { return ast.isCompleteParse(); } }