From be1cfd2f59933725726ec5810e0c189a4aca6ad7 Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Sun, 8 Jul 2018 16:52:14 +0200 Subject: Replaced StringBuilder by simple char array in "hotspot" method --- src/core/lombok/bytecode/ClassFileMetaData.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/bytecode/ClassFileMetaData.java b/src/core/lombok/bytecode/ClassFileMetaData.java index 0dc6a6c8..826eed83 100644 --- a/src/core/lombok/bytecode/ClassFileMetaData.java +++ b/src/core/lombok/bytecode/ClassFileMetaData.java @@ -116,23 +116,24 @@ public class ClassFileMetaData { int end = pos + size; // the resulting string might be smaller - StringBuilder result = new StringBuilder(size); + char[] result = new char[size]; + int length = 0; while (pos < end) { int first = (byteCode[pos++] & 0xFF); if (first < 0x80) { - result.append((char)first); + result[length++] = (char)first; } else if ((first & 0xE0) == 0xC0) { int x = (first & 0x1F) << 6; int y = (byteCode[pos++] & 0x3F); - result.append((char)(x | y)); + result[length++] = (char)(x | y); } else { int x = (first & 0x0F) << 12; int y = (byteCode[pos++] & 0x3F) << 6; int z = (byteCode[pos++] & 0x3F); - result.append((char)(x | y | z)); + result[length++] = (char)(x | y | z); } } - return result.toString(); + return new String(result, 0, length); } /** -- cgit From 5ec61bb62d3dd2d9509ade090e750dd43e36c0f3 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 25 Jul 2018 21:41:17 +0200 Subject: [fixes issue #1759] We removed the ‘flag usage’ check on builder instead of replacing it with the non-experimental check about 3 years ago when builder moved out of experimental. The check has now been restored. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/javac/handlers/HandleBuilder.java | 2 ++ 1 file changed, 2 insertions(+) (limited to 'src/core') diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java index bb495fbc..f04ea8b1 100644 --- a/src/core/lombok/javac/handlers/HandleBuilder.java +++ b/src/core/lombok/javac/handlers/HandleBuilder.java @@ -99,6 +99,8 @@ public class HandleBuilder extends JavacAnnotationHandler { } @Override public void handle(AnnotationValues annotation, JCAnnotation ast, JavacNode annotationNode) { + handleFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder"); + Builder builderInstance = annotation.getInstance(); // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them. -- cgit From 7e94041dbc177476020969b00d3411020418f903 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Wed, 25 Jul 2018 23:19:00 +0200 Subject: Added key ‘dangerousconfig.lombok.disable’. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/core/lombok/ConfigurationKeys.java | 9 ++++++++- src/core/lombok/core/LombokConfiguration.java | 15 ++++++++++----- src/core/lombok/core/configuration/ConfigurationApp.java | 7 ++++--- src/core/lombok/core/configuration/ConfigurationKey.java | 12 +++++++++++- .../core/configuration/ConfigurationResolverFactory.java | 6 +++--- src/core/lombok/eclipse/EclipseAST.java | 12 ++++++++---- src/core/lombok/eclipse/TransformEclipseAST.java | 6 +++++- src/core/lombok/javac/JavacAST.java | 7 +++++-- src/core/lombok/javac/JavacTransformer.java | 11 +++++++++-- 9 files changed, 63 insertions(+), 22 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index f5134bbd..1a28c0fa 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2017 The Project Lombok Authors. + * Copyright (C) 2013-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -38,6 +38,13 @@ public class ConfigurationKeys { // ----- global ----- + /** + * lombok configuration: {@code dangerousconfig.lombok.disable} = {@code true} | {@code false}. + * + * If {@code true}, lombok is disabled entirely. + */ + public static final ConfigurationKey LOMBOK_DISABLE = new ConfigurationKey("dangerousconfig.lombok.disable", "Disables lombok transformers. It does not flag any lombok mentions (so, @Cleanup silently does nothing), and does not disable patched operations in eclipse either. Don't use this unless you know what you're doing. (default: false).", true) {}; + /** * lombok configuration: {@code lombok.addGeneratedAnnotation} = {@code true} | {@code false}. * diff --git a/src/core/lombok/core/LombokConfiguration.java b/src/core/lombok/core/LombokConfiguration.java index eb7b3d75..4a79c797 100644 --- a/src/core/lombok/core/LombokConfiguration.java +++ b/src/core/lombok/core/LombokConfiguration.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 The Project Lombok Authors. + * Copyright (C) 2013-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,6 +21,7 @@ */ package lombok.core; +import java.net.URI; import java.util.Collections; import lombok.core.configuration.BubblingConfigurationResolver; @@ -44,7 +45,7 @@ public class LombokConfiguration { static { if (System.getProperty("lombok.disableConfig") != null) { configurationResolverFactory = new ConfigurationResolverFactory() { - @Override public ConfigurationResolver createResolver(AST ast) { + @Override public ConfigurationResolver createResolver(URI sourceLocation) { return NULL_RESOLVER; } }; @@ -63,13 +64,17 @@ public class LombokConfiguration { } static T read(ConfigurationKey key, AST ast) { - return configurationResolverFactory.createResolver(ast).resolve(key); + return configurationResolverFactory.createResolver(ast.getAbsoluteFileLocation()).resolve(key); + } + + public static T read(ConfigurationKey key, URI sourceLocation) { + return configurationResolverFactory.createResolver(sourceLocation).resolve(key); } private static ConfigurationResolverFactory createFileSystemBubblingResolverFactory() { return new ConfigurationResolverFactory() { - @Override public ConfigurationResolver createResolver(AST ast) { - return new BubblingConfigurationResolver(cache.sourcesForJavaFile(ast.getAbsoluteFileLocation(), ConfigurationProblemReporter.CONSOLE)); + @Override public ConfigurationResolver createResolver(URI sourceLocation) { + return new BubblingConfigurationResolver(cache.sourcesForJavaFile(sourceLocation, ConfigurationProblemReporter.CONSOLE)); } }; } diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java index efe57e38..9cfec2e7 100644 --- a/src/core/lombok/core/configuration/ConfigurationApp.java +++ b/src/core/lombok/core/configuration/ConfigurationApp.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -118,7 +118,7 @@ public class ConfigurationApp extends LombokApp { boolean verbose = args.verbose; if (args.generate) { - return generate(keys, verbose); + return generate(keys, verbose, !args.key.isEmpty()); } return display(keys, verbose, args.paths, !args.key.isEmpty()); @@ -130,8 +130,9 @@ public class ConfigurationApp extends LombokApp { return this; } - public int generate(Collection> keys, boolean verbose) { + public int generate(Collection> keys, boolean verbose, boolean explicit) { for (ConfigurationKey key : keys) { + if (!explicit && key.isHidden()) continue; String keyName = key.getKeyName(); ConfigurationDataType type = key.getType(); String description = key.getDescription(); diff --git a/src/core/lombok/core/configuration/ConfigurationKey.java b/src/core/lombok/core/configuration/ConfigurationKey.java index d46a70b0..18075190 100644 --- a/src/core/lombok/core/configuration/ConfigurationKey.java +++ b/src/core/lombok/core/configuration/ConfigurationKey.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2013-2014 The Project Lombok Authors. + * Copyright (C) 2013-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -43,13 +43,19 @@ public abstract class ConfigurationKey { private final String keyName; private final String description; private final ConfigurationDataType type; + private final boolean hidden; public ConfigurationKey(String keyName, String description) { + this(keyName, description, false); + } + + public ConfigurationKey(String keyName, String description, boolean hidden) { this.keyName = checkName(keyName); @SuppressWarnings("unchecked") ConfigurationDataType type = ConfigurationDataType.toDataType((Class>)getClass()); this.type = type; this.description = description; + this.hidden = hidden; registerKey(keyName, this); } @@ -65,6 +71,10 @@ public abstract class ConfigurationKey { return type; } + public final boolean isHidden() { + return hidden; + } + @Override public String toString() { return keyName + " (" + type + "): " + description; } diff --git a/src/core/lombok/core/configuration/ConfigurationResolverFactory.java b/src/core/lombok/core/configuration/ConfigurationResolverFactory.java index 83b58c2f..b640b271 100644 --- a/src/core/lombok/core/configuration/ConfigurationResolverFactory.java +++ b/src/core/lombok/core/configuration/ConfigurationResolverFactory.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2014 The Project Lombok Authors. + * Copyright (C) 2014-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -21,8 +21,8 @@ */ package lombok.core.configuration; -import lombok.core.AST; +import java.net.URI; public interface ConfigurationResolverFactory { - ConfigurationResolver createResolver(AST ast); + ConfigurationResolver createResolver(URI sourceLocation); } diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java index dc2c9843..7cd2e400 100644 --- a/src/core/lombok/eclipse/EclipseAST.java +++ b/src/core/lombok/eclipse/EclipseAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2013 The Project Lombok Authors. + * Copyright (C) 2009-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -73,16 +73,20 @@ public class EclipseAST extends AST { private static final URI NOT_CALCULATED_MARKER = URI.create("https://projectlombok.org/not/calculated"); private URI memoizedAbsoluteFileLocation = NOT_CALCULATED_MARKER; + public static URI getAbsoluteFileLocation(CompilationUnitDeclaration ast) { + return getAbsoluteFileLocation0(ast); + } + public URI getAbsoluteFileLocation() { if (memoizedAbsoluteFileLocation != NOT_CALCULATED_MARKER) return memoizedAbsoluteFileLocation; - memoizedAbsoluteFileLocation = getAbsoluteFileLocation0(); + memoizedAbsoluteFileLocation = getAbsoluteFileLocation0(this.compilationUnitDeclaration); return memoizedAbsoluteFileLocation; } /** This is the call, but we wrapped it to memoize this. */ - private URI getAbsoluteFileLocation0() { - String fileName = getFileName(); + private static URI getAbsoluteFileLocation0(CompilationUnitDeclaration ast) { + String fileName = toFileName(ast); if (fileName != null && (fileName.startsWith("file:") || fileName.startsWith("sourcecontrol:"))) { // Some exotic build systems get real fancy with filenames. Known culprits: // The 'jazz' source control system _probably_ (not confirmed yet) uses sourcecontrol://jazz: urls. diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index 683465c9..541924ad 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2012 The Project Lombok Authors. + * Copyright (C) 2009-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -25,6 +25,8 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Field; +import lombok.ConfigurationKeys; +import lombok.core.LombokConfiguration; import lombok.core.debug.DebugSnapshotStore; import lombok.core.debug.HistogramTracker; import lombok.patcher.Symbols; @@ -143,6 +145,8 @@ public class TransformEclipseAST { // Do NOT abort if (ast.bits & ASTNode.HasAllMethodBodies) != 0 - that doesn't work. + if (Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, EclipseAST.getAbsoluteFileLocation(ast)))) return; + try { DebugSnapshotStore.INSTANCE.snapshot(ast, "transform entry"); long histoToken = lombokTracker == null ? 0L : lombokTracker.start(); diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java index 4ca2c050..091612cc 100644 --- a/src/core/lombok/javac/JavacAST.java +++ b/src/core/lombok/javac/JavacAST.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 The Project Lombok Authors. + * Copyright (C) 2009-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -93,8 +93,11 @@ public class JavacAST extends AST { } @Override public URI getAbsoluteFileLocation() { + return getAbsoluteFileLocation((JCCompilationUnit) top().get()); + } + + public static URI getAbsoluteFileLocation(JCCompilationUnit cu) { try { - JCCompilationUnit cu = (JCCompilationUnit) top().get(); return cu.sourcefile.toUri(); } catch (Exception e) { return null; diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java index 54977a59..2e37b32b 100644 --- a/src/core/lombok/javac/JavacTransformer.java +++ b/src/core/lombok/javac/JavacTransformer.java @@ -1,5 +1,5 @@ /* - * Copyright (C) 2009-2017 The Project Lombok Authors. + * Copyright (C) 2009-2018 The Project Lombok Authors. * * Permission is hereby granted, free of charge, to any person obtaining a copy * of this software and associated documentation files (the "Software"), to deal @@ -35,6 +35,9 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.Context; import com.sun.tools.javac.util.List; +import lombok.ConfigurationKeys; +import lombok.core.LombokConfiguration; + public class JavacTransformer { private final HandlerLibrary handlers; private final Messager messager; @@ -65,7 +68,11 @@ public class JavacTransformer { java.util.List asts = new ArrayList(); - for (JCCompilationUnit unit : compilationUnits) asts.add(new JavacAST(messager, context, unit)); + for (JCCompilationUnit unit : compilationUnits) { + if (!Boolean.TRUE.equals(LombokConfiguration.read(ConfigurationKeys.LOMBOK_DISABLE, JavacAST.getAbsoluteFileLocation(unit)))) { + asts.add(new JavacAST(messager, context, unit)); + } + } for (JavacAST ast : asts) { ast.traverse(new AnnotationVisitor(priority)); -- cgit From dc715da8b79bff32116ac477d0ac04875bd21167 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Thu, 26 Jul 2018 00:00:24 +0200 Subject: pre-release version bump --- src/core/lombok/core/Version.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java index 70af48e0..7b19d00e 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -30,9 +30,9 @@ public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). // Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example. // Official builds always end in an even number. (Since 0.10.2). - private static final String VERSION = "1.18.1"; - private static final String RELEASE_NAME = "Edgy Guinea Pig"; -// private static final String RELEASE_NAME = "Envious Ferret"; + private static final String VERSION = "1.18.2"; +// private static final String RELEASE_NAME = "Edgy Guinea Pig"; + private static final String RELEASE_NAME = "Envious Ferret"; // Named version history: // Angry Butterfly -- cgit From 61fbd4a7f82180871e635a0ca80248e0cec02cf3 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Thu, 26 Jul 2018 00:17:09 +0200 Subject: post-release version bump --- src/core/lombok/core/Version.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java index 7b19d00e..4b119873 100644 --- a/src/core/lombok/core/Version.java +++ b/src/core/lombok/core/Version.java @@ -30,9 +30,9 @@ public class Version { // ** CAREFUL ** - this class must always compile with 0 dependencies (it must not refer to any other sources or libraries). // Note: In 'X.Y.Z', if Z is odd, its a snapshot build built from the repository, so many different 0.10.3 versions can exist, for example. // Official builds always end in an even number. (Since 0.10.2). - private static final String VERSION = "1.18.2"; -// private static final String RELEASE_NAME = "Edgy Guinea Pig"; - private static final String RELEASE_NAME = "Envious Ferret"; + private static final String VERSION = "1.18.3"; + private static final String RELEASE_NAME = "Edgy Guinea Pig"; +// private static final String RELEASE_NAME = "Envious Ferret"; // Named version history: // Angry Butterfly -- cgit From 3d432c38d0cfeb36b8e7402eca56faaafcf7bac7 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 29 Jul 2018 16:37:21 +0200 Subject: code impl of FieldNameConstants rewrite + test updates for it --- src/core/lombok/ConfigurationKeys.java | 11 +- .../eclipse/handlers/HandleFieldNameConstants.java | 144 +++++++++++++-------- .../lombok/experimental/FieldNameConstants.java | 28 +++- .../javac/handlers/HandleFieldNameConstants.java | 129 ++++++++++-------- 4 files changed, 188 insertions(+), 124 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java index 1a28c0fa..184ded27 100644 --- a/src/core/lombok/ConfigurationKeys.java +++ b/src/core/lombok/ConfigurationKeys.java @@ -529,18 +529,11 @@ public class ConfigurationKeys { public static final ConfigurationKey FIELD_NAME_CONSTANTS_FLAG_USAGE = new ConfigurationKey("lombok.fieldNameConstants.flagUsage", "Emit a warning or error if @FieldNameConstants is used.") {}; /** - * lombok configuration: {@code lombok.fieldNameConstants.prefix} = <String: aJavaIdentifierPrefix> (Default: {@code PREFIX_}). + * lombok configuration: {@code lombok.fieldNameConstants.innerTypeName} = <String: AValidJavaTypeName> (Default: {@code Fields}). * * The names of the constants generated by {@code @FieldNameConstants} will be prefixed with this value. */ - public static final ConfigurationKey FIELD_NAME_CONSTANTS_PREFIX = new ConfigurationKey("lombok.fieldNameConstants.prefix", "names of constants generated by @FieldNameConstants will be prefixed with this value. (default: 'PREFIX_').") {}; - - /** - * lombok configuration: {@code lombok.fieldNameConstants.suffix} = <String: aJavaIdentifierPrefix> (Default: nothing). - * - * The names of the constants generated by {@code @FieldNameConstants} will be suffixed with this value. - */ - public static final ConfigurationKey FIELD_NAME_CONSTANTS_SUFFIX = new ConfigurationKey("lombok.fieldNameConstants.suffix", "names of constants generated by @FieldNameConstants will be suffixed with this value. (default: nothing).") {}; + public static final ConfigurationKey FIELD_NAME_CONSTANTS_INNER_TYPE_NAME = new ConfigurationKey("lombok.fieldNameConstants.innerTypeName", "The default name of the inner type generated by @FieldNameConstants. (default: 'Fields').") {}; // ----- Wither ----- diff --git a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java index c3a28f7f..15650490 100644 --- a/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/eclipse/handlers/HandleFieldNameConstants.java @@ -24,32 +24,37 @@ package lombok.eclipse.handlers; import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; -import java.lang.reflect.Modifier; -import java.util.Collection; +import java.util.ArrayList; +import java.util.List; import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; import lombok.core.AnnotationValues; -import lombok.core.handlers.HandlerUtil; import lombok.eclipse.Eclipse; import lombok.eclipse.EclipseAnnotationHandler; import lombok.eclipse.EclipseNode; import lombok.experimental.FieldNameConstants; import org.eclipse.jdt.internal.compiler.ast.ASTNode; +import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; +import org.eclipse.jdt.internal.compiler.ast.Clinit; +import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration; +import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall; import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration; import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference; +import org.eclipse.jdt.internal.compiler.ast.Statement; import org.eclipse.jdt.internal.compiler.ast.StringLiteral; import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration; import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; +import org.eclipse.jdt.internal.compiler.lookup.ClassScope; import org.eclipse.jdt.internal.compiler.lookup.TypeConstants; import org.mangosdk.spi.ProviderFor; @ProviderFor(EclipseAnnotationHandler.class) public class HandleFieldNameConstants extends EclipseAnnotationHandler { - public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, String prefix, String suffix) { + public void generateFieldNameConstantsForType(EclipseNode typeNode, EclipseNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) { TypeDeclaration typeDecl = null; if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get(); @@ -57,22 +62,29 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler qualified = new ArrayList(); + for (EclipseNode field : typeNode.down()) { - if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level, prefix, suffix); + if (fieldQualifiesForFieldNameConstantsGeneration(field, onlyExplicit)) qualified.add(field); + } + + if (qualified.isEmpty()) { + errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing"); + } else { + createInnerTypeFieldNameConstants(typeNode, errorNode.get(), level, qualified, asEnum, innerTypeName); } } - private void generateFieldNameConstantsForField(EclipseNode fieldNode, ASTNode pos, AccessLevel level, String prefix, String suffix) { - if (hasAnnotation(FieldNameConstants.class, fieldNode)) return; - createFieldNameConstantsForField(level, prefix, suffix, fieldNode, fieldNode, pos, false); - } - - private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field) { + private boolean fieldQualifiesForFieldNameConstantsGeneration(EclipseNode field, boolean onlyExplicit) { if (field.getKind() != Kind.FIELD) return false; + if (hasAnnotation(FieldNameConstants.Exclude.class, field)) return false; + if (hasAnnotation(FieldNameConstants.Include.class, field)) return true; + if (onlyExplicit) return false; + FieldDeclaration fieldDecl = (FieldDeclaration) field.get(); return filterField(fieldDecl); } @@ -81,55 +93,75 @@ public class HandleFieldNameConstants extends EclipseAnnotationHandler fieldNodes, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { - for (EclipseNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, prefix, suffix, fieldNode, errorNode, source, whineIfExists); - } - - private void createFieldNameConstantsForField(AccessLevel level, String prefix, String suffix, EclipseNode fieldNode, EclipseNode errorNode, ASTNode source, boolean whineIfExists) { - if (fieldNode.getKind() != Kind.FIELD) { - errorNode.addError("@FieldNameConstants is only supported on a class, an enum, or a field"); + FieldNameConstants annotationInstance = annotation.getInstance(); + AccessLevel level = annotationInstance.level(); + boolean asEnum = annotationInstance.asEnum(); + boolean usingLombokv1_18_2 = annotation.isExplicit("prefix") || annotation.isExplicit("suffix") || node.getKind() == Kind.FIELD; + + if (usingLombokv1_18_2) { + annotationNode.addError("@FieldNameConstants has been redesigned in lombok v1.18.4; please upgrade your project dependency on lombok. See https://projectlombok.org/features/experimental/FieldNameConstants for more information."); return; } - FieldDeclaration field = (FieldDeclaration) fieldNode.get(); - String fieldName = new String(field.name); - String constantName = prefix + HandlerUtil.camelCaseToConstant(fieldName) + suffix; - if (constantName.equals(fieldName)) { - fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field."); + if (level == AccessLevel.NONE) { + annotationNode.addWarning("AccessLevel.NONE is not compatible with @FieldNameConstants. If you don't want the inner type, simply remove FieldNameConstants."); return; } - int pS = source.sourceStart, pE = source.sourceEnd; - long p = (long) pS << 32 | pE; - FieldDeclaration fieldConstant = new FieldDeclaration(constantName.toCharArray(), pS,pE); - fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; - fieldConstant.modifiers = toEclipseModifier(level) | Modifier.STATIC | Modifier.FINAL; - fieldConstant.type = new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p,p,p}); - fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0); - injectField(fieldNode.up(), fieldConstant); + String innerTypeName = annotationInstance.innerTypeName(); + if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); + if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields"; + + generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded()); + } + + private void createInnerTypeFieldNameConstants(EclipseNode typeNode, ASTNode source, AccessLevel level, List fields, boolean asEnum, String innerTypeName) { + if (fields.isEmpty()) return; + + TypeDeclaration parent = (TypeDeclaration) typeNode.get(); + TypeDeclaration innerType = new TypeDeclaration(parent.compilationResult); + innerType.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + innerType.modifiers = toEclipseModifier(level) | (asEnum ? ClassFileConstants.AccEnum : ClassFileConstants.AccStatic | ClassFileConstants.AccFinal); + char[] name = innerTypeName.toCharArray(); + innerType.name = name; + innerType.traverse(new SetGeneratedByVisitor(source), (ClassScope) null); + EclipseNode innerNode = injectType(typeNode, innerType); + + ConstructorDeclaration constructor = new ConstructorDeclaration(parent.compilationResult); + constructor.selector = name; + constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart; + constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd; + constructor.modifiers = ClassFileConstants.AccPrivate; + ExplicitConstructorCall superCall = new ExplicitConstructorCall(0); + superCall.sourceStart = source.sourceStart; + superCall.sourceEnd = source.sourceEnd; + superCall.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + constructor.constructorCall = superCall; + if (!asEnum) constructor.statements = new Statement[0]; + + injectMethod(innerNode, constructor); + + if (asEnum) injectMethod(innerNode, new Clinit(parent.compilationResult)); + + for (EclipseNode fieldNode : fields) { + FieldDeclaration field = (FieldDeclaration) fieldNode.get(); + char[] fName = field.name; + int pS = source.sourceStart, pE = source.sourceEnd; + long p = (long) pS << 32 | pE; + FieldDeclaration fieldConstant = new FieldDeclaration(fName, pS, pE); + fieldConstant.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG; + fieldConstant.modifiers = asEnum ? 0 : ClassFileConstants.AccPublic | ClassFileConstants.AccStatic | ClassFileConstants.AccFinal; + fieldConstant.type = asEnum ? null : new QualifiedTypeReference(TypeConstants.JAVA_LANG_STRING, new long[] {p, p, p}); + if (asEnum) { + AllocationExpression ac = new AllocationExpression(); + ac.enumConstant = fieldConstant; + ac.sourceStart = source.sourceStart; + ac.sourceEnd = source.sourceEnd; + fieldConstant.initialization = ac; + } else { + fieldConstant.initialization = new StringLiteral(field.name, pS, pE, 0); + } + injectField(innerNode, fieldConstant); + } } } diff --git a/src/core/lombok/experimental/FieldNameConstants.java b/src/core/lombok/experimental/FieldNameConstants.java index 31c2970c..d6886890 100644 --- a/src/core/lombok/experimental/FieldNameConstants.java +++ b/src/core/lombok/experimental/FieldNameConstants.java @@ -29,12 +29,32 @@ import java.lang.annotation.Target; import lombok.AccessLevel; /** - * Generates String constants containing the field name for each field. + * Generates an inner type, containing String constants containing the field name for each field. Alternatively, generates an inner enum with enum values matching each field name. */ -@Target({ElementType.TYPE, ElementType.FIELD}) +@Target(ElementType.TYPE) @Retention(RetentionPolicy.SOURCE) public @interface FieldNameConstants { lombok.AccessLevel level() default AccessLevel.PUBLIC; - String prefix() default " CONFIG DEFAULT "; - String suffix() default " CONFIG DEFAULT "; + boolean asEnum() default false; + String innerTypeName() default ""; + + /** + * Only include fields and methods explicitly marked with {@code @FieldNameConstants.Include}. + * Normally, all (non-static) fields are included by default. + */ + boolean onlyExplicitlyIncluded() default false; + + /** + * If present, do not include this field in the generated fieldnames inner type. + */ + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface Exclude {} + + /** + * If present, include this field in the generated fieldnames inner type (default). + */ + @Target(ElementType.FIELD) + @Retention(RetentionPolicy.SOURCE) + public @interface Include {} } diff --git a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java index 8ff136fc..5b120948 100644 --- a/src/core/lombok/javac/handlers/HandleFieldNameConstants.java +++ b/src/core/lombok/javac/handlers/HandleFieldNameConstants.java @@ -24,13 +24,11 @@ package lombok.javac.handlers; import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage; import static lombok.javac.handlers.JavacHandlerUtil.*; -import java.lang.reflect.Modifier; -import java.util.Collection; +import java.util.ArrayList; import lombok.AccessLevel; import lombok.ConfigurationKeys; import lombok.core.AST.Kind; -import lombok.core.handlers.HandlerUtil; import lombok.core.AnnotationValues; import lombok.experimental.FieldNameConstants; import lombok.javac.JavacAnnotationHandler; @@ -40,16 +38,23 @@ import lombok.javac.JavacTreeMaker; import org.mangosdk.spi.ProviderFor; import com.sun.tools.javac.code.Flags; +import com.sun.tools.javac.tree.JCTree; import com.sun.tools.javac.tree.JCTree.JCAnnotation; +import com.sun.tools.javac.tree.JCTree.JCBlock; import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCExpression; +import com.sun.tools.javac.tree.JCTree.JCMethodDecl; import com.sun.tools.javac.tree.JCTree.JCModifiers; +import com.sun.tools.javac.tree.JCTree.JCStatement; +import com.sun.tools.javac.tree.JCTree.JCTypeParameter; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition; +import com.sun.tools.javac.util.List; +import com.sun.tools.javac.util.Name; @ProviderFor(JavacAnnotationHandler.class) public class HandleFieldNameConstants extends JavacAnnotationHandler { - public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, String prefix, String suffix) { + public void generateFieldNameConstantsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean asEnum, String innerTypeName, boolean onlyExplicit) { JCClassDecl typeDecl = null; if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get(); @@ -57,22 +62,31 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler qualified = new ArrayList(); + for (JavacNode field : typeNode.down()) { - if (fieldQualifiesForFieldNameConstantsGeneration(field)) generateFieldNameConstantsForField(field, errorNode.get(), level, prefix, suffix); + if (fieldQualifiesForFieldNameConstantsGeneration(field, onlyExplicit)) qualified.add(field); + } + + if (qualified.isEmpty()) { + errorNode.addWarning("No fields qualify for @FieldNameConstants, therefore this annotation does nothing"); + } else { + createInnerTypeFieldNameConstants(typeNode, errorNode.get(), level, qualified, asEnum, innerTypeName); } } - private void generateFieldNameConstantsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, String prefix, String suffix) { - if (hasAnnotation(FieldNameConstants.class, fieldNode)) return; - createFieldNameConstantsForField(level, prefix, suffix, fieldNode, fieldNode, false); - } - - private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field) { + private boolean fieldQualifiesForFieldNameConstantsGeneration(JavacNode field, boolean onlyExplicit) { if (field.getKind() != Kind.FIELD) return false; + boolean exclAnn = JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(FieldNameConstants.Exclude.class, field); + boolean inclAnn = JavacHandlerUtil.hasAnnotationAndDeleteIfNeccessary(FieldNameConstants.Include.class, field); + if (exclAnn) return false; + if (inclAnn) return true; + if (onlyExplicit) return false; + JCVariableDecl fieldDecl = (JCVariableDecl) field.get(); if (fieldDecl.name.toString().startsWith("$")) return false; if ((fieldDecl.mods.flags & Flags.STATIC) != 0) return false; @@ -82,56 +96,61 @@ public class HandleFieldNameConstants extends JavacAnnotationHandler annotation, JCAnnotation ast, JavacNode annotationNode) { handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_NAME_CONSTANTS_FLAG_USAGE, "@FieldNameConstants"); - Collection fields = annotationNode.upFromAnnotationToFields(); deleteAnnotationIfNeccessary(annotationNode, FieldNameConstants.class); deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel"); JavacNode node = annotationNode.up(); - FieldNameConstants annotatationInstance = annotation.getInstance(); - AccessLevel level = annotatationInstance.level(); - String prefix = annotatationInstance.prefix(); - String suffix = annotatationInstance.suffix(); - if (prefix.equals(" CONFIG DEFAULT ")) prefix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_PREFIX); - if (suffix.equals(" CONFIG DEFAULT ")) suffix = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_SUFFIX); - if (prefix == null) prefix = "FIELD_"; - if (suffix == null) suffix = ""; - if (node == null) return; - switch (node.getKind()) { - case FIELD: - if (level != AccessLevel.NONE) createFieldNameConstantsForFields(level, prefix, suffix, fields, annotationNode, annotationNode, true); - break; - case TYPE: - if (level == AccessLevel.NONE) { - annotationNode.addWarning("type-level '@FieldNameConstants' does not work with AccessLevel.NONE."); - return; - } - generateFieldNameConstantsForType(node, annotationNode, level, prefix, suffix); - break; - } - } - - private void createFieldNameConstantsForFields(AccessLevel level, String prefix, String suffix, Collection fieldNodes, JavacNode annotationNode, JavacNode errorNode, boolean whineIfExists) { - for (JavacNode fieldNode : fieldNodes) createFieldNameConstantsForField(level, prefix, suffix, fieldNode, errorNode, whineIfExists); - } - - private void createFieldNameConstantsForField(AccessLevel level, String prefix, String suffix, JavacNode fieldNode, JavacNode source, boolean whineIfExists) { - if (fieldNode.getKind() != Kind.FIELD) { - source.addError("@FieldNameConstants is only supported on a class, an enum, or a field"); + FieldNameConstants annotationInstance = annotation.getInstance(); + AccessLevel level = annotationInstance.level(); + boolean asEnum = annotationInstance.asEnum(); + boolean usingLombokv1_18_2 = annotation.isExplicit("prefix") || annotation.isExplicit("suffix") || node.getKind() == Kind.FIELD; + + if (usingLombokv1_18_2) { + annotationNode.addError("@FieldNameConstants has been redesigned in lombok v1.18.4; please upgrade your project dependency on lombok. See https://projectlombok.org/features/experimental/FieldNameConstants for more information."); return; } - JCVariableDecl field = (JCVariableDecl) fieldNode.get(); - String fieldName = field.name.toString(); - String constantName = prefix + HandlerUtil.camelCaseToConstant(fieldName) + suffix; - if (constantName.equals(fieldName)) { - fieldNode.addWarning("Not generating constant for this field: The name of the constant would be equal to the name of this field."); + + if (level == AccessLevel.NONE) { + annotationNode.addWarning("AccessLevel.NONE is not compatible with @FieldNameConstants. If you don't want the inner type, simply remove @FieldNameConstants."); return; } - JavacTreeMaker treeMaker = fieldNode.getTreeMaker(); - JCModifiers modifiers = treeMaker.Modifiers(toJavacModifier(level) | Modifier.STATIC | Modifier.FINAL); - JCExpression returnType = chainDots(fieldNode, "java", "lang", "String"); - JCExpression init = treeMaker.Literal(fieldNode.getName()); - JCVariableDecl fieldConstant = treeMaker.VarDef(modifiers, fieldNode.toName(constantName), returnType, init); - injectField(fieldNode.up(), fieldConstant); + String innerTypeName = annotationInstance.innerTypeName(); + if (innerTypeName.isEmpty()) innerTypeName = annotationNode.getAst().readConfiguration(ConfigurationKeys.FIELD_NAME_CONSTANTS_INNER_TYPE_NAME); + if (innerTypeName == null || innerTypeName.isEmpty()) innerTypeName = "Fields"; + + generateFieldNameConstantsForType(node, annotationNode, level, asEnum, innerTypeName, annotationInstance.onlyExplicitlyIncluded()); + } + + private void createInnerTypeFieldNameConstants(JavacNode typeNode, DiagnosticPosition pos, AccessLevel level, java.util.List fields, boolean asEnum, String innerTypeName) { + if (fields.isEmpty()) return; + + JavacTreeMaker maker = typeNode.getTreeMaker(); + JCModifiers mods = maker.Modifiers(toJavacModifier(level) | (asEnum ? Flags.ENUM : Flags.STATIC | Flags.FINAL)); + + Name fieldsName = typeNode.toName(innerTypeName); + JCClassDecl innerType = maker.ClassDef(mods, fieldsName, List.nil(), null, List.nil(), List.nil()); + JavacNode innerNode = injectType(typeNode, innerType); + + JCModifiers genConstrMods = maker.Modifiers(Flags.GENERATEDCONSTR | (asEnum ? 0L : Flags.PRIVATE)); + JCBlock genConstrBody = maker.Block(0L, List.of(maker.Exec(maker.Apply(List.nil(), maker.Ident(typeNode.toName("super")), List.nil())))); + JCMethodDecl genConstr = maker.MethodDef(genConstrMods, typeNode.toName(""), null, List.nil(), List.nil(), List.nil(), genConstrBody, null); + + injectMethod(innerNode, genConstr); + + for (JavacNode field : fields) { + JCModifiers enumValueMods = maker.Modifiers(Flags.PUBLIC | Flags.STATIC | Flags.FINAL | (asEnum ? Flags.ENUM : 0L)); + JCExpression returnType; + JCExpression init; + if (asEnum) { + returnType = maker.Ident(fieldsName); + init = maker.NewClass(null, List.nil(), maker.Ident(fieldsName), List.nil(), null); + } else { + returnType = chainDots(field, "java", "lang", "String"); + init = maker.Literal(field.getName()); + } + JCVariableDecl enumField = maker.VarDef(enumValueMods, ((JCVariableDecl) field.get()).name, returnType, init); + injectField(innerNode, enumField); + } } -} \ No newline at end of file +} -- cgit From eeab3c0021503bca69012cf71cbbfe2505be2293 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 29 Jul 2018 16:37:54 +0200 Subject: A few upgrades for the printers used with @lombok.core.PrintAST. --- src/core/lombok/eclipse/EclipseASTVisitor.java | 105 +++++++++++++++++++++++-- src/core/lombok/javac/JavacASTVisitor.java | 14 ++-- 2 files changed, 107 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/eclipse/EclipseASTVisitor.java b/src/core/lombok/eclipse/EclipseASTVisitor.java index f5b49cbb..63557f41 100644 --- a/src/core/lombok/eclipse/EclipseASTVisitor.java +++ b/src/core/lombok/eclipse/EclipseASTVisitor.java @@ -26,7 +26,9 @@ import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.io.PrintStream; import java.lang.reflect.Modifier; +import org.eclipse.jdt.internal.compiler.ast.ASTNode; import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration; +import org.eclipse.jdt.internal.compiler.ast.AllocationExpression; import org.eclipse.jdt.internal.compiler.ast.Annotation; import org.eclipse.jdt.internal.compiler.ast.Argument; import org.eclipse.jdt.internal.compiler.ast.Block; @@ -38,6 +40,7 @@ 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.ast.TypeReference; +import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants; /** * Implement so you can ask any EclipseAST.Node to traverse depth-first through all children, @@ -199,8 +202,82 @@ public interface EclipseASTVisitor { print(""); } + private String printFlags(int flags, ASTNode node) { + StringBuilder out = new StringBuilder(); + if ((flags & ClassFileConstants.AccPublic) != 0) { + flags &= ~ClassFileConstants.AccPublic; + out.append("public "); + } + if ((flags & ClassFileConstants.AccPrivate) != 0) { + flags &= ~ClassFileConstants.AccPrivate; + out.append("private "); + } + if ((flags & ClassFileConstants.AccProtected) != 0) { + flags &= ~ClassFileConstants.AccProtected; + out.append("protected "); + } + if ((flags & ClassFileConstants.AccStatic) != 0) { + flags &= ~ClassFileConstants.AccStatic; + out.append("static "); + } + if ((flags & ClassFileConstants.AccFinal) != 0) { + flags &= ~ClassFileConstants.AccFinal; + out.append("final "); + } + if ((flags & ClassFileConstants.AccSynchronized) != 0) { + flags &= ~ClassFileConstants.AccSynchronized; + out.append("synchronized "); + } + if ((flags & ClassFileConstants.AccNative) != 0) { + flags &= ~ClassFileConstants.AccNative; + out.append("native "); + } + if ((flags & ClassFileConstants.AccInterface) != 0) { + flags &= ~ClassFileConstants.AccInterface; + out.append("interface "); + } + if ((flags & ClassFileConstants.AccAbstract) != 0) { + flags &= ~ClassFileConstants.AccAbstract; + out.append("abstract "); + } + if ((flags & ClassFileConstants.AccStrictfp) != 0) { + flags &= ~ClassFileConstants.AccStrictfp; + out.append("strictfp "); + } + if ((flags & ClassFileConstants.AccSynthetic) != 0) { + flags &= ~ClassFileConstants.AccSynthetic; + out.append("synthetic "); + } + if ((flags & ClassFileConstants.AccAnnotation) != 0) { + flags &= ~ClassFileConstants.AccAnnotation; + out.append("annotation "); + } + if ((flags & ClassFileConstants.AccEnum) != 0) { + flags &= ~ClassFileConstants.AccEnum; + out.append("enum "); + } + + if ((flags & ClassFileConstants.AccVolatile) != 0) { + flags &= ~ClassFileConstants.AccVolatile; + if (node instanceof FieldDeclaration) out.append("volatile "); + else out.append("volatile/bridge "); + } + if ((flags & ClassFileConstants.AccTransient) != 0) { + flags &= ~ClassFileConstants.AccTransient; + if (node instanceof Argument) out.append("varargs "); + else if (node instanceof FieldDeclaration) out.append("transient "); + else out.append("transient/varargs "); + } + + if (flags != 0) { + out.append(String.format(" 0x%08X ", flags)); + } + + return out.toString().trim(); + } + public void visitType(EclipseNode node, TypeDeclaration type) { - print("", str(type.name), isGenerated(type) ? " (GENERATED)" : "", position(node)); + print(" %s", str(type.name), isGenerated(type) ? " (GENERATED)" : "", position(node), printFlags(type.modifiers, type)); indent++; if (printContent) { print("%s", type); @@ -239,8 +316,8 @@ public interface EclipseASTVisitor { } public void visitField(EclipseNode node, FieldDeclaration field) { - print("", isGenerated(field) ? " (GENERATED)" : "", - str(field.type), str(field.name), field.initialization, position(node)); + print(" %s", isGenerated(field) ? " (GENERATED)" : "", + str(field.type), str(field.name), field.initialization, position(node), printFlags(field.modifiers, field)); indent++; if (printContent) { if (field.initialization != null) print("%s", field.initialization); @@ -260,9 +337,13 @@ public interface EclipseASTVisitor { public void visitMethod(EclipseNode node, AbstractMethodDeclaration method) { String type = method instanceof ConstructorDeclaration ? "CONSTRUCTOR" : "METHOD"; - print("<%s %s: %s%s%s>", type, str(method.selector), method.statements != null ? "filled" : "blank", - isGenerated(method) ? " (GENERATED)" : "", position(node)); + print("<%s %s: %s%s%s> %s", type, str(method.selector), method.statements != null ? ("filled(" + method.statements.length + ")") : "blank", + isGenerated(method) ? " (GENERATED)" : "", position(node), printFlags(method.modifiers, method)); indent++; + if (method instanceof ConstructorDeclaration) { + ConstructorDeclaration cd = (ConstructorDeclaration) method; + print("--> constructorCall: %s", cd.constructorCall == null ? "-NONE-" : cd.constructorCall); + } if (printContent) { if (method.statements != null) print("%s", method); disablePrinting++; @@ -281,7 +362,8 @@ public interface EclipseASTVisitor { } public void visitMethodArgument(EclipseNode node, Argument arg, AbstractMethodDeclaration method) { - print("", isGenerated(arg) ? " (GENERATED)" : "", str(arg.type), str(arg.name), arg.initialization, position(node)); + print(" %s", isGenerated(arg) ? " (GENERATED)" : "", + str(arg.type), str(arg.name), arg.initialization, position(node), printFlags(arg.modifiers, arg)); indent++; } @@ -295,7 +377,8 @@ public interface EclipseASTVisitor { } public void visitLocal(EclipseNode node, LocalDeclaration local) { - print("", isGenerated(local) ? " (GENERATED)" : "", str(local.type), str(local.name), local.initialization, position(node)); + print(" %s", isGenerated(local) ? " (GENERATED)" : "", + str(local.type), str(local.name), local.initialization, position(node), printFlags(local.modifiers, local)); indent++; } @@ -310,6 +393,14 @@ public interface EclipseASTVisitor { public void visitStatement(EclipseNode node, Statement statement) { print("<%s%s%s>", statement.getClass(), isGenerated(statement) ? " (GENERATED)" : "", position(node)); + if (statement instanceof AllocationExpression) { + AllocationExpression alloc = (AllocationExpression) statement; + print(" --> arguments: %s", alloc.arguments == null ? "NULL" : alloc.arguments.length); + print(" --> genericTypeArguments: %s", alloc.genericTypeArguments == null ? "NULL" : alloc.genericTypeArguments.length); + print(" --> typeArguments: %s", alloc.typeArguments == null ? "NULL" : alloc.typeArguments.length); + print(" --> enumConstant: %s", alloc.enumConstant); + print(" --> inferredReturnType: %s", alloc.inferredReturnType); + } indent++; print("%s", statement); } diff --git a/src/core/lombok/javac/JavacASTVisitor.java b/src/core/lombok/javac/JavacASTVisitor.java index 565980f9..d4f8f731 100644 --- a/src/core/lombok/javac/JavacASTVisitor.java +++ b/src/core/lombok/javac/JavacASTVisitor.java @@ -149,8 +149,12 @@ public interface JavacASTVisitor { print(""); } + private String printFlags(long f) { + return Flags.toString(f); + } + @Override public void visitType(JavacNode node, JCClassDecl type) { - print("", type.name); + print(" %s", type.name, printFlags(type.mods.flags)); indent++; if (printContent) { print("%s", type); @@ -185,7 +189,7 @@ public interface JavacASTVisitor { } @Override public void visitField(JavacNode node, JCVariableDecl field) { - print("", field.vartype, field.name); + print(" %s", field.vartype, field.name, printFlags(field.mods.flags)); indent++; if (printContent) { if (field.init != null) print("%s", field.init); @@ -210,7 +214,7 @@ public interface JavacASTVisitor { type = "DEFAULTCONSTRUCTOR"; } else type = "CONSTRUCTOR"; } else type = "METHOD"; - print("<%s %s> returns: %s", type, method.name, method.restype); + print("<%s %s> %s returns: %s", type, method.name, printFlags(method.mods.flags), method.restype); indent++; if (printContent) { if (method.body == null) print("(ABSTRACT)"); @@ -230,7 +234,7 @@ public interface JavacASTVisitor { } @Override public void visitMethodArgument(JavacNode node, JCVariableDecl arg, JCMethodDecl method) { - print("", arg.vartype, arg.name); + print(" %s", arg.vartype, arg.name, printFlags(arg.mods.flags)); indent++; } @@ -244,7 +248,7 @@ public interface JavacASTVisitor { } @Override public void visitLocal(JavacNode node, JCVariableDecl local) { - print("", local.vartype, local.name); + print(" %s", local.vartype, local.name, printFlags(local.mods.flags)); indent++; } -- cgit From b9fb35cb8e81d73b9b9b650022a1564b14761885 Mon Sep 17 00:00:00 2001 From: Reinier Zwitserloot Date: Sun, 29 Jul 2018 16:38:16 +0200 Subject: Printing missing gradle integration would print for any non-javac, non-gradle compiler. Fixed that. --- src/core/lombok/core/AnnotationProcessor.java | 25 +++++++++++----------- .../lombok/javac/handlers/HandleFieldDefaults.java | 2 +- 2 files changed, 14 insertions(+), 13 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java index 04448ecb..89dfa555 100644 --- a/src/core/lombok/core/AnnotationProcessor.java +++ b/src/core/lombok/core/AnnotationProcessor.java @@ -49,7 +49,7 @@ import lombok.patcher.ClassRootFinder; @SupportedAnnotationTypes("*") public class AnnotationProcessor extends AbstractProcessor { - + private static String trace(Throwable t) { StringWriter w = new StringWriter(); t.printStackTrace(new PrintWriter(w, true)); @@ -65,7 +65,7 @@ public class AnnotationProcessor extends AbstractProcessor { private final List registered = Arrays.asList(new JavacDescriptor(), new EcjDescriptor()); private final List active = new ArrayList(); private final List delayedWarnings = new ArrayList(); - + /** * This method is a simplified version of {@link lombok.javac.apt.LombokProcessor.getJavacProcessingEnvironment} * It simply returns the processing environment, but in case of gradle incremental compilation, @@ -73,34 +73,35 @@ public class AnnotationProcessor extends AbstractProcessor { */ public static ProcessingEnvironment getJavacProcessingEnvironment(ProcessingEnvironment procEnv, List delayedWarnings) { ProcessingEnvironment javacProcEnv = tryRecursivelyObtainJavacProcessingEnvironment(procEnv); - + if (javacProcEnv == null) { - delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment."); + if (!procEnv.getClass().getName().startsWith("org.eclipse.jdt.")) { + delayedWarnings.add("Can't get the delegate of the gradle IncrementalProcessingEnvironment."); + } } - + return javacProcEnv; } - + private static ProcessingEnvironment tryRecursivelyObtainJavacProcessingEnvironment(ProcessingEnvironment procEnv) { if (procEnv.getClass().getName().equals("com.sun.tools.javac.processing.JavacProcessingEnvironment")) { return procEnv; } - + for (Class procEnvClass = procEnv.getClass(); procEnvClass != null; procEnvClass = procEnvClass.getSuperclass()) { try { Field field = procEnvClass.getDeclaredField("delegate"); field.setAccessible(true); Object delegate = field.get(procEnv); - + return tryRecursivelyObtainJavacProcessingEnvironment((ProcessingEnvironment) delegate); } catch (final Exception e) { // no valid delegate, try superclass } } - + return null; } - static class JavacDescriptor extends ProcessorDescriptor { private Processor processor; @@ -111,9 +112,9 @@ public class AnnotationProcessor extends AbstractProcessor { @Override boolean want(ProcessingEnvironment procEnv, List delayedWarnings) { ProcessingEnvironment javacProcEnv = getJavacProcessingEnvironment(procEnv, delayedWarnings); - + if (javacProcEnv == null) return false; - + try { ClassLoader classLoader = findAndPatchClassLoader(javacProcEnv); processor = (Processor) Class.forName("lombok.javac.apt.LombokProcessor", false, classLoader).newInstance(); diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java index 52f6c39c..aa381c0d 100644 --- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java +++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java @@ -44,7 +44,7 @@ import com.sun.tools.javac.tree.JCTree.JCClassDecl; import com.sun.tools.javac.tree.JCTree.JCVariableDecl; /** - * Handles the {@code lombok.FieldDefaults} annotation for eclipse. + * Handles the {@code lombok.FieldDefaults} annotation for javac. */ @ProviderFor(JavacASTVisitor.class) @HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier. -- cgit From 100cff228d0f4d68219460aefe89b70877b726dc Mon Sep 17 00:00:00 2001 From: Roland Praml Date: Mon, 9 Jul 2018 20:29:21 +0200 Subject: reduced calls of traverse invocations --- src/core/lombok/eclipse/HandlerLibrary.java | 18 ++++++++++----- src/core/lombok/eclipse/TransformEclipseAST.java | 28 +++++++++++++++++++----- 2 files changed, 34 insertions(+), 12 deletions(-) (limited to 'src/core') diff --git a/src/core/lombok/eclipse/HandlerLibrary.java b/src/core/lombok/eclipse/HandlerLibrary.java index 07c6f97b..75a22f03 100644 --- a/src/core/lombok/eclipse/HandlerLibrary.java +++ b/src/core/lombok/eclipse/HandlerLibrary.java @@ -32,6 +32,7 @@ import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Set; import java.util.SortedSet; import java.util.TreeSet; @@ -212,21 +213,25 @@ public class HandlerLibrary { * @param ast The Compilation Unit that contains the Annotation AST Node. * @param annotationNode The Lombok AST Node representing the Annotation AST Node. * @param annotation 'node.get()' - convenience parameter. + * @param priority current prioritiy + * @return the priority we want to run - MAX_VALUE means never */ - public void handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) { + public long handleAnnotation(CompilationUnitDeclaration ast, EclipseNode annotationNode, org.eclipse.jdt.internal.compiler.ast.Annotation annotation, long priority) { TypeResolver resolver = new TypeResolver(annotationNode.getImportList()); TypeReference rawType = annotation.type; - if (rawType == null) return; + if (rawType == null) return Long.MAX_VALUE; String fqn = resolver.typeRefToFullyQualifiedName(annotationNode, typeLibrary, toQualifiedName(annotation.type.getTypeName())); - if (fqn == null) return; + if (fqn == null) return Long.MAX_VALUE; AnnotationHandlerContainer container = annotationHandlers.get(fqn); - if (container == null) return; - if (priority != container.getPriority()) return; + if (container == null) return Long.MAX_VALUE; + + if (priority < container.getPriority()) return container.getPriority(); // we want to run at this priority + if (priority > container.getPriority()) return Long.MAX_VALUE; // it's over- we do not want to run again if (!annotationNode.isCompleteParse() && container.deferUntilPostDiet()) { if (needsHandling(annotation)) container.preHandle(annotation, annotationNode); - return; + return Long.MAX_VALUE; } try { @@ -236,6 +241,7 @@ public class HandlerLibrary { } catch (Throwable t) { error(ast, String.format("Lombok annotation handler %s failed", container.handler.getClass()), t); } + return Long.MAX_VALUE; } /** diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java index 541924ad..24e24495 100644 --- a/src/core/lombok/eclipse/TransformEclipseAST.java +++ b/src/core/lombok/eclipse/TransformEclipseAST.java @@ -24,6 +24,8 @@ package lombok.eclipse; import static lombok.eclipse.handlers.EclipseHandlerUtil.*; import java.lang.reflect.Field; +import java.util.HashSet; +import java.util.Set; import lombok.ConfigurationKeys; import lombok.core.LombokConfiguration; @@ -186,42 +188,56 @@ public class TransformEclipseAST { * then handles any PrintASTs. */ public void go() { + long nextPriority = Long.MIN_VALUE; for (Long d : handlers.getPriorities()) { - ast.traverse(new AnnotationVisitor(d)); + if (nextPriority > d) { + continue; + } + AnnotationVisitor visitor = new AnnotationVisitor(d); + ast.traverse(visitor); + // if no visitor interested for this AST, nextPriority would be MAX_VALUE and we bail out immediatetly + nextPriority = visitor.getNextPriority(); handlers.callASTVisitors(ast, d, ast.isCompleteParse()); } } private static class AnnotationVisitor extends EclipseASTAdapter { private final long priority; + // this is the next priority we continue to visit. + // Long.MAX_VALUE means never. Each visit method will potentially reduce the next priority + private long nextPriority = Long.MAX_VALUE; public AnnotationVisitor(long priority) { this.priority = priority; } + public long getNextPriority() { + return nextPriority; + } + @Override public void visitAnnotationOnField(FieldDeclaration field, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority); + nextPriority = Math.min(nextPriority, handlers.handleAnnotation(top, annotationNode, annotation, priority)); } @Override public void visitAnnotationOnMethodArgument(Argument arg, AbstractMethodDeclaration method, EclipseNode annotationNode, Annotation annotation) { CompilationUnitDeclaration top = (CompilationUnitDeclaration) annotationNode.top().get(); - handlers.handleAnnotation(top, annotationNode, annotation, priority);