From 65cd03b6c592f825b037a6647888f4eafbaf3388 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 14 Jun 2009 23:40:10 +0200 Subject: Added support to generate errors, both on specific nodes in an AST (generified code in HandlerLibrary for unintelligible annotation param values), and more severe general errors for eclipse's error log. Also unrolled the foreach loop on ServiceLoader, because any given .next() call can throw a ServiceLoaderError, which we now handle somewhat more nicely. --- src/lombok/eclipse/Eclipse.java | 34 ++++++++++++++ src/lombok/eclipse/EclipseAST.java | 83 ++++++++++++++++++++++++++++++++++ src/lombok/eclipse/HandlerLibrary.java | 66 ++++++++++++--------------- 3 files changed, 145 insertions(+), 38 deletions(-) create mode 100644 src/lombok/eclipse/Eclipse.java (limited to 'src') diff --git a/src/lombok/eclipse/Eclipse.java b/src/lombok/eclipse/Eclipse.java new file mode 100644 index 00000000..e1ff95cd --- /dev/null +++ b/src/lombok/eclipse/Eclipse.java @@ -0,0 +1,34 @@ +package lombok.eclipse; + +import org.eclipse.core.runtime.ILog; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Platform; +import org.eclipse.core.runtime.Status; +import org.osgi.framework.Bundle; + +public class Eclipse { + private static final String DEFAULT_BUNDLE = "org.eclipse.jdt.core"; + public static void error(String message) { + error(message, DEFAULT_BUNDLE, null); + } + + public static void error(String message, Throwable error) { + error(message, DEFAULT_BUNDLE, error); + } + + public static void error(String message, String bundleName) { + error(message, bundleName, null); + } + + public static void error(String message, String bundleName, Throwable error) { + Bundle bundle = Platform.getBundle(bundleName); + if ( bundle == null ) { + System.err.printf("Can't find bundle %s while trying to report error:\n%s\n", bundleName, message); + return; + } + + ILog log = Platform.getLog(bundle); + + log.log(new Status(IStatus.ERROR, bundleName, message, error)); + } +} diff --git a/src/lombok/eclipse/EclipseAST.java b/src/lombok/eclipse/EclipseAST.java index 83c2872d..edf70d70 100644 --- a/src/lombok/eclipse/EclipseAST.java +++ b/src/lombok/eclipse/EclipseAST.java @@ -12,6 +12,9 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import org.eclipse.jdt.core.compiler.CategorizedProblem; +import org.eclipse.jdt.internal.compiler.CompilationResult; +import org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem; import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; import org.eclipse.jdt.internal.compiler.ast.Argument; @@ -22,6 +25,9 @@ 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; +import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; +import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; +import org.eclipse.jdt.internal.compiler.util.Util; public class EclipseAST { public void traverse(EclipseASTVisitor visitor) { @@ -75,6 +81,66 @@ public class EclipseAST { return nodeMap.get(node); } + private static class ParseProblem { + final boolean isWarning; + final String message; + final Node node; + final int sourceStart; + final int sourceEnd; + + public ParseProblem(boolean isWarning, String message, Node node, int sourceStart, int sourceEnd) { + this.isWarning = isWarning; + this.message = message; + this.node = node; + this.sourceStart = sourceStart; + this.sourceEnd = sourceEnd; + } + } + + public void propagateProblems() { + if ( queuedProblems.isEmpty() ) return; + CompilationUnitDeclaration cud = (CompilationUnitDeclaration) top().getEclipseNode(); + if ( cud.compilationResult == null ) return; + for ( ParseProblem problem : queuedProblems ) addProblemToCompilationResult(problem); + queuedProblems.clear(); + } + + private final List queuedProblems = new ArrayList(); + + private void addProblem(ParseProblem problem) { + queuedProblems.add(problem); + propagateProblems(); + } + + private void addProblemToCompilationResult(ParseProblem problem) { + Node referenceContextNode = problem.node; + while ( !(referenceContextNode.getEclipseNode() instanceof ReferenceContext) ) { + referenceContextNode = referenceContextNode.up(); + } + ReferenceContext referenceContext = (ReferenceContext)referenceContextNode.getEclipseNode(); + char[] fileName = getFileName().toCharArray(); + String message = problem.message; + int lineNumber = 0; + int columnNumber = 1; + int startPosition = problem.sourceStart; + int endPosition = problem.sourceEnd; + if (referenceContext != null) { + CompilationResult result = referenceContext.compilationResult(); + int[] lineEnds = null; + lineNumber = startPosition >= 0 + ? Util.getLineNumber(startPosition, lineEnds = result.getLineSeparatorPositions(), 0, lineEnds.length-1) + : 0; + columnNumber = startPosition >= 0 + ? Util.searchColumnNumber(result.getLineSeparatorPositions(), lineNumber,startPosition) + : 0; + } + CategorizedProblem ecProblem = new AptProblem(referenceContext, + fileName, message, 0, new String[0], + problem.isWarning ? ProblemSeverities.Warning : ProblemSeverities.Error, + startPosition, endPosition, lineNumber, columnNumber); + ((CompilationUnitDeclaration)top().getEclipseNode()).compilationResult.record(ecProblem, referenceContext); + } + public final class Node { final ASTNode node; Node parent; @@ -86,6 +152,22 @@ public class EclipseAST { this.children = children == null ? Collections.emptyList() : children; } + public void addError(String message) { + this.addError(message, this.getEclipseNode().sourceStart, this.getEclipseNode().sourceEnd); + } + + public void addError(String message, int sourceStart, int sourceEnd) { + addProblem(new ParseProblem(false, message, this, sourceStart, sourceEnd)); + } + + public void addWarning(String message) { + this.addWarning(message, this.getEclipseNode().sourceStart, this.getEclipseNode().sourceEnd); + } + + public void addWarning(String message, int sourceStart, int sourceEnd) { + addProblem(new ParseProblem(true, message, this, sourceStart, sourceEnd)); + } + public ASTNode getEclipseNode() { return node; } @@ -135,6 +217,7 @@ public class EclipseAST { } public void reparse() { + propagateProblems(); if ( completeParse ) return; boolean newCompleteParse = isComplete(compilationUnitDeclaration); if ( !newCompleteParse ) return; diff --git a/src/lombok/eclipse/HandlerLibrary.java b/src/lombok/eclipse/HandlerLibrary.java index fae4acb4..bcfb606b 100644 --- a/src/lombok/eclipse/HandlerLibrary.java +++ b/src/lombok/eclipse/HandlerLibrary.java @@ -8,16 +8,15 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Proxy; import java.lang.reflect.Type; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.ServiceConfigurationError; import java.util.ServiceLoader; import lombok.eclipse.EclipseAST.Node; import lombok.transformations.TypeLibrary; import lombok.transformations.TypeResolver; -import org.eclipse.jdt.core.compiler.CategorizedProblem; -import org.eclipse.jdt.internal.compiler.CompilationResult; -import org.eclipse.jdt.internal.compiler.apt.dispatch.AptProblem; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess; import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration; @@ -30,10 +29,7 @@ import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference; import org.eclipse.jdt.internal.compiler.ast.SingleNameReference; import org.eclipse.jdt.internal.compiler.ast.TypeReference; import org.eclipse.jdt.internal.compiler.impl.Constant; -import org.eclipse.jdt.internal.compiler.impl.ReferenceContext; import org.eclipse.jdt.internal.compiler.lookup.TypeIds; -import org.eclipse.jdt.internal.compiler.problem.ProblemSeverities; -import org.eclipse.jdt.internal.compiler.util.Util; public class HandlerLibrary { private TypeLibrary typeLibrary = new TypeLibrary(); @@ -156,6 +152,20 @@ public class HandlerLibrary { c = tryClass("java.lang." + typeName); if ( c != null ) return c; + if ( !fqn ) { + c = tryClass(typeName); + if ( c != null ) return c; + } + + //Try star imports + for ( ImportReference ref : ast.imports ) { + String im = str(ref.tokens); + if ( im.endsWith(".*") ) { + c = tryClass(im.substring(0, im.length() -1) + typeName); + if ( c != null ) return c; + } + } + throw new EnumDecodeFail(pair, "I can't find this class. Try using the fully qualified name."); } @@ -234,11 +244,17 @@ public class HandlerLibrary { @SuppressWarnings("unchecked") public static HandlerLibrary load() { HandlerLibrary lib = new HandlerLibrary(); - for ( EclipseAnnotationHandler handler : ServiceLoader.load(EclipseAnnotationHandler.class) ) { - Class annotationClass = lib.findAnnotationClass(handler.getClass()); - HandlerContainer container = new HandlerContainer(handler, annotationClass); - lib.handlers.put(container.annotationClass.getName(), container); - lib.typeLibrary.addType(container.annotationClass.getName()); + Iterator it = ServiceLoader.load(EclipseAnnotationHandler.class).iterator(); + while ( it.hasNext() ) { + try { + EclipseAnnotationHandler handler = it.next(); + Class annotationClass = lib.findAnnotationClass(handler.getClass()); + HandlerContainer container = new HandlerContainer(handler, annotationClass); + lib.handlers.put(container.annotationClass.getName(), container); + lib.typeLibrary.addType(container.annotationClass.getName()); + } catch ( ServiceConfigurationError e ) { + Eclipse.error("Can't load Lombok handler for eclipse: ", e); + } } return lib; @@ -284,33 +300,7 @@ public class HandlerLibrary { Object annInstance = createAnnotation(container.annotationClass, ast, annotation); container.handle(annInstance, annotation, node); } catch (EnumDecodeFail e) { - if ( ast.compilationResult != null ) { - Node referenceContextNode = node; - while ( !(referenceContextNode.getEclipseNode() instanceof ReferenceContext) ) { - referenceContextNode = referenceContextNode.up(); - } - ReferenceContext referenceContext = (ReferenceContext)referenceContextNode.getEclipseNode(); - char[] fileName = node.getFileName().toCharArray(); - String message = e.getMessage(); - int lineNumber = 0; - int columnNumber = 1; - int startPosition = e.pair.sourceStart; - int endPosition = e.pair.sourceEnd; - if (referenceContext != null) { - CompilationResult result = referenceContext.compilationResult(); - int[] lineEnds = null; - lineNumber = startPosition >= 0 - ? Util.getLineNumber(startPosition, lineEnds = result.getLineSeparatorPositions(), 0, lineEnds.length-1) - : 0; - columnNumber = startPosition >= 0 - ? Util.searchColumnNumber(result.getLineSeparatorPositions(), lineNumber,startPosition) - : 0; - } - CategorizedProblem problem = new AptProblem(referenceContext, - fileName, message, 0, new String[0], ProblemSeverities.Error, - startPosition, endPosition, lineNumber, columnNumber); - ast.compilationResult.record(problem, referenceContext); - } + node.addError(e.getMessage(), e.pair.sourceStart, e.pair.sourceEnd); } } } -- cgit