From 56150952c451f0d8c2018424191d4480ac5e8460 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 11 Mar 2013 22:04:27 +0100 Subject: Added @Log4j2 support. --- src/core/lombok/eclipse/handlers/HandleLog.java | 15 +++++- .../lombok/extern/apachecommons/CommonsLog.java | 3 +- src/core/lombok/extern/java/Log.java | 3 +- src/core/lombok/extern/log4j/Log4j.java | 3 +- src/core/lombok/extern/log4j/Log4j2.java | 62 ++++++++++++++++++++++ src/core/lombok/extern/slf4j/Slf4j.java | 3 +- src/core/lombok/extern/slf4j/XSlf4j.java | 3 +- src/core/lombok/javac/handlers/HandleLog.java | 17 +++++- 8 files changed, 101 insertions(+), 8 deletions(-) create mode 100644 src/core/lombok/extern/log4j/Log4j2.java (limited to 'src') diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java index bffe2d62..2e7b4475 100644 --- a/src/core/lombok/eclipse/handlers/HandleLog.java +++ b/src/core/lombok/eclipse/handlers/HandleLog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -177,6 +177,16 @@ public class HandleLog { } } + /** + * Handles the {@link lombok.extern.log4j.Log4j2} annotation for Eclipse. + */ + @ProviderFor(EclipseAnnotationHandler.class) + public static class HandleLog4j2Log extends EclipseAnnotationHandler { + @Override public void handle(AnnotationValues annotation, Annotation source, EclipseNode annotationNode) { + processAnnotation(LoggingFramework.LOG4J2, annotation, source, annotationNode); + } + } + /** * Handles the {@link lombok.extern.slf4j.Slf4j} annotation for Eclipse. */ @@ -224,6 +234,9 @@ public class HandleLog { // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class); LOG4J("org.apache.log4j.Logger", "org.apache.log4j.Logger", "getLogger", "@Log4j"), + // private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(TargetType.class); + LOG4J2("org.apache.logging.log4j.Logger", "org.apache.logging.log4j.LogManager", "getLogger", "@Log4j2"), + // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class); SLF4J("org.slf4j.Logger", "org.slf4j.LoggerFactory", "getLogger", "@Slf4j"), diff --git a/src/core/lombok/extern/apachecommons/CommonsLog.java b/src/core/lombok/extern/apachecommons/CommonsLog.java index f178ae05..024e3744 100644 --- a/src/core/lombok/extern/apachecommons/CommonsLog.java +++ b/src/core/lombok/extern/apachecommons/CommonsLog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -52,6 +52,7 @@ import java.lang.annotation.Target; * @see org.apache.commons.logging.LogFactory#getLog(java.lang.Class) org.apache.commons.logging.LogFactory.getLog(Class target) * @see lombok.extern.java.Log @Log * @see lombok.extern.log4j.Log4j @Log4j + * @see lombok.extern.log4j.Log4j2 @Log4j2 * @see lombok.extern.slf4j.Slf4j @Slf4j * @see lombok.extern.slf4j.XSlf4j @XSlf4j */ diff --git a/src/core/lombok/extern/java/Log.java b/src/core/lombok/extern/java/Log.java index 90c62956..7ae4e07b 100644 --- a/src/core/lombok/extern/java/Log.java +++ b/src/core/lombok/extern/java/Log.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -51,6 +51,7 @@ import java.lang.annotation.Target; * @see java.util.logging.Logger#getLogger(java.lang.String) java.util.logging.Logger.getLogger(String name) * @see lombok.extern.apachecommons.CommonsLog @CommonsLog * @see lombok.extern.log4j.Log4j @Log4j + * @see lombok.extern.log4j.Log4j2 @Log4j2 * @see lombok.extern.slf4j.Slf4j @Slf4j * @see lombok.extern.slf4j.XSlf4j @XSlf4j */ diff --git a/src/core/lombok/extern/log4j/Log4j.java b/src/core/lombok/extern/log4j/Log4j.java index 9cfc5839..29e1b27c 100644 --- a/src/core/lombok/extern/log4j/Log4j.java +++ b/src/core/lombok/extern/log4j/Log4j.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -50,6 +50,7 @@ import java.lang.annotation.Target; * * @see org.apache.log4j.Logger org.apache.log4j.Logger * @see org.apache.log4j.Logger#getLogger(java.lang.Class) org.apache.log4j.Logger.getLogger(Class target) + * @see lombok.extern.log4j.Log4j2 @Log4j2 * @see lombok.extern.apachecommons.CommonsLog @CommonsLog * @see lombok.extern.java.Log @Log * @see lombok.extern.slf4j.Slf4j @Slf4j diff --git a/src/core/lombok/extern/log4j/Log4j2.java b/src/core/lombok/extern/log4j/Log4j2.java new file mode 100644 index 00000000..2a0f09e1 --- /dev/null +++ b/src/core/lombok/extern/log4j/Log4j2.java @@ -0,0 +1,62 @@ +/* + * Copyright (C) 2013 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.extern.log4j; + +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Causes lombok to generate a logger field. + *

+ * Complete documentation is found at the project lombok features page for lombok log annotations. + *

+ * Example: + *

+ * @Log4j2
+ * public class LogExample {
+ * }
+ * 
+ * + * will generate: + * + *
+ * public class LogExample {
+ *     private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.Logger.getLogger(LogExample.class);
+ * }
+ * 
+ * + * This annotation is valid for classes and enumerations.
+ * + * @see org.apache.logging.log4j.Logger org.apache.logging.log4j.Logger + * @see org.apache.logging.log4j.LogManager#getLogger(java.lang.Class) org.apache.logging.log4j.LogManager.getLogger(Class target) + * @see lombok.extern.log4j.Log4j @Log4j + * @see lombok.extern.apachecommons.CommonsLog @CommonsLog + * @see lombok.extern.java.Log @Log + * @see lombok.extern.slf4j.Slf4j @Slf4j + * @see lombok.extern.slf4j.XSlf4j @XSlf4j + */ +@Retention(RetentionPolicy.SOURCE) +@Target(ElementType.TYPE) +public @interface Log4j2 { +} \ No newline at end of file diff --git a/src/core/lombok/extern/slf4j/Slf4j.java b/src/core/lombok/extern/slf4j/Slf4j.java index 14dbcba6..45942971 100644 --- a/src/core/lombok/extern/slf4j/Slf4j.java +++ b/src/core/lombok/extern/slf4j/Slf4j.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -51,6 +51,7 @@ import java.lang.annotation.Target; * @see lombok.extern.apachecommons.CommonsLog @CommonsLog * @see lombok.extern.java.Log @Log * @see lombok.extern.log4j.Log4j @Log4j + * @see lombok.extern.log4j.Log4j2 @Log4j2 */ @Retention(RetentionPolicy.SOURCE) @Target(ElementType.TYPE) diff --git a/src/core/lombok/extern/slf4j/XSlf4j.java b/src/core/lombok/extern/slf4j/XSlf4j.java index bdf8a62c..599c68ab 100644 --- a/src/core/lombok/extern/slf4j/XSlf4j.java +++ b/src/core/lombok/extern/slf4j/XSlf4j.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2012 The Project Lombok Authors. + * Copyright (C) 2012-2013 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 @@ -51,6 +51,7 @@ import java.lang.annotation.Target; * @see lombok.extern.apachecommons.CommonsLog @CommonsLog * @see lombok.extern.java.Log @Log * @see lombok.extern.log4j.Log4j @Log4j + * @see lombok.extern.log4j.Log4j2 @Log4j2 * @see lombok.extern.slf4j.Slf4j @Slf4j */ @Retention(RetentionPolicy.SOURCE) diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java index 62a55c44..35a32be5 100644 --- a/src/core/lombok/javac/handlers/HandleLog.java +++ b/src/core/lombok/javac/handlers/HandleLog.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2010-2012 The Project Lombok Authors. + * Copyright (C) 2010-2013 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 @@ -82,7 +82,7 @@ public class HandleLog { private static boolean createField(LoggingFramework framework, JavacNode typeNode, JCFieldAccess loggingType, JCTree source) { TreeMaker maker = typeNode.getTreeMaker(); - // private static final log = (); + // private static final log = (); JCExpression loggerType = chainDotsString(typeNode, framework.getLoggerTypeName()); JCExpression factoryMethod = chainDotsString(typeNode, framework.getLoggerFactoryMethodName()); @@ -127,6 +127,16 @@ public class HandleLog { } } + /** + * Handles the {@link lombok.extern.log4j.Log4j2} annotation for javac. + */ + @ProviderFor(JavacAnnotationHandler.class) + public static class HandleLog4j2Log extends JavacAnnotationHandler { + @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + processAnnotation(LoggingFramework.LOG4J2, annotation, annotationNode); + } + } + /** * Handles the {@link lombok.extern.slf4j.Slf4j} annotation for javac. */ @@ -163,6 +173,9 @@ public class HandleLog { // private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger(TargetType.class); LOG4J(lombok.extern.log4j.Log4j.class, "org.apache.log4j.Logger", "org.apache.log4j.Logger.getLogger"), + // private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(TargetType.class); + LOG4J2(lombok.extern.log4j.Log4j2.class, "org.apache.logging.log4j.Logger", "org.apache.logging.log4j.LogManager.getLogger"), + // private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(TargetType.class); SLF4J(lombok.extern.slf4j.Slf4j.class, "org.slf4j.Logger", "org.slf4j.LoggerFactory.getLogger"), -- cgit From ce73a67803a357f45d1e000d4dc3d1f5004d204a Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 11 Mar 2013 23:21:22 +0100 Subject: Added installer support for JBoss Developer Studio which is an eclipse variant. Also fixed a bug where eclipses installed in user.home weren't found automatically on windows. Also fixed a bug where STS installed in C:\Program Files (X86) wasn't found automatically. --- .../lombok/installer/eclipse/EclipseFinder.java | 22 ++++--- .../lombok/installer/eclipse/JbdsFinder.java | 70 +++++++++++++++++++++ .../lombok/installer/eclipse/JbdsLocation.java | 45 +++++++++++++ .../installer/eclipse/JbdsLocationProvider.java | 69 ++++++++++++++++++++ .../lombok/installer/eclipse/STSFinder.java | 2 +- src/installer/lombok/installer/eclipse/jbds.png | Bin 0 -> 3470 bytes 6 files changed, 199 insertions(+), 9 deletions(-) create mode 100644 src/installer/lombok/installer/eclipse/JbdsFinder.java create mode 100644 src/installer/lombok/installer/eclipse/JbdsLocation.java create mode 100644 src/installer/lombok/installer/eclipse/JbdsLocationProvider.java create mode 100644 src/installer/lombok/installer/eclipse/jbds.png (limited to 'src') diff --git a/src/installer/lombok/installer/eclipse/EclipseFinder.java b/src/installer/lombok/installer/eclipse/EclipseFinder.java index 9fbcabbc..8a1a689a 100644 --- a/src/installer/lombok/installer/eclipse/EclipseFinder.java +++ b/src/installer/lombok/installer/eclipse/EclipseFinder.java @@ -64,14 +64,10 @@ public class EclipseFinder extends IdeFinder { /** * Returns a list of paths of Eclipse installations. - * Eclipse installations are found by checking for the existence of 'eclipse.exe' in the following locations: - *
    - *
  • X:\*Program Files*\*Eclipse*
  • - *
  • X:\*Eclipse*
  • - *
* - * Where 'X' is tried for all local disk drives, unless there's a problem calling fsutil, in which case only - * C: is tried. + * The search process works by scanning for each 'source dir' for either an eclipse installation or a folder containing the text returned + * by getDirName(). If such a folder is found, this process is applied recursively. On windows, this process is run on each drive letter + * which represents a physical hard disk. If the native windows API call to determine these drive letters fails, only 'C:' is checked. */ private List getSourceDirsOnWindowsWithDriveLetters() { List driveLetters = asList("C"); @@ -83,12 +79,22 @@ public class EclipseFinder extends IdeFinder { List sourceDirs = new ArrayList(); for (String letter : driveLetters) { for (String possibleSource : getSourceDirsOnWindows()) { - sourceDirs.add(letter + ":" + possibleSource); + if (!isDriveSpecificOnWindows(possibleSource)) { + sourceDirs.add(letter + ":" + possibleSource); + } } } + for (String possibleSource : getSourceDirsOnWindows()) { + if (isDriveSpecificOnWindows(possibleSource)) sourceDirs.add(possibleSource); + } + return sourceDirs; } + public boolean isDriveSpecificOnWindows(String path) { + return path.length() > 1 && path.charAt(1) == ':'; + } + protected List getSourceDirsOnMac() { return Arrays.asList("/Applications", System.getProperty("user.home", ".")); } diff --git a/src/installer/lombok/installer/eclipse/JbdsFinder.java b/src/installer/lombok/installer/eclipse/JbdsFinder.java new file mode 100644 index 00000000..2dfaacba --- /dev/null +++ b/src/installer/lombok/installer/eclipse/JbdsFinder.java @@ -0,0 +1,70 @@ +/* + * Copyright (C) 2013 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.installer.eclipse; + +import java.util.Arrays; +import java.util.List; + +import lombok.installer.CorruptedIdeLocationException; +import lombok.installer.IdeFinder; +import lombok.installer.IdeLocation; + +import org.mangosdk.spi.ProviderFor; + +/** + * JBDS (JBoss Developer Studio) is an eclipse variant. + * Other than different executable names, it's the same as eclipse, as far as lombok support goes. + */ +@ProviderFor(IdeFinder.class) +public class JbdsFinder extends EclipseFinder { + @Override protected IdeLocation createLocation(String guess) throws CorruptedIdeLocationException { + return new JbdsLocationProvider().create0(guess); + } + + @Override protected String getDirName() { + return "studio"; + } + + @Override protected String getMacExecutableName() { + return "jbdevstudio.app"; + } + + @Override protected String getUnixExecutableName() { + return "jbdevstudio"; + } + + @Override protected String getWindowsExecutableName() { + return "jbdevstudio.exe"; + } + + @Override protected List getSourceDirsOnWindows() { + return Arrays.asList("\\", "\\Program Files", "\\Program Files (x86)", System.getProperty("user.home", ".")); + } + + @Override protected List getSourceDirsOnMac() { + return Arrays.asList("/Applications", System.getProperty("user.home", ".")); + } + + @Override protected List getSourceDirsOnUnix() { + return Arrays.asList(System.getProperty("user.home", ".")); + } +} diff --git a/src/installer/lombok/installer/eclipse/JbdsLocation.java b/src/installer/lombok/installer/eclipse/JbdsLocation.java new file mode 100644 index 00000000..81fb5261 --- /dev/null +++ b/src/installer/lombok/installer/eclipse/JbdsLocation.java @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2013 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.installer.eclipse; + +import java.io.File; +import java.net.URL; + +import lombok.installer.CorruptedIdeLocationException; + +public class JbdsLocation extends EclipseLocation { + public JbdsLocation(String nameOfLocation, File pathToEclipseIni) throws CorruptedIdeLocationException { + super(nameOfLocation, pathToEclipseIni); + } + + @Override public URL getIdeIcon() { + return JbdsLocation.class.getResource("jbds.png"); + } + + @Override protected String getIniFileName() { + return "jbdevstudio.ini"; + } + + @Override protected String getTypeName() { + return "JBoss Developer Studio"; + } +} diff --git a/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java b/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java new file mode 100644 index 00000000..e6df0e43 --- /dev/null +++ b/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java @@ -0,0 +1,69 @@ +/* + * Copyright (C) 2013 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.installer.eclipse; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import lombok.installer.CorruptedIdeLocationException; +import lombok.installer.IdeLocation; +import lombok.installer.IdeLocationProvider; +import lombok.installer.IdeFinder.OS; + +import org.mangosdk.spi.ProviderFor; + +@ProviderFor(IdeLocationProvider.class) +public class JbdsLocationProvider extends EclipseLocationProvider { + @Override protected List getEclipseExecutableNames() { + return Arrays.asList("jbdevstudio.app", "jbdevstudio.exe", "jbdevstudioc.exe", "jbdevstudio"); + } + + @Override protected String getIniName() { + return "jbdevstudio.ini"; + } + + @Override protected IdeLocation makeLocation(String name, File ini) throws CorruptedIdeLocationException { + return new JbdsLocation(name, ini); + } + + @Override protected String getMacAppName() { + return "jbdevstudio.app"; + } + + @Override protected String getUnixAppName() { + return "jbdevstudio"; + } + + @Override public Pattern getLocationSelectors(OS os) { + switch (os) { + case MAC_OS_X: + return Pattern.compile("^(jbdevstudio|jbdevstudio\\.ini|jbdevstudio\\.app)$", Pattern.CASE_INSENSITIVE); + case WINDOWS: + return Pattern.compile("^(jbdevstudioc?\\.exe|jbdevstudio\\.ini)$", Pattern.CASE_INSENSITIVE); + default: + case UNIX: + return Pattern.compile("^(jbdevstudio|jbdevstudio\\.ini)$", Pattern.CASE_INSENSITIVE); + } + } +} diff --git a/src/installer/lombok/installer/eclipse/STSFinder.java b/src/installer/lombok/installer/eclipse/STSFinder.java index 74b8ed34..82bc9b80 100644 --- a/src/installer/lombok/installer/eclipse/STSFinder.java +++ b/src/installer/lombok/installer/eclipse/STSFinder.java @@ -57,7 +57,7 @@ public class STSFinder extends EclipseFinder { } @Override protected List getSourceDirsOnWindows() { - return Arrays.asList("\\", "\\springsource", "\\Program Files", "\\Program Files\\springsource", System.getProperty("user.home", "."), System.getProperty("user.home", ".") + "\\springsource"); + return Arrays.asList("\\", "\\springsource", "\\Program Files", "\\Program Files (x86)", "\\Program Files\\springsource", "\\Program Files (x86)\\springsource", System.getProperty("user.home", "."), System.getProperty("user.home", ".") + "\\springsource"); } @Override protected List getSourceDirsOnMac() { diff --git a/src/installer/lombok/installer/eclipse/jbds.png b/src/installer/lombok/installer/eclipse/jbds.png new file mode 100644 index 00000000..ca7738e6 Binary files /dev/null and b/src/installer/lombok/installer/eclipse/jbds.png differ -- cgit From 9400f39d12813740634bba233aacc6edcf62c584 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 12 Mar 2013 00:25:50 +0100 Subject: Fix for issue #436: In eclipse, calling i.e. `list.get(i).extensionMethod()` would fail with VerifyError when that code is executed in eclipse. --- src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'src') diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java index 008e722a..a3d77055 100644 --- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java +++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java @@ -236,10 +236,8 @@ public class PatchExtensionMethod { for (int i = 0, iend = arguments.size(); i < iend; i++) { Expression arg = arguments.get(i); if (fixedBinding.parameters[i].isArrayType() != arg.resolvedType.isArrayType()) break; - if (arg.resolvedType.isArrayType()) { - if (arg instanceof MessageSend) { - ((MessageSend) arg).valueCast = arg.resolvedType; - } + if (arg instanceof MessageSend) { + ((MessageSend) arg).valueCast = arg.resolvedType; } if (!fixedBinding.parameters[i].isBaseType() && arg.resolvedType.isBaseType()) { int id = arg.resolvedType.id; -- cgit From cb9b907839aa0c72ffa41f8a13bfab5cb1341258 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Tue, 12 Mar 2013 01:29:15 +0100 Subject: In delombok, we mark the AST as changed if we remove an annotation; this fixes the issue where delombok would leave lombok annotations in the file if that annotation had no actual effect (such as @Getter on a field if there is an explicit getX method for that field). issue #443: delombok would screw up @SneakyThrows on methods or constructors with empty bodies. Now we generate warnings for this. --- .../eclipse/handlers/HandleSneakyThrows.java | 24 ++++++++++++++++++---- .../lombok/javac/handlers/HandleSneakyThrows.java | 19 +++++++++++++++-- .../lombok/javac/handlers/JavacHandlerUtil.java | 1 + 3 files changed, 38 insertions(+), 6 deletions(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java index b7c8a5d8..aa78ca3b 100644 --- a/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/eclipse/handlers/HandleSneakyThrows.java @@ -40,6 +40,8 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer; import org.eclipse.jdt.internal.compiler.ast.Block; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.Expression; import org.eclipse.jdt.internal.compiler.ast.MemberValuePair; import org.eclipse.jdt.internal.compiler.ast.MessageSend; @@ -147,7 +149,21 @@ public class HandleSneakyThrows extends EclipseAnnotationHandler { return; } - if (method.statements == null) return; + if (method.statements == null || method.statements.length == 0) { + boolean hasConstructorCall = false; + if (method instanceof ConstructorDeclaration) { + ExplicitConstructorCall constructorCall = ((ConstructorDeclaration) method).constructorCall; + hasConstructorCall = constructorCall != null && !constructorCall.isImplicitSuper() && !constructorCall.isImplicitThis(); + } + + if (hasConstructorCall) { + annotation.addWarning("Calls to sibling / super constructors are always excluded from @SneakyThrows; @SneakyThrows has been ignored because there is no other code in this constructor."); + } else { + annotation.addWarning("This method or constructor is empty; @SneakyThrows has been ignored."); + } + + return; + } Statement[] contents = method.statements; @@ -160,9 +176,9 @@ public class HandleSneakyThrows extends EclipseAnnotationHandler { } private Statement buildTryCatchBlock(Statement[] contents, DeclaredException exception, ASTNode source, AbstractMethodDeclaration method) { - int methodStart = method.bodyStart; - int methodEnd = method.bodyEnd; - long methodPosEnd = methodEnd << 32 | (methodEnd & 0xFFFFFFFFL); + int methodStart = method.bodyStart; + int methodEnd = method.bodyEnd; + long methodPosEnd = ((long) methodEnd) << 32 | (methodEnd & 0xFFFFFFFFL); TryStatement tryStatement = new TryStatement(); setGeneratedBy(tryStatement, source); diff --git a/src/core/lombok/javac/handlers/HandleSneakyThrows.java b/src/core/lombok/javac/handlers/HandleSneakyThrows.java index a5bd74e7..c2394fc8 100644 --- a/src/core/lombok/javac/handlers/HandleSneakyThrows.java +++ b/src/core/lombok/javac/handlers/HandleSneakyThrows.java @@ -84,13 +84,20 @@ public class HandleSneakyThrows extends JavacAnnotationHandler { return; } - if (method.body == null) return; - if (method.body.stats.isEmpty()) return; + if (method.body == null || method.body.stats.isEmpty()) { + generateEmptyBlockWarning(methodNode, annotation, false); + return; + } final JCStatement constructorCall = method.body.stats.get(0); final boolean isConstructorCall = isConstructorCall(constructorCall); List contents = isConstructorCall ? method.body.stats.tail : method.body.stats; + if (contents == null || contents.isEmpty()) { + generateEmptyBlockWarning(methodNode, annotation, true); + return; + } + for (String exception : exceptions) { contents = List.of(buildTryCatchBlock(methodNode, contents, exception, annotation.get())); } @@ -99,6 +106,14 @@ public class HandleSneakyThrows extends JavacAnnotationHandler { methodNode.rebuild(); } + private void generateEmptyBlockWarning(JavacNode methodNode, JavacNode annotation, boolean hasConstructorCall) { + if (hasConstructorCall) { + annotation.addWarning("Calls to sibling / super constructors are always excluded from @SneakyThrows; @SneakyThrows has been ignored because there is no other code in this constructor."); + } else { + annotation.addWarning("This method or constructor is empty; @SneakyThrows has been ignored."); + } + } + private boolean isConstructorCall(final JCStatement supect) { if (!(supect instanceof JCExpressionStatement)) return false; final JCExpression supectExpression = ((JCExpressionStatement) supect).expr; diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java index c2de5b05..e79dd5dc 100644 --- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java +++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java @@ -305,6 +305,7 @@ public class JavacHandlerUtil { return; } + parentNode.getAst().setChanged(); deleteImportFromCompilationUnit(annotation, annotationType.getName()); } -- cgit From f341a00baa992e652f119164e24cf64699281e0d Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 18 Mar 2013 21:22:59 +0100 Subject: fixed javadoc of XAnnotationHandler; they used to be interfaces but now they are abstract classes. --- src/core/lombok/eclipse/EclipseAnnotationHandler.java | 2 +- src/core/lombok/javac/JavacAnnotationHandler.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/EclipseAnnotationHandler.java b/src/core/lombok/eclipse/EclipseAnnotationHandler.java index 84304339..ca9965f7 100644 --- a/src/core/lombok/eclipse/EclipseAnnotationHandler.java +++ b/src/core/lombok/eclipse/EclipseAnnotationHandler.java @@ -29,7 +29,7 @@ import lombok.core.SpiLoadUtil; * * You MUST replace 'T' with a specific annotation type, such as: * - * {@code public class HandleGetter implements EclipseAnnotationHandler} + * {@code public class HandleGetter extends EclipseAnnotationHandler} * * Because this generics parameter is inspected to figure out which class you're interested in. * diff --git a/src/core/lombok/javac/JavacAnnotationHandler.java b/src/core/lombok/javac/JavacAnnotationHandler.java index 169e2026..a86aa6c6 100644 --- a/src/core/lombok/javac/JavacAnnotationHandler.java +++ b/src/core/lombok/javac/JavacAnnotationHandler.java @@ -33,7 +33,7 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation; * * You MUST replace 'T' with a specific annotation type, such as: * - * {@code public class HandleGetter implements JavacAnnotationHandler} + * {@code public class HandleGetter extends JavacAnnotationHandler} * * Because this generics parameter is inspected to figure out which class you're interested in. * -- cgit From 5ec852b35b9f6e0f330098a302ce0d655f792ff7 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 18 Mar 2013 22:10:20 +0100 Subject: Some halfway work on introducing hideNulls feature to toString. Aborted because it is a lot more work than anticipated, but this code is prettier and slightly more bugfree so worth checking in. --- src/core/lombok/eclipse/handlers/HandleToString.java | 18 +++++++++++------- src/core/lombok/javac/handlers/HandleToString.java | 20 ++++++++++++-------- 2 files changed, 23 insertions(+), 15 deletions(-) (limited to 'src') diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java index 75d4acef..d864153f 100644 --- a/src/core/lombok/eclipse/handlers/HandleToString.java +++ b/src/core/lombok/eclipse/handlers/HandleToString.java @@ -209,21 +209,25 @@ public class HandleToString extends EclipseAnnotationHandler { } for (EclipseNode field : fields) { - TypeReference fType = getFieldType(field, fieldAccess); + TypeReference fieldType = getFieldType(field, fieldAccess); Expression fieldAccessor = createFieldAccessor(field, fieldAccess, source); + // The distinction between primitive and object will be useful if we ever add a 'hideNulls' option. + boolean fieldBaseTypeIsPrimitive = BUILT_IN_TYPES.contains(new String(fieldType.getLastToken())); + boolean fieldIsPrimitive = fieldType.dimensions() == 0 && fieldBaseTypeIsPrimitive; + boolean fieldIsPrimitiveArray = fieldType.dimensions() == 1 && fieldBaseTypeIsPrimitive; + boolean fieldIsObjectArray = fieldType.dimensions() > 0 && !fieldIsPrimitiveArray; + @SuppressWarnings("unused") + boolean fieldIsObject = !fieldIsPrimitive && !fieldIsPrimitiveArray && !fieldIsObjectArray; + Expression ex; - if (fType.dimensions() > 0) { + if (fieldIsPrimitiveArray || fieldIsObjectArray) { MessageSend arrayToString = new MessageSend(); arrayToString.sourceStart = pS; arrayToString.sourceEnd = pE; arrayToString.receiver = generateQualifiedNameRef(source, TypeConstants.JAVA, TypeConstants.UTIL, "Arrays".toCharArray()); arrayToString.arguments = new Expression[] { fieldAccessor }; setGeneratedBy(arrayToString.arguments[0], source); - if (fType.dimensions() > 1 || !BUILT_IN_TYPES.contains(new String(fType.getLastToken()))) { - arrayToString.selector = "deepToString".toCharArray(); - } else { - arrayToString.selector = "toString".toCharArray(); - } + arrayToString.selector = (fieldIsObjectArray ? "deepToString" : "toString").toCharArray(); ex = arrayToString; } else { ex = fieldAccessor; diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java index 520acf62..5b3c033c 100644 --- a/src/core/lombok/javac/handlers/HandleToString.java +++ b/src/core/lombok/javac/handlers/HandleToString.java @@ -198,18 +198,22 @@ public class HandleToString extends JavacAnnotationHandler { } for (JavacNode fieldNode : fields) { - JCVariableDecl field = (JCVariableDecl) fieldNode.get(); JCExpression expr; JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess); - if (getFieldType(fieldNode, fieldAccess) instanceof JCArrayTypeTree) { - boolean multiDim = ((JCArrayTypeTree)field.vartype).elemtype instanceof JCArrayTypeTree; - boolean primitiveArray = ((JCArrayTypeTree)field.vartype).elemtype instanceof JCPrimitiveTypeTree; - boolean useDeepTS = multiDim || !primitiveArray; - - JCExpression hcMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepTS ? "deepToString" : "toString"); - expr = maker.Apply(List.nil(), hcMethod, List.of(fieldAccessor)); + JCExpression fieldType = getFieldType(fieldNode, fieldAccess); + + // The distinction between primitive and object will be useful if we ever add a 'hideNulls' option. + boolean fieldIsPrimitive = fieldType instanceof JCPrimitiveTypeTree; + boolean fieldIsPrimitiveArray = fieldType instanceof JCArrayTypeTree && ((JCArrayTypeTree) fieldType).elemtype instanceof JCPrimitiveTypeTree; + boolean fieldIsObjectArray = !fieldIsPrimitiveArray && fieldType instanceof JCArrayTypeTree; + @SuppressWarnings("unused") + boolean fieldIsObject = !fieldIsPrimitive && !fieldIsPrimitiveArray && !fieldIsObjectArray; + + if (fieldIsPrimitiveArray || fieldIsObjectArray) { + JCExpression tsMethod = chainDots(typeNode, "java", "util", "Arrays", fieldIsObjectArray ? "deepToString" : "toString"); + expr = maker.Apply(List.nil(), tsMethod, List.of(fieldAccessor)); } else expr = fieldAccessor; if (first) { -- cgit From 66f32d5073bc726f76f958471ea93ec5a29c354b Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Mon, 18 Mar 2013 23:57:09 +0100 Subject: Fixed issue 459: Delombok would choke on try-with-resources. --- .../lombok/delombok/PrettyCommentsPrinter.java | 28 ++++++++++++++++++++++ 1 file changed, 28 insertions(+) (limited to 'src') diff --git a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java index 6e9a1c94..9c6a2bd7 100644 --- a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java +++ b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java @@ -22,6 +22,11 @@ * CA 95054 USA or visit www.sun.com if you need additional information or * have any questions. */ + +/* + * Code derived from com.sun.tools.javac.tree.Pretty, from the langtools project. + * A version can be found at, for example, http://hg.openjdk.java.net/jdk7/build/langtools + */ package lombok.delombok; import static com.sun.tools.javac.code.Flags.ANNOTATION; @@ -981,6 +986,29 @@ public class PrettyCommentsPrinter extends JCTree.Visitor { public void visitTry(JCTry tree) { try { print("try "); + List resources = null; + try { + Field f = JCTry.class.getField("resources"); + resources = (List) f.get(tree); + } catch (Exception ignore) { + // In JDK6 and down this field does not exist; resources will retain its initializer value which is what we want. + } + + if (resources != null && resources.nonEmpty()) { + boolean first = true; + print("("); + for (Object var0 : resources) { + JCTree var = (JCTree) var0; + if (!first) { + println(); + indent(); + } + printStat(var); + first = false; + } + print(") "); + } + printStat(tree.body); for (List l = tree.catchers; l.nonEmpty(); l = l.tail) { printStat(l.head); -- cgit From 9630fc96e8382d68505a4cb8ab2ae08aec48e776 Mon Sep 17 00:00:00 2001 From: Roel Spilker Date: Tue, 26 Mar 2013 02:42:14 +0100 Subject: Massive performance improvements, and a few potentially breaking changes for other lombok plugin developers. --- src/core/lombok/core/AST.java | 15 +- src/core/lombok/core/AnnotationValues.java | 19 +-- src/core/lombok/core/ImportList.java | 43 +++++ src/core/lombok/core/LombokNode.java | 58 ++----- src/core/lombok/core/TypeLibrary.java | 68 +++----- src/core/lombok/core/TypeResolver.java | 102 ++++------- src/core/lombok/eclipse/EclipseAST.java | 23 +-- src/core/lombok/eclipse/EclipseImportList.java | 131 ++++++++++++++ src/core/lombok/eclipse/HandlerLibrary.java | 41 +++-- .../eclipse/handlers/EclipseHandlerUtil.java | 2 +- src/core/lombok/javac/HandlerLibrary.java | 32 ++-- src/core/lombok/javac/JavacAST.java | 17 +- src/core/lombok/javac/JavacImportList.java | 105 ++++++++++++ .../lombok/javac/handlers/JavacHandlerUtil.java | 2 +- src/utils/lombok/core/ImmutableList.java | 188 +++++++++++++++++++++ src/utils/lombok/eclipse/Eclipse.java | 6 +- 16 files changed, 599 insertions(+), 253 deletions(-) create mode 100644 src/core/lombok/core/ImportList.java create mode 100644 src/core/lombok/eclipse/EclipseImportList.java create mode 100644 src/core/lombok/javac/JavacImportList.java create mode 100644 src/utils/lombok/core/ImmutableList.java (limited to 'src') diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java index 68f36412..644d9449 100644 --- a/src/core/lombok/core/AST.java +++ b/src/core/lombok/core/AST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -30,7 +30,6 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.IdentityHashMap; import java.util.List; @@ -54,15 +53,15 @@ public abstract class AST, L extends LombokNode, private L top; private final String fileName; private final String packageDeclaration; - private final Collection imports; + private final ImportList imports; Map identityDetector = new IdentityHashMap(); private Map nodeMap = new IdentityHashMap(); private boolean changed = false; - protected AST(String fileName, String packageDeclaration, Collection imports) { + protected AST(String fileName, String packageDeclaration, ImportList imports) { this.fileName = fileName == null ? "(unknown).java" : fileName; this.packageDeclaration = packageDeclaration; - this.imports = Collections.unmodifiableCollection(new ArrayList(imports)); + this.imports = imports; } public void setChanged() { @@ -96,7 +95,7 @@ public abstract class AST, L extends LombokNode, * * Example: "java.util.IOException". */ - public final Collection getImportStatements() { + public final ImportList getImportList() { return imports; } @@ -159,8 +158,8 @@ public abstract class AST, L extends LombokNode, oldChild.parent = targetNode; } - targetNode.children.clear(); - ((List)targetNode.children).addAll(children); + targetNode.children = ImmutableList.copyOf(children); + return targetNode; } diff --git a/src/core/lombok/core/AnnotationValues.java b/src/core/lombok/core/AnnotationValues.java index df056dd4..d04797cb 100644 --- a/src/core/lombok/core/AnnotationValues.java +++ b/src/core/lombok/core/AnnotationValues.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -435,23 +435,16 @@ public class AnnotationValues { } /* 2. Walk through non-star imports and search for a match. */ { - for (String im : ast == null ? Collections.emptyList() : ast.getImportStatements()) { - if (im.endsWith(".*")) continue; - int idx = im.lastIndexOf('.'); - String simple = idx == -1 ? im : im.substring(idx+1); - if (simple.equals(prefix)) { - return im + typeName.substring(prefix.length()); - } + if (prefix.equals(typeName)) { + String fqn = ast.getImportList().getFullyQualifiedNameForSimpleName(typeName); + if (fqn != null) return fqn; } } /* 3. Walk through star imports and, if they start with "java.", use Class.forName based resolution. */ { - List imports = ast == null ? Collections.emptyList() : new ArrayList(ast.getImportStatements()); - imports.add("java.lang.*"); - for (String im : imports) { - if (!im.endsWith(".*") || !im.startsWith("java.")) continue; + for (String potential : ast.getImportList().applyNameToStarImports("java", typeName)) { try { - Class c = Class.forName(im.substring(0, im.length()-1) + typeName); + Class c = Class.forName(potential); if (c != null) return c.getName(); } catch (Throwable t) { //Class.forName failed for whatever reason - it most likely does not exist, continue. diff --git a/src/core/lombok/core/ImportList.java b/src/core/lombok/core/ImportList.java new file mode 100644 index 00000000..95e266c4 --- /dev/null +++ b/src/core/lombok/core/ImportList.java @@ -0,0 +1,43 @@ +/* + * Copyright (C) 2013 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.util.Collection; + +public interface ImportList { + /** + * If there is an explicit import of the stated unqualified type name, return that. Otherwise, return null. + */ + String getFullyQualifiedNameForSimpleName(String unqualified); + + /** + * Returns true if the package name is explicitly star-imported, OR the packageName refers to this source file's own package name, OR packageName is 'java.lang'. + */ + boolean hasStarImport(String packageName); + + /** + * Takes all explicit non-static star imports whose first element is equal to {@code startsWith}, replaces the star with {@code unqualified}, and returns these. + */ + Collection applyNameToStarImports(String startsWith, String unqualified); + + String applyUnqualifiedNameToPackage(String unqualified); +} diff --git a/src/core/lombok/core/LombokNode.java b/src/core/lombok/core/LombokNode.java index eac59806..588adc55 100644 --- a/src/core/lombok/core/LombokNode.java +++ b/src/core/lombok/core/LombokNode.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -42,7 +42,7 @@ public abstract class LombokNode, L extends LombokNode children; + protected ImmutableList children; protected L parent; /** structurally significant are those nodes that can be annotated in java 1.6 or are method-like toplevels, @@ -62,7 +62,7 @@ public abstract class LombokNode, L extends LombokNode() : children; + this.children = children != null ? ImmutableList.copyOf(children) : ImmutableList.of(); for (L child : this.children) { child.parent = (L) this; if (!child.isStructurallySignificant) @@ -91,12 +91,12 @@ public abstract class LombokNode, L extends LombokNode getImportStatements() { - return ast.getImportStatements(); + public ImportList getImportList() { + return ast.getImportList(); } /** @@ -120,35 +120,6 @@ public abstract class LombokNode, L extends LombokNode, L extends LombokNode down() { - return new ArrayList(children); + public ImmutableList down() { + return children; } /** @@ -235,13 +203,13 @@ public abstract class LombokNode, L extends LombokNode, L extends LombokNode, L extends LombokNode
  • foo.Spork
  • Spork
  • foo.*
  • */ public class TypeLibrary { - private final Map> keyToFqnMap; - private final String singletonValue; - private final List singletonKeys; + private final Map unqualifiedToQualifiedMap; + private final String unqualified, qualified; public TypeLibrary() { - keyToFqnMap = new HashMap>(); - singletonKeys = null; - singletonValue = null; + unqualifiedToQualifiedMap = new HashMap(); + unqualified = null; + qualified = null; } private TypeLibrary(String fqnSingleton) { - keyToFqnMap = null; - singletonValue = fqnSingleton; + unqualifiedToQualifiedMap = null; + qualified = fqnSingleton; int idx = fqnSingleton.lastIndexOf('.'); if (idx == -1) { - singletonKeys = Collections.singletonList(fqnSingleton); + unqualified = fqnSingleton; } else { - singletonKeys = Arrays.asList(fqnSingleton, fqnSingleton.substring(idx + 1), fqnSingleton.substring(0, idx) + ".*"); + unqualified = fqnSingleton.substring(idx + 1); } } @@ -71,42 +65,28 @@ public class TypeLibrary { * @param fullyQualifiedTypeName the FQN type name, such as 'java.lang.String'. */ public void addType(String fullyQualifiedTypeName) { - if (keyToFqnMap == null) throw new IllegalStateException("SingleType library"); + fullyQualifiedTypeName = fullyQualifiedTypeName.replace("$", "."); int idx = fullyQualifiedTypeName.lastIndexOf('.'); if (idx == -1) throw new IllegalArgumentException( "Only fully qualified types are allowed (and stuff in the default package is not palatable to us either!)"); + String unqualified = fullyQualifiedTypeName.substring(idx + 1); + if (unqualifiedToQualifiedMap == null) throw new IllegalStateException("SingleType library"); - fullyQualifiedTypeName = fullyQualifiedTypeName.replace("$", "."); - final String simpleName = fullyQualifiedTypeName.substring(idx +1); - final String packageName = fullyQualifiedTypeName.substring(0, idx); - - if (keyToFqnMap.put(fullyQualifiedTypeName, Collections.singletonList(fullyQualifiedTypeName)) != null) return; - - addToMap(simpleName, fullyQualifiedTypeName); - addToMap(packageName + ".*", fullyQualifiedTypeName); - } - - private TypeLibrary addToMap(String keyName, String fullyQualifiedTypeName) { - List list = keyToFqnMap.get(keyName); - if (list == null) { - list = new ArrayList(); - keyToFqnMap.put(keyName, list); - } - - list.add(fullyQualifiedTypeName); - return this; + unqualifiedToQualifiedMap.put(unqualified, fullyQualifiedTypeName); + unqualifiedToQualifiedMap.put(fullyQualifiedTypeName, fullyQualifiedTypeName); } /** - * Returns all items in the type library that may be a match to the provided type. + * Translates an unqualified name such as 'String' to 'java.lang.String', _if_ you added 'java.lang.String' to the library via the {@code addType} method. + * Also returns the input if it is equal to a fully qualified name added to this type library. * - * @param typeReference something like 'String', 'java.lang.String', or 'java.lang.*'. - * @return A list of Fully Qualified Names for all types in the library that fit the reference. + * Returns null if it does not match any type in this type library. */ - public Collection findCompatible(String typeReference) { - if (singletonKeys != null) return singletonKeys.contains(typeReference) ? Collections.singletonList(singletonValue) : Collections.emptyList(); - - List result = keyToFqnMap.get(typeReference); - return result == null ? Collections.emptyList() : Collections.unmodifiableList(result); + public String toQualified(String typeReference) { + if (unqualifiedToQualifiedMap == null) { + if (typeReference.equals(unqualified) || typeReference.equals(qualified)) return qualified; + return null; + } + return unqualifiedToQualifiedMap.get(typeReference); } } diff --git a/src/core/lombok/core/TypeResolver.java b/src/core/lombok/core/TypeResolver.java index 27f0bfc1..e2ba03b5 100644 --- a/src/core/lombok/core/TypeResolver.java +++ b/src/core/lombok/core/TypeResolver.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2011 The Project Lombok Authors. + * Copyright (C) 2009-2013 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 @@ -21,11 +21,6 @@ */ package lombok.core; -import java.util.Collection; -import java.util.Collections; -import java.util.HashSet; -import java.util.Set; - import lombok.core.AST.Kind; /** @@ -35,60 +30,54 @@ import lombok.core.AST.Kind; * and this importer also can't find inner types from superclasses/interfaces. */ public class TypeResolver { - private Collection imports; + private ImportList imports; /** * Creates a new TypeResolver that can be used to resolve types in a source file with the given package and import statements. */ - public TypeResolver(String packageString, Collection importStrings) { - this.imports = makeImportList(packageString, importStrings); - } - - private static Collection makeImportList(String packageString, Collection importStrings) { - Set imports = new HashSet(); - if (packageString != null) imports.add(packageString + ".*"); - imports.addAll(importStrings == null ? Collections.emptySet() : importStrings); - imports.add("java.lang.*"); - return imports; + public TypeResolver(ImportList importList) { + this.imports = importList; } +// private static ImportList makeImportList(String packageString, Collection importStrings) { +// Set imports = new HashSet(); +// if (packageString != null) imports.add(packageString + ".*"); +// imports.addAll(importStrings == null ? Collections.emptySet() : importStrings); +// imports.add("java.lang.*"); +// return imports; +// } +// public boolean typeMatches(LombokNode context, String fqn, String typeRef) { - return !findTypeMatches(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef).isEmpty(); + return typeRefToFullyQualifiedName(context, TypeLibrary.createLibraryForSingleType(fqn), typeRef) != null; } - /** - * Finds type matches for the stated type reference. The provided context is scanned for local type names - * that shadow type names listed in import statements. If such a shadowing occurs, no matches are returned - * for any shadowed types, as you would expect. - */ - public Collection findTypeMatches(LombokNode context, TypeLibrary library, String typeRef) { + public String typeRefToFullyQualifiedName(LombokNode context, TypeLibrary library, String typeRef) { // When asking if 'Foo' could possibly be referring to 'bar.Baz', the answer is obviously no. - Collection potentialMatches = library.findCompatible(typeRef); - if (potentialMatches.isEmpty()) return Collections.emptyList(); + String qualified = library.toQualified(typeRef); + if (qualified == null) return null; - // If input type appears to be fully qualified, we found a winner. - int idx = typeRef.indexOf('.'); - if (idx > -1) return potentialMatches; + // When asking if 'lombok.Getter' could possibly be referring to 'lombok.Getter', the answer is obviously yes. + if (typeRef.equals(qualified)) return typeRef; - // If there's an import statement that explicitly imports a 'Getter' that isn't any of our potentials, return no matches, - // because if you want to know if 'Foo' could refer to 'bar.Foo' when 'baz.Foo' is explicitly imported, the answer is no. - if (nameConflictInImportList(typeRef, potentialMatches)) return Collections.emptyList(); + // When asking if 'Getter' could possibly be referring to 'lombok.Getter' if 'import lombok.Getter;' is in the source file, the answer is yes. + String fromExplicitImport = imports.getFullyQualifiedNameForSimpleName(typeRef); + if (fromExplicitImport != null) { + // ... and if 'import foobar.Getter;' is in the source file, the answer is no. + return fromExplicitImport.equals(qualified) ? qualified : null; + } - // Check if any of our potentials are even imported in the first place. If not: no matches. - // Note that (ourPackage.*) is added to the imports. - potentialMatches = eliminateImpossibleMatches(potentialMatches, library); - if (potentialMatches.isEmpty()) return Collections.emptyList(); + // When asking if 'Getter' could possibly be referring to 'lombok.Getter' and 'import lombok.*; / package lombok;' isn't in the source file. the answer is no. + String pkgName = qualified.substring(0, qualified.length() - typeRef.length() - 1); + if (!imports.hasStarImport(pkgName)) return null; - // Now the hard part - inner classes or method local classes in our own scope. - // For method locals, this refers to any statements that are 'above' the type reference with the same name. - // For inners, this refers to siblings of us or any parent node that are type declarations. + // Now the hard part: Given that there is a star import, 'Getter' most likely refers to 'lombok.Getter', but type shadowing may occur in which case it doesn't. LombokNode n = context; mainLoop: while (n != null) { if (n.getKind() == Kind.TYPE && typeRef.equals(n.getName())) { // Our own class or one of our outer classes is named 'typeRef' so that's what 'typeRef' is referring to, not one of our type library classes. - return Collections.emptyList(); + return null; } if (n.getKind() == Kind.STATEMENT || n.getKind() == Kind.LOCAL) { @@ -99,7 +88,7 @@ public class TypeResolver { for (LombokNode child : newN.down()) { // We found a method local with the same name above our code. That's the one 'typeRef' is referring to, not // anything in the type library we're trying to find, so, no matches. - if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList(); + if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return null; if (child == n) break; } } @@ -110,41 +99,14 @@ public class TypeResolver { if (n.getKind() == Kind.TYPE || n.getKind() == Kind.COMPILATION_UNIT) { for (LombokNode child : n.down()) { // Inner class that's visible to us has 'typeRef' as name, so that's the one being referred to, not one of our type library classes. - if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return Collections.emptyList(); + if (child.getKind() == Kind.TYPE && typeRef.equals(child.getName())) return null; } } n = n.directUp(); } - // No class in this source file is a match, the