diff options
-rw-r--r-- | src/core/lombok/core/AST.java | 2 | ||||
-rw-r--r-- | src/core/lombok/core/LombokConfiguration.java | 63 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/ConfigurationDataType.java | 118 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/ConfigurationKey.java | 109 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/ConfigurationResolver.java | 26 | ||||
-rw-r--r-- | src/core/lombok/core/configuration/StringResolver.java | 84 | ||||
-rw-r--r-- | src/core/lombok/eclipse/handlers/HandleLog.java | 2 |
7 files changed, 386 insertions, 18 deletions
diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java index 954438bd..50eeb399 100644 --- a/src/core/lombok/core/AST.java +++ b/src/core/lombok/core/AST.java @@ -36,7 +36,7 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; -import lombok.core.LombokConfiguration.ConfigurationKey; +import lombok.core.configuration.ConfigurationKey; /** * Lombok wraps the AST produced by a target platform into its own AST system, mostly because both Eclipse and javac diff --git a/src/core/lombok/core/LombokConfiguration.java b/src/core/lombok/core/LombokConfiguration.java index 88c0be60..40c4a67c 100644 --- a/src/core/lombok/core/LombokConfiguration.java +++ b/src/core/lombok/core/LombokConfiguration.java @@ -21,7 +21,11 @@ */ package lombok.core; -import java.lang.reflect.Type; +import java.util.List; + +import javax.lang.model.SourceVersion; + +import lombok.core.configuration.ConfigurationKey; public class LombokConfiguration { @@ -29,23 +33,50 @@ public class LombokConfiguration { // prevent instantiation } - /* - * Typical usage: use this as a supertypetoken. - */ - public abstract static class ConfigurationKey<T> { - private final String keyName; - - public ConfigurationKey(String keyName) { - this.keyName = keyName; - System.out.println("registering " + keyName); - } - } - @SuppressWarnings("unchecked") static <T> T read(ConfigurationKey<T> key, AST<?, ?, ?> ast) { - Type it = key.getClass().getGenericSuperclass(); - if (key.keyName.equals("lombok.log.varName")) return (T)"loggertje"; - if (key.keyName.equals("lombok.log.static")) return (T)Boolean.FALSE; +// if (key.keyName.equals("lombok.log.varName")) return (T)"loggertje"; +// if (key.keyName.equals("lombok.log.static")) return (T)Boolean.FALSE; return null; } + + @SuppressWarnings("rawtypes") + public static void main(String[] args) { + try { new ConfigurationKey<List<String>>("List<String>") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Integer>("Integer") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Class<?>>("Class<?>") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<SourceVersion>("SourceVersion") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Class>("Class") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Class<Number>>("Class<Number>") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Class<? extends Number>>("Class<? extends Number>") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Class<? super String>>("Class<? super String>") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Number>("Number") {}; } catch (Exception e) { e.printStackTrace();} + try { class Between extends ConfigurationKey<String> { + public Between() { + super("between"); + } + }; + new Between(){}; + } catch (Exception e) { e.printStackTrace();} + + try { new ConfigurationKey<String>("more than once") {}; } catch (Exception e) { e.printStackTrace();} + try { new ConfigurationKey<Integer>("more than once") {}; } catch (Exception e) { e.printStackTrace();} + + System.out.println(System.identityHashCode(ConfigurationKey.registeredKeys())); + System.out.println(System.identityHashCode(ConfigurationKey.registeredKeys())); + + ConfigurationKey<?> first = null; + try { first = new ConfigurationKey<Integer>("anint") {}; } catch (Exception e) { e.printStackTrace();} + System.out.println(System.identityHashCode(ConfigurationKey.registeredKeys())); + System.out.println(System.identityHashCode(ConfigurationKey.registeredKeys())); + + ConfigurationKey<?> second = null; + try { second = new ConfigurationKey<Integer>("anint") {}; } catch (Exception e) { e.printStackTrace();} + System.out.println(System.identityHashCode(ConfigurationKey.registeredKeys())); + System.out.println(System.identityHashCode(ConfigurationKey.registeredKeys())); + + System.out.println(first == second); + System.out.println(first.getClass() == second.getClass()); + System.out.println(first.equals(second)); + } } diff --git a/src/core/lombok/core/configuration/ConfigurationDataType.java b/src/core/lombok/core/configuration/ConfigurationDataType.java new file mode 100644 index 00000000..5a8c37f1 --- /dev/null +++ b/src/core/lombok/core/configuration/ConfigurationDataType.java @@ -0,0 +1,118 @@ +/* + * 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.configuration; + +import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; +import java.lang.reflect.WildcardType; +import java.util.Arrays; +import java.util.List; + +public final class ConfigurationDataType { + private static final List<Class<?>> SIMPLE_TYPES = Arrays.<Class<?>>asList(String.class, Integer.class, Boolean.class, Long.class, Byte.class, Short.class, Character.class, Float.class, Double.class); + + private final boolean isList; + private final Class<?> elementType; + + public static ConfigurationDataType toDataType(Class<? extends ConfigurationKey<?>> keyClass) { + if (keyClass.getSuperclass() != ConfigurationKey.class) { + throw new IllegalArgumentException("No direct subclass of ConfigurationKey: " + keyClass.getName()); + } + + Type type = keyClass.getGenericSuperclass(); + if (!(type instanceof ParameterizedType)) { + throw new IllegalArgumentException("Missing type parameter in "+ type); + } + + ParameterizedType parameterized = (ParameterizedType) type; + Type argumentType = parameterized.getActualTypeArguments()[0]; + + boolean isList = false; + if (argumentType instanceof ParameterizedType) { + ParameterizedType parameterizedArgument = (ParameterizedType) argumentType; + if (parameterizedArgument.getRawType() == List.class) { + isList = true; + argumentType = parameterizedArgument.getActualTypeArguments()[0]; + } + } + + if (SIMPLE_TYPES.contains(argumentType) || isEnum(argumentType)) { + return new ConfigurationDataType(isList, (Class<?>)argumentType); + } + + if (argumentType instanceof ParameterizedType) { + ParameterizedType parameterizedArgument = (ParameterizedType) argumentType; + if (parameterizedArgument.getRawType() == Class.class) { + Type classType = parameterizedArgument.getActualTypeArguments()[0]; + if (!(classType instanceof WildcardType)) { + throw new IllegalArgumentException("Illegal specific Class type parameter in " + type); + } + WildcardType wildcard = (WildcardType) classType; + if (wildcard.getLowerBounds().length != 0 || wildcard.getUpperBounds().length != 1 || wildcard.getUpperBounds()[0] != Object.class) { + throw new IllegalArgumentException("Illegal bound wildcard Class type parameter in " + type); + } + return new ConfigurationDataType(isList, Class.class); + } + } + + if (argumentType == Class.class) { + return new ConfigurationDataType(isList, Class.class); + } + + throw new IllegalArgumentException("Unsupported type parameter in " + type); + } + + private ConfigurationDataType(boolean isList, Class<?> elementType) { + this.isList = isList; + this.elementType = elementType; + } + + public boolean isList() { + return isList; + } + + public Class<?> getElementType() { + return elementType; + } + + @Override + public int hashCode() { + return (isList ? 1231 : 1237) + elementType.hashCode(); + } + + @Override + public boolean equals(Object obj) { + if (!(obj instanceof ConfigurationDataType)) return false; + ConfigurationDataType other = (ConfigurationDataType) obj; + return isList == other.isList && elementType == other.elementType; + } + + @Override + public String toString() { + if (isList) return "java.util.List<" + elementType.getName() + ">"; + return elementType.getName(); + } + + private static boolean isEnum(Type argumentType) { + return argumentType instanceof Class && ((Class<?>) argumentType).isEnum(); + } +}
\ No newline at end of file diff --git a/src/core/lombok/core/configuration/ConfigurationKey.java b/src/core/lombok/core/configuration/ConfigurationKey.java new file mode 100644 index 00000000..aaa673af --- /dev/null +++ b/src/core/lombok/core/configuration/ConfigurationKey.java @@ -0,0 +1,109 @@ +/* + * 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.configuration; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; + +/** + * Describes a configuration key and its type. + * <p> + * The recommended usage is to create a type token: + * <pre> + * private static ConfigurationKey<String> KEY = new ConfigurationKey<String>("keyName") {}; + * </pre> + */ +public abstract class ConfigurationKey<T> { + private static final Map<String, ConfigurationDataType> registeredKeys = new HashMap<String, ConfigurationDataType>(); + private static Map<String, ConfigurationDataType> copy; + + private final String keyName; + private final ConfigurationDataType type; + + public ConfigurationKey(String keyName) { + this.keyName = checkName(keyName); + @SuppressWarnings("unchecked") + ConfigurationDataType type = ConfigurationDataType.toDataType((Class<? extends ConfigurationKey<?>>)getClass()); + this.type = type; + + registerKey(keyName, type); + } + + public final String getKeyName() { + return keyName; + } + + public final ConfigurationDataType getType() { + return type; + } + + @Override + public final int hashCode() { + final int prime = 31; + int result = 1; + result = prime * result + keyName.hashCode(); + result = prime * result + type.hashCode(); + return result; + } + + /** + * Two configuration are considered equal if and only if their {@code keyName} and {@code type} are equal. + */ + @Override + public final boolean equals(Object obj) { + if (this == obj) return true; + if (!(obj instanceof ConfigurationKey)) return false; + ConfigurationKey<?> other = (ConfigurationKey<?>) obj; + return keyName.equals(other.keyName) && type.equals(other.type); + } + + private static String checkName(String keyName) { + if (keyName == null) throw new NullPointerException("keyName"); + if (keyName.contains("=")) throw new IllegalArgumentException("Invalid character '=' in keyName: " + keyName); + return keyName; + } + + /** + * Returns a copy of the currently registered keys. + */ + public static Map<String, ConfigurationDataType> registeredKeys() { + synchronized (registeredKeys) { + if (copy == null) copy = Collections.unmodifiableMap(new HashMap<String, ConfigurationDataType>(registeredKeys)); + return copy; + } + } + + private static void registerKey(String keyName, ConfigurationDataType type) { + synchronized (registeredKeys) { + ConfigurationDataType existingType = registeredKeys.get(keyName); + if (existingType == null) { + registeredKeys.put(keyName, type); + copy = null; + return; + } + if (!existingType.equals(type)) { + throw new IllegalArgumentException("Key '" + keyName + "' already registered with a different type, existing " + existingType + " != provided " + type); + } + } + } +}
\ No newline at end of file diff --git a/src/core/lombok/core/configuration/ConfigurationResolver.java b/src/core/lombok/core/configuration/ConfigurationResolver.java new file mode 100644 index 00000000..6f52fc6e --- /dev/null +++ b/src/core/lombok/core/configuration/ConfigurationResolver.java @@ -0,0 +1,26 @@ +/* + * 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.configuration; + +public interface ConfigurationResolver { + <T> T resolve(ConfigurationKey<T> key); +} diff --git a/src/core/lombok/core/configuration/StringResolver.java b/src/core/lombok/core/configuration/StringResolver.java new file mode 100644 index 00000000..d939d916 --- /dev/null +++ b/src/core/lombok/core/configuration/StringResolver.java @@ -0,0 +1,84 @@ +/* + * 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.configuration; + +import java.util.List; +import java.util.Map; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class StringResolver implements ConfigurationResolver { + + private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))"); + + public StringResolver(String content) { + Map<String, ConfigurationDataType> registeredKeys = ConfigurationKey.registeredKeys(); + for (String line : content.trim().split("\\s*\\n\\s*")) { + if (line.isEmpty() || line.startsWith("#")) continue; + Matcher matcher = LINE.matcher(line); + System.out.println("\nLINE: " + line); + + String operator = null; + String keyName = null; + String value = null; + + if (matcher.matches()) { + if (matcher.group(1) == null) { + keyName = matcher.group(2); + operator = matcher.group(3); + value = matcher.group(4); + } else { + keyName = matcher.group(1); + operator = "clear"; + value = null; + } + ConfigurationDataType type = registeredKeys.get(keyName); + if (type == null) { + System.out.println("Unknown key " + keyName); + } else { + boolean listOperator = operator.equals("+=") || operator.equals("-="); + if (listOperator && !type.isList()) { + System.out.println(keyName + " is not a list"); + } else if (operator.equals("=") && type.isList()) { + System.out.println(keyName + " IS a list"); + } else { + System.out.printf("!! %s %s %s", keyName, operator, value); + } + } + } else { + System.out.println("no match:" + line); + } + } + } + + @Override public <T> T resolve(ConfigurationKey<T> key) { + return null; + } + + public static void main(String[] args) { + ConfigurationKey<String> AAP = new ConfigurationKey<String>("aap") {}; + ConfigurationKey<List<String>> NOOT = new ConfigurationKey<List<String>>("noot") {}; + + ConfigurationResolver resolver = new StringResolver(" aap = 3 \naap += 4\n\r noot+=mies\nnoot=wim\nclear noot\nclear aap\r\n#foo-= bar\nblablabla\na=b=c\n\n\nclear test\n\nclear \nclear test="); + String aapValue = resolver.resolve(AAP); + } +} diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java index 64ec5f96..8c09237e 100644 --- a/src/core/lombok/eclipse/handlers/HandleLog.java +++ b/src/core/lombok/eclipse/handlers/HandleLog.java @@ -28,7 +28,7 @@ import java.lang.reflect.Modifier; import java.util.Arrays; import lombok.core.AnnotationValues; -import lombok.core.LombokConfiguration.ConfigurationKey; +import lombok.core.configuration.ConfigurationKey; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; import lombok.eclipse.handlers.EclipseHandlerUtil.MemberExistsResult; |