aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitignore2
-rw-r--r--AUTHORS18
-rw-r--r--LICENSE2
-rw-r--r--README1
-rw-r--r--build.xml511
-rw-r--r--buildScripts/eclipse-run-tests.template6
-rw-r--r--buildScripts/ivy-repo/net.java.openjdk.custom-javac6-1.6.0.18.xml4
-rw-r--r--buildScripts/ivy-repo/net.java.openjdk.custom-javac7-1.7.0.xml4
-rw-r--r--buildScripts/ivy-repo/netbeans.org-boot-6.8beta.xml2
-rw-r--r--buildScripts/ivy-repo/netbeans.org-modules.java.source-6.8beta.xml2
-rw-r--r--buildScripts/ivy-repo/netbeans.org-openide.modules-6.8beta.xml2
-rw-r--r--buildScripts/ivy-repo/netbeans.org-openide.util-6.8beta.xml2
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.200.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.300.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.7.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.8.100.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.6.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.9.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-ecj-3.6.2.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-ecj-4.3.1.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-ecj-I20140430.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.200.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.6.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.9.1.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.6.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.9.1.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-osgi-3.6.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.eclipse.custom-osgi-3.9.0.xml4
-rw-r--r--buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.24.xml (renamed from buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.15.xml)6
-rw-r--r--buildScripts/ivy-repo/projectlombok.org-jsch-ant-fixed-0.1.42.xml2
-rw-r--r--buildScripts/ivy-repo/projectlombok.org-markdownj-1.02b4.xml4
-rw-r--r--buildScripts/ivy-repo/projectlombok.org-spi-0.2.4.xml2
-rw-r--r--buildScripts/ivy-repo/projectlombok.org-spi-0.2.7.xml2
-rw-r--r--buildScripts/ivy-repo/zwitserloot.com-cmdreader-1.2.xml4
-rw-r--r--buildScripts/ivy.xml29
-rw-r--r--buildScripts/ivysettings.xml2
-rw-r--r--buildScripts/src/lombok/website/CompileChangelog.java59
-rw-r--r--buildScripts/src/lombok/website/WebUpToDate.java190
-rw-r--r--buildScripts/supporters.ant.xml57
-rw-r--r--buildScripts/website.ant.xml359
-rw-r--r--doc/changelog.markdown433
-rw-r--r--doc/maven-pom.xml4
-rw-r--r--doc/utils-maven-pom.xml4
-rw-r--r--docker/.dockerignore1
-rw-r--r--docker/ant/Dockerfile33
-rw-r--r--docker/ant/files/jdk-8/build.xml25
-rw-r--r--docker/ant/files/jdk-9/build.xml35
-rw-r--r--docker/ant/readme.md33
-rw-r--r--docker/gradle/Dockerfile31
-rw-r--r--docker/gradle/files/build.gradle5
-rw-r--r--docker/gradle/readme.md33
-rw-r--r--docker/maven/Dockerfile34
-rw-r--r--docker/maven/files/jdk-8/pom.xml44
-rw-r--r--docker/maven/files/jdk-9/pom.xml53
-rw-r--r--docker/maven/readme.md33
-rwxr-xr-xdocker/provision/ant/ant-1.10.1.sh4
-rwxr-xr-xdocker/provision/gradle/gradle-4.2.1.sh4
-rwxr-xr-xdocker/provision/jdk/java-10.sh4
-rwxr-xr-xdocker/provision/jdk/java-8.sh6
-rwxr-xr-xdocker/provision/jdk/java-9.sh4
-rwxr-xr-xdocker/provision/maven/maven-3.5.0.sh4
-rw-r--r--docker/readme.md31
-rw-r--r--docker/shared/lombok.config4
-rw-r--r--docker/shared/src/main/java/HelloWorld.java13
-rw-r--r--src/core/lombok/AllArgsConstructor.java28
-rw-r--r--src/core/lombok/Builder.java (renamed from src/core/lombok/experimental/Builder.java)78
-rw-r--r--src/core/lombok/Cleanup.java10
-rw-r--r--src/core/lombok/ConfigurationKeys.java181
-rw-r--r--src/core/lombok/Data.java6
-rw-r--r--src/core/lombok/Delegate.java6
-rw-r--r--src/core/lombok/EqualsAndHashCode.java29
-rw-r--r--src/core/lombok/Generated.java41
-rw-r--r--src/core/lombok/Getter.java23
-rw-r--r--src/core/lombok/Lombok.java33
-rw-r--r--src/core/lombok/NoArgsConstructor.java25
-rw-r--r--src/core/lombok/RequiredArgsConstructor.java27
-rw-r--r--src/core/lombok/Setter.java24
-rw-r--r--src/core/lombok/Singular.java38
-rw-r--r--src/core/lombok/SneakyThrows.java9
-rw-r--r--src/core/lombok/Synchronized.java6
-rw-r--r--src/core/lombok/ToString.java14
-rw-r--r--src/core/lombok/Value.java12
-rw-r--r--src/core/lombok/bytecode/AsmUtil.java2
-rw-r--r--src/core/lombok/bytecode/ClassFileMetaData.java7
-rw-r--r--src/core/lombok/bytecode/PostCompilerApp.java22
-rw-r--r--src/core/lombok/bytecode/PreventNullAnalysisRemover.java4
-rw-r--r--src/core/lombok/bytecode/SneakyThrowsRemover.java4
-rw-r--r--src/core/lombok/core/AST.java32
-rw-r--r--src/core/lombok/core/AgentLauncher.java (renamed from src/core/lombok/core/Agent.java)74
-rw-r--r--src/core/lombok/core/AnnotationProcessor.java26
-rw-r--r--src/core/lombok/core/GuavaTypeMap.java59
-rw-r--r--src/core/lombok/core/LombokInternalAliasing.java4
-rw-r--r--src/core/lombok/core/Main.java5
-rw-r--r--src/core/lombok/core/PostCompiler.java8
-rw-r--r--src/core/lombok/core/PublicApiCreatorApp.java2
-rw-r--r--src/core/lombok/core/TypeLibrary.java47
-rw-r--r--src/core/lombok/core/TypeResolver.java16
-rw-r--r--src/core/lombok/core/Version.java14
-rw-r--r--src/core/lombok/core/configuration/AllowHelper.java37
-rw-r--r--src/core/lombok/core/configuration/BubblingConfigurationResolver.java21
-rw-r--r--src/core/lombok/core/configuration/CallSuperType.java27
-rw-r--r--src/core/lombok/core/configuration/ConfigurationApp.java2
-rw-r--r--src/core/lombok/core/configuration/ConfigurationParser.java4
-rw-r--r--src/core/lombok/core/configuration/FileSystemSourceCache.java77
-rw-r--r--src/core/lombok/core/configuration/FlagUsageType.java2
-rw-r--r--src/core/lombok/core/debug/AssertionLogger.java115
-rw-r--r--src/core/lombok/core/handlers/HandlerUtil.java42
-rw-r--r--src/core/lombok/core/handlers/Singulars.java86
-rw-r--r--src/core/lombok/core/handlers/singulars.txt56
-rw-r--r--src/core/lombok/eclipse/EclipseAST.java8
-rw-r--r--src/core/lombok/eclipse/EclipseASTVisitor.java2
-rw-r--r--src/core/lombok/eclipse/EclipseNode.java48
-rw-r--r--src/core/lombok/eclipse/TransformEclipseAST.java2
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java402
-rw-r--r--src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java349
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilder.java678
-rw-r--r--src/core/lombok/eclipse/handlers/HandleBuilderDefault.java46
-rw-r--r--src/core/lombok/eclipse/handlers/HandleConstructor.java195
-rw-r--r--src/core/lombok/eclipse/handlers/HandleData.java16
-rw-r--r--src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java155
-rw-r--r--src/core/lombok/eclipse/handlers/HandleFieldDefaults.java91
-rw-r--r--src/core/lombok/eclipse/handlers/HandleGetter.java14
-rw-r--r--src/core/lombok/eclipse/handlers/HandleHelper.java152
-rw-r--r--src/core/lombok/eclipse/handlers/HandleLog.java15
-rw-r--r--src/core/lombok/eclipse/handlers/HandleNonNull.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandlePrintAST.java2
-rw-r--r--src/core/lombok/eclipse/handlers/HandleSetter.java26
-rw-r--r--src/core/lombok/eclipse/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/eclipse/handlers/HandleUtilityClass.java194
-rw-r--r--src/core/lombok/eclipse/handlers/HandleVal.java40
-rw-r--r--src/core/lombok/eclipse/handlers/HandleValue.java16
-rw-r--r--src/core/lombok/eclipse/handlers/HandleWither.java108
-rw-r--r--src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java667
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java58
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java56
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java261
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java51
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java189
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java129
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java313
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java52
-rw-r--r--src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java300
-rw-r--r--src/core/lombok/experimental/Accessors.java18
-rw-r--r--src/core/lombok/experimental/Delegate.java8
-rw-r--r--src/core/lombok/experimental/ExtensionMethod.java10
-rw-r--r--src/core/lombok/experimental/FieldDefaults.java8
-rw-r--r--src/core/lombok/experimental/Helper.java (renamed from src/core/lombok/experimental/Value.java)33
-rw-r--r--src/core/lombok/experimental/NonFinal.java2
-rw-r--r--src/core/lombok/experimental/PackagePrivate.java2
-rw-r--r--src/core/lombok/experimental/UtilityClass.java41
-rw-r--r--src/core/lombok/experimental/Wither.java24
-rw-r--r--src/core/lombok/experimental/package-info.java4
-rw-r--r--src/core/lombok/experimental/var.java31
-rw-r--r--src/core/lombok/extern/apachecommons/CommonsLog.java15
-rw-r--r--src/core/lombok/extern/java/Log.java15
-rw-r--r--src/core/lombok/extern/jbosslog/JBossLog.java64
-rw-r--r--src/core/lombok/extern/log4j/Log4j.java15
-rw-r--r--src/core/lombok/extern/log4j/Log4j2.java17
-rw-r--r--src/core/lombok/extern/slf4j/Slf4j.java17
-rw-r--r--src/core/lombok/extern/slf4j/XSlf4j.java15
-rw-r--r--src/core/lombok/javac/CapturingDiagnosticListener.java4
-rw-r--r--src/core/lombok/javac/CompilerMessageSuppressor.java206
-rw-r--r--src/core/lombok/javac/HandlerLibrary.java13
-rw-r--r--src/core/lombok/javac/Javac8BasedLombokOptions.java4
-rw-r--r--src/core/lombok/javac/Javac9BasedLombokOptions.java48
-rw-r--r--src/core/lombok/javac/JavacAST.java282
-rw-r--r--src/core/lombok/javac/JavacASTAdapter.java4
-rw-r--r--src/core/lombok/javac/JavacASTVisitor.java5
-rw-r--r--src/core/lombok/javac/JavacAnnotationHandler.java7
-rw-r--r--src/core/lombok/javac/JavacImportList.java26
-rw-r--r--src/core/lombok/javac/JavacNode.java58
-rw-r--r--src/core/lombok/javac/JavacResolution.java80
-rw-r--r--src/core/lombok/javac/JavacTransformer.java9
-rw-r--r--src/core/lombok/javac/apt/EmptyLombokFileObject.java1
-rw-r--r--src/core/lombok/javac/apt/InterceptingJavaFileManager.java10
-rw-r--r--src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java113
-rw-r--r--src/core/lombok/javac/apt/LombokFileObjects.java207
-rw-r--r--src/core/lombok/javac/apt/LombokProcessor.java402
-rw-r--r--src/core/lombok/javac/apt/Processor.java374
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilder.java616
-rw-r--r--src/core/lombok/javac/handlers/HandleBuilderDefault.java49
-rw-r--r--src/core/lombok/javac/handlers/HandleConstructor.java154
-rw-r--r--src/core/lombok/javac/handlers/HandleData.java17
-rw-r--r--src/core/lombok/javac/handlers/HandleDelegate.java10
-rw-r--r--src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java188
-rw-r--r--src/core/lombok/javac/handlers/HandleFieldDefaults.java85
-rw-r--r--src/core/lombok/javac/handlers/HandleGetter.java13
-rw-r--r--src/core/lombok/javac/handlers/HandleHelper.java151
-rw-r--r--src/core/lombok/javac/handlers/HandleLog.java15
-rw-r--r--src/core/lombok/javac/handlers/HandleNonNull.java3
-rw-r--r--src/core/lombok/javac/handlers/HandlePrintAST.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleSetter.java35
-rw-r--r--src/core/lombok/javac/handlers/HandleSynchronized.java2
-rw-r--r--src/core/lombok/javac/handlers/HandleToString.java6
-rw-r--r--src/core/lombok/javac/handlers/HandleUtilityClass.java161
-rw-r--r--src/core/lombok/javac/handlers/HandleVal.java70
-rw-r--r--src/core/lombok/javac/handlers/HandleValue.java27
-rw-r--r--src/core/lombok/javac/handlers/HandleWither.java112
-rw-r--r--src/core/lombok/javac/handlers/JavacHandlerUtil.java557
-rw-r--r--src/core/lombok/javac/handlers/JavacSingularsRecipes.java310
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java58
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java56
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java222
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java51
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java162
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java120
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java229
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java57
-rw-r--r--src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java196
-rw-r--r--src/core/lombok/package-info.java4
-rw-r--r--src/core/lombok/val.java4
-rw-r--r--src/core/lombok/var.java35
-rw-r--r--src/core9/module-info.java38
-rw-r--r--src/delombok/lombok/delombok/Delombok.java123
-rw-r--r--src/delombok/lombok/delombok/DelombokApp.java16
-rw-r--r--src/delombok/lombok/delombok/DelombokResult.java3
-rw-r--r--src/delombok/lombok/delombok/DocCommentIntegrator.java8
-rw-r--r--src/delombok/lombok/delombok/FormatPreferences.java15
-rw-r--r--src/delombok/lombok/delombok/LombokOptionsFactory.java13
-rw-r--r--src/delombok/lombok/delombok/PrettyCommentsPrinter.java1680
-rw-r--r--src/delombok/lombok/delombok/PrettyPrinter.java1524
-rw-r--r--src/delombok/lombok/delombok/UnicodeEscapeWriter.java2
-rw-r--r--src/delombok/lombok/delombok/ant/DelombokTask.java279
-rw-r--r--src/delombok/lombok/delombok/ant/DelombokTaskImpl.java91
-rw-r--r--src/delombok/lombok/delombok/ant/Format.java35
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java72
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java128
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java249
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java75
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java53
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java4
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposalPortal.java3
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java384
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java53
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchVal.java93
-rw-r--r--src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java21
-rw-r--r--src/eclipseAgent/lombok/launch/PatchFixesHider.java671
-rw-r--r--src/installer/lombok/installer/IdeLocation.java7
-rw-r--r--src/installer/lombok/installer/IdeLocationProvider.java22
-rw-r--r--src/installer/lombok/installer/Installer.java19
-rw-r--r--src/installer/lombok/installer/InstallerGUI.java203
-rw-r--r--src/installer/lombok/installer/OsUtils.java (renamed from src/installer/lombok/installer/IdeFinder.java)21
-rw-r--r--src/installer/lombok/installer/eclipse/EclipseLocationProvider.java144
-rw-r--r--src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java (renamed from src/installer/lombok/installer/eclipse/STSLocation.java)38
-rw-r--r--src/installer/lombok/installer/eclipse/EclipseProductLocation.java (renamed from src/installer/lombok/installer/eclipse/EclipseLocation.java)87
-rw-r--r--src/installer/lombok/installer/eclipse/EclipseProductLocationProvider.java (renamed from src/installer/lombok/installer/eclipse/EclipseFinder.java)262
-rw-r--r--src/installer/lombok/installer/eclipse/JbdsFinder.java70
-rw-r--r--src/installer/lombok/installer/eclipse/JbdsLocationProvider.java49
-rw-r--r--src/installer/lombok/installer/eclipse/MyEclipseLocationProvider.java (renamed from src/installer/lombok/installer/eclipse/JbdsLocation.java)33
-rw-r--r--src/installer/lombok/installer/eclipse/RhdsLocationProvider.java44
-rw-r--r--src/installer/lombok/installer/eclipse/STS4LocationProvider.java44
-rw-r--r--src/installer/lombok/installer/eclipse/STSFinder.java70
-rw-r--r--src/installer/lombok/installer/eclipse/STSLocationProvider.java48
-rw-r--r--src/installer/lombok/installer/eclipse/StandardProductDescriptor.java158
-rw-r--r--src/installer/lombok/installer/eclipse/myeclipse.pngbin0 -> 1073 bytes
-rw-r--r--src/installer/lombok/installer/eclipse/rhds.pngbin0 -> 3470 bytes
-rw-r--r--src/j9stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java48
-rw-r--r--src/launch/lombok/launch/Agent.java47
-rw-r--r--src/launch/lombok/launch/AnnotationProcessor.java129
-rw-r--r--src/launch/lombok/launch/Main.java41
-rw-r--r--src/launch/lombok/launch/ShadowClassLoader.java485
-rw-r--r--src/stubs/com/sun/tools/javac/code/Symbol.java84
-rw-r--r--src/stubs/com/sun/tools/javac/code/Symtab.java20
-rw-r--r--src/stubs/com/sun/tools/javac/file/BaseFileManager.java18
-rw-r--r--src/stubs/com/sun/tools/javac/file/PathFileObject.java12
-rw-r--r--src/stubs/com/sun/tools/javac/main/Arguments.java13
-rw-r--r--src/stubs/com/sun/tools/javac/main/JavaCompiler.java37
-rw-r--r--src/stubs/com/sun/tools/javac/main/Option.java1
-rw-r--r--src/stubs/com/sun/tools/javac/parser/JavacParser.java6
-rw-r--r--src/stubs/com/sun/tools/javac/util/Options.java20
-rw-r--r--src/stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java48
-rw-r--r--src/stubsstubs/com/sun/tools/javac/code/Attribute.java15
-rw-r--r--src/stubsstubs/com/sun/tools/javac/code/Type.java3
-rw-r--r--src/stubsstubs/com/sun/tools/javac/comp/Todo.java3
-rw-r--r--src/stubsstubs/com/sun/tools/javac/main/JavacOption.java5
-rw-r--r--src/stubsstubs/com/sun/tools/javac/main/Option.java3
-rw-r--r--src/stubsstubs/com/sun/tools/javac/main/OptionName.java3
-rw-r--r--src/stubsstubs/com/sun/tools/javac/util/Context.java5
-rw-r--r--src/stubsstubs/com/sun/tools/javac/util/List.java3
-rw-r--r--src/stubsstubs/com/sun/tools/javac/util/Name.java8
-rw-r--r--src/testAP/org/projectlombok/testAp/ExampleAnnotation.java10
-rw-r--r--src/testAP/org/projectlombok/testAp/TestAp.java77
-rw-r--r--src/useTestAP/UseTestAp.java13
-rw-r--r--src/utils/lombok/core/LombokImmutableList.java6
-rw-r--r--src/utils/lombok/eclipse/Eclipse.java19
-rw-r--r--src/utils/lombok/javac/CommentCatcher.java4
-rw-r--r--src/utils/lombok/javac/Javac.java55
-rw-r--r--src/utils/lombok/javac/JavacTreeMaker.java1
-rw-r--r--src/utils/lombok/javac/PackageName.java55
-rw-r--r--src/utils/lombok/javac/TreeMirrorMaker.java33
-rw-r--r--src/utils/lombok/javac/java8/CommentCollectingParserFactory.java10
-rw-r--r--src/utils/lombok/javac/java9/CommentCollectingParser.java53
-rw-r--r--src/utils/lombok/javac/java9/CommentCollectingParserFactory.java70
-rw-r--r--src/website/log4j.properties6
-rw-r--r--src/website/lombok/website/CompileChangelog.java147
-rw-r--r--src/website/lombok/website/FetchCurrentVersion.java33
-rw-r--r--src/website/lombok/website/WebsiteMaker.java403
-rw-r--r--ssh.knownHosts2
-rw-r--r--test/configuration/resource/configurationRoot/out.txt26
-rw-r--r--test/core/src/lombok/AbstractRunTests.java76
-rw-r--r--test/core/src/lombok/DirectoryRunner.java44
-rw-r--r--test/core/src/lombok/LombokTestSource.java165
-rw-r--r--test/core/src/lombok/RunAllTests.java4
-rw-r--r--test/core/src/lombok/RunTestsViaDelombok.java28
-rw-r--r--test/core/src/lombok/RunTestsViaEcj.java15
-rw-r--r--test/core/src/lombok/core/RunCoreTests.java31
-rw-r--r--test/core/src/lombok/core/TestSingulars.java56
-rw-r--r--test/pretty/resource/after/Cast.java2
-rw-r--r--test/pretty/resource/after/CastWithIntersection.java2
-rw-r--r--test/pretty/resource/after/DefaultMethod.java2
-rw-r--r--test/pretty/resource/after/Enum.java9
-rw-r--r--test/pretty/resource/after/ExoticJava.java46
-rw-r--r--test/pretty/resource/after/ForLoop.java7
-rw-r--r--test/pretty/resource/after/Interfaces.java5
-rw-r--r--test/pretty/resource/after/Lambda.java13
-rw-r--r--test/pretty/resource/after/TypeAnnotations.java22
-rw-r--r--test/pretty/resource/before/Cast.java2
-rw-r--r--test/pretty/resource/before/ExoticJava.java46
-rw-r--r--test/pretty/resource/before/ForLoop.java7
-rw-r--r--test/pretty/resource/before/Lambda.java18
-rw-r--r--test/pretty/resource/before/TypeAnnotations.java23
-rw-r--r--test/transform/knownBroken/before/I1132RecursiveGenerics.java19
-rw-r--r--test/transform/knownBroken/before/I1302BuilderInInstanceInnerClass.java5
-rw-r--r--test/transform/resource/after-delombok/Accessors.java8
-rw-r--r--test/transform/resource/after-delombok/AccessorsConfiguration.java2
-rw-r--r--test/transform/resource/after-delombok/BuilderChainAndFluent.java31
-rw-r--r--test/transform/resource/after-delombok/BuilderComplex.java6
-rw-r--r--test/transform/resource/after-delombok/BuilderDefaults.java111
-rw-r--r--test/transform/resource/after-delombok/BuilderDefaultsGenerics.java79
-rw-r--r--test/transform/resource/after-delombok/BuilderDefaultsWarnings.java99
-rw-r--r--test/transform/resource/after-delombok/BuilderGenericMethod.java40
-rw-r--r--test/transform/resource/after-delombok/BuilderInstanceMethod.java53
-rw-r--r--test/transform/resource/after-delombok/BuilderSimple.java2
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java140
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java94
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularLists.java123
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularMaps.java213
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularNoAuto.java121
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java93
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularSets.java153
-rw-r--r--test/transform/resource/after-delombok/BuilderSingularWithPrefixes.java56
-rw-r--r--test/transform/resource/after-delombok/BuilderValueData.java109
-rw-r--r--test/transform/resource/after-delombok/BuilderWithAccessors.java15
-rw-r--r--test/transform/resource/after-delombok/BuilderWithDeprecated.java111
-rw-r--r--test/transform/resource/after-delombok/BuilderWithExistingBuilderClass.java6
-rw-r--r--test/transform/resource/after-delombok/BuilderWithRecursiveGenerics.java85
-rw-r--r--test/transform/resource/after-delombok/BuilderWithToBuilder.java185
-rw-r--r--test/transform/resource/after-delombok/BuilderWithTolerate.java40
-rw-r--r--test/transform/resource/after-delombok/ConflictingStaticConstructorNames.java6
-rw-r--r--test/transform/resource/after-delombok/Constructors.java22
-rw-r--r--test/transform/resource/after-delombok/ConstructorsConfiguration.java8
-rw-r--r--test/transform/resource/after-delombok/ConstructorsWithAccessors.java32
-rw-r--r--test/transform/resource/after-delombok/DataConfiguration.java10
-rw-r--r--test/transform/resource/after-delombok/DataExtended.java6
-rw-r--r--test/transform/resource/after-delombok/DataIgnore.java7
-rw-r--r--test/transform/resource/after-delombok/DataOnEnum.java2
-rw-r--r--test/transform/resource/after-delombok/DataOnLocalClass.java18
-rw-r--r--test/transform/resource/after-delombok/DataPlain.java32
-rw-r--r--test/transform/resource/after-delombok/DataWithGetter.java9
-rw-r--r--test/transform/resource/after-delombok/DataWithGetterNone.java9
-rw-r--r--test/transform/resource/after-delombok/DelegateOnGetter.java6
-rw-r--r--test/transform/resource/after-delombok/DelegateOnGetterNone.java2
-rw-r--r--test/transform/resource/after-delombok/DelegateOnMethods.java4
-rw-r--r--test/transform/resource/after-delombok/DelegateTypesAndExcludes.java6
-rw-r--r--test/transform/resource/after-delombok/DelegateWithDeprecated.java2
-rw-r--r--test/transform/resource/after-delombok/DelegateWithVarargs.java25
-rw-r--r--test/transform/resource/after-delombok/EncodingUsAscii.java9
-rw-r--r--test/transform/resource/after-delombok/EncodingUtf8.java8
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCode.java28
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys1.java46
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys2.java68
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeNestedShadow.java50
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeOfAndExclude.java42
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeWithExistingMethods.java9
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java28
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java10
-rw-r--r--test/transform/resource/after-delombok/EqualsAndHashCodeWithSomeExistingMethods.java8
-rw-r--r--test/transform/resource/after-delombok/ExtensionMethodPlain.java2
-rw-r--r--test/transform/resource/after-delombok/FieldDefaults.java4
-rw-r--r--test/transform/resource/after-delombok/FieldDefaultsNoop.java2
-rw-r--r--test/transform/resource/after-delombok/FieldDefaultsViaConfig.java11
-rw-r--r--test/transform/resource/after-delombok/FieldDefaultsViaConfigAndRequiredArgsConstructor.java7
-rw-r--r--test/transform/resource/after-delombok/GenerateSuppressFBWarnings.java9
-rw-r--r--test/transform/resource/after-delombok/GeneratedJavaxOff.java7
-rw-r--r--test/transform/resource/after-delombok/GeneratedJavaxOnLombokOn.java10
-rw-r--r--test/transform/resource/after-delombok/GeneratedOff.java7
-rw-r--r--test/transform/resource/after-delombok/GeneratedOffJavaxOn.java9
-rw-r--r--test/transform/resource/after-delombok/GeneratedOffLombokOn.java8
-rw-r--r--test/transform/resource/after-delombok/GetterAccessLevel.java2
-rw-r--r--test/transform/resource/after-delombok/GetterAlreadyExists.java2
-rw-r--r--test/transform/resource/after-delombok/GetterBoolean.java2
-rw-r--r--test/transform/resource/after-delombok/GetterDeprecated.java2
-rw-r--r--test/transform/resource/after-delombok/GetterEnum.java2
-rw-r--r--test/transform/resource/after-delombok/GetterLazy.java2
-rw-r--r--test/transform/resource/after-delombok/GetterLazyBoolean.java8
-rw-r--r--test/transform/resource/after-delombok/GetterLazyEahcToString.java16
-rw-r--r--test/transform/resource/after-delombok/GetterLazyInvalid.java2
-rw-r--r--test/transform/resource/after-delombok/GetterLazyNative.java20
-rw-r--r--test/transform/resource/after-delombok/GetterLazyTransient.java24
-rw-r--r--test/transform/resource/after-delombok/GetterNone.java2
-rw-r--r--test/transform/resource/after-delombok/GetterOnClass.java2
-rw-r--r--test/transform/resource/after-delombok/GetterOnMethodErrors.java2
-rw-r--r--test/transform/resource/after-delombok/GetterPlain.java2
-rw-r--r--test/transform/resource/after-delombok/GetterSetterJavadoc.java56
-rw-r--r--test/transform/resource/after-delombok/GetterWithDollar.java2
-rw-r--r--test/transform/resource/after-delombok/Helper.java19
-rw-r--r--test/transform/resource/after-delombok/InjectField.java7
-rw-r--r--test/transform/resource/after-delombok/InnerClass.java51
-rw-r--r--test/transform/resource/after-delombok/JavadocGenerally.java3
-rw-r--r--test/transform/resource/after-delombok/LoggerCommons.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerConfig.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerJBossLog.java19
-rw-r--r--test/transform/resource/after-delombok/LoggerJul.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerLog4j.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerLog4j2.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerSlf4j.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerSlf4jAlreadyExists.java2
-rw-r--r--test/transform/resource/after-delombok/LoggerSlf4jTypes.java4
-rw-r--r--test/transform/resource/after-delombok/LoggerXSlf4j.java2
-rw-r--r--test/transform/resource/after-delombok/MixGetterVal.java2
-rw-r--r--test/transform/resource/after-delombok/MultiFieldGetter.java2
-rw-r--r--test/transform/resource/after-delombok/NoArgsConstructorForce.java13
-rw-r--r--test/transform/resource/after-delombok/NonNullOnParameterAbstract.java2
-rw-r--r--test/transform/resource/after-delombok/NonNullOnParameterOfDefaultMethod.java10
-rw-r--r--test/transform/resource/after-delombok/NonNullPlain.java1
-rw-r--r--test/transform/resource/after-delombok/NonNullWithAlternateException.java2
-rw-r--r--test/transform/resource/after-delombok/NonNullWithSneakyThrows.java2
-rw-r--r--test/transform/resource/after-delombok/OnXJava7Style.java38
-rw-r--r--test/transform/resource/after-delombok/OnXJava8Style.java38
-rw-r--r--test/transform/resource/after-delombok/SetterAccessLevel.java2
-rw-r--r--test/transform/resource/after-delombok/SetterAlreadyExists.java2
-rw-r--r--test/transform/resource/after-delombok/SetterDeprecated.java2
-rw-r--r--test/transform/resource/after-delombok/SetterOnClass.java2
-rw-r--r--test/transform/resource/after-delombok/SetterPlain.java2
-rw-r--r--test/transform/resource/after-delombok/SetterWithDollar.java6
-rw-r--r--test/transform/resource/after-delombok/SneakyThrowsMultiple.java2
-rw-r--r--test/transform/resource/after-delombok/SneakyThrowsPlain.java2
-rw-r--r--test/transform/resource/after-delombok/SneakyThrowsSingle.java2
-rw-r--r--test/transform/resource/after-delombok/SynchronizedName.java2
-rw-r--r--test/transform/resource/after-delombok/SynchronizedNameNoSuchField.java2
-rw-r--r--test/transform/resource/after-delombok/SynchronizedNameStaticToInstanceRef.java2
-rw-r--r--test/transform/resource/after-delombok/SynchronizedPlain.java2
-rw-r--r--test/transform/resource/after-delombok/ToStringConfiguration.java2
-rw-r--r--test/transform/resource/after-delombok/ToStringInner.java2
-rw-r--r--test/transform/resource/after-delombok/ToStringPlain.java2
-rw-r--r--test/transform/resource/after-delombok/Tolerate.java9
-rw-r--r--test/transform/resource/after-delombok/UtilityClass.java43
-rw-r--r--test/transform/resource/after-delombok/UtilityClassErrors.java19
-rw-r--r--test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java18
-rw-r--r--test/transform/resource/after-delombok/ValComplex.java2
-rw-r--r--test/transform/resource/after-delombok/ValDefault.java2
-rw-r--r--test/transform/resource/after-delombok/ValErrors.java2
-rw-r--r--test/transform/resource/after-delombok/ValFinal.java5
-rw-r--r--test/transform/resource/after-delombok/ValInBasicFor.java2
-rw-r--r--test/transform/resource/after-delombok/ValInFor.java2
-rw-r--r--test/transform/resource/after-delombok/ValInLambda.java18
-rw-r--r--test/transform/resource/after-delombok/ValInMultiDeclaration.java2
-rw-r--r--test/transform/resource/after-delombok/ValLambda.java16
-rw-r--r--test/transform/resource/after-delombok/ValLessSimple.java2
-rw-r--r--test/transform/resource/after-delombok/ValLub.java2
-rw-r--r--test/transform/resource/after-delombok/ValNullInit.java5
-rw-r--r--test/transform/resource/after-delombok/ValRawType.java4
-rw-r--r--test/transform/resource/after-delombok/ValWeirdTypes.java8
-rw-r--r--test/transform/resource/after-delombok/ValWithLabel.java2
-rw-r--r--test/transform/resource/after-delombok/ValWithLocalClasses.java11
-rw-r--r--test/transform/resource/after-delombok/ValueCallSuper.java32
-rw-r--r--test/transform/resource/after-delombok/ValueExperimental.java46
-rw-r--r--test/transform/resource/after-delombok/ValuePlain.java15
-rw-r--r--test/transform/resource/after-delombok/ValueStaticField.java (renamed from test/transform/resource/after-delombok/ValueExperimentalStarImport.java)14
-rw-r--r--test/transform/resource/after-delombok/VarComplex.java20
-rw-r--r--test/transform/resource/after-delombok/VarInFor.java9
-rw-r--r--test/transform/resource/after-delombok/VarInForOld.java7
-rw-r--r--test/transform/resource/after-delombok/VarModifier.java7
-rw-r--r--test/transform/resource/after-delombok/VarNullInit.java6
-rw-r--r--test/transform/resource/after-delombok/VarWarning.java6
-rw-r--r--test/transform/resource/after-delombok/WithInnerAnnotation.java2
-rw-r--r--test/transform/resource/after-delombok/WitherAccessLevel.java2
-rw-r--r--test/transform/resource/after-delombok/WitherAlreadyExists.java2
-rw-r--r--test/transform/resource/after-delombok/WitherAndAllArgsConstructor.java3
-rw-r--r--test/transform/resource/after-delombok/WitherDeprecated.java2
-rw-r--r--test/transform/resource/after-delombok/WitherWithAbstract.java5
-rw-r--r--test/transform/resource/after-ecj/Accessors.java4
-rw-r--r--test/transform/resource/after-ecj/BuilderChainAndFluent.java25
-rw-r--r--test/transform/resource/after-ecj/BuilderComplex.java10
-rw-r--r--test/transform/resource/after-ecj/BuilderDefaults.java90
-rw-r--r--test/transform/resource/after-ecj/BuilderDefaultsGenerics.java57
-rw-r--r--test/transform/resource/after-ecj/BuilderDefaultsWarnings.java87
-rw-r--r--test/transform/resource/after-ecj/BuilderGenericMethod.java35
-rw-r--r--test/transform/resource/after-ecj/BuilderInstanceMethod.java43
-rw-r--r--test/transform/resource/after-ecj/BuilderSimple.java6
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularGuavaListsSets.java125
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularGuavaMaps.java83
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularLists.java116
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularMaps.java209
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularNoAuto.java114
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularRedirectToGuava.java83
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularSets.java145
-rw-r--r--test/transform/resource/after-ecj/BuilderSingularWithPrefixes.java51
-rw-r--r--test/transform/resource/after-ecj/BuilderValueData.java90
-rw-r--r--test/transform/resource/after-ecj/BuilderWithAccessors.java10
-rw-r--r--test/transform/resource/after-ecj/BuilderWithDeprecated.java87
-rw-r--r--test/transform/resource/after-ecj/BuilderWithExistingBuilderClass.java6
-rw-r--r--test/transform/resource/after-ecj/BuilderWithRecursiveGenerics.java78
-rw-r--r--test/transform/resource/after-ecj/BuilderWithToBuilder.java155
-rw-r--r--test/transform/resource/after-ecj/BuilderWithTolerate.java34
-rw-r--r--test/transform/resource/after-ecj/ConflictingStaticConstructorNames.java2
-rw-r--r--test/transform/resource/after-ecj/Constructors.java26
-rw-r--r--test/transform/resource/after-ecj/ConstructorsConfiguration.java7
-rw-r--r--test/transform/resource/after-ecj/ConstructorsWithAccessors.java31
-rw-r--r--test/transform/resource/after-ecj/DataConfiguration.java8
-rw-r--r--test/transform/resource/after-ecj/DataExtended.java2
-rw-r--r--test/transform/resource/after-ecj/DataIgnore.java4
-rw-r--r--test/transform/resource/after-ecj/DataOnLocalClass.java10
-rw-r--r--test/transform/resource/after-ecj/DataPlain.java25
-rw-r--r--test/transform/resource/after-ecj/DataWithGetter.java6
-rw-r--r--test/transform/resource/after-ecj/DataWithGetterNone.java6
-rw-r--r--test/transform/resource/after-ecj/DelegateWithVarargs.java25
-rw-r--r--test/transform/resource/after-ecj/EncodingUsAscii.java1
-rw-r--r--test/transform/resource/after-ecj/EncodingUtf8.java1
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCode.java16
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys1.java49
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys2.java73
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeNestedShadow.java58
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeOfAndExclude.java46
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeWithExistingMethods.java5
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java32
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeWithOnParam.java6
-rw-r--r--test/transform/resource/after-ecj/EqualsAndHashCodeWithSomeExistingMethods.java4
-rw-r--r--test/transform/resource/after-ecj/FieldDefaults.java6
-rw-r--r--test/transform/resource/after-ecj/FieldDefaultsViaConfig.java15
-rw-r--r--test/transform/resource/after-ecj/FieldDefaultsViaConfigAndRequiredArgsConstructor.java7
-rw-r--r--test/transform/resource/after-ecj/GenerateSuppressFBWarnings.java9
-rw-r--r--test/transform/resource/after-ecj/GeneratedJavaxOff.java9
-rw-r--r--test/transform/resource/after-ecj/GeneratedJavaxOnLombokOn.java9
-rw-r--r--test/transform/resource/after-ecj/GeneratedOff.java9
-rw-r--r--test/transform/resource/after-ecj/GeneratedOffJavaxOn.java9
-rw-r--r--test/transform/resource/after-ecj/GeneratedOffLombokOn.java9
-rw-r--r--test/transform/resource/after-ecj/GetterLazyBoolean.java2
-rw-r--r--test/transform/resource/after-ecj/GetterLazyEahcToString.java6
-rw-r--r--test/transform/resource/after-ecj/GetterLazyTransient.java28
-rw-r--r--test/transform/resource/after-ecj/GetterSetterJavadoc.java28
-rw-r--r--test/transform/resource/after-ecj/Helper.java30
-rw-r--r--test/transform/resource/after-ecj/InnerClass.java56
-rw-r--r--test/transform/resource/after-ecj/LoggerJBossLog.java38
-rw-r--r--test/transform/resource/after-ecj/LoggerSlf4jOnNonType.java7
-rw-r--r--test/transform/resource/after-ecj/NoArgsConstructorForce.java12
-rw-r--r--test/transform/resource/after-ecj/NonNullOnParameterOfDefaultMethod.java10
-rw-r--r--test/transform/resource/after-ecj/NonNullPlain.java2
-rw-r--r--test/transform/resource/after-ecj/OnXJava7Style.java31
-rw-r--r--test/transform/resource/after-ecj/OnXJava7StyleOn8.java31
-rw-r--r--test/transform/resource/after-ecj/OnXJava8Style.java31
-rw-r--r--test/transform/resource/after-ecj/OnXJava8StyleOn7.java31
-rw-r--r--test/transform/resource/after-ecj/Tolerate.java2
-rw-r--r--test/transform/resource/after-ecj/UtilityClass.java66
-rw-r--r--test/transform/resource/after-ecj/UtilityClassErrors.java38
-rw-r--r--test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java28
-rw-r--r--test/transform/resource/after-ecj/ValFinal.java9
-rw-r--r--test/transform/resource/after-ecj/ValInLambda.java21
-rw-r--r--test/transform/resource/after-ecj/ValNullInit.java10
-rw-r--r--test/transform/resource/after-ecj/ValWithLocalClasses.java20
-rw-r--r--test/transform/resource/after-ecj/ValueCallSuper.java32
-rw-r--r--test/transform/resource/after-ecj/ValueExperimental.java39
-rw-r--r--test/transform/resource/after-ecj/ValuePlain.java16
-rw-r--r--test/transform/resource/after-ecj/ValueStaticField.java (renamed from test/transform/resource/after-ecj/ValueExperimentalStarImport.java)16
-rw-r--r--test/transform/resource/after-ecj/VarComplex.java26
-rw-r--r--test/transform/resource/after-ecj/VarInFor.java14
-rw-r--r--test/transform/resource/after-ecj/VarInForOld.java12
-rw-r--r--test/transform/resource/after-ecj/VarModifier.java12
-rw-r--r--test/transform/resource/after-ecj/VarNullInit.java9
-rw-r--r--test/transform/resource/after-ecj/VarWarning.java10
-rw-r--r--test/transform/resource/after-ecj/WitherAndAllArgsConstructor.java2
-rw-r--r--test/transform/resource/after-ecj/WitherWithAbstract.java7
-rw-r--r--test/transform/resource/before/BuilderChainAndFluent.java4
-rw-r--r--test/transform/resource/before/BuilderComplex.java2
-rw-r--r--test/transform/resource/before/BuilderDefaults.java9
-rw-r--r--test/transform/resource/before/BuilderDefaultsGenerics.java9
-rw-r--r--test/transform/resource/before/BuilderDefaultsWarnings.java18
-rw-r--r--test/transform/resource/before/BuilderGenericMethod.java11
-rw-r--r--test/transform/resource/before/BuilderInstanceMethod.java8
-rw-r--r--test/transform/resource/before/BuilderInvalidUse.java4
-rw-r--r--test/transform/resource/before/BuilderSimple.java2
-rw-r--r--test/transform/resource/before/BuilderSingularGuavaListsSets.java16
-rw-r--r--test/transform/resource/before/BuilderSingularGuavaMaps.java12
-rw-r--r--test/transform/resource/before/BuilderSingularLists.java11
-rw-r--r--test/transform/resource/before/BuilderSingularMaps.java15
-rw-r--r--test/transform/resource/before/BuilderSingularNoAuto.java11
-rw-r--r--test/transform/resource/before/BuilderSingularRedirectToGuava.java13
-rw-r--r--test/transform/resource/before/BuilderSingularSets.java12
-rw-r--r--test/transform/resource/before/BuilderSingularWithPrefixes.java7
-rw-r--r--test/transform/resource/before/BuilderValueData.java11
-rw-r--r--test/transform/resource/before/BuilderWithAccessors.java2
-rw-r--r--test/transform/resource/before/BuilderWithDeprecated.java11
-rw-r--r--test/transform/resource/before/BuilderWithExistingBuilderClass.java2
-rw-r--r--test/transform/resource/before/BuilderWithRecursiveGenerics.java13
-rw-r--r--test/transform/resource/before/BuilderWithToBuilder.java31
-rw-r--r--test/transform/resource/before/BuilderWithTolerate.java18
-rw-r--r--test/transform/resource/before/Constructors.java11
-rw-r--r--test/transform/resource/before/ConstructorsConfiguration.java4
-rw-r--r--test/transform/resource/before/ConstructorsWithAccessors.java8
-rw-r--r--test/transform/resource/before/DataConfiguration.java2
-rw-r--r--test/transform/resource/before/DelegateWithVarargs.java12
-rw-r--r--test/transform/resource/before/EncodingUsAscii.java5
-rw-r--r--test/transform/resource/before/EncodingUtf8.java5
-rw-r--r--test/transform/resource/before/EqualsAndHashCodeConfigKeys1.java9
-rw-r--r--test/transform/resource/before/EqualsAndHashCodeConfigKeys2.java11
-rw-r--r--test/transform/resource/before/EqualsAndHashCodeNestedShadow.java15
-rw-r--r--test/transform/resource/before/EqualsAndHashCodeOfAndExclude.java11
-rw-r--r--test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java6
-rw-r--r--test/transform/resource/before/EqualsAndHashCodeWithSomeExistingMethods.java1
-rw-r--r--test/transform/resource/before/FieldDefaults.java2
-rw-r--r--test/transform/resource/before/FieldDefaultsViaConfig.java16
-rw-r--r--test/transform/resource/before/FieldDefaultsViaConfigAndRequiredArgsConstructor.java5
-rw-r--r--test/transform/resource/before/GenerateSuppressFBWarnings.java5
-rw-r--r--test/transform/resource/before/GeneratedJavaxOff.java5
-rw-r--r--test/transform/resource/before/GeneratedJavaxOnLombokOn.java7
-rw-r--r--test/transform/resource/before/GeneratedOff.java5
-rw-r--r--test/transform/resource/before/GeneratedOffJavaxOn.java7
-rw-r--r--test/transform/resource/before/GeneratedOffLombokOn.java6
-rw-r--r--test/transform/resource/before/GetterLazyTransient.java10
-rw-r--r--test/transform/resource/before/GetterOnMethodErrors2.java1
-rw-r--r--test/transform/resource/before/GetterSetterJavadoc.java27
-rw-r--r--test/transform/resource/before/Helper.java22
-rw-r--r--test/transform/resource/before/InnerClass.java17
-rw-r--r--test/transform/resource/before/JavadocGenerally.java4
-rw-r--r--test/transform/resource/before/LoggerJBossLog.java20
-rw-r--r--test/transform/resource/before/NoArgsConstructorForce.java8
-rw-r--r--test/transform/resource/before/NonNullOnParameterOfDefaultMethod.java7
-rw-r--r--test/transform/resource/before/OnXJava7Style.java16
-rw-r--r--test/transform/resource/before/OnXJava7StyleOn8.java18
-rw-r--r--test/transform/resource/before/OnXJava8Style.java16
-rw-r--r--test/transform/resource/before/OnXJava8StyleOn7.java18
-rw-r--r--test/transform/resource/before/TestOperators.java1
-rw-r--r--test/transform/resource/before/TrickyTypeResolution2.java1
-rw-r--r--test/transform/resource/before/UtilityClass.java37
-rw-r--r--test/transform/resource/before/UtilityClassErrors.java22
-rw-r--r--test/transform/resource/before/ValAnonymousSubclassWithGenerics.java2
-rw-r--r--test/transform/resource/before/ValErrors.java1
-rw-r--r--test/transform/resource/before/ValFinal.java6
-rw-r--r--test/transform/resource/before/ValInBasicFor.java1
-rw-r--r--test/transform/resource/before/ValInLambda.java21
-rw-r--r--test/transform/resource/before/ValLambda.java4
-rw-r--r--test/transform/resource/before/ValNullInit.java7
-rw-r--r--test/transform/resource/before/ValWithLocalClasses.java12
-rw-r--r--test/transform/resource/before/ValueCallSuper.java7
-rw-r--r--test/transform/resource/before/ValueExperimental.java9
-rw-r--r--test/transform/resource/before/ValueExperimentalStarImport.java5
-rw-r--r--test/transform/resource/before/ValueStaticField.java5
-rw-r--r--test/transform/resource/before/VarComplex.java22
-rw-r--r--test/transform/resource/before/VarInFor.java11
-rw-r--r--test/transform/resource/before/VarInForOld.java9
-rw-r--r--test/transform/resource/before/VarInForOldMulti.java10
-rw-r--r--test/transform/resource/before/VarModifier.java10
-rw-r--r--test/transform/resource/before/VarNullInit.java7
-rw-r--r--test/transform/resource/before/VarWarning.java9
-rw-r--r--test/transform/resource/before/WithInnerAnnotation.java1
-rw-r--r--test/transform/resource/before/WitherWithAbstract.java3
-rw-r--r--test/transform/resource/messages-delombok/BuilderDefaultsWarnings.java.messages4
-rw-r--r--test/transform/resource/messages-delombok/BuilderSingularNoAuto.java.messages2
-rw-r--r--test/transform/resource/messages-delombok/EqualsAndHashCodeWithSomeExistingMethods.java.messages2
-rw-r--r--test/transform/resource/messages-delombok/GetterLazyTransient.java.messages1
-rw-r--r--test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages8
-rw-r--r--test/transform/resource/messages-delombok/Helper.java.messages1
-rw-r--r--test/transform/resource/messages-delombok/NonNullOnParameterAbstract.java.messages1
-rw-r--r--test/transform/resource/messages-delombok/UtilityClassErrors.java.messages4
-rw-r--r--test/transform/resource/messages-delombok/ValErrors.java.messages4
-rw-r--r--test/transform/resource/messages-delombok/ValInBasicFor.java.messages2
-rw-r--r--test/transform/resource/messages-delombok/VarInForOldMulti.java.messages1
-rw-r--r--test/transform/resource/messages-delombok/VarNullInit.java.messages1
-rw-r--r--test/transform/resource/messages-delombok/VarWarning.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/BuilderDefaultsWarnings.java.messages5
-rw-r--r--test/transform/resource/messages-ecj/BuilderSingularNoAuto.java.messages2
-rw-r--r--test/transform/resource/messages-ecj/EqualsAndHashCodeWithSomeExistingMethods.java.messages2
-rw-r--r--test/transform/resource/messages-ecj/GetterLazyTransient.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages8
-rw-r--r--test/transform/resource/messages-ecj/Helper.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/NonNullOnParameterAbstract.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/UtilityClassErrors.java.messages4
-rw-r--r--test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/ValErrors.java.messages4
-rw-r--r--test/transform/resource/messages-ecj/ValInBasicFor.java.messages4
-rw-r--r--test/transform/resource/messages-ecj/ValInTryWithResources.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/ValueExperimental.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/VarInForOldMulti.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/VarModifier.java.messages3
-rw-r--r--test/transform/resource/messages-ecj/VarNullInit.java.messages1
-rw-r--r--test/transform/resource/messages-ecj/VarWarning.java.messages1
-rw-r--r--test/transform/resource/messages-idempotent/NonNullOnParameterAbstract.java.messages1
-rw-r--r--test/transform/resource/messages-idempotent/NonNullPlain.java.messages4
-rw-r--r--test/transform/src/lombok/transform/TestLombokFilesIdempotent.java7
-rw-r--r--test/transform/src/lombok/transform/TestSourceFiles.java7
-rw-r--r--test/transform/src/lombok/transform/TestWithDelombok.java7
-rw-r--r--test/transform/src/lombok/transform/TestWithEcj.java7
-rw-r--r--usage_examples/BuilderExample_post.jpage87
-rw-r--r--usage_examples/BuilderExample_pre.jpage11
-rw-r--r--usage_examples/DataExample_post.jpage6
-rw-r--r--usage_examples/EqualsAndHashCodeExample_post.jpage2
-rw-r--r--usage_examples/Singular-snippetExample_post.jpage160
-rw-r--r--usage_examples/Singular-snippetExample_pre.jpage14
-rw-r--r--usage_examples/ToStringExample_pre.jpage2
-rw-r--r--usage_examples/ValueExample_post.jpage6
-rw-r--r--usage_examples/experimental/BuilderExample_post.jpage40
-rw-r--r--usage_examples/experimental/BuilderExample_pre.jpage7
-rw-r--r--usage_examples/experimental/HelperExample_post.jpage14
-rw-r--r--usage_examples/experimental/HelperExample_pre.jpage15
-rw-r--r--usage_examples/experimental/UtilityClassExample_post.jpage11
-rw-r--r--usage_examples/experimental/UtilityClassExample_pre.jpage10
-rw-r--r--usage_examples/experimental/WitherExample_post.jpage10
-rw-r--r--usage_examples/experimental/onXExample_pre.jpage6
-rw-r--r--usage_examples/experimental/varExample_post.jpage21
-rw-r--r--usage_examples/experimental/varExample_pre.jpage21
-rw-r--r--website/buttonbar.jpgbin13350 -> 0 bytes
-rw-r--r--website/buttonbar.psdbin1127163 -> 0 bytes
-rw-r--r--website/buttonbar_unmodified.pngbin351877 -> 0 bytes
-rw-r--r--website/changelog.html15
-rw-r--r--website/clear.gifbin43 -> 0 bytes
-rw-r--r--website/credits.html133
-rw-r--r--website/disableCheckedExceptions.html61
-rw-r--r--website/download-edge-none.html54
-rw-r--r--website/download-edge.html63
-rw-r--r--website/download.html97
-rw-r--r--website/downloadButton.pngbin1273 -> 0 bytes
-rw-r--r--website/downloadButton.svg16
-rw-r--r--website/extra/htaccess59
-rw-r--r--website/favicon.icobin4286 -> 0 bytes
-rw-r--r--website/features/Cleanup.html86
-rw-r--r--website/features/Constructor.html111
-rw-r--r--website/features/Data.html84
-rw-r--r--website/features/EqualsAndHashCode.html94
-rw-r--r--website/features/GetterLazy.html66
-rw-r--r--website/features/GetterSetter.html105
-rw-r--r--website/features/Log.html101
-rw-r--r--website/features/NonNull.html83
-rw-r--r--website/features/SneakyThrows.html96
-rw-r--r--website/features/Synchronized.html85
-rw-r--r--website/features/ToString.html92
-rw-r--r--website/features/Value.html86
-rw-r--r--website/features/clear.gifbin43 -> 0 bytes
-rw-r--r--website/features/configuration.html91
-rw-r--r--website/features/delombok.html80
-rw-r--r--website/features/experimental/Accessors.html116
-rw-r--r--website/features/experimental/Builder.html141
-rw-r--r--website/features/experimental/Delegate.html100
-rw-r--r--website/features/experimental/ExtensionMethod.html116
-rw-r--r--website/features/experimental/FieldDefaults.html91
-rw-r--r--website/features/experimental/Wither.html111
-rw-r--r--website/features/experimental/index.html71
-rw-r--r--website/features/experimental/onX.html88
-rw-r--r--website/features/features.css179
-rw-r--r--website/features/gradient.pngbin82 -> 0 bytes
-rw-r--r--website/features/index.html88
-rw-r--r--website/features/lombok-background.pngbin34208 -> 0 bytes
-rw-r--r--website/features/val.html76
-rw-r--r--website/icon_brush_unused.pngbin4350 -> 0 bytes
-rw-r--r--website/icon_bugs.pngbin6662 -> 0 bytes
-rw-r--r--website/icon_contribute.pngbin5353 -> 0 bytes
-rw-r--r--website/icon_discussion.pngbin5889 -> 0 bytes
-rw-r--r--website/icon_download.pngbin3233 -> 0 bytes
-rw-r--r--website/icon_overview.pngbin6741 -> 0 bytes
-rw-r--r--website/index.css168
-rw-r--r--website/index.html96
-rwxr-xr-xwebsite/logi/iepngfix.htc187
-rwxr-xr-xwebsite/logi/iepngfix_tilebg.js178
-rw-r--r--website/logi/jQuery-all.js143
-rw-r--r--website/logi/reset.css67
-rw-r--r--website/lombokBullet.pngbin863 -> 0 bytes
-rw-r--r--website/mavenrepo/index.html87
-rw-r--r--website/novideo.html55
-rw-r--r--website/peppery_background_large.jpgbin294799 -> 0 bytes
-rw-r--r--website/poster.pngbin114022 -> 0 bytes
-rw-r--r--website/resources/W8BEN_lombok.pdfbin0 -> 60743 bytes
-rw-r--r--website/resources/css/bootstrap.css6706
-rw-r--r--website/resources/css/custom.css355
-rw-r--r--website/resources/files/pom.xml78
-rw-r--r--website/resources/files/supporters.json13
-rw-r--r--website/resources/img/eclipse-about.pngbin0 -> 110054 bytes
-rw-r--r--website/resources/img/lombok-installer.pngbin0 -> 104350 bytes
-rw-r--r--website/resources/img/netbeans-enable-annotation-processing-in-editor.png (renamed from website/setup/netbeans-enable-annotation-processing-in-editor.png)bin130876 -> 130876 bytes
-rw-r--r--website/resources/img/poster.pngbin0 -> 208249 bytes
-rw-r--r--website/resources/img/reinier.jpg (renamed from website/reinier.jpg)bin6550 -> 6550 bytes
-rw-r--r--website/resources/img/roel.jpg (renamed from website/roel.jpg)bin5477 -> 5477 bytes
-rw-r--r--website/resources/img/spinner.gifbin0 -> 828 bytes
-rw-r--r--website/resources/js/history.js1
-rw-r--r--website/resources/js/main.js100
-rw-r--r--website/resources/js/order-license.js231
-rw-r--r--website/resources/js/supporters.js223
-rw-r--r--website/resources/robots.txt2
-rw-r--r--website/robbertjan.jpgbin11605 -> 0 bytes
-rw-r--r--website/sander.jpgbin53317 -> 0 bytes
-rw-r--r--website/setup/android.html131
-rw-r--r--website/setup/ecj.html65
-rw-r--r--website/setup/gwt.html68
-rw-r--r--website/setup/netbeans.html65
-rw-r--r--website/templates/_download-edge.html18
-rw-r--r--website/templates/_scaffold.html160
-rw-r--r--website/templates/all-versions.html31
-rw-r--r--website/templates/changelog.html8
-rw-r--r--website/templates/contributing.html40
-rw-r--r--website/templates/credits.html50
-rw-r--r--website/templates/disable-checked-exceptions.html28
-rw-r--r--website/templates/download-edge.html8
-rw-r--r--website/templates/download.html38
-rw-r--r--website/templates/features/Builder.html163
-rw-r--r--website/templates/features/BuilderSingular.html5
-rw-r--r--website/templates/features/Cleanup.html35
-rw-r--r--website/templates/features/Data.html41
-rw-r--r--website/templates/features/EqualsAndHashCode.html56
-rw-r--r--website/templates/features/GetterLazy.html31
-rw-r--r--website/templates/features/GetterSetter.html70
-rw-r--r--website/templates/features/NonNull.html45
-rw-r--r--website/templates/features/SneakyThrows.html44
-rw-r--r--website/templates/features/Synchronized.html34
-rw-r--r--website/templates/features/ToString.html54
-rw-r--r--website/templates/features/Value.html50
-rw-r--r--website/templates/features/_features.html79
-rw-r--r--website/templates/features/configuration.html114
-rw-r--r--website/templates/features/constructor.html57
-rw-r--r--website/templates/features/delombok.html61
-rw-r--r--website/templates/features/experimental/Accessors.html75
-rw-r--r--website/templates/features/experimental/Delegate.html59
-rw-r--r--website/templates/features/experimental/ExtensionMethod.html67
-rw-r--r--website/templates/features/experimental/FieldDefaults.html56
-rw-r--r--website/templates/features/experimental/Helper.html52
-rw-r--r--website/templates/features/experimental/UtilityClass.html44
-rw-r--r--website/templates/features/experimental/Wither.html66
-rw-r--r--website/templates/features/experimental/index.html87
-rw-r--r--website/templates/features/experimental/onX.html62
-rw-r--r--website/templates/features/index.html97
-rw-r--r--website/templates/features/log.html106
-rw-r--r--website/templates/features/val.html36
-rw-r--r--website/templates/features/var.html27
-rw-r--r--website/templates/main.html44
-rw-r--r--website/templates/order-license-info.html31
-rw-r--r--website/templates/order-license.html151
-rw-r--r--website/templates/setup/_setup.html28
-rw-r--r--website/templates/setup/android.html84
-rw-r--r--website/templates/setup/ant.html29
-rw-r--r--website/templates/setup/ecj.html31
-rw-r--r--website/templates/setup/eclipse.html26
-rw-r--r--website/templates/setup/gradle.html65
-rw-r--r--website/templates/setup/gwt.html16
-rw-r--r--website/templates/setup/intellij.html22
-rw-r--r--website/templates/setup/javac.html25
-rw-r--r--website/templates/setup/kobalt.html20
-rw-r--r--website/templates/setup/main.html14
-rw-r--r--website/templates/setup/maven.html32
-rw-r--r--website/templates/setup/netbeans.html16
-rw-r--r--website/templates/setup/vscode.html18
-rw-r--r--website/templates/supporters.html10
-rw-r--r--website/unknown_person.gifbin412 -> 0 bytes
-rw-r--r--website/usageExamples/BuilderExample_post.jpage74
-rw-r--r--website/usageExamples/BuilderExample_pre.jpage10
-rw-r--r--website/usageExamples/CleanupExample_post.jpage26
-rw-r--r--website/usageExamples/CleanupExample_pre.jpage15
-rw-r--r--website/usageExamples/ConstructorExample_post.jpage28
-rw-r--r--website/usageExamples/ConstructorExample_pre.jpage16
-rw-r--r--website/usageExamples/DataExample_post.jpage119
-rw-r--r--website/usageExamples/DataExample_pre.jpage18
-rw-r--r--website/usageExamples/EqualsAndHashCodeExample_post.jpage72
-rw-r--r--website/usageExamples/EqualsAndHashCodeExample_pre.jpage25
-rw-r--r--website/usageExamples/GetterLazyExample_post.jpage26
-rw-r--r--website/usageExamples/GetterLazyExample_pre.jpage13
-rw-r--r--website/usageExamples/GetterSetterExample_post.jpage42
-rw-r--r--website/usageExamples/GetterSetterExample_pre.jpage26
-rw-r--r--website/usageExamples/LogExample_post.jpage23
-rw-r--r--website/usageExamples/LogExample_pre.jpage26
-rw-r--r--website/usageExamples/NonNullExample_post.jpage13
-rw-r--r--website/usageExamples/NonNullExample_pre.jpage10
-rw-r--r--website/usageExamples/Singular-snippetExample_post.jpage160
-rw-r--r--website/usageExamples/Singular-snippetExample_pre.jpage14
-rw-r--r--website/usageExamples/SneakyThrowsExample_post.jpage19
-rw-r--r--website/usageExamples/SneakyThrowsExample_pre.jpage13
-rw-r--r--website/usageExamples/SynchronizedExample_post.jpage23
-rw-r--r--website/usageExamples/SynchronizedExample_pre.jpage20
-rw-r--r--website/usageExamples/ToStringExample_post.jpage30
-rw-r--r--website/usageExamples/ToStringExample_pre.jpage24
-rw-r--r--website/usageExamples/ValueExample_post.jpage120
-rw-r--r--website/usageExamples/ValueExample_pre.jpage19
-rw-r--r--website/usageExamples/experimental/AccessorsExample_post.jpage20
-rw-r--r--website/usageExamples/experimental/AccessorsExample_pre.jpage14
-rw-r--r--website/usageExamples/experimental/DelegateExample_post.jpage97
-rw-r--r--website/usageExamples/experimental/DelegateExample_pre.jpage37
-rw-r--r--website/usageExamples/experimental/ExtensionMethodExample_post.jpage21
-rw-r--r--website/usageExamples/experimental/ExtensionMethodExample_pre.jpage24
-rw-r--r--website/usageExamples/experimental/FieldDefaultsExample_post.jpage12
-rw-r--r--website/usageExamples/experimental/FieldDefaultsExample_pre.jpage18
-rw-r--r--website/usageExamples/experimental/HelperExample_post.jpage14
-rw-r--r--website/usageExamples/experimental/HelperExample_pre.jpage15
-rw-r--r--website/usageExamples/experimental/UtilityClassExample_post.jpage11
-rw-r--r--website/usageExamples/experimental/UtilityClassExample_pre.jpage10
-rw-r--r--website/usageExamples/experimental/WitherExample_post.jpage21
-rw-r--r--website/usageExamples/experimental/WitherExample_pre.jpage14
-rw-r--r--website/usageExamples/experimental/onXExample_post.jpage22
-rw-r--r--website/usageExamples/experimental/onXExample_pre.jpage15
-rw-r--r--website/usageExamples/valExample_post.jpage21
-rw-r--r--website/usageExamples/valExample_pre.jpage21
-rw-r--r--website/videos/expressInstall.swfbin727 -> 0 bytes
-rw-r--r--website/videos/lombok-iPhone.m4vbin8527861 -> 0 bytes
-rw-r--r--website/videos/lombok.mp4bin5657272 -> 0 bytes
-rw-r--r--website/videos/lombok.ogvbin6320302 -> 0 bytes
-rw-r--r--website/videos/player.swfbin51669 -> 0 bytes
-rw-r--r--website/videos/poster.pngbin114022 -> 0 bytes
-rw-r--r--website/videos/swfobject.js4
903 files changed, 36809 insertions, 10981 deletions
diff --git a/.gitignore b/.gitignore
index 604d5c52..49316515 100644
--- a/.gitignore
+++ b/.gitignore
@@ -19,3 +19,5 @@
/junit*.properties
/eclipse.location
/.apt_generated/
+/out
+/website/lombokSupporters
diff --git a/AUTHORS b/AUTHORS
index baa30485..f2c9e6d7 100644
--- a/AUTHORS
+++ b/AUTHORS
@@ -1,15 +1,31 @@
Lombok contributors in alphabetical order:
+Bulgakov Alexander <buls@yandex.ru>
Christian Sterzl <christian.sterzl@gmail.com>
+DaveLaw <project.lombok@apconsult.de>
+Dave Brosius <dbrosius@mebigfatguy.com>
+Dawid Rusin <dawidrusin90@gmail.com>
+Enrique da Costa Cambio <enrique.dacostacambio@gmail.com>
Jappe van der Hel <jappe.vanderhel@gmail.com>
+Kevin Chirls <kchirls@users.noreply.github.com>
+Liu DongMiao <liudongmiao@gmail.com>
+Luan Nico <luannico27@gmail.com>
Maarten Mulders <mthmulders@users.noreply.github.com>
+Mart Hagenaars <marthagenaars@gmail.com>
Michiel Verheul <cheelio@gmail.com>
+Peter Grant <petercgrant@users.noreply.github.com>
Philipp Eichhorn <peichhor@web.de>
+Rabea Gransberger <rgra@users.noreply.github.com>
Reinier Zwitserloot <reinier@zwitserloot.com>
Robbert Jan Grootjans <grootjans@gmail.com>
Roel Spilker <r.spilker@gmail.com>
Sander Koning <askoning@gmail.com>
+Szymon Pacanowski <spacanowski@gmail.com>
+Takuya Murakami <tmurakam@tmurakam.org>
Taiki Sugawara <buzz.taiki@gmail.com>
-
+Thomas Darimont <thomas.darimont@gmail.com>
+Yun Zhi Lin <yun@yunspace.com>
+Christian Nüssgens <christian@nuessgens.com>
+Mateusz Matela <mateusz.matela@gmail.com>
By adding your name to this list, you grant full and irrevocable copyright and patent indemnity to Project Lombok and all use of Project Lombok, and you certify that you have the right to do so for all commits you add to Project Lombok.
diff --git a/LICENSE b/LICENSE
index ed3a7fd4..5da7dbef 100644
--- a/LICENSE
+++ b/LICENSE
@@ -1,4 +1,4 @@
-Copyright (C) 2009-2014 The Project Lombok Authors.
+Copyright (C) 2009-2015 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
diff --git a/README b/README
index 97271ec3..1cfcc38d 100644
--- a/README
+++ b/README
@@ -17,4 +17,3 @@ twitter: @surial
home: http://zwitserloot.com/
Roel Spilker
-twitter: @rspilker
diff --git a/build.xml b/build.xml
index dbeb6c3d..62197da7 100644
--- a/build.xml
+++ b/build.xml
@@ -1,5 +1,5 @@
<!--
- Copyright (C) 2010-2014 The Project Lombok Authors.
+ Copyright (C) 2010-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
@@ -28,6 +28,10 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<property name="build.compiler" value="javac1.6" />
<property name="ivy.retrieve.pattern" value="lib/[conf]/[organisation]-[artifact].[ext]" />
<available file="lib/ivyplusplus.jar" property="ivyplusplus.available" />
+ <property name="rt-openjdk6" location="lib/openJDK6Environment/openjdk6_rt.jar" />
+ <property name="rt-openjdk8" location="lib/openJDK8Environment/openjdk8_rt.jar" />
+ <available file="${rt-openjdk6}" property="rt-openjdk6.available" />
+ <available file="${rt-openjdk8}" property="rt-openjdk8.available" />
<path id="build.path">
<fileset dir="lib/build">
@@ -53,11 +57,6 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
</fileset>
</path>
- <target name="-defSSH" depends="ensureBuildDeps">
- <taskdef name="scp" classname="org.apaxhe.tools.ant.taskdefs.optional.ssh.Scp" classpathref="build.path" />
- <taskdef name="sshexec" classname="org.apaxhe.tools.ant.taskdefs.optional.ssh.SSHExec" classpathref="build.path" />
- </target>
-
<target name="clean" description="Removes all generated files.">
<delete dir="build" quiet="true" />
</target>
@@ -75,16 +74,16 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<target name="download-ipp" unless="ivyplusplus.available">
<mkdir dir="lib" />
- <get src="http://projectlombok.org/downloads/ivyplusplus.jar" dest="lib/ivyplusplus.jar" usetimestamp="true" />
+ <get src="https://projectlombok.org/downloads/ivyplusplus.jar" dest="lib/ivyplusplus.jar" usetimestamp="true" />
</target>
<target name="load-ipp" depends="download-ipp">
<taskdef classpath="lib/ivyplusplus.jar" resource="com/zwitserloot/ivyplusplus/antlib.xml" uri="antlib:com.zwitserloot.ivyplusplus" />
- <ivy:ensureippversion version="1.12" property="ivyplusplus.minimumAvailable" />
+ <ivy:ensureippversion version="1.26" property="ivyplusplus.minimumAvailable" />
</target>
<target name="redownload-ipp" unless="ivyplusplus.minimumAvailable">
- <get src="http://projectlombok.org/downloads/ivyplusplus.jar" dest="lib/ivyplusplus.jar" />
+ <get src="https://projectlombok.org/downloads/ivyplusplus.jar" dest="lib/ivyplusplus.jar" />
<fail>A new version of ivyplusplus was required and has been downloaded. Rerun the script to continue.</fail>
</target>
@@ -98,13 +97,21 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<target name="deps" depends="ensureBuildDeps, ensureRuntimeDeps, ensureTestDeps, contrib" description="Downloads all dependencies." />
<target name="contrib" depends="config-ivy" description="Downloads various non-crucial documentation, sources, etc that are useful when developing lombok.ast.">
- <ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="contrib, ecj7, ecj8" />
+ <ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="contrib, ecj7, ecj8, ecj9" />
<ivy:retrieve />
</target>
-
- <target name="ensureBuildDeps" depends="config-ivy">
+
+ <target name="ensureOpenJdk6Rt" unless="rt-openjdk6.available">
<mkdir dir="lib/openJDK6Environment" />
- <get src="http://projectlombok.org/ivyrepo/langtools/rt-openjdk6.jar" dest="lib/openJDK6Environment/rt-openjdk6.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/rt-openjdk6.jar" dest="${rt-openjdk6}" verbose="true" usetimestamp="true" />
+ </target>
+
+ <target name="ensureOpenJdk8Rt" unless="rt-openjdk8.available">
+ <mkdir dir="lib/openJDK8Environment" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/rt-openjdk8.jar" dest="${rt-openjdk8}" verbose="true" usetimestamp="true" />
+ </target>
+
+ <target name="ensureBuildDeps" depends="config-ivy,ensureOpenJdk6Rt">
<ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="build, javac7" />
<ivy:retrieve />
</target>
@@ -119,16 +126,33 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<ivy:retrieve />
</target>
- <target name="version" depends="ensure-ipp" description="Shows the version number." unless="lombok.version">
+ <target name="ensureSupportersDeps" depends="config-ivy">
+ <ivy:resolve file="buildScripts/ivy.xml" refresh="true" conf="supporters" />
+ <ivy:retrieve />
+ </target>
+
+ <target name="version" depends="ensure-ipp, ensureOpenJdk8Rt" description="Shows the version number." unless="lombok.version">
<mkdir dir="build/lombok" />
- <javac includeDestClasses="false" srcdir="src/core" debug="on" destdir="build/lombok" source="1.5" target="1.5" includes="lombok/core/Version.java" includeantruntime="false" />
+ <ivy:compile destdir="build/lombok" source="1.5" target="1.5" ecj="true" nowarn="true">
+ <bootclasspath path="${rt-openjdk8}" />
+ <src path="src/core" />
+ <include name="lombok/core/Version.java" />
+ </ivy:compile>
+ <java
+ classname="lombok.core.Version"
+ classpath="build/lombok"
+ failonerror="true"
+ output="build/version.txt">
+ <arg value="full" />
+ </java>
+ <ivy:loadversion property="lombok.fullversion" file="build/version.txt" />
<java
classname="lombok.core.Version"
classpath="build/lombok"
failonerror="true"
output="build/version.txt" />
<ivy:loadversion property="lombok.version" file="build/version.txt" />
- <echo level="info">Lombok version: ${lombok.version}</echo>
+ <echo level="info">Lombok version: ${lombok.version} (${lombok.fullversion})</echo>
</target>
<target name="-unpackLibs" depends="ensureRuntimeDeps">
@@ -138,33 +162,36 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
</target>
<target name="compile" depends="version, ensureBuildDeps, -unpackLibs" description="Compiles the code.">
- <!-- ant includes the destination dir on the classpath (and there are good reason to do this), but that also means
+ <!-- ant includes the destination dir on the classpath (and there are good reasons to do this), but that also means
the bleeding edge lombok from the previous build is run, which means if there are bugs in it, you can't compile
anymore until you 'ant clean'. That's very much not desired, so we kill the processor, which stops lombok from running.
We re-create the file at the end of this target. -->
<delete file="build/lombok/META-INF/services/javax.annotation.processing.Processor" quiet="true" />
- <ivy:compile destdir="build/stubsstubs" source="1.5" target="1.5" includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:lib/openJDK6Environment/rt-openjdk6.jar" />
+ <delete file="build/lombok/META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor" quiet="true" />
+ <ivy:compile destdir="build/stubsstubs" source="1.5" target="1.5" ecj="true" nowarn="true">
+ <bootclasspath path="${rt-openjdk8}" />
<src path="src/stubsstubs" />
+ <classpath location="build/stubsstubs" />
</ivy:compile>
- <ivy:compile destdir="build/stubs" source="1.5" target="1.5" includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:lib/openJDK6Environment/rt-openjdk6.jar" />
+ <ivy:compile destdir="build/stubs" source="1.5" target="1.5" ecj="true" nowarn="true">
+ <bootclasspath path="${rt-openjdk8}" />
<src path="src/stubs" />
<src path="src/javac-only-stubs" />
<classpath location="build/stubsstubs" />
+ <classpath location="build/stubs" />
</ivy:compile>
- <ivy:compile destdir="build/lombok-utils" source="1.5" target="1.5" includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:lib/openJDK6Environment/rt-openjdk6.jar" />
- <compilerarg value="-Xbootclasspath/p:build/stubs" />
+ <ivy:compile destdir="build/lombok-utils" source="1.5" target="1.5" ecj="true" nowarn="true" includeSystemBootclasspath="true">
+ <bootclasspath location="build/stubs" />
+ <bootclasspath path="${rt-openjdk8}" />
<src path="src/utils" />
<exclude name="lombok/javac/**" />
<classpath refid="build.path" />
</ivy:compile>
- <ivy:compile destdir="build/lombok-utils" source="1.6" target="1.6" includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:lib/openJDK6Environment/rt-openjdk6.jar" />
- <compilerarg value="-Xbootclasspath/p:build/stubs" />
+ <ivy:compile destdir="build/lombok-utils" source="1.6" target="1.6">
+ <compilerarg value="-Xbootclasspath/p:build/stubs${path.separator}${rt-openjdk6}" />
+ <compilerarg value="-Xlint:-options" />
<src path="src/utils" />
<include name="lombok/javac/**" />
<classpath location="build/lombok-utils" />
@@ -175,20 +202,64 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<fileset dir="build/lombok-utils" />
</copy>
- <ivy:compile destdir="build/lombok" source="1.5" target="1.5" includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:lib/openJDK6Environment/rt-openjdk6.jar" />
- <compilerarg value="-Xbootclasspath/p:build/stubs" />
+ <mkdir dir="build/transformedSources" />
+ <copy todir="build/transformedSources">
+ <fileset dir="src/eclipseAgent">
+ <include name="**/*Transplants.java" />
+ </fileset>
+ <filterchain>
+ <lineContainsRegExp negate="true">
+ <regexp pattern="^\s*@SuppressWarnings.*$" />
+ </lineContainsRegExp>
+ </filterchain>
+ </copy>
+
+ <ivy:compile destdir="build/lombok" source="1.4" target="1.4" ecj="true" nowarn="true" includeSystemBootclasspath="true">
+ <bootclasspath location="build/stubs" />
+ <bootclasspath path="${rt-openjdk8}" />
+ <src path="build/transformedSources" />
+ </ivy:compile>
+
+ <ivy:compile destdir="build/lombok/Class50" source="1.4" target="1.6" ecj="true" nowarn="true" includeSystemBootclasspath="true">
+ <bootclasspath location="build/stubs" />
+ <bootclasspath path="${rt-openjdk8}" />
+ <src path="build/transformedSources" />
+ </ivy:compile>
+
+ <ivy:compile destdir="build/lombok" source="1.5" target="1.5" ecj="true" nowarn="true" includeSystemBootclasspath="true">
+ <bootclasspath location="build/stubs" />
+ <bootclasspath path="${rt-openjdk8}" />
+ <src path="src/launch" />
<src path="src/core" />
<src path="src/installer" />
<src path="src/eclipseAgent" />
<exclude name="lombok/javac/**" />
+ <exclude name="**/*Transplants.java" />
<classpath location="build/lombok" />
<classpath refid="build.path" />
</ivy:compile>
- <ivy:compile destdir="build/lombok" source="1.6" target="1.6" includeantruntime="false">
- <compilerarg value="-Xbootclasspath/p:lib/openJDK6Environment/rt-openjdk6.jar" />
- <compilerarg value="-Xbootclasspath/p:build/stubs" />
+ <ivy:compile destdir="build/lombok" source="1.9" target="1.9">
+ <compilerarg value="-Xlint:none" />
+ <!-- The above is because javac9 warns about 'service interface provided but not exported or used', probably because lombok uses SPI internally, and uses the 'old' classpath discovery system for it. We're fine with this, hence, ignore this warning. -->
+ <src path="src/core9" />
+ <src path="src/j9stubs" />
+ <!-- This includes org.mapstruct.ap.spi.AstModifyingAnnotationProcessor; putting this on the classpath doesn't work (needs to be internal or a module) so we just add it and then delete the class file for convenience. -->
+ </ivy:compile>
+ <delete file="build/lombok/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.class" />
+
+ <ivy:compile destdir="build/lombok/Class50" source="1.5" target="1.6" ecj="true" nowarn="true" includeSystemBootclasspath="true">
+ <bootclasspath location="build/stubs" />
+ <bootclasspath path="${rt-openjdk8}" />
+ <src path="src/eclipseAgent" />
+ <include name="lombok/launch/PatchFixesHider.java" />
+ <classpath location="build/lombok" />
+ <classpath refid="build.path" />
+ </ivy:compile>
+
+ <ivy:compile destdir="build/lombok" source="1.6" target="1.6">
+ <compilerarg value="-Xbootclasspath/p:build/stubs${path.separator}${rt-openjdk6}" />
+ <compilerarg value="-Xlint:-options" />
<src path="src/core" />
<src path="src/delombok" />
<include name="lombok/javac/**" />
@@ -196,37 +267,86 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<classpath location="build/lombok" />
<classpath refid="build.path" />
</ivy:compile>
+ <delete dir="build/lombok-proc-result" quiet="true" />
+ <ivy:compile destdir="build/lombok-proc-result" source="1.6" target="1.6" nowarn="true">
+ <compilerarg value="-Xbootclasspath/p:build/stubs" />
+ <compilerarg value="-proc:only" />
+ <compilerarg value="-processor" />
+ <compilerarg value="org.mangosdk.spi.processor.SpiProcessor" />
+ <src path="src/launch" />
+ <src path="src/core" />
+ <src path="src/installer" />
+ <src path="src/eclipseAgent" />
+ <src path="src/delombok" />
+ <classpath location="build/lombok" />
+ <classpath refid="build.path" />
+ </ivy:compile>
+ <copy todir="build/lombok">
+ <fileset dir="build/lombok-proc-result">
+ <include name="META-INF/services/*" />
+ </fileset>
+ </copy>
<mkdir dir="build/lombok/META-INF" />
<mkdir dir="build/lombok/META-INF/services" />
- <echo file="build/lombok/META-INF/services/javax.annotation.processing.Processor">lombok.core.AnnotationProcessor</echo>
+ <echo file="build/lombok/META-INF/services/javax.annotation.processing.Processor">lombok.launch.AnnotationProcessorHider$AnnotationProcessor
+lombok.launch.AnnotationProcessorHider$ClaimingProcessor</echo>
+ <echo file="build/lombok/META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor">lombok.launch.AnnotationProcessorHider$AstModificationNotifier</echo>
+ </target>
+
+ <target name="-latestChanges" depends="version">
+ <ant antfile="buildScripts/website.ant.xml" target="latestChanges" inheritAll="false">
+ <property name="lombok.version" value="${lombok.version}" />
+ <property name="lombok.fullversion" value="${lombok.fullversion}" />
+ </ant>
</target>
- <target name="dist" description="Builds THE lombok.jar file which contains everything." depends="version, compile">
+ <target name="dist" description="Builds THE lombok.jar file which contains everything." depends="version, compile, -latestChanges">
<mkdir dir="dist" />
<copy file="doc/changelog.markdown" tofile="build/changelog.txt" />
<tstamp>
<format property="releaseTimestamp" pattern="yyyy-MM-dd" />
</tstamp>
<echo file="release-timestamp.txt">${releaseTimestamp}</echo>
- <taskdef name="jarjar" classname="com.tonicsystems.jarjar.JarJarTask" classpath="lib/build/com.googlecode.jarjar-jarjar.jar" />
- <jarjar destfile="dist/lombok-${lombok.version}.jar">
- <fileset dir="build/lombok">
- <exclude name="com/sun/tools/javac/**"/>
- </fileset>
- <fileset dir="build" includes="changelog.txt" />
+ <zip destfile="dist/lombok-${lombok.version}.jar">
+ <fileset dir="build" includes="changelog.txt, latestchanges.html" />
<fileset dir="." includes="LICENSE" />
<fileset dir="." includes="AUTHORS" />
<fileset dir="." includes="release-timestamp.txt" />
- <rule pattern="com.zwitserloot.cmdreader.**" result="lombok.libs.com.zwitserloot.cmdreader.@1" />
- <rule pattern="org.objectweb.asm.**" result="lombok.libs.org.objectweb.asm.@1" />
+ <fileset dir="build/lombok">
+ <include name="module-info.class" />
+ <include name="lombok/*.class" />
+ <include name="lombok/experimental/**" />
+ <include name="lombok/extern/**" />
+ <include name="lombok/launch/**" />
+ <include name="lombok/delombok/ant/Tasks*" />
+ <include name="lombok/javac/apt/Processor.class" />
+ </fileset>
+ <mappedresources>
+ <fileset dir="build/lombok">
+ <exclude name="com/sun/tools/javac/**" />
+ <exclude name="module-info.class" />
+ <exclude name="lombok/*.class" />
+ <exclude name="lombok/javac/apt/Processor.class" />
+ <exclude name="lombok/experimental/**" />
+ <exclude name="lombok/extern/**" />
+ <exclude name="lombok/launch/**" />
+ <exclude name="lombok/delombok/ant/Tasks*" />
+ </fileset>
+ <firstmatchmapper>
+ <globmapper from="*.class" to="*.SCL.lombok" />
+ <identitymapper />
+ </firstmatchmapper>
+ </mappedresources>
+ </zip>
+ <jar destfile="dist/lombok-${lombok.version}.jar" update="true">
<manifest>
- <attribute name="Premain-Class" value="lombok.core.Agent" />
- <attribute name="Agent-Class" value="lombok.core.Agent" />
+ <attribute name="Premain-Class" value="lombok.launch.Agent" />
+ <attribute name="Agent-Class" value="lombok.launch.Agent" />
<attribute name="Can-Redefine-Classes" value="true" />
- <attribute name="Main-Class" value="lombok.core.Main" />
+ <attribute name="Main-Class" value="lombok.launch.Main" />
<attribute name="Lombok-Version" value="${lombok.version}" />
</manifest>
- </jarjar>
+ </jar>
<delete file="release-timestamp.txt" />
<copy file="dist/lombok-${lombok.version}.jar" tofile="dist/lombok.jar" />
<property name="lombok.dist.built" value="true" />
@@ -251,11 +371,13 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<conf name="test" sources="contrib" />
<module name="lombok" depends="build, test">
<srcdir dir="src/core" />
+ <srcdir dir="src/launch" />
<srcdir dir="src/utils" />
<srcdir dir="src/eclipseAgent" />
<srcdir dir="src/installer" />
<srcdir dir="src/delombok" />
<srcdir dir="src/stubs" />
+ <srcdir dir="src/testAP" />
<srcdir dir="experimental/src" />
<srcdir dir="test/transform/src" test="true" />
<srcdir dir="test/core/src" test="true" />
@@ -263,7 +385,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<srcdir dir="test/configuration/src" test="true" />
</module>
<settings>
- <url url="http://projectlombok.org/downloads/lombok.intellij.settings" />
+ <url url="https://projectlombok.org/downloads/lombok.intellij.settings" />
</settings>
<apt enabled="true" />
</ivy:intellijgen>
@@ -280,11 +402,14 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<target name="eclipse" depends="-addEclipseDeps, deps, contrib" description="Creates eclipse project files and downloads all dependencies. Open this directory as project in eclipse after running this target. This will NOT let you start a debug session for eclipse; use target 'eclipseForDebugging' instead to do that.">
<ivy:eclipsegen source="1.6">
<srcdir dir="src/core" />
+ <srcdir dir="src/launch" />
<srcdir dir="src/utils" />
<srcdir dir="src/eclipseAgent" />
<srcdir dir="src/installer" />
<srcdir dir="src/delombok" />
<srcdir dir="src/stubs" />
+ <srcdir dir="src/testAP" />
+ <srcdir dir="src/website" />
<srcdir dir="experimental/src" />
<srcdir dir="test/transform/src" />
<srcdir dir="test/core/src" />
@@ -294,7 +419,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<conf name="test" sources="contrib" />
<local org="org.projectlombok" name="lombok.patcher" dir="../lombok.patcher" />
<settings>
- <url url="http://projectlombok.org/downloads/lombok.eclipse.settings" />
+ <url url="https://projectlombok.org/downloads/lombok.eclipse.settings" />
</settings>
<apt location="lib/build/projectlombok.org-spi.jar" />
</ivy:eclipsegen>
@@ -335,6 +460,7 @@ the common tasks and can be called on to run the main aspects of all the sub-scr
<antcall target="-augmentClasspath"><param name="pluginName" value="org.eclipse.osgi" /></antcall>
<antcall target="-augmentClasspath"><param name="pluginName" value="org.eclipse.jdt.core" /></antcall>
<antcall target="-augmentClasspath"><param name="pluginName" value="org.eclipse.jdt.ui" /></antcall>
+ <antcall target="-augmentClasspath"><param name="pluginName" value="org.eclipse.jface.text" /></antcall>
<antcall target="-augmentClasspath"><param name="pluginName" value="org.eclipse.core.resources" /></antcall>
<antcall target="-augmentClasspath"><param name="pluginName" value="org.eclipse.core.jobs" /></antcall>
@@ -397,7 +523,8 @@ ${sourceWarning}</echo>
<target name="-test-compile" depends="ensureTestDeps, compile" unless="skipTests">
<mkdir dir="build/tests" />
- <ivy:compile destdir="build/tests" source="1.5" target="1.5" includeantruntime="false">
+ <ivy:compile destdir="build/tests" source="1.5" target="1.5" ecj="true" nowarn="true">
+ <bootclasspath path="${rt-openjdk8}" />
<classpath refid="test.path" />
<classpath refid="build.path" />
<classpath path="build/lombok" />
@@ -408,13 +535,19 @@ ${sourceWarning}</echo>
</ivy:compile>
</target>
- <target name="test-ecj" depends="dist, contrib" unless="tests.skip">
- <java jar="lib/ecj7/org.eclipse.custom-ecj.jar" fork="true" failonerror="true">
+ <target name="test-ecj" depends="dist, contrib, setupJavaOracle8TestEnvironment" unless="tests.skip">
+ <condition property="ecj.loc" value="lib/ecj9/*" else="lib/ecj8/*">
+ <equals arg1="${ant.java.version}" arg2="9" />
+ </condition>
+ <java classname="org.eclipse.jdt.internal.compiler.batch.Main" fork="true" failonerror="true">
+ <classpath path="${ecj.loc}" />
<jvmarg value="-javaagent:dist/lombok.jar=ecj" />
<arg value="-source" />
<arg value="1.6" />
<arg value="-target" />
<arg value="1.6" />
+ <arg value="-cp" />
+ <arg value="dist/lombok.jar" />
<arg value="test/ecj/SimpleTest.java" />
</java>
</target>
@@ -439,19 +572,20 @@ ${sourceWarning}</echo>
<filter token="ECJ_LOCATION" value="${test.location.ecj}" />
<filter token="RT_LOCATION" value="${test.location.bootclasspath}" />
<filter token="JAVA_VERSION" value="${test.javaversion}" />
+ <filter token="PATH_SEP" value="${path.separator}" />
</filterset>
</copy>
<echo>WARNING: If you wish to test JDK8 features in eclipse, there must be a JDK8 installation configured in your eclipse, and it must be called 'JavaSE-1.8'.</echo>
</target>
- <target name="setupJavaOpenJDK6TestEnvironment" depends="contrib" description="Sets up the test so that 'ant test' will test against OpenJDK6.">
+ <target name="setupJavaOpenJDK6TestEnvironment" depends="ensureTestDeps, contrib" description="Sets up the test so that 'ant test' will test against OpenJDK6.">
<mkdir dir="lib/openJDK6Environment" />
- <get src="http://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18.jar" dest="lib/openJDK6Environment/javac6.jar" verbose="true" usetimestamp="true" />
- <get src="http://projectlombok.org/ivyrepo/langtools/rt-openjdk6.jar" dest="lib/openJDK6Environment/rt-openjdk6.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18.jar" dest="lib/openJDK6Environment/javac6.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/rt-openjdk6.jar" dest="${rt-openjdk6}" verbose="true" usetimestamp="true" />
<propertyfile file="testenvironment.properties">
<entry key="test.location.javac" value="lib/openJDK6Environment/javac6.jar" />
<entry key="test.location.ecj" value="lib/ecj7/org.eclipse.custom-ecj.jar" />
- <entry key="test.location.bootclasspath" value="lib/openJDK6Environment/rt-openjdk6.jar" />
+ <entry key="test.location.bootclasspath" value="${rt-openjdk6}" />
<entry key="test.location.name" value="OpenJDK6" />
<entry key="test.javaversion" value="6" />
</propertyfile>
@@ -459,10 +593,10 @@ ${sourceWarning}</echo>
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
- <target name="setupJavaOpenJDK7TestEnvironment" depends="contrib" description="Sets up the test so that 'ant test' will test against OpenJDK7.">
+ <target name="setupJavaOpenJDK7TestEnvironment" depends="ensureTestDeps, contrib" description="Sets up the test so that 'ant test' will test against OpenJDK7.">
<mkdir dir="lib/openJDK7Environment" />
- <get src="http://projectlombok.org/ivyrepo/langtools/javac-1.7.0.jar" dest="lib/openJDK7Environment/javac7.jar" verbose="true" usetimestamp="true" />
- <get src="http://projectlombok.org/ivyrepo/langtools/rt-openjdk7.jar" dest="lib/openJDK7Environment/rt-openjdk7.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/javac-1.7.0.jar" dest="lib/openJDK7Environment/javac7.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/rt-openjdk7.jar" dest="lib/openJDK7Environment/rt-openjdk7.jar" verbose="true" usetimestamp="true" />
<propertyfile file="testenvironment.properties">
<entry key="test.location.javac" value="lib/openJDK7Environment/javac7.jar" />
<entry key="test.location.ecj" value="lib/ecj7/org.eclipse.custom-ecj.jar" />
@@ -474,10 +608,10 @@ ${sourceWarning}</echo>
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
- <target name="setupJavaOracle7TestEnvironment" depends="contrib" description="Sets up the test so that 'ant test' will test against OpenJDK7.">
+ <target name="setupJavaOracle7TestEnvironment" depends="ensureTestDeps, contrib" description="Sets up the test so that 'ant test' will test against Oracle JDK7.">
<mkdir dir="lib/oracleJDK7Environment" />
- <get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk7-tools.jar" dest="lib/oracleJDK7Environment/tools.jar" verbose="true" usetimestamp="true" />
- <get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk7-rt.jar" dest="lib/oracleJDK7Environment/rt.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/oracle-jdk7-tools.jar" dest="lib/oracleJDK7Environment/tools.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/oracle-jdk7-rt.jar" dest="lib/oracleJDK7Environment/rt.jar" verbose="true" usetimestamp="true" />
<propertyfile file="testenvironment.properties">
<entry key="test.location.javac" value="lib/oracleJDK7Environment/tools.jar" />
<entry key="test.location.ecj" value="lib/ecj7/org.eclipse.custom-ecj.jar" />
@@ -489,11 +623,11 @@ ${sourceWarning}</echo>
<antcall target="-createEclipseLaunchForTestEnvironmentIfEclipseProject" />
</target>
- <target name="setupJavaOracle8TestEnvironment" depends="contrib" description="Sets up the test so that 'ant test' will test against OpenJDK8.">
+ <target name="setupJavaOracle8TestEnvironment" depends="ensureTestDeps, contrib" description="Sets up the test so that 'ant test' will test against Oracle JDK8.">
<mkdir dir="lib/oracleJDK8Environment" />
- <get src="http://projectlombok.org/ivyrepo/langtools/jdk8-javac.jar" dest="lib/oracleJDK8Environment/javac8.jar" verbose="true" usetimestamp="true" />
- <get src="http://projectlombok.org/ivyrepo/langtools/oracle-jdk8-rt.jar" dest="lib/oracleJDK8Environment/rt.jar" verbose="true" usetimestamp="true" />
- <get src="http://projectlombok.org/ivyrepo/langtools/jdk8-javac-sources.zip" dest="lib/oracleJDK8Environment/javac8-sources.zip" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/jdk8-javac.jar" dest="lib/oracleJDK8Environment/javac8.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/oracle-jdk8-rt.jar" dest="lib/oracleJDK8Environment/rt.jar" verbose="true" usetimestamp="true" />
+ <get src="https://projectlombok.org/ivyrepo/langtools/jdk8-javac-sources.zip" dest="lib/oracleJDK8Environment/javac8-sources.zip" verbose="true" usetimestamp="true" />
<propertyfile file="testenvironment.properties">
<entry key="test.location.javac" value="lib/oracleJDK8Environment/javac8.jar" />
<entry key="test.location.ecj" value="lib/ecj8/org.eclipse.custom-ecj.jar" />
@@ -529,8 +663,61 @@ You can also create your own by writing a 'testenvironment.properties' file. The
* test.javaversion = 6
</fail>
</target>
-
- <target name="test" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj" unless="tests.skip" description="Runs the tests.">
+
+ <target name="test" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj, -test-check, -test8, -test9" />
+
+ <target name="-test-check">
+ <condition property="test9.run">
+ <and>
+ <not><isset property="tests.skip" /></not>
+ <equals arg1="${ant.java.version}" arg2="9" />
+ </and>
+ </condition>
+ <condition property="test8.run">
+ <and>
+ <not><isset property="tests.skip" /></not>
+ <not><equals arg1="${ant.java.version}" arg2="9" /></not>
+ </and>
+ </condition>
+ </target>
+
+ <target name="-test9" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj" if="test9.run">
+ <echo>Running test suite in JDK9+ mode</echo>
+ <junit haltonfailure="no" fork="true">
+ <jvmarg value="-javaagent:dist/lombok.jar" />
+ <jvmarg value="-Ddelombok.bootclasspath=${test.location.bootclasspath}" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED" />
+ <jvmarg value="--add-opens" />
+ <jvmarg value="jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED" />
+ <formatter type="plain" usefile="false" unless="tests.quiet" />
+ <classpath refid="test.path" />
+ <classpath path="${test.location.ecj}" />
+ <classpath path="${test.location.javac}" />
+ <classpath path="build/lombok" />
+ <classpath path="build/tests" />
+ <batchtest>
+ <fileset dir="test/core/src">
+ <include name="lombok/RunAllTests.java" />
+ </fileset>
+ </batchtest>
+ </junit>
+ </target>
+
+ <target name="-test8" depends="-loadTestEnvironmentProperties, -failIfNoTestEnvironmentProperties, -test-compile, dist, test-ecj" if="test8.run" description="Runs the tests.">
+ <echo>Running test suite in JDK6-8 mode</echo>
<junit haltonfailure="no" fork="true">
<jvmarg value="-javaagent:dist/lombok.jar" />
<jvmarg value="-Ddelombok.bootclasspath=${test.location.bootclasspath}" />
@@ -542,20 +729,10 @@ You can also create your own by writing a 'testenvironment.properties' file. The
<classpath path="build/tests" />
<batchtest>
<fileset dir="test/core/src">
- <include name="**/Test*.java" />
- </fileset>
- <fileset dir="test/transform/src">
- <include name="**/Test*.java" />
- </fileset>
- <fileset dir="test/bytecode/src">
- <include name="**/Test*.java" />
- </fileset>
- <fileset dir="test/configuration/src">
- <include name="**/Test*.java" />
+ <include name="lombok/RunAllTests.java" />
</fileset>
</batchtest>
</junit>
- <echo level="info">All tests successful.</echo>
</target>
<target name="utils-javadoc" depends="compile">
@@ -563,8 +740,8 @@ You can also create your own by writing a 'testenvironment.properties' file. The
<javadoc sourcepath="src/utils" defaultexcludes="yes" destdir="build/utils-api" windowtitle="Lombok Utils">
<classpath refid="build.path" />
<link href="http://download.oracle.com/javase/6/docs/api/" />
- <header><![CDATA[<a href='http://projectlombok.org/' target='_blank'>Lombok</a> - ]]>v${lombok.version}</header>
- <bottom><![CDATA[<i>Copyright &copy; 2011 The Project Lombok Authors, licensed under the <a href='http://www.opensource.org/licenses/mit-license.php'>MIT licence</a>.]]></bottom>
+ <header><![CDATA[<a href='https://projectlombok.org/' target='_blank'>Lombok</a> - ]]>v${lombok.version}</header>
+ <bottom><![CDATA[<i>Copyright &copy; 2011-2015 The Project Lombok Authors, licensed under the <a href='http://www.opensource.org/licenses/mit-license.php' target='_blank'>MIT licence</a>.]]></bottom>
</javadoc>
<!-- bugfix for boneheaded javadoc bug where ?is-external=true is inserted before an anchor ref, breaking the anchor ref.
is-external=true doesn't actually do anything, so, we'll just get rid of it. -->
@@ -601,6 +778,7 @@ You can also create your own by writing a 'testenvironment.properties' file. The
<target name="javadoc" depends="compile, version" description="Builds javadoc into doc/api.">
<ant antfile="buildScripts/website.ant.xml" target="javadoc" inheritAll="false">
<property name="lombok.version" value="${lombok.version}" />
+ <property name="lombok.fullversion" value="${lombok.fullversion}" />
</ant>
</target>
@@ -610,6 +788,7 @@ You can also create your own by writing a 'testenvironment.properties' file. The
</jar>
<jar destfile="dist/lombok-${lombok.version}-sources.jar">
<fileset dir="src/core" />
+ <fileset dir="src/launch" />
<fileset dir="src/utils" />
<fileset dir="src/eclipseAgent" />
<fileset dir="src/installer" />
@@ -635,51 +814,63 @@ You can also create your own by writing a 'testenvironment.properties' file. The
</tar>
</target>
- <target name="maven-publish" depends="config-ssh, -defSSH, maven, utils-maven" description="Build a maven artifact bundle then upload it to projectlombok.org and ask the server to upload it to maven central">
- <scp
- localFile="build/mavenPublish/mavenPublish.tar.bz2"
- todir="${ssh.username}@projectlombok.org:/data/lombok/staging"
- keyfile="${ssh.keyfile}" passphrase=""
- sftp="false" verbose="true" trust="true" />
- <scp
- localFile="build/utils-mavenPublish/utils-mavenPublish.tar.bz2"
- todir="${ssh.username}@projectlombok.org:/data/lombok/staging"
- keyfile="${ssh.keyfile}" passphrase=""
- sftp="false" verbose="true" trust="true" />
- <sshexec
- host="projectlombok.org"
+ <target name="maven-publish" depends="config-ssh, maven, utils-maven" description="Build a maven artifact bundle then upload it to projectlombok.org and ask the server to upload it to maven central">
+ <ivy:scpUpload
+ from="build/mavenPublish/mavenPublish.tar.bz2"
+ to="/data/lombok/staging"
+ server="projectlombok.org"
username="${ssh.username}"
- keyfile="${ssh.keyfile}" passphrase=""
- trust="true" command="/data/lombok/stagingCmd/publishToMavenCentral" />
- <echo>The artifact has been published to staging. Now go to http://oss.sonatype.org/ and log in as Reinier, then doublecheck if all is well and 'release' it.</echo>
- <sshexec
- host="projectlombok.org"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:scpUpload
+ from="build/utils-mavenPublish/utils-mavenPublish.tar.bz2"
+ to="/data/lombok/staging"
+ server="projectlombok.org"
username="${ssh.username}"
- keyfile="${ssh.keyfile}" passphrase=""
- trust="true" command="/data/lombok/stagingCmd/showMavenCentralPassword" />
- </target>
-
- <target name="publish" description="Publishes the latest build to googlecode." depends="config-ssh, -defSSH, version, dist, dist-utils, test">
- <scp
- localFile="dist/lombok-utils-${lombok.version}.jar"
- todir="${ssh.username}@projectlombok.org:/data/lombok/staging"
- keyfile="${ssh.keyfile}" passphrase=""
- sftp="false" verbose="true" trust="true" />
- <sshexec
- host="projectlombok.org"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:sshExec
+ cmd="/data/lombok/stagingCmd/publishToMavenCentral"
+ server="projectlombok.org"
username="${ssh.username}"
- keyfile="${ssh.keyfile}" passphrase=""
- trust="true" command="/data/lombok/stagingCmd/deployLombokUtils '${lombok.version}'" />
- <scp
- localFile="dist/lombok-${lombok.version}.jar"
- todir="${ssh.username}@projectlombok.org:/data/lombok/staging"
- keyfile="${ssh.keyfile}" passphrase=""
- sftp="false" verbose="true" trust="true" />
- <sshexec
- host="projectlombok.org"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <echo>The artifact has been published to staging. Now go to https://oss.sonatype.org/ and log in as Reinier, then doublecheck if all is well and 'release' it.</echo>
+ <ivy:sshExec
+ cmd="/data/lombok/stagingCmd/showMavenCentralPassword"
+ server="projectlombok.org"
username="${ssh.username}"
- keyfile="${ssh.keyfile}" passphrase=""
- trust="true" command="/data/lombok/stagingCmd/deployLombok '${lombok.version}'" />
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ </target>
+
+ <target name="publish" description="Publishes the latest build to googlecode." depends="config-ssh, version, dist, dist-utils, test">
+ <ivy:scpUpload
+ from="dist/lombok-utils-${lombok.version}.jar"
+ to="/data/lombok/staging"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:sshExec
+ cmd="/data/lombok/stagingCmd/deployLombokUtils '${lombok.version}'"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:scpUpload
+ from="dist/lombok-${lombok.version}.jar"
+ to="/data/lombok/staging"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:sshExec
+ cmd="/data/lombok/stagingCmd/deployLombok '${lombok.version}'"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
</target>
<target name="publish-all" depends="clean, version, website-publish, maven-publish, publish"
@@ -689,6 +880,7 @@ You can also create your own by writing a 'testenvironment.properties' file. The
description="Publishes an edge release for those who need to test a cutting edge build.">
<ant antfile="buildScripts/website.ant.xml" target="edgeRelease" inheritAll="false">
<property name="lombok.version" value="${lombok.version}" />
+ <property name="lombok.fullversion" value="${lombok.fullversion}" />
<property name="ssh.username" value="${ssh.username}" />
<property name="ssh.keyfile" value="${ssh.keyfile}" />
</ant>
@@ -708,18 +900,91 @@ You can also create your own by writing a 'testenvironment.properties' file. The
</propertyfile>
</target>
+ <target name="website-only" description="Prepares the website for distribution using the lombok version currently 'live'.">
+ <ant antfile="buildScripts/website.ant.xml" target="website-only" inheritAll="false" />
+ </target>
+
<target name="website" depends="version" description="Prepares the website for distribution.">
<ant antfile="buildScripts/website.ant.xml" target="website" inheritAll="false">
<property name="lombok.version" value="${lombok.version}" />
+ <property name="lombok.fullversion" value="${lombok.fullversion}" />
</ant>
</target>
- <target name="website-publish" depends="config-ssh, clean, version"
+ <target name="website-supporters" depends="ensureSupportersDeps, website-only" description="Updates the supporters repo and adds it to the website build.">
+ <ant antfile="buildScripts/supporters.ant.xml" target="deployToWebsiteBuild" inheritAll="false" />
+ </target>
+
+ <target name="website-supporters-fast" depends="website-only" description="Updates the supporters repo and adds it to the website build.">
+ <ant antfile="buildScripts/supporters.ant.xml" target="deployToWebsiteBuild" inheritAll="false">
+ <property name="noUpdateRepo" value="true" />
+ </ant>
+ </target>
+
+ <target name="website-only-publish" depends="config-ssh, clean, ensureSupportersDeps"
+ description="Prepares the website (using lombok version current 'live') for distribution and then publishes it to projectlombok.org.">
+ <ant antfile="buildScripts/website.ant.xml" target="website-only-publish" inheritAll="false">
+ <property name="ssh.username" value="${ssh.username}" />
+ <property name="ssh.keyfile" value="${ssh.keyfile}" />
+ </ant>
+ </target>
+
+ <target name="website-publish" depends="config-ssh, clean, version, ensureSupportersDeps"
description="Prepares the website for distribution and then publishes it to projectlombok.org.">
<ant antfile="buildScripts/website.ant.xml" target="website-publish" inheritAll="false">
<property name="lombok.version" value="${lombok.version}" />
+ <property name="lombok.fullversion" value="${lombok.fullversion}" />
<property name="ssh.username" value="${ssh.username}" />
<property name="ssh.keyfile" value="${ssh.keyfile}" />
</ant>
</target>
+
+ <target name="testAp-compile" depends="ensureBuildDeps">
+ <delete file="build/testAP/META-INF/services/javax.annotation.processing.Processor" quiet="true" />
+ <ivy:compile destdir="build/testAP" source="1.7" target="1.7">
+ <src path="src/testAP" />
+ </ivy:compile>
+
+ <mkdir dir="build/testAP/META-INF" />
+ <mkdir dir="build/testAP/META-INF/services" />
+ <echo file="build/testAP/META-INF/services/javax.annotation.processing.Processor">org.projectlombok.testAp.TestAp</echo>
+ </target>
+
+ <target name="testAp-dist" depends="testAp-compile">
+ <mkdir dir="dist" />
+ <tstamp>
+ <format property="releaseTimestamp" pattern="yyyy-MM-dd" />
+ </tstamp>
+ <zip destfile="dist/testAp-${releaseTimestamp}.jar">
+ <fileset dir="." includes="LICENSE" />
+ <fileset dir="build/testAp" />
+ </zip>
+ <copy file="dist/testAp-${releaseTimestamp}.jar" tofile="dist/testAp.jar" />
+ </target>
+
+ <target name="testAp" depends="testAp-dist, dist">
+ <echo>Running in order: First Lombok, Then testAP</echo>
+
+ <delete dir="build/useTestAp" quiet="true" />
+ <mkdir dir="build/useTestAp" />
+ <javac verbose="false" source="1.7" target="1.7" destdir="build/useTestAp" includeantruntime="false">
+ <src path="src/useTestAP" />
+ <classpath location="dist/lombok.jar" />
+ <classpath location="dist/testAp.jar" />
+ <compilerarg value="-processor" />
+ <compilerarg value="lombok.launch.AnnotationProcessorHider$AnnotationProcessor,org.projectlombok.testAp.TestAp" />
+ </javac>
+
+ <echo>Running in order: First TestAP, Then Lombok</echo>
+
+ <delete dir="build/useTestAp" quiet="true" />
+ <mkdir dir="build/useTestAp" />
+ <javac verbose="false" source="1.7" target="1.7" destdir="build/useTestAp" includeantruntime="false">
+ <src path="src/useTestAP" />
+ <classpath location="dist/lombok.jar" />
+ <classpath location="dist/testAp.jar" />
+ <compilerarg value="-processor" />
+ <compilerarg value="org.projectlombok.testAp.TestAp,lombok.launch.AnnotationProcessorHider$AnnotationProcessor" />
+ </javac>
+ </target>
</project>
diff --git a/buildScripts/eclipse-run-tests.template b/buildScripts/eclipse-run-tests.template
index b7bc8b0d..0c00c236 100644
--- a/buildScripts/eclipse-run-tests.template
+++ b/buildScripts/eclipse-run-tests.template
@@ -18,11 +18,13 @@
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry containerPath=&quot;org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.@JAVA_VERSION@&quot; path=&quot;1&quot; type=&quot;4&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lombok/@ECJ_LOCATION@&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
<listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lombok/@JAVAC_LOCATION@&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
- <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;false&quot; project=&quot;lombok&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lombok/lib/test/com.google.guava-guava.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry internalArchive=&quot;/lombok/lib/test/com.google.code.findbugs-findbugs.jar&quot; path=&quot;3&quot; type=&quot;2&quot;/&gt;&#10;"/>
+ <listEntry value="&lt;?xml version=&quot;1.0&quot; encoding=&quot;UTF-8&quot; standalone=&quot;no&quot;?&gt;&#10;&lt;runtimeClasspathEntry id=&quot;org.eclipse.jdt.launching.classpathentry.defaultClasspath&quot;&gt;&#10;&lt;memento exportedEntriesOnly=&quot;true&quot; project=&quot;lombok&quot;/&gt;&#10;&lt;/runtimeClasspathEntry&gt;&#10;"/>
</listAttribute>
<booleanAttribute key="org.eclipse.jdt.launching.DEFAULT_CLASSPATH" value="false"/>
<stringAttribute key="org.eclipse.jdt.launching.JRE_CONTAINER" value="org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/JavaSE-1.@JAVA_VERSION@"/>
<stringAttribute key="org.eclipse.jdt.launching.MAIN_TYPE" value="lombok.RunAllTests"/>
<stringAttribute key="org.eclipse.jdt.launching.PROJECT_ATTR" value="lombok"/>
- <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-javaagent:dist/lombok.jar -Ddelombok.bootclasspath=@RT_LOCATION@"/>
+ <stringAttribute key="org.eclipse.jdt.launching.VM_ARGUMENTS" value="-javaagent:dist/lombok.jar -Dshadow.override.lombok=${project_loc:lombok}/bin@PATH_SEP@${project_loc:lombok}/lib/runtime/* -Ddelombok.bootclasspath=@RT_LOCATION@"/>
</launchConfiguration>
diff --git a/buildScripts/ivy-repo/net.java.openjdk.custom-javac6-1.6.0.18.xml b/buildScripts/ivy-repo/net.java.openjdk.custom-javac6-1.6.0.18.xml
index f2c59547..f30c7b02 100644
--- a/buildScripts/ivy-repo/net.java.openjdk.custom-javac6-1.6.0.18.xml
+++ b/buildScripts/ivy-repo/net.java.openjdk.custom-javac6-1.6.0.18.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="runtime" url="http://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18-sources.zip" />
+ <artifact conf="runtime" url="https://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/langtools/javac-1.6.0.18-sources.zip" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/net.java.openjdk.custom-javac7-1.7.0.xml b/buildScripts/ivy-repo/net.java.openjdk.custom-javac7-1.7.0.xml
index 2ef76782..f6a0d938 100644
--- a/buildScripts/ivy-repo/net.java.openjdk.custom-javac7-1.7.0.xml
+++ b/buildScripts/ivy-repo/net.java.openjdk.custom-javac7-1.7.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="runtime" url="http://projectlombok.org/ivyrepo/langtools/javac-1.7.0.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/langtools/javac-1.7.0-sources.zip" />
+ <artifact conf="runtime" url="https://projectlombok.org/ivyrepo/langtools/javac-1.7.0.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/langtools/javac-1.7.0-sources.zip" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/netbeans.org-boot-6.8beta.xml b/buildScripts/ivy-repo/netbeans.org-boot-6.8beta.xml
index 4f6b6a86..eddbc5cc 100644
--- a/buildScripts/ivy-repo/netbeans.org-boot-6.8beta.xml
+++ b/buildScripts/ivy-repo/netbeans.org-boot-6.8beta.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/netbeans/boot_6.8beta.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/netbeans/boot_6.8beta.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/netbeans.org-modules.java.source-6.8beta.xml b/buildScripts/ivy-repo/netbeans.org-modules.java.source-6.8beta.xml
index 352b390a..8f230399 100644
--- a/buildScripts/ivy-repo/netbeans.org-modules.java.source-6.8beta.xml
+++ b/buildScripts/ivy-repo/netbeans.org-modules.java.source-6.8beta.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/netbeans/org-netbeans-modules-java-source_6.8beta.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/netbeans/org-netbeans-modules-java-source_6.8beta.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/netbeans.org-openide.modules-6.8beta.xml b/buildScripts/ivy-repo/netbeans.org-openide.modules-6.8beta.xml
index 6549869e..baee69e0 100644
--- a/buildScripts/ivy-repo/netbeans.org-openide.modules-6.8beta.xml
+++ b/buildScripts/ivy-repo/netbeans.org-openide.modules-6.8beta.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/netbeans/org-openide-modules_6.8beta.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/netbeans/org-openide-modules_6.8beta.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/netbeans.org-openide.util-6.8beta.xml b/buildScripts/ivy-repo/netbeans.org-openide.util-6.8beta.xml
index 3ef68928..b7427dc2 100644
--- a/buildScripts/ivy-repo/netbeans.org-openide.util-6.8beta.xml
+++ b/buildScripts/ivy-repo/netbeans.org-openide.util-6.8beta.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/netbeans/org-openide-util_6.8beta.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/netbeans/org-openide-util_6.8beta.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.200.xml b/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.200.xml
index ed4f5fd5..077f4f47 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.200.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.200.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.200.v20120521-2346.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.200.v20120521-2346-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.200.v20120521-2346.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.200.v20120521-2346-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.300.xml b/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.300.xml
index 4ac11822..f4002ee8 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.300.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-core.jobs-3.5.300.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.300.v20130429-1813.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.300.v20130429-1813-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.300.v20130429-1813.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.jobs_3.5.300.v20130429-1813-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.7.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.7.0.xml
index 9fe7836e..b1ddf043 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.7.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.7.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.7.100.v20110510-0712.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.7.100.v20110510-0712-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.7.100.v20110510-0712.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.7.100.v20110510-0712-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.8.100.xml b/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.8.100.xml
index c76dba24..eac7fe7b 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.8.100.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-core.resources-3.8.100.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.8.100.v20130521-2026.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.8.100.v20130521-2026-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.8.100.v20130521-2026.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.resources_3.8.100.v20130521-2026-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.6.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.6.0.xml
index fe812bbc..a5fe9784 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.6.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.6.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.6.0.v20100505.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.6.0.v20100505-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.6.0.v20100505.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.6.0.v20100505-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.9.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.9.0.xml
index 45d6a9c3..0e06d062 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.9.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-core.runtime-3.9.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.9.0.v20130326-1255.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.9.0.v20130326-1255-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.9.0.v20130326-1255.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.core.runtime_3.9.0.v20130326-1255-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-ecj-3.6.2.xml b/buildScripts/ivy-repo/org.eclipse.custom-ecj-3.6.2.xml
index fc9fa661..7da4c2ce 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-ecj-3.6.2.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-ecj-3.6.2.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/ecj-3.6.2.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/ecjsrc-3.6.2.zip" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/ecj-3.6.2.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/ecjsrc-3.6.2.zip" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-ecj-4.3.1.xml b/buildScripts/ivy-repo/org.eclipse.custom-ecj-4.3.1.xml
index 4ebfc8a4..8d0a8f0c 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-ecj-4.3.1.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-ecj-4.3.1.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/ecj-4.3.1.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/ecjsrc-4.3.1.zip" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/ecj-4.3.1.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/ecjsrc-4.3.1.zip" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-ecj-I20140430.xml b/buildScripts/ivy-repo/org.eclipse.custom-ecj-I20140430.xml
index 8ba65a2a..193f8a27 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-ecj-I20140430.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-ecj-I20140430.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/ecj-I20140430-0800.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/ecjsrc-I20140430-0800.zip" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/ecj-I20140430-0800.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/ecjsrc-I20140430-0800.zip" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.0.xml
index 889a2ceb..69d18ae4 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.0.v20100503.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.0.v20100503-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.0.v20100503.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.0.v20100503-sources.jar" />
</publications>
</ivy-module> \ No newline at end of file
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.200.xml b/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.200.xml
index 74f7a705..d0a128ec 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.200.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-equinox.common-3.6.200.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.200.v20130402-1505.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.200.v20130402-1505-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.200.v20130402-1505.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.equinox.common_3.6.200.v20130402-1505-sources.jar" />
</publications>
</ivy-module> \ No newline at end of file
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.6.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.6.0.xml
index f9a8f52d..2c46df18 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.6.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.6.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.6.0.v_A58.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.6.0.v_A58-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.6.0.v_A58.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.6.0.v_A58-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.9.1.xml b/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.9.1.xml
index 0e7c5363..946aa65a 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.9.1.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-jdt.core-3.9.1.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.9.1.v20130905-0837.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.9.1.v20130905-0837-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.9.1.v20130905-0837.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.core_3.9.1.v20130905-0837-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.6.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.6.0.xml
index dbee2865..6dcf54f0 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.6.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.6.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.6.0.v20100602-1600.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.6.0.v20100602-1600-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.6.0.v20100602-1600.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.6.0.v20100602-1600-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.9.1.xml b/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.9.1.xml
index 0577ee8a..e57bad7a 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.9.1.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-jdt.ui-3.9.1.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.9.1.v20130820-1427.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.9.1.v20130820-1427-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.9.1.v20130820-1427.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.jdt.ui_3.9.1.v20130820-1427-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.6.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.6.0.xml
index 93a7f381..7cca0e05 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.6.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.6.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.6.0.v20100517.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.6.0.v20100517-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.6.0.v20100517.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.6.0.v20100517-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.9.0.xml b/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.9.0.xml
index 247d76de..83e009eb 100644
--- a/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.9.0.xml
+++ b/buildScripts/ivy-repo/org.eclipse.custom-osgi-3.9.0.xml
@@ -8,7 +8,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.9.0.v20130529-1710.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.9.0.v20130529-1710-sources.jar" />
+ <artifact conf="default" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.9.0.v20130529-1710.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/eclipse/org.eclipse.osgi_3.9.0.v20130529-1710-sources.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.15.xml b/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.24.xml
index df00b1c6..87e1594f 100644
--- a/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.15.xml
+++ b/buildScripts/ivy-repo/org.projectlombok-lombok.patcher-0.24.xml
@@ -1,14 +1,14 @@
<ivy-module version="2.0">
- <info organisation="org.projectlombok" module="lombok.patcher" revision="0.15" publication="20140522015400">
+ <info organisation="org.projectlombok" module="lombok.patcher" revision="0.24" publication="20171128000000">
<license name="MIT License" url="http://www.opensource.org/licenses/mit-license.php" />
<ivyauthor name="rzwitserloot" url="http://zwitserloot.com/" />
<ivyauthor name="rspilker" url="http://github.com/rspilker" />
- <description homepage="http://projectlombok.org/" />
+ <description homepage="https://projectlombok.org/" />
</info>
<configurations>
<conf name="default" />
</configurations>
<publications>
- <artifact conf="default" url="http://projectlombok.org/downloads/lombok.patcher-0.15.jar" />
+ <artifact conf="default" url="https://projectlombok.org/downloads/lombok.patcher-0.24.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/projectlombok.org-jsch-ant-fixed-0.1.42.xml b/buildScripts/ivy-repo/projectlombok.org-jsch-ant-fixed-0.1.42.xml
index 6fc445b9..318796a4 100644
--- a/buildScripts/ivy-repo/projectlombok.org-jsch-ant-fixed-0.1.42.xml
+++ b/buildScripts/ivy-repo/projectlombok.org-jsch-ant-fixed-0.1.42.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/tools/ant-jsch-fixed.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/tools/ant-jsch-fixed.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/projectlombok.org-markdownj-1.02b4.xml b/buildScripts/ivy-repo/projectlombok.org-markdownj-1.02b4.xml
index 06c581ec..232cbb57 100644
--- a/buildScripts/ivy-repo/projectlombok.org-markdownj-1.02b4.xml
+++ b/buildScripts/ivy-repo/projectlombok.org-markdownj-1.02b4.xml
@@ -1,11 +1,11 @@
<ivy-module version="2.0">
<info organisation="projectlombok.org" module="markdownj" revision="1.02b4" publication="20100419062500">
- <description homepage="http://code.google.com/p/markdownj/" />
+ <description homepage="https://github.com/myabc/markdownj" />
</info>
<configurations>
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/tools/markdownj-1.02b4-0.3.0.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/tools/markdownj-1.02b4-0.3.0.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/projectlombok.org-spi-0.2.4.xml b/buildScripts/ivy-repo/projectlombok.org-spi-0.2.4.xml
index da949c50..ca1a5f9f 100644
--- a/buildScripts/ivy-repo/projectlombok.org-spi-0.2.4.xml
+++ b/buildScripts/ivy-repo/projectlombok.org-spi-0.2.4.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/tools/spi-0.2.4.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/tools/spi-0.2.4.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/projectlombok.org-spi-0.2.7.xml b/buildScripts/ivy-repo/projectlombok.org-spi-0.2.7.xml
index c945fe8f..bfb99fca 100644
--- a/buildScripts/ivy-repo/projectlombok.org-spi-0.2.7.xml
+++ b/buildScripts/ivy-repo/projectlombok.org-spi-0.2.7.xml
@@ -7,6 +7,6 @@
<conf name="build" />
</configurations>
<publications>
- <artifact conf="build" url="http://projectlombok.org/ivyrepo/tools/spi-0.2.7.jar" />
+ <artifact conf="build" url="https://projectlombok.org/ivyrepo/tools/spi-0.2.7.jar" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy-repo/zwitserloot.com-cmdreader-1.2.xml b/buildScripts/ivy-repo/zwitserloot.com-cmdreader-1.2.xml
index 1692a969..fc0b3f2c 100644
--- a/buildScripts/ivy-repo/zwitserloot.com-cmdreader-1.2.xml
+++ b/buildScripts/ivy-repo/zwitserloot.com-cmdreader-1.2.xml
@@ -9,7 +9,7 @@
<conf name="sources" />
</configurations>
<publications>
- <artifact conf="runtime" url="http://projectlombok.org/ivyrepo/tools/com.zwitserloot.cmdreader-1.2.jar" />
- <artifact type="zip" conf="sources" url="http://projectlombok.org/ivyrepo/tools/com.zwitserloot.cmdreader-src-1.2.zip" />
+ <artifact conf="runtime" url="https://projectlombok.org/ivyrepo/tools/com.zwitserloot.cmdreader-1.2.jar" />
+ <artifact type="zip" conf="sources" url="https://projectlombok.org/ivyrepo/tools/com.zwitserloot.cmdreader-src-1.2.zip" />
</publications>
</ivy-module>
diff --git a/buildScripts/ivy.xml b/buildScripts/ivy.xml
index 41f58632..a27c909e 100644
--- a/buildScripts/ivy.xml
+++ b/buildScripts/ivy.xml
@@ -11,32 +11,39 @@
<conf name="contrib" />
<conf name="ecj7" />
<conf name="ecj8" />
+ <conf name="ecj9" />
<conf name="javac6" />
<conf name="javac7" />
+ <conf name="supporters" />
</configurations>
<dependencies>
- <dependency org="org.projectlombok" name="lombok.patcher" rev="0.15" conf="buildBase->default; runtime->default" />
+ <dependency org="org.projectlombok" name="lombok.patcher" rev="0.24" conf="buildBase->default; runtime->default" />
<dependency org="zwitserloot.com" name="cmdreader" rev="1.2" conf="buildBase->runtime; runtime" />
<dependency org="junit" name="junit" rev="4.8.2" conf="test->default; contrib->sources" />
<dependency org="log4j" name="log4j" rev="1.2.16" conf="test->default; contrib->sources" />
<dependency org="org.apache.logging.log4j" name="log4j-api" rev="2.0-beta4" conf="test->default; contrib->sources" />
- <dependency org="commons-logging" name="commons-logging" rev="1.1.1" conf="test->default; contrib->sources"/>
- <dependency org="org.slf4j" name="slf4j-api" rev="1.6.1" conf="test->default; contrib->sources"/>
- <dependency org="org.slf4j" name="slf4j-ext" rev="1.6.1" conf="test->default; contrib->sources"/>
- <dependency org="com.googlecode.jarjar" name="jarjar" rev="1.1" conf="buildBase->default" />
+ <dependency org="commons-logging" name="commons-logging" rev="1.1.1" conf="test->default; contrib->sources" />
+ <dependency org="org.slf4j" name="slf4j-api" rev="1.6.1" conf="test->default; contrib->sources" />
+ <dependency org="org.slf4j" name="slf4j-ext" rev="1.6.1" conf="test->default; contrib->sources" />
+ <dependency org="org.jboss.logging" name="jboss-logging" rev="3.3.0.Final" conf="test->default; contrib->sources" />
+
+ <dependency org="com.google.guava" name="guava" rev="18.0" conf="test->default; contrib->sources" />
+ <dependency org="com.google.code.findbugs" name="findbugs" rev="3.0.0" conf="test->master" />
<dependency org="org.apache.ant" name="ant" rev="1.8.1" conf="buildBase->default; contrib->sources" />
<dependency org="projectlombok.org" name="spi" rev="0.2.7" conf="buildBase->build" />
- <dependency org="com.jcraft" name="jsch" rev="0.1.42" conf="buildBase->default" />
- <dependency org="projectlombok.org" name="jsch-ant-fixed" rev="0.1.42" conf="buildBase->build" />
+ <dependency org="com.hierynomus" name="sshj" rev="0.23.0" conf="buildBase->default" />
<dependency org="projectlombok.org" name="markdownj" rev="1.02b4" conf="buildBase->build" />
<dependency org="de.java2html" name="java2html" rev="5.0" conf="buildBase->default" />
+ <dependency org="org.freemarker" name="freemarker" rev="2.3.25-incubating" conf="buildBase->default" />
<dependency org="net.java.openjdk.custom" name="javac6" rev="1.6.0.18" conf="javac6->runtime; contrib->sources" />
<dependency org="net.java.openjdk.custom" name="javac7" rev="1.7.0" conf="javac7->runtime; contrib->sources" />
<dependency org="org.eclipse.custom" name="ecj" rev="4.3.1" conf="ecj7->default; contrib->sources" />
- <dependency org="org.eclipse.custom" name="ecj" rev="I20140430" conf="ecj8->default; contrib->sources; eclipseBuild->default" />
+ <dependency org="org.eclipse.jdt.core.compiler" name="ecj" rev="4.6.1" conf="ecj8->default; contrib->sources" />
+ <dependency org="org.eclipse.tycho" name="org.eclipse.jdt.core" rev="3.13.50.v20171007-0855" conf="ecj9->default; eclipseBuild->default" />
+ <dependency org="org.eclipse.tycho" name="org.eclipse.jdt.compiler.apt" rev="1.3.50.v20170920-0950" conf="ecj9->default; eclipseBuild->default" />
<dependency org="netbeans.org" name="boot" rev="6.8beta" conf="netbeansBuild->build" />
<dependency org="netbeans.org" name="openide.modules" rev="6.8beta" conf="netbeansBuild->build" />
@@ -50,5 +57,11 @@
<dependency org="org.eclipse.custom" name="osgi" rev="3.9.0" conf="eclipseBuild->default; contrib->sources" />
<dependency org="org.eclipse.custom" name="core.resources" rev="3.8.100" conf="eclipseBuild->default; contrib->sources" />
<dependency org="org.eclipse.custom" name="core.jobs" rev="3.5.300" conf="eclipseBuild->default; contrib->sources" />
+
+ <dependency org="org.eclipse.jgit" name="org.eclipse.jgit.ant" rev="4.11.0.201803080745-r" conf="supporters->default" />
+ <dependency org="org.eclipse.jgit" name="org.eclipse.jgit" rev="4.11.0.201803080745-r" conf="supporters->default" />
+ <dependency org="com.jcraft" name="jsch" rev="0.1.54" conf="supporters->default" />
+ <dependency org="com.rimerosolutions.ant" name="ant-git-tasks" rev="1.3.2" conf="supporters->default" />
+ <dependency org="org.slf4j" name="slf4j-simple" rev="1.6.1" conf="supporters->default" />
</dependencies>
</ivy-module>
diff --git a/buildScripts/ivysettings.xml b/buildScripts/ivysettings.xml
index 17919ea2..bafdc801 100644
--- a/buildScripts/ivysettings.xml
+++ b/buildScripts/ivysettings.xml
@@ -4,7 +4,7 @@
<filesystem name="projectLocalRepo">
<ivy pattern="${ivy.settings.dir}/ivy-repo/[organization]-[module]-[revision].xml" />
</filesystem>
- <ibiblio name="maven-repo2" m2compatible="true" root="http://repo2.maven.org/maven2" />
+ <ibiblio name="maven-repo2" m2compatible="true" root="https://repo1.maven.org/maven2" />
</chain>
</resolvers>
<settings defaultResolver="projectRepos" validate="false" />
diff --git a/buildScripts/src/lombok/website/CompileChangelog.java b/buildScripts/src/lombok/website/CompileChangelog.java
deleted file mode 100644
index 60b70aa3..00000000
--- a/buildScripts/src/lombok/website/CompileChangelog.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package lombok.website;
-
-import com.petebevin.markdown.MarkdownProcessor;
-import java.io.ByteArrayOutputStream;
-import java.io.FileInputStream;
-import java.io.FileOutputStream;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
-
-public class CompileChangelog {
- public static void main(String[] args) {
- String fileIn = args[0];
- String fileOut = args[1];
- boolean edge = args.length > 3 && "-edge".equals(args[2]);
- String version = edge ? args[3] : null;
-
- try {
- FileInputStream in = new FileInputStream(fileIn);
- ByteArrayOutputStream out = new ByteArrayOutputStream();
-
- byte[] b = new byte[65536];
- while (true) {
- int r = in.read(b);
- if ( r == -1 ) break;
- out.write(b, 0, r);
- }
- in.close();
- String markdown = new String(out.toByteArray(), "UTF-8");
-
- String result = edge ? buildEdge(markdown, version) : build(markdown);
-
- FileOutputStream file = new FileOutputStream(fileOut);
- file.write(result.getBytes("UTF-8"));
- file.close();
- System.exit(0);
- } catch (Throwable e) {
- e.printStackTrace();
- System.exit(1);
- }
- }
-
- private static String build(String markdown) {
- return new MarkdownProcessor().markdown(markdown);
- }
-
- private static final Pattern LAST_CHANGELOG = Pattern.compile(
- "^.*### v$", Pattern.CASE_INSENSITIVE | Pattern.DOTALL);
- private static String buildEdge(String markdown, String version) {
- if (version.toUpperCase().endsWith("-HEAD") || version.toUpperCase().endsWith("-EDGE")) {
- version = version.substring(0, version.length() - 5);
- }
-
- Pattern p = Pattern.compile(
- "(?is-m)^.*###\\s*v" + version + ".*?\n(.*?)(?:###\\s*v.*)?$");
- Matcher m = p.matcher(markdown);
- String subMarkdown = m.matches() ? m.group(1) : "* No changelog records for this edge release.";
- return new MarkdownProcessor().markdown(subMarkdown);
- }
-}
diff --git a/buildScripts/src/lombok/website/WebUpToDate.java b/buildScripts/src/lombok/website/WebUpToDate.java
deleted file mode 100644
index 0fe4c1e9..00000000
--- a/buildScripts/src/lombok/website/WebUpToDate.java
+++ /dev/null
@@ -1,190 +0,0 @@
-/*
- * Modified from http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/taskdefs/UpToDate.java?view=markup
- *
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements. See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License. You may obtain a copy of the License at
- *
- * http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- *
- */
-package lombok.website;
-
-import java.io.File;
-import java.util.Vector;
-import java.util.Enumeration;
-import java.util.Iterator;
-import java.net.MalformedURLException;
-import java.net.URL;
-import org.apache.tools.ant.BuildException;
-import org.apache.tools.ant.Project;
-import org.apache.tools.ant.Task;
-import org.apache.tools.ant.taskdefs.condition.Condition;
-import org.apache.tools.ant.types.Resource;
-import org.apache.tools.ant.types.FileSet;
-import org.apache.tools.ant.types.resources.Union;
-import org.apache.tools.ant.types.resources.FileResource;
-import org.apache.tools.ant.types.resources.URLResource;
-import org.apache.tools.ant.types.selectors.SelectorUtils;
-
-public class WebUpToDate extends Task implements Condition {
- private String property;
- private String value;
- private String urlbase;
- private File sourceFile;
- private Vector sourceFileSets = new Vector();
- private Union sourceResources = new Union();
-
- /**
- * The property to set if the target file is more up-to-date than
- * (each of) the source file(s).
- *
- * @param property the name of the property to set if Target is up-to-date.
- */
- public void setProperty(String property) {
- this.property = property;
- }
-
- /**
- * The value to set the named property to if the target file is more
- * up-to-date than (each of) the source file(s). Defaults to 'true'.
- *
- * @param value the value to set the property to if Target is up-to-date
- */
- public void setValue(String value) {
- this.value = value;
- }
-
- /**
- * Returns the value, or "true" if a specific value wasn't provided.
- */
- private String getValue() {
- return (value != null) ? value : "true";
- }
-
- /**
- * The file that must be older than the target file
- * if the property is to be set.
- *
- * @param file the file we are checking against the target file.
- */
- public void setSrcfile(File file) {
- this.sourceFile = file;
- }
-
- /**
- * Nested &lt;srcfiles&gt; element.
- * @param fs the source files
- */
- public void addSrcfiles(FileSet fs) {
- sourceFileSets.addElement(fs);
- }
-
- /**
- * Nested resource collections as sources.
- * @return the source resources to configure.
- * @since Ant 1.7
- */
- public Union createSrcResources() {
- return sourceResources;
- }
-
- public void setUrlbase(String base) {
- if (base.charAt(base.length()-1) != '/') this.urlbase = base + "/";
- else this.urlbase = base;
- }
-
- /**
- * Evaluate (all) target and source file(s) to
- * see if the target(s) is/are up-to-date.
- * @return true if the target(s) is/are up-to-date
- */
- public boolean eval() {
- if (sourceFileSets.size() == 0 && sourceResources.size() == 0 && sourceFile == null) {
- throw new BuildException("At least one srcfile or a nested <srcfiles> or <srcresources> element must be set.");
- }
-
- if ((sourceFileSets.size() > 0 || sourceResources.size() > 0) && sourceFile != null) {
- throw new BuildException("Cannot specify both the srcfile attribute and a nested <srcfiles> or <srcresources> element.");
- }
-
- if (urlbase == null) {
- throw new BuildException("The urlbase attribute must be set.");
- }
-
- // if the source file isn't there, throw an exception
- if (sourceFile != null && !sourceFile.exists()) {
- throw new BuildException(sourceFile.getAbsolutePath() + " not found.");
- }
-
- boolean upToDate = true;
- if (sourceFile != null) {
- Resource fileResource = new FileResource(sourceFile);
- upToDate = isUpToDate(fileResource);
- }
-
- if (upToDate) {
- Enumeration e = sourceFileSets.elements();
- while (upToDate && e.hasMoreElements()) {
- FileSet fs = (FileSet)e.nextElement();
- Iterator it = fs.iterator();
- while (upToDate && it.hasNext()) {
- Resource r = (Resource)it.next();
- upToDate = isUpToDate(r);
- }
- }
- }
-
- if (upToDate) {
- Resource[] r = sourceResources.listResources();
- for (int i = 0; upToDate && i < r.length; i++) {
- upToDate = isUpToDate(r[i]);
- }
- }
-
- return upToDate;
- }
-
- private boolean isUpToDate(Resource r) throws BuildException {
- String url = urlbase + r.getName();
- Resource urlResource;
- try {
- urlResource = new URLResource(new URL(url));
- } catch (MalformedURLException e) {
- throw new BuildException("url is malformed: " + url, e);
- }
-
- if (SelectorUtils.isOutOfDate(r, urlResource, 20)) {
- log(r.getName() + " is newer than " + url, Project.MSG_VERBOSE);
- return false;
- } else {
- return true;
- }
- }
-
- /**
- * Sets property to true if target file(s) have a more recent timestamp
- * than (each of) the corresponding source file(s).
- * @throws BuildException on error
- */
- public void execute() throws BuildException {
- if (property == null) {
- throw new BuildException("property attribute is required.", getLocation());
- }
- boolean upToDate = eval();
-
- if (upToDate) {
- getProject().setNewProperty(property, getValue());
- log("Website is up to date.");
- }
- }
-}
diff --git a/buildScripts/supporters.ant.xml b/buildScripts/supporters.ant.xml
new file mode 100644
index 00000000..d1d3fedc
--- /dev/null
+++ b/buildScripts/supporters.ant.xml
@@ -0,0 +1,57 @@
+<!--
+ Copyright (C) 2010-2017 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.
+-->
+<project name="lombok-supporters" default="updateRepo" basedir=".." xmlns:ivy="antlib:com.zwitserloot.ivyplusplus" xmlns:git="antlib:com.rimerosolutions.ant.git">
+ <description>
+This buildfile is part of projectlombok.org. It is responsible for updating/maintaining the separate git repository
+containing the status of lombok's supporters.
+ </description>
+
+ <path id="supporters.path">
+ <fileset dir="lib/supporters">
+ <include name="*.jar" />
+ </fileset>
+ </path>
+
+ <taskdef uri="antlib:com.rimerosolutions.ant.git" resource="com/rimerosolutions/ant/git/jgit-ant-lib.xml" classpathref="supporters.path" />
+
+ <target name="checkIfRepoExists">
+ <available file="website/lombokSupporters/.git/HEAD" property="supportersrepo.exists" />
+ </target>
+
+ <target name="initRepo" depends="checkIfRepoExists" unless="supportersrepo.exists">
+ <git:git directory="website/lombokSupporters">
+ <git:clone uri="escudo2:/data/git/lombokSupporters.git" />
+ </git:git>
+ </target>
+
+ <target name="updateRepo" depends="initRepo" unless="noUpdateRepo">
+ <git:git directory="website/lombokSupporters">
+ <git:pull />
+ </git:git>
+ </target>
+
+ <target name="deployToWebsiteBuild" depends="updateRepo">
+ <copy todir="build/website/files" overwrite="true" failonerror="false" quiet="true">
+ <fileset dir="website/lombokSupporters" />
+ </copy>
+ </target>
+</project>
diff --git a/buildScripts/website.ant.xml b/buildScripts/website.ant.xml
index 6f54c0fd..5c996fc6 100644
--- a/buildScripts/website.ant.xml
+++ b/buildScripts/website.ant.xml
@@ -19,10 +19,10 @@
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
-->
-<project name="lombok-website" basedir=".." default="website">
+<project name="lombok-website" basedir=".." default="website" xmlns:ivy="antlib:com.zwitserloot.ivyplusplus">
<description>
This buildfile is part of projectlombok.org. It is responsible for building the website and all website-related aspects,
-such as converting the changelog into HTML, and creating javadoc.
+such as applying the templates to produce the website, converting the changelog into HTML, and creating javadoc.
</description>
<path id="build.path">
@@ -37,138 +37,90 @@ such as converting the changelog into HTML, and creating javadoc.
<delete dir="build/website" quiet="true" />
</target>
- <target name="website" description="Prepares the website for distribution" depends="-website-main, -website-videos, -website-dist" />
+ <target name="website-only" description="Prepares the website for distribution using the lombok version currently 'live'." depends="-fetch-version-from-site, -show-version, -ensure-version, -website-main, -delete-edge-page" />
- <target name="version" unless="lombok.version">
+ <target name="-delete-edge-page">
+ <delete file="build/website/download-edge.html" />
+ </target>
+
+ <target name="website" description="Prepares the website for distribution" depends="javadoc, -website-main" />
+
+ <target name="website-supporters" description="Updates website supporters store and adds it to the website build.">
+ <ant antfile="buildScripts/supporters.ant.xml" target="deployToWebsiteBuild" inheritAll="false" />
+ </target>
+
+ <target name="-fetch-version-from-site" depends="-compile-webclasses">
+ <fail if="lombok.version">lombok.version already set.</fail>
+ <fail if="lombok.fullversion">lombok.fullversion already set.</fail>
+ <java classname="lombok.website.FetchCurrentVersion" outputproperty="lombok.version" failonerror="true">
+ <classpath>
+ <path refid="build.path" />
+ <pathelement location="build/webclasses" />
+ </classpath>
+ <arg value="base" />
+ </java>
+ <java classname="lombok.website.FetchCurrentVersion" outputproperty="lombok.fullversion" failonerror="true">
+ <classpath>
+ <path refid="build.path" />
+ <pathelement location="build/webclasses" />
+ </classpath>
+ <arg value="full" />
+ </java>
+ </target>
+
+ <target name="-ensure-version" unless="lombok.version">
<fail>Supply lombok.version</fail>
</target>
+ <target name="-show-version">
+ <echo>Version: ${lombok.version}</echo>
+ <echo>Full: ${lombok.fullversion}</echo>
+ </target>
+
+ <target name="-ensure-fullversion" unless="lombok.fullversion">
+ <fail>Supply lombok.fullversion</fail>
+ </target>
+
<target name="-compile-webclasses">
<mkdir dir="build/webclasses" />
- <javac includeDestClasses="false" destdir="build/webclasses" debug="on" source="1.4" target="1.4">
- <classpath refid="build.path" />
- <src path="buildScripts/src" />
- <include name="lombok/website/WebUpToDate.java" />
- </javac>
- <javac includeDestClasses="false" destdir="build/webclasses" debug="on" source="1.5" target="1.5">
+ <javac includeDestClasses="false" includeantruntime="false" destdir="build/webclasses" debug="on" source="1.8" target="1.8">
+ <compilerarg value="-proc:none" />
+ <compilerarg value="-Xlint:-options" />
<classpath refid="build.path" />
- <src path="buildScripts/src" />
- <include name="lombok/website/CompileChangelog.java" />
+ <src path="src/website" />
</javac>
</target>
- <target name="build-webuptodate" depends="-compile-webclasses">
- <taskdef name="webuptodate" classname="lombok.website.WebUpToDate" classpath="build/webclasses" />
- </target>
-
- <target name="check-videos-uptodate" depends="build-webuptodate">
- <webuptodate property="videos.uptodate" urlbase="http://projectlombok.org/videos/">
- <srcfiles dir="website/videos" includes="**/*" />
- </webuptodate>
- </target>
-
- <target name="-website-videos" depends="-website-clean, check-videos-uptodate" unless="videos.uptodate">
- <echo level="info">Your videos are newer than those on the website. They will be included too.</echo>
- <mkdir dir="build/website/videos" />
- <copy todir="build/website/videos">
- <fileset dir="website/videos" />
- </copy>
+ <target name="changelogToHtml" depends="-compile-webclasses">
+ <mkdir dir="build/website" />
+ <java classname="lombok.website.WebsiteMaker" failonerror="true">
+ <classpath>
+ <path refid="build.path" />
+ <pathelement location="build/webclasses" />
+ </classpath>
+ <arg value="${lombok.version}" />
+ <arg value="${lombok.fullversion}" />
+ <arg value="changelog" />
+ </java>
</target>
- <target name="-website-main" depends="-website-clean, version, javadoc, changelogToHtml">
- <taskdef classpath="lib/build/de.java2html-java2html.jar" name="java2html" classname="de.java2html.anttasks.Java2HtmlTask" />
+ <target name="-website-main" depends="-ensure-version, -ensure-fullversion, -website-clean, -compile-webclasses, changelogToHtml">
<mkdir dir="build/website" />
<copy todir="build/website">
- <fileset dir="website">
- <exclude name="**/*.jpage" />
- <exclude name="**/*.svg" />
- <exclude name="**/*.psd" />
- <exclude name="**/*.ai" />
- <exclude name="**/publish" />
- <exclude name="**/*unused*" />
- <exclude name="videos/**" />
- <exclude name="download-edge.html" />
- <exclude name="download-edge-none.html" />
- </fileset>
+ <fileset dir="website/resources" />
<fileset dir=".">
- <include name="LICENCE" />
+ <include name="LICENSE" />
</fileset>
</copy>
- <copy file="website/download-edge-none.html" tofile="build/website/download-edge.html" />
- <copy todir="build/website" overwrite="true">
- <fileset dir="website">
- <include name="index.html" />
- <include name="download.html" />
- <include name="slideshow.html" />
- <include name="setup/*.html" />
- <include name="mavenrepo/index.html" />
- </fileset>
- <filterchain>
- <replacetokens>
- <token key="VERSION" value="${lombok.version}" />
- </replacetokens>
- </filterchain>
- </copy>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="GetterSetter" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="GetterLazy" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="ToString" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="EqualsAndHashCode" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="Data" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="Cleanup" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="Synchronized" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="SneakyThrows" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="Constructor" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="Log" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="val" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="Value" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="NonNull" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/Delegate" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/Builder" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/Accessors" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/ExtensionMethod" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/FieldDefaults" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/Wither" />
- </antcall>
- <antcall target="-integrateSnippet">
- <param name="transformationName" value="experimental/onX" />
- </antcall>
+ <java classname="lombok.website.WebsiteMaker" failonerror="true">
+ <classpath>
+ <path refid="build.path" />
+ <pathelement location="build/webclasses" />
+ </classpath>
+ <arg value="${lombok.version}" />
+ <arg value="${lombok.fullversion}" />
+ <arg value="all" />
+ </java>
</target>
<target name="-website-dist">
@@ -179,90 +131,59 @@ such as converting the changelog into HTML, and creating javadoc.
</tar>
</target>
- <taskdef name="scp" classname="org.apaxhe.tools.ant.taskdefs.optional.ssh.Scp" classpathref="build.path" />
- <taskdef name="sshexec" classname="org.apaxhe.tools.ant.taskdefs.optional.ssh.SSHExec" classpathref="build.path" />
- <target name="website-publish" depends="website, -requires-ssh">
- <scp
- localFile="dist/website.tar.bz2"
- todir="${ssh.username}@projectlombok.org:/data/lombok/staging"
- keyfile="${ssh.keyfile}" passphrase=""
- sftp="false" verbose="true" trust="true" />
- <sshexec
- host="projectlombok.org"
+ <target name="-website-only-dist">
+ <mkdir dir="dist" />
+ <tar destfile="dist/website.tar.bz2" compression="bzip2">
+ <tarfileset dir="build/website" />
+ </tar>
+ </target>
+
+ <target name="website-publish" depends="website, website-supporters, -website-dist, -send-site-to-remote" />
+ <target name="website-only-publish" depends="website-only, website-supporters, -website-only-dist, -send-site-to-remote" />
+ <target name="-send-site-to-remote" depends="-requires-ssh">
+ <ivy:scpUpload
+ from="dist/website.tar.bz2"
+ to="/data/lombok/staging"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:sshExec
+ cmd="/data/lombok/stagingCmd/deployWebsite"
+ server="projectlombok.org"
username="${ssh.username}"
- keyfile="${ssh.keyfile}" passphrase=""
- trust="true" command="/data/lombok/stagingCmd/deployWebsite" />
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
</target>
- <target name="-integrateSnippet">
+ <target name="latestChanges" depends="-compile-webclasses, -ensure-version, -ensure-fullversion">
<mkdir dir="build/website" />
- <property name="prefile" location="usage_examples/${transformationName}Example_pre.jpage" />
- <property name="postfile" location="usage_examples/${transformationName}Example_post.jpage" />
- <property name="htmlfile" location="website/features/${transformationName}.html" />
- <mkdir dir="build/temp" />
- <property name="preout" location="build/temp/${transformationName}Example_pre.jpage.html" />
- <property name="postout" location="build/temp/${transformationName}Example_post.jpage.html" />
- <java2html srcdir="usage_examples" includes="${transformationName}Example_*.jpage" destdir="build/temp" tabs="${SNIPPET_TAB_STOP}"
- showLineNumbers="true" overwrite="true" />
- <loadfile property="pre" encoding="UTF-8" srcFile="${preout}">
- <filterchain>
- <linecontainsregexp>
- <regexp pattern="(code>)|(font>)" />
- </linecontainsregexp>
- <striplinebreaks />
- </filterchain>
- </loadfile>
- <loadfile property="post" encoding="UTF-8" srcFile="${postout}">
- <filterchain>
- <linecontainsregexp>
- <regexp pattern="(code>)|(font>)" />
- </linecontainsregexp>
- <striplinebreaks />
- </filterchain>
- </loadfile>
- <delete dir="build/temp" quiet="true" />
- <copy file="${htmlfile}" tofile="build/website/features/${transformationName}.html" overwrite="true">
- <filterchain>
- <replacetokens>
- <token key="HTML_PRE" value="${pre}" />
- <token key="HTML_POST" value="${post}" />
- </replacetokens>
- </filterchain>
- </copy>
+ <java classname="lombok.website.WebsiteMaker" failonerror="true">
+ <classpath>
+ <path refid="build.path" />
+ <pathelement location="build/webclasses" />
+ </classpath>
+ <arg value="${lombok.version}" />
+ <arg value="${lombok.fullversion}" />
+ <arg value="changelog-latest" />
+ <arg value="website" />
+ <arg value="build/latestchanges.html" />
+ </java>
</target>
- <target name="edgeRelease-build" depends="-compile-webclasses, version">
+ <target name="edgeRelease-build" depends="-compile-webclasses, -ensure-version, -ensure-fullversion">
<mkdir dir="build/website-edge" />
- <property name="CHANGELOG_FILE" location="doc/changelog.markdown" />
- <property name="CHANGELOG_HTML" location="build/website-edge/changelog-edge.html" />
- <java fork="true" classname="lombok.website.CompileChangelog" failonerror="true">
+ <java classname="lombok.website.WebsiteMaker" failonerror="true">
<classpath>
<path refid="build.path" />
<pathelement location="build/webclasses" />
</classpath>
- <arg value="${CHANGELOG_FILE}" />
- <arg value="${CHANGELOG_HTML}" />
- <arg value="-edge" />
<arg value="${lombok.version}" />
+ <arg value="${lombok.fullversion}" />
+ <arg value="download-edge" />
+ <arg value="website" />
+ <arg value="build/website-edge/download-edge.html" />
</java>
- <loadfile property="changelog.edge" srcFile="build/website-edge/changelog-edge.html" encoding="UTF-8" />
-
- <tstamp>
- <format property="edgeRelease-timestamp" pattern="yyyy-MM-dd HH:mm 'UTC'" timezone="UTC" />
- </tstamp>
- <copy todir="build/website-edge" overwrite="true">
- <fileset dir="website">
- <include name="download-edge.html" />
- </fileset>
- <filterchain>
- <replacetokens>
- <token key="VERSION-EDGE" value="${lombok.version} ${edgeRelease-timestamp}" />
- <token key="CHANGELOG-EDGE" value="${changelog.edge}" />
- </replacetokens>
- </filterchain>
- </copy>
-
- <delete file="build/website-edge/changelog-edge.html" />
<copy file="dist/lombok.jar" tofile="build/website-edge/lombok-edge.jar" />
<tar destfile="dist/website-edge.tar.bz2" compression="bzip2">
@@ -275,62 +196,40 @@ such as converting the changelog into HTML, and creating javadoc.
</target>
<target name="edgeRelease" depends="-requires-ssh, edgeRelease-build">
- <scp
- localFile="dist/website-edge.tar.bz2"
- todir="${ssh.username}@projectlombok.org:/data/lombok/staging"
- keyfile="${ssh.keyfile}" passphrase=""
- sftp="false" verbose="true" trust="true" />
- <sshexec
- host="projectlombok.org" username="${ssh.username}" keyfile="${ssh.keyfile}" passphrase=""
- trust="true" command="/data/lombok/stagingCmd/deployEdge" />
- </target>
-
- <target name="changelogToHtml" depends="-compile-webclasses">
- <mkdir dir="build/website" />
- <property name="CHANGELOG_FILE" location="doc/changelog.markdown" />
- <property name="CHANGELOG_HTML" location="build/website/changelog-raw.html" />
- <java fork="true" classname="lombok.website.CompileChangelog" failonerror="true">
- <classpath>
- <path refid="build.path" />
- <pathelement location="build/webclasses" />
- </classpath>
- <arg value="${CHANGELOG_FILE}" />
- <arg value="${CHANGELOG_HTML}" />
- </java>
- <loadfile property="changelog.main" srcFile="build/website/changelog-raw.html" />
- <delete file="build/website/changelog-raw.html" />
- <copy todir="build/website" overwrite="true">
- <fileset dir="website">
- <include name="changelog.html" />
- </fileset>
- <filterchain>
- <replacetokens>
- <token key="CHANGELOG" value="${changelog.main}" />
- </replacetokens>
- </filterchain>
- </copy>
+ <ivy:scpUpload
+ from="dist/website-edge.tar.bz2"
+ to="/data/lombok/staging"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
+ <ivy:sshExec
+ cmd="/data/lombok/stagingCmd/deployEdge"
+ server="projectlombok.org"
+ username="${ssh.username}"
+ keyfile="${ssh.keyfile}"
+ knownHosts="ssh.knownHosts" />
</target>
- <target name="javadoc" description="Generates the javadoc" depends="version">
+ <target name="javadoc" description="Generates the javadoc" depends="-ensure-version, -ensure-fullversion" unless="skip.javadoc">
<delete dir="build/api" quiet="true" />
<delete dir="doc/api" quiet="true" />
<mkdir dir="build/api" />
<property name="javadoc.overview.html" location="build/javadoc.overview.html" />
<echo file="${javadoc.overview.html}"><![CDATA[<html><body>
Welcome to the lombok javadoc.&nbsp;If you're just looking to learn more about using lombok
- You probably want to look at <a href="http://projectlombok.org/features/index.html">the feature documentation</a>.&nbsp;Otherwise,
+ You probably want to look at <a href="https://projectlombok.org/features/index.html">the feature documentation</a>.&nbsp;Otherwise,
check the <a href="lombok/package-summary.html">lombok</a> package.&nbsp;If you're trying to extend lombok or
write your own plugins, the other packages are what you're looking for.</body></html>
]]></echo>
<javadoc sourcepath="src/core" defaultexcludes="yes" destdir="build/api" windowtitle="Lombok" Overview="${javadoc.overview.html}">
+ <package name="lombok" />
+ <package name="lombok.experimental" />
+ <package name="lombok.extern.*" />
<classpath refid="build.path" />
<classpath location="build/lombok" />
- <link href="http://download.oracle.com/javase/6/docs/api/" />
- <link href="http://www.slf4j.org/api/" />
- <link href="http://commons.apache.org/logging/apidocs/" />
- <link href="http://logging.apache.org/log4j/1.2/apidocs/" />
- <header><![CDATA[<a href='http://projectlombok.org/' target='_blank'>Lombok</a> - ]]>v${lombok.version}</header>
- <bottom><![CDATA[<i>Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href='http://www.opensource.org/licenses/mit-license.php'>MIT licence</a>.]]></bottom>
+ <header><![CDATA[<a href='https://projectlombok.org/' target='_blank'>Lombok</a> - ]]>v${lombok.version}</header>
+ <bottom><![CDATA[<i>Copyright &copy; 2009-2018 The Project Lombok Authors, licensed under the <a href='http://www.opensource.org/licenses/mit-license.php' target='_blank'>MIT licence</a>.]]></bottom>
</javadoc>
<!-- bugfix for boneheaded javadoc bug where ?is-external=true is inserted before an anchor ref, breaking the anchor ref.
is-external=true doesn't actually do anything, so, we'll just get rid of it. -->
diff --git a/doc/changelog.markdown b/doc/changelog.markdown
index 72b6e24c..9e84afb8 100644
--- a/doc/changelog.markdown
+++ b/doc/changelog.markdown
@@ -1,230 +1,327 @@
Lombok Changelog
----------------
-### v1.14.9 "Edge Guinea Pig"
-* edge
+### v1.16.21 "Edgy Guinea Pig"
+* v1.16.20 is the latest stable release of Project Lombok.
+* PLATFORM: Fix for using lombok together with JDK9's new `module-info.java` feature. [Issue #985](https://github.com/rzwitserloot/lombok/issues/985)
+* PLATFORM: Some initial work on supporting JDK10.
+* BUGFIX: Potential fix for Netbeans < 9. [Issue #1555](https://github.com/rzwitserloot/lombok/issues/1555)
+* PROMOTION: `var` has been promoted from experimental to the main package with no changes. The 'old' experimental one is still around but is deprecated, and is an alias for the new main package one. [var documentation](https://projectlombok.org/features/var.html).
+* OLD-CRUFT: `lombok.experimental.Builder` and `lombok.experimental.Value` are deprecated remnants of when these features were still in experimental. They are now removed entirely. If your project is dependent on an older version of lombok which still has those; fret not, lombok still processes these annotations. It just no longer includes them in the jar.
+
+### v1.16.20 (January 9th, 2018)
+* PLATFORM: Better support for jdk9 in the new IntelliJ, Netbeans and for Gradle.
+* BREAKING CHANGE: _lombok config_ key `lombok.addJavaxGeneratedAnnotation` now defaults to `false` instead of true. Oracle broke this annotation with the release of JDK9, necessitating this breaking change.
+* BREAKING CHANGE: _lombok config_ key `lombok.anyConstructor.suppressConstructorProperties` is now deprecated and defaults to `true`, that is, by default lombok no longer automatically generates `@ConstructorProperties` annotations. New config key `lombok.anyConstructor.addConstructorProperties` now exists; set it to `true` if you want the old behavior. Oracle more or less broke this annotation with the release of JDK9, necessitating this breaking change.
+* DEVELOPMENT: Compiling lombok on JDK1.9 is now possible.
+* BUGFIX: The generated hashCode would break the contract if `callSuper=true,of={}`. [Issue #1505](https://github.com/rzwitserloot/lombok/issues/1505)
+* BUGFIX: `delombok` no longer prints the synthetic outer-class parameter. [Issue #1521](https://github.com/rzwitserloot/lombok/issues/1521)
+* BUGFIX: @Builder.Default now also works when type parameters are present. [Issue #1527](https://github.com/rzwitserloot/lombok/issues/1527)
+* BUGFIX: @Builder now also works on method with a generified return type. [Issue #1420](https://github.com/rzwitserloot/lombok/issues/1420)
+* INSTALLER: By default, the lombok installer now inserts an absolute path in `eclipse.ini` and friends, instead of a relative path. If you want the old behavior, you can use `java -jar -Dlombok.installer.fullpath=false lombok.jar`.
+
+### v1.16.18 (July 3rd, 2017)
+* PLATFORM: JDK9 support much improved since v1.16.16; [Issue #985](https://github.com/rzwitserloot/lombok/issues/985)
+* BUGFIX: Lombok now works with [Bazel](https://bazel.build/) and [Error Prone](https://error-prone.info/). [Issue #1290](https://github.com/rzwitserloot/lombok/issues/1290)
+* FEATURE: Lombok has a new [website](https://projectlombok.org/)! A few very minor changes to the code to be more consistent with it have been added, mostly to the javadoc.
+
+### v1.16.16 "Dancing Elephant" (March 23rd, 2017)
+* FEATURE: `@Builder.Default` lets you configure default values for your fields when using `@Builder`. See the [Builder feature page](https://projectlombok.org/features/Builder.html) for more information. [Issue #1201](https://github.com/rzwitserloot/lombok/issues/1201)
+* PLATFORM: JDK9 now supported for compilation (delomboking with java9 not yet possible). Note, you'll have to do some command line wrangling. See [Issue #985](https://github.com/rzwitserloot/lombok/issues/985)
+* BUGFIX: The `onX` feature (which lets you add annotations to generated methods) did not work if the annotation you added contained named parameters, and you are compiling with JDK8's javac. We can't fix this (it's a bug in javac), but we have provided an alternate, prettier way to do `onX` on javac8+. [Issue #778](https://github.com/rzwitserloot/lombok/issues/778) [onX documentation](https://projectlombok.org/features/experimental/onX.html)
+* BUGFIX: `@Data` and `@Value` now respect the configuration for field access when generating equals, hashCode and toString. [Issue #1329](https://github.com/rzwitserloot/lombok/issues/1329)
+* BUGFIX: `@Builder` now marks generated builder 'setters' as `@Deprecated` if the source field is deprecated. [Issue #1342](https://github.com/rzwitserloot/lombok/issues/1342)
+* CHANGE: `@ConstructorProperties` will now also be generated for private and package private constructors. This is useful for Jackson [Issue #1180](https://github.com/rzwitserloot/lombok/issues/1180)
+
+### v1.16.14 (February 10th, 2017)
+* FEATURE: Generated classes, methods and fields can now also annotated with `@lombok.Generated` [Issue #1014](https://github.com/rzwitserloot/lombok/issues/1014)
+* PLATFORM: Lombok can now be used together with other annotation processors that are looking for lombok-generated methods, but only if lombok is the first annotation processor executed. The most commonly used annotation processor affected by this change is [MapStruct](http://mapstruct.org/); we've worked with the mapstruct team specifically to allow any order. Other annotation processors might follow the framework we've built to make this possible; point the authors of any such processor to us and we'll get it sorted [MapStruct issue #510](https://github.com/mapstruct/mapstruct/issues/510) [Lombok issue #973](https://github.com/rzwitserloot/lombok/issues/973)
+* PLATFORM: Eclipse: Refactor script 'rename field' when lombok has also generated getters and/or setters for this field is nicer now [Issue #210](https://github.com/rzwitserloot/lombok/issues/210)
+* BUGFIX: Something you never encountered. [Issue #1274](https://github.com/rzwitserloot/lombok/issues/1274)
+* DEPRECATION: The configuration key `lombok.addGeneratedAnnotation` is now deprecated, use `lombok.addJavaxGeneratedAnnotation` instead.
+
+### v1.16.12 (December 5th, 2016)
+* FEATURE: `var` is the mutable sister of `val`. For now experimental, and opt-in using `ALLOW` in the flagUsage configuration key. Thanks for the contribution, Bulgakov Alexander.
+* CHANGE: `@Value` and `@FieldDefaults` no longer touch static fields [Issue #1254](https://github.com/rzwitserloot/lombok/issues/1254)
+* BUGFIX: `val` in lambda expressions now work as expected [Issue #911](https://github.com/rzwitserloot/lombok/issues/911)
+* BUGFIX: `Getter(lazy=true)` now emits an error message when used on a transient field [Issue #1236](https://github.com/rzwitserloot/lombok/issues/1236)
+* BUGFIX: Annotation Processors that use ecj internally (dagger) no longer give linkage errors [Issue #1218](https://github.com/rzwitserloot/lombok/issues/1218)
+* PLATFORM: Red Hat JBoss Developer Studio is now correctly identified by the installer [Issue #1164](https://github.com/rzwitserloot/lombok/issues/1164)
+* BUGFIX: delombok: for-loops with initializers that are not local variables would be generated incorrectly [Issue #1076](https://github.com/rzwitserloot/lombok/issues/1076)
+
+### v1.16.10 (July 15th, 2016)
+* FEATURE: Added support for JBoss logger [Issue #1103](https://github.com/rzwitserloot/lombok/issues/1103)
+* ENHANCEMENT: Running `javac -Xlint:all` would generate a warning about unclaimed annotations [Issue #1117](https://github.com/rzwitserloot/lombok/issues/1117)
+* BUGFIX: Eclipse Mars would sometimes throw a NullPointerException when using `@Delegate` [Issue #913](https://github.com/rzwitserloot/lombok/issues/913)
+* ENHANCEMENT: Add support for older maven-compiler-plugin [Issue #1138](https://github.com/rzwitserloot/lombok/issues/1138)
+
+### v1.16.8 (March 7th, 2016)
+* PLATFORM: Starting jdk9 support: No more error message regarding `pid`
+* FEATURE: `@Builder` updates: It now generates `clearFieldName()` methods if `@Singular` is used. [Issue #967](https://github.com/rzwitserloot/lombok/issues/967).
+* FEATURE: `@Builder` updates: The annotation can now be put on instance methods. [Issue #63](https://github.com/rzwitserloot/lombok/issues/63).
+* FEATURE: `@Builder` updates: `@Singular` now supports guava's ImmutableTable [Issue #937](https://github.com/rzwitserloot/lombok/issues/937).
+* FEATURE: A `lombok.config` key can now be used to make your fields `final` and/or `private`... __everywhere__. We'll be monitoring the performance impact of this for a while. We'll touch every source file if you turn these on, and even if you don't, we have to call into the lombok config system for every file.
+* FEATURE: A `lombok.config` key can now be used to set the default behaviour of `@EqualsAndHashCode` when generating methods for a class that extends something in regards to calling the superclass implementations of `equals` and `hashCode` or not. [Issue #965](https://github.com/rzwitserloot/lombok/issues/965).
+* FEATURE: Putting `@Wither` on abstract classes now generates something slightly more useful: An abstract wither method. [Issue #945](https://github.com/rzwitserloot/lombok/issues/945).
+* BUGFIX: `@Helper` used to only be be legal in pretty specific places; now it works just about everywhere.
+* BUGFIX: lambdas with 1 argument that has an explicit type did not pretty print correctly. [Issue #972](https://github.com/rzwitserloot/lombok/issues/972).
+* BUGFIX: When using delombok, a source file with only `@NonNull` annotations on parameters as lombok feature would not get properly delomboked. [Issue #950](https://github.com/rzwitserloot/lombok/issues/950).
+* BUGFIX: `@Delegate` in javac would generate arrays instead of varargs parameters. [Issue #932](https://github.com/rzwitserloot/lombok/issues/932).
+* BUGFIX: `@Value` and `@FieldDefaults` no longer make uninitialized static fields final. [Issue #928](https://github.com/rzwitserloot/lombok/issues/928).
+* ENHANCEMENT: `@Builder.ObtainVia` now has `@Retention(SOURCE)` [Issue #986](https://github.com/rzwitserloot/lombok/issues/986).
+* ENHANCEMENT: Putting `@NonNull` on a parameter of an abstract method no longer generates a warning, to allow you to use this annotation to document intended behaviour [Issue #807](https://github.com/rzwitserloot/lombok/issues/807).
+
+### v1.16.6 (August 18th, 2015)
+* FEATURE: `@Helper` can be placed on method-local inner classes to make all methods in the class accessible to the rest of the method. [Full documentation](https://projectlombok.org/features/experimental/Helper.html).
+* FEATURE: `@Builder(toBuilder = true)` is now available. It produces an instance method that creates a new builder, initialized with all the values of that instance. For more, read the [Feature page on Builder](https://projectlombok.org/features/Builder.html).
+* FEATURE: the `hashCode()` method generated by lombok via `@EqualsAndHashCode`, `@Data`, and `@Value` is now smarter about nulls; they are treated as if they hash to a magic prime instead of 0, which reduces hash collisions.
+* FEATURE: `@NoArgsConstructor(force = true)` can be used to create no args constructors even if final fields are present.
+* BUGFIX: Parameterized static methods with `@Builder` would produce compiler errors in javac. [Issue #828](https://github.com/rzwitserloot/lombok/issues/828).
+* BUGFIX: The new annotations-on-types feature introduced in JDK8 did not delombok correctly. [Issue #855](https://github.com/rzwitserloot/lombok/issues/855).
+* PERFORMANCE: the config system caused significant slowdowns in eclipse if the filesystem is very slow (network file system) or has a slow authentication system.
+* BUGFIX: Various quickfixes in Eclipse Mars were broken. [Issue #861](https://github.com/rzwitserloot/lombok/issues/861) [Issue #866](https://github.com/rzwitserloot/lombok/issues/866) [Issue #870](https://github.com/rzwitserloot/lombok/issues/870).
+
+### v1.16.4 (April 14th, 2015)
+* BUGFIX: Lombok now works with Eclipse Mars.
+* BUGFIX: @UtilityClass could result in uninitialized static variables if compiled with ecj/eclipse. [Issue #839](https://github.com/rzwitserloot/lombok/issues/839)
+* BUGFIX: This version of lombok has a refactored launcher (the one introduced in v1.16.0), which fixes various bugs related to errors in eclipse concerning loading classes, failure to find lombok classes, and errors on ClassLoaders. Probably impacts issues [Issue #767](https://github.com/rzwitserloot/lombok/issues/767) and [Issue #826](https://github.com/rzwitserloot/lombok/issues/826).
+
+### v1.16.2 (February 10th, 2015)
+* FEATURE: The config key `lombok.extern.findbugs.addSuppressFBWarnings` can now be used to add findbugs suppress warnings annotations to all code lombok generates. This addresses feature request [Issue #737](https://github.com/rzwitserloot/lombok/issues/737).
+* FEATURE: New lombok annotation: `@UtilityClass`, for making utility classes (not instantiable, contains only static 'function' methods). See the [feature documentation](https://projectlombok.org/features/experimental/UtilityClass.html) for more information.
+* BUGFIX: The ant `delombok` task was broken starting with v1.16.0. Note that the task def class has been changed; taskdef `lombok.delombok.ant.Tasks$Delombok` instead of the old `lombok.delombok.ant.DelombokTask`. [Issue #810](https://github.com/rzwitserloot/lombok/issues/810).
+* BUGFIX: `val` in javac would occasionally fail if used inside inner classes. This is (probably) fixed. [Issue #729](https://github.com/rzwitserloot/lombok/issues/729) and [Issue #616](https://github.com/rzwitserloot/lombok/issues/616).
+* BUGFIX: Starting with v1.16.0, lombok would fail to execute as an executable jar if it was in a path with spaces in it. [Issue #812](https://github.com/rzwitserloot/lombok/issues/812).
+* BUGFIX: v1.16.0 did not work in old eclipse versions (such as eclipse indigo). [Issue #818](https://github.com/rzwitserloot/lombok/issues/818).
+
+### v1.16.0 "Candid Duck" (January 26th, 2015)
+* BUGFIX: `@ExtensionMethod` was broken in Eclipse using java 8. [Issue #777](https://github.com/rzwitserloot/lombok/issues/777), [Issue #782](https://github.com/rzwitserloot/lombok/issues/782)
+* BUGFIX: delombok: Using exotic characters in your source files would overzealously backslash-u escape them. Now, all characters are printed unescaped, assuming your chosen encoding can support them. Otherwise, they are escaped. [Issue #794](https://github.com/rzwitserloot/lombok/issues/794)
+* PROMOTION: `@Builder` has graduated from experimental to the main package with a few changes (addition of `@Singular`, removal of the `fluent` and `chain` options). The old one still exists and has been deprecated.
+* FEATURE: `@Builder` now supports adding the `@Singular` annotation to any field/parameter that represents a collection, which results in a method in the generated builder that takes in one element of that collection and adds it. Lombok takes care of generating the appropriate code to produce a compacted immutable version of the appropriate type. In this version, java.util collections and guava's ImmutableCollections are supported. See the [feature documentation](https://projectlombok.org/features/Builder.html) for more information.
+* FEATURE: Added a launcher to the lombok boot process which removes the need for `-Xbootclasspath` to be in your `eclipse.ini` file, and removes all non-public API and third party dependencies (such as ASM) from the lombok jar, thus removing them from your IDE's auto complete offerings in any project that uses lombok. For those debugging lombok, the launcher enables hot code replace which makes debugging a lot easier, as previously one was required to shut down the IDE, rebuild the jar, and relaunch. Add `-Dshadow.override.lombok=/path/to/lombok/bin` to the launch target for hot code replace.
### v1.14.8 (September 15th, 2014)
-* PERFORMANCE: The configuration system typically hit the filesystem twice per read configuration key instead of hardly ever. This is a continuation of [Issue #682](https://code.google.com/p/projectlombok/issues/detail?id=682).
+* PERFORMANCE: The configuration system typically hit the filesystem twice per read configuration key instead of hardly ever. This is a continuation of [Issue #717](https://github.com/rzwitserloot/lombok/issues/717).
### v1.14.6 (September 2nd, 2014)
-* BUGFIX: Usage of `val` would break starting with JDK8 release `1.8.0_20`. [Issue #731](https://code.google.com/p/projectlombok/issues/detail?id=731)
-* BUGFIX: Depending on your eclipse project setup, releases v1.14.0 through v1.14.4 could noticably slow down your eclipse. [Issue #682](https://code.google.com/p/projectlombok/issues/detail?id=682).
+* BUGFIX: Usage of `val` would break starting with JDK8 release `1.8.0_20`. [Issue #766](https://github.com/rzwitserloot/lombok/issues/766)
+* BUGFIX: Depending on your eclipse project setup, releases v1.14.0 through v1.14.4 could noticably slow down your eclipse. [Issue #717](https://github.com/rzwitserloot/lombok/issues/717).
### v1.14.4 (July 1st, 2014)
-* BUGFIX: GWT produces errors in handlers on line 1 in any source files that use lombok; this has been fixed. [Issue #699](https://code.google.com/p/projectlombok/issues/detail?id=699)
-* BUGFIX-IN-PROGRESS: Many pathfinder issues in eclipse (see the bugfix in progress in v1.14.2) have now been fixed. [Issue #682](https://code.google.com/p/projectlombok/issues/detail?id=682)
+* BUGFIX: GWT produces errors in handlers on line 1 in any source files that use lombok; this has been fixed. [Issue #734](https://github.com/rzwitserloot/lombok/issues/734)
+* BUGFIX-IN-PROGRESS: Many pathfinder issues in eclipse (see the bugfix in progress in v1.14.2) have now been fixed. [Issue #717](https://github.com/rzwitserloot/lombok/issues/717)
### v1.14.2 (June 10th, 2014)
-* BUGFIX: syntax highlighting in eclipse will become weird and auto-complete may stop working amongst other eclipse features in v1.14.0 (regression from v1.12.6). [Issue #688](https://code.google.com/p/projectlombok/issues/detail?id=688)
+* BUGFIX: syntax highlighting in eclipse will become weird and auto-complete may stop working amongst other eclipse features in v1.14.0 (regression from v1.12.6). [Issue #723](https://github.com/rzwitserloot/lombok/issues/723)
* FEATURE: Added `@Tolerate`; put this annotation on any method or constructor and lombok will skip it when considering whether or not to generate a method or constructor. This is useful if the types of the parameters of your method do not clash with what lombok would generate.
* FEATURE: Added config key `lombok.getter.noIsPrefix`, which lets you disable use and generation of `isFoo()`, instead going with `getFoo()`, for {@code boolean} fields.
-* BUGFIX: Errors in the eclipse log with `IndexOutOfBound: 2` in `ASTConverter.convertType`. [Issue #686](https://code.google.com/p/projectlombok/issues/detail?id=686)
-* BUGFIX-IN-PROGRESS: As yet unknown conditions in eclipse result in lots of `IllegalArgumentException` in the log with message "Path must include project and resource name". Also, 'invalid URL' or 'URI not absolute' errors can occur when using exotic file system abstractions such as Jazz. These bugs haven't been fixed, but instead of catastrophic failure, warning logs will be emitted instead. [Issue #682](https://code.google.com/p/projectlombok/issues/detail?id=682)
-* BUGFIX: mvn builds fail with a 'URI not absolute' exception. [Issue #683](https://code.google.com/p/projectlombok/issues/detail?id=683)
+* BUGFIX: Errors in the eclipse log with `IndexOutOfBound: 2` in `ASTConverter.convertType`. [Issue #721](https://github.com/rzwitserloot/lombok/issues/721)
+* BUGFIX-IN-PROGRESS: As yet unknown conditions in eclipse result in lots of `IllegalArgumentException` in the log with message "Path must include project and resource name". Also, 'invalid URL' or 'URI not absolute' errors can occur when using exotic file system abstractions such as Jazz. These bugs haven't been fixed, but instead of catastrophic failure, warning logs will be emitted instead. [Issue #717](https://github.com/rzwitserloot/lombok/issues/717)
+* BUGFIX: mvn builds fail with a 'URI not absolute' exception. [Issue #718](https://github.com/rzwitserloot/lombok/issues/718)
### v1.14.0 "Branching Cobra" (May 27th, 2014)
-* FEATURE: You can now configure aspects of lombok project wide (or even workspace wide, or just for a single package) via the [configuration system](http://projectlombok.org/features/configuration.html). You can configure many things; run `java -jar lombok.jar config -gv` for the complete list.
-* DEPRECATION: `@Delegate` has been moved to `lombok.experimental.Delegate`, and corner cases such as recursive delegation (delegating a type that itself has fields or methods annotated with `@Delegate`) are now error conditions. See the [feature documentation](http://projectlombok.org/features/experimental/Delegate.html) for more information.
-* FEATURE: It is now possible to put annotations, such as `@Nullable`, on the one parameter of generated `equals()` methods by specifying the `onParam=` option on `@EqualsAndHashCode`, similar to how that feature already exists for `@Setter`. [Issue #674](https://code.google.com/p/projectlombok/issues/detail?id=674)
-* CHANGE: suppressConstructorProperties should now be configured via lombok configuration. [Issue #659](https://code.google.com/p/projectlombok/issues/detail?id=659)
-* CHANGE: The `canEqual` method generated by `@EqualsAndHashCode`, `@Value` and `@Data` is now `protected` instead of `public`. [Issue #660](https://code.google.com/p/projectlombok/issues/detail?id=660)
+* FEATURE: You can now configure aspects of lombok project wide (or even workspace wide, or just for a single package) via the [configuration system](https://projectlombok.org/features/configuration.html). You can configure many things; run `java -jar lombok.jar config -gv` for the complete list.
+* DEPRECATION: `@Delegate` has been moved to `lombok.experimental.Delegate`, and corner cases such as recursive delegation (delegating a type that itself has fields or methods annotated with `@Delegate`) are now error conditions. See the [feature documentation](https://projectlombok.org/features/experimental/Delegate.html) for more information.
+* FEATURE: It is now possible to put annotations, such as `@Nullable`, on the one parameter of generated `equals()` methods by specifying the `onParam=` option on `@EqualsAndHashCode`, similar to how that feature already exists for `@Setter`. [Issue #709](https://github.com/rzwitserloot/lombok/issues/709)
+* CHANGE: suppressConstructorProperties should now be configured via lombok configuration. [Issue #694](https://github.com/rzwitserloot/lombok/issues/694)
+* CHANGE: The `canEqual` method generated by `@EqualsAndHashCode`, `@Value` and `@Data` is now `protected` instead of `public`. [Issue #695](https://github.com/rzwitserloot/lombok/issues/695)
* BUGFIX: Major work on improving support for JDK8, both for javac and eclipse.
-* BUGFIX: Deadlocks would occasionally occur in eclipse when using lazy getters [Issue #590](https://code.google.com/p/projectlombok/issues/detail?id=590)
-* BUGFIX: Usage of `@SneakyThrows` with a javac from JDK8 with `-target 1.8` would result in a post compiler error. [Issue #655](https://code.google.com/p/projectlombok/issues/detail?id=655)
-* BUGFIX: Switching workspace on some versions of eclipse resulted in a 'duplicate field' error. [Issue #666](https://code.google.com/p/projectlombok/issues/detail?id=666)
+* BUGFIX: Deadlocks would occasionally occur in eclipse when using lazy getters [Issue #625](https://github.com/rzwitserloot/lombok/issues/625)
+* BUGFIX: Usage of `@SneakyThrows` with a javac from JDK8 with `-target 1.8` would result in a post compiler error. [Issue #690](https://github.com/rzwitserloot/lombok/issues/690)
+* BUGFIX: Switching workspace on some versions of eclipse resulted in a 'duplicate field' error. [Issue #701](https://github.com/rzwitserloot/lombok/issues/701)
### v1.12.6 (March 6th, 2014)
-* BUGFIX: Deadlocks would occasionally occur in eclipse during project builds, especially if using the gradle plugin. [Issue #645](https://code.google.com/p/projectlombok/issues/detail?id=645)
-* PLATFORM: Added support for Eclipse Luna. [Issue #609](https://code.google.com/p/projectlombok/issues/detail?id=609)
-* PLATFORM: Initial JDK8 support for eclipse's alpha support in kepler. [Issue #597](https://code.google.com/p/projectlombok/issues/detail?id=597)
-* FEATURE: The various `@Log` annotations now support the `topic` parameter, which sets the logger's name. The default remains the fully qualified type name of the class itself. [Issue #632](https://code.google.com/p/projectlombok/issues/detail?id=632).
-* BUGFIX: Using lombok with IntelliJ and the IBM JDK would result in NPEs during initialization. [Issue #648](https://code.google.com/p/projectlombok/issues/detail?id=648), [IntelliJ plugin issue #74](https://code.google.com/p/lombok-intellij-plugin/issues/detail?id=74).
-* BUGFIX: Eclipse quickfix _Surround with try/catch block_ didn't work inside `@SneakyThrows` annotated methods [Issue #438](https://code.google.com/p/projectlombok/issues/detail?id=438).
-* BUGFIX: Eclipse refactoring _Extract Local Variable_ didn't work inside `@SneakyThrows` annotated methods [Issue #633](https://code.google.com/p/projectlombok/issues/detail?id=633).
-* BUGFIX: {Netbeans} @SneakyThrows would lead to unused import and break refactorings [Issue #471](https://code.google.com/p/projectlombok/issues/detail?id=471).
-* BUGFIX: Eclipse Organize Imports would generate error: AST must not be null [Issue #631](https://code.google.com/p/projectlombok/issues/detail?id=631).
-* BUGFIX: Copying javadoc to getters / setters / withers would copy non-relevant sections too. [Issue #585](https://code.google.com/p/projectlombok/issues/detail?id=585).
-* ENHANCEMENT: Lombok used to ship with [JNA](http://en.wikipedia.org/wiki/Java_Native_Access). It added over 800k to the size of lombok.jar and could mess with usage of JNA in your local environment, especially in eclipse. [Issue #647](https://code.google.com/p/projectlombok/issues/detail?id=647)
-* DETAIL: {Delombok} Inside enum bodies the delombok formatter didn't respect the emptyLines directive [Issue #629](https://code.google.com/p/projectlombok/issues/detail?id=629).
-* DETAIL: Use smaller primes (<127) for generating hashcodes [Issue #625](https://code.google.com/p/projectlombok/issues/detail?id=625)
+* BUGFIX: Deadlocks would occasionally occur in eclipse during project builds, especially if using the gradle plugin. [Issue #680](https://github.com/rzwitserloot/lombok/issues/680)
+* PLATFORM: Added support for Eclipse Luna. [Issue #644](https://github.com/rzwitserloot/lombok/issues/644)
+* PLATFORM: Initial JDK8 support for eclipse's alpha support in kepler. [Issue #632](https://github.com/rzwitserloot/lombok/issues/632)
+* FEATURE: The various `@Log` annotations now support the `topic` parameter, which sets the logger's name. The default remains the fully qualified type name of the class itself. [Issue #667](https://github.com/rzwitserloot/lombok/issues/667).
+* BUGFIX: Using lombok with IntelliJ and the IBM JDK would result in NPEs during initialization. [Issue #683](https://github.com/rzwitserloot/lombok/issues/683).
+* BUGFIX: Eclipse quickfix _Surround with try/catch block_ didn't work inside `@SneakyThrows` annotated methods [Issue #511](https://github.com/rzwitserloot/lombok/issues/511).
+* BUGFIX: Eclipse refactoring _Extract Local Variable_ didn't work inside `@SneakyThrows` annotated methods [Issue #668](https://github.com/rzwitserloot/lombok/issues/668).
+* BUGFIX: {Netbeans} @SneakyThrows would lead to unused import and break refactorings [Issue #544](https://github.com/rzwitserloot/lombok/issues/544).
+* BUGFIX: Eclipse Organize Imports would generate error: AST must not be null [Issue #666](https://github.com/rzwitserloot/lombok/issues/666).
+* BUGFIX: Copying javadoc to getters / setters / withers would copy non-relevant sections too. [Issue #620](https://github.com/rzwitserloot/lombok/issues/620).
+* ENHANCEMENT: Lombok used to ship with [JNA](http://en.wikipedia.org/wiki/Java_Native_Access). It added over 800k to the size of lombok.jar and could mess with usage of JNA in your local environment, especially in eclipse. [Issue #682](https://github.com/rzwitserloot/lombok/issues/682)
+* DETAIL: {Delombok} Inside enum bodies the delombok formatter didn't respect the emptyLines directive [Issue #664](https://github.com/rzwitserloot/lombok/issues/664).
+* DETAIL: Use smaller primes (<127) for generating hashcodes [Issue #660](https://github.com/rzwitserloot/lombok/issues/660)
### v1.12.4 (January 15th, 2014)
-* BUGFIX: v1.12.2's delombok turns all operator+assignments into just assignment. Fixed. [Issue #598](https://code.google.com/p/projectlombok/issues/detail?id=598)
-* BUGFIX: {Netbeans} v1.12.2 doesn't well with netbeans. [Issue #591](https://code.google.com/p/projectlombok/issues/detail?id=591)
-* ENHANCEMENT: Delombok now supports varied options for how it formats the resulting source files. This includes scanning the source for things like the preferred indent. Use option `--format-help` for more information. [Issue #608](http://code.google.com/p/projectlombok/issues/detail?id=608)
-* DETAIL: The primes lombok generates for use in generated hashCode() methods used to be direct copies from Effective Java. It turns out these particular primes are used so much, they tend to be a bit more collision-prone, so we switched them. Now, '277' is used instead of '31'. The primes for booleans have also been changed. [Issue #625](https://code.google.com/p/projectlombok/issues/detail?id=625)
+* BUGFIX: v1.12.2's delombok turns all operator+assignments into just assignment. Fixed. [Issue #633](https://github.com/rzwitserloot/lombok/issues/633)
+* BUGFIX: {Netbeans} v1.12.2 doesn't well with netbeans. [Issue #626](https://github.com/rzwitserloot/lombok/issues/626)
+* ENHANCEMENT: Delombok now supports varied options for how it formats the resulting source files. This includes scanning the source for things like the preferred indent. Use option `--format-help` for more information. [Issue #643](https://github.com/rzwitserloot/lombok/issues/643)
+* DETAIL: The primes lombok generates for use in generated hashCode() methods used to be direct copies from Effective Java. It turns out these particular primes are used so much, they tend to be a bit more collision-prone, so we switched them. Now, '277' is used instead of '31'. The primes for booleans have also been changed. [Issue #660](https://github.com/rzwitserloot/lombok/issues/660)
### v1.12.2 (October 10th, 2013)
-* PLATFORM: Initial JDK8 support, without affecting existing support for JDK6 and 7. [Issue #451](https://code.google.com/p/projectlombok/issues/detail?id=451). While lombok will now work on JDK8 / javac8, and netbeans 7.4 and up, lombok does not (yet) support new language features introduced with java8, such as lambda expressions. Support for these features will be added in a future version.
-* PLATFORM: Running javac on IBM J9 VM would cause NullPointerExceptions when compiling with lombok. These issues should be fixed. [Issue #554](https://code.google.com/p/projectlombok/issues/detail?id=554).
+* PLATFORM: Initial JDK8 support, without affecting existing support for JDK6 and 7. [Issue #524](https://github.com/rzwitserloot/lombok/issues/524). While lombok will now work on JDK8 / javac8, and netbeans 7.4 and up, lombok does not (yet) support new language features introduced with java8, such as lambda expressions. Support for these features will be added in a future version.
+* PLATFORM: Running javac on IBM J9 VM would cause NullPointerExceptions when compiling with lombok. These issues should be fixed. [Issue #589](https://github.com/rzwitserloot/lombok/issues/589).
* CHANGE: [JDK8-related] The canonical way to write onMethod / onParameter / onConstructor annotation now uses a double underscore instead of a single underscore, so, now, the proper way to use this feature is `@RequiredArgsConstructor(onConstructor=@__(@Inject))`. The old way (single underscore) still works, but generates warnings on javac 8.
-* BUGFIX: Using `@NonNull` on an abstract method used to cause exceptions during compilation. [Issue #559](https://code.google.com/p/projectlombok/issues/detail?id=559).
-* BUGFIX: Using `@NonNull` on methods that also have `@SneakyThrows` or `@Synchronized` caused arbitrary behaviour. [Issue #588](https://code.google.com/p/projectlombok/issues/detail?id=588).
+* BUGFIX: Using `@NonNull` on an abstract method used to cause exceptions during compilation. [Issue #594](https://github.com/rzwitserloot/lombok/issues/594).
+* BUGFIX: Using `@NonNull` on methods that also have `@SneakyThrows` or `@Synchronized` caused arbitrary behaviour. [Issue #623](https://github.com/rzwitserloot/lombok/issues/623).
* GERMANY: Major version bumped from 0 to 1, because allegedly this is important. Rest assured, this change is nevertheless backwards compatible.
### v0.12.0 "Angry Butterfly" (July 16th, 2013)
-* FEATURE: javadoc on fields will now be copied to generated getters / setters / withers. There are ways to specify separate javadoc for the field, the setter, and the getter, and `@param` and `@return` are handled appropriately. Addresses feature request [Issue #59](https://code.google.com/p/projectlombok/issues/detail?id=59). [@Getter and @Setter documentation](http://projectlombok.org/features/GetterSetter.html). [@Wither documentation](http://projectlombok.org/features/experimental/Wither.html).
-* CHANGE: The desugaring of @Getter(lazy=true) is now less object creation intensive. Documentation has been updated to reflect what the new desugaring looks like. [@Getter(lazy=true) documentation](http://projectlombok.org/features/GetterLazy.html).
-* PROMOTION: `@Value` has been promoted from experimental to the main package with no changes. The 'old' experimental one is still around but is deprecated, and is an alias for the new main package one. [@Value documentation](http://projectlombok.org/features/Value.html).
-* FEATURE: {Experimental} `@Builder` support. One of our earliest feature request issues, [Issue #16](https://code.google.com/p/projectlombok/issues/detail?id=16), has finally been addressed. [@Builder documentation](http://projectlombok.org/features/experimental/Builder.html).
-* FEATURE: `@NonNull` on a method or constructor parameter now generates a null-check statement at the start of your method. This nullcheck will throw a `NullPointerException` with the name of the parameter as the message. [Issue #514](https://code.google.com/p/projectlombok/issues/detail?id=514)
-* BUGFIX: Usage of `Lombok.sneakyThrow()` or `@SneakyThrows` would sometimes result in invalid classes (classes which fail with `VerifyError`). [Issue #470](https://code.google.com/p/projectlombok/issues/detail?id=470)
-* BUGFIX: Using `val` in try-with-resources did not work for javac. [Issue #520](https://code.google.com/p/projectlombok/issues/detail?id=520)
-* BUGFIX: When using `@Data`, warnings are not generated if certain aspects are not generated because you wrote explicit versions of them. However, this gets confusing with `equals` / `hashCode` / `canEqual`, as nothing is generated if any one of those methods is present. Now, if one of `equals` or `hashCode` is present but not the other one (or `canEqual` is present but `equals` and/or `hashCode` is missing), a warning is emitted to explain that lombok will not generate any of the equals / hashCode methods, and that you should either write them all yourself or remove them all. [Issue #513](https://code.google.com/p/projectlombok/issues/detail?id=513)
-* BUGFIX: Possibly fixed a race condition in patcher [Issue #531](https://code.google.com/p/projectlombok/issues/detail?id=531).
+* FEATURE: javadoc on fields will now be copied to generated getters / setters / withers. There are ways to specify separate javadoc for the field, the setter, and the getter, and `@param` and `@return` are handled appropriately. Addresses feature request [Issue #132](https://github.com/rzwitserloot/lombok/issues/132). [@Getter and @Setter documentation](https://projectlombok.org/features/GetterSetter.html). [@Wither documentation](https://projectlombok.org/features/experimental/Wither.html).
+* CHANGE: The desugaring of @Getter(lazy=true) is now less object creation intensive. Documentation has been updated to reflect what the new desugaring looks like. [@Getter(lazy=true) documentation](https://projectlombok.org/features/GetterLazy.html).
+* PROMOTION: `@Value` has been promoted from experimental to the main package with no changes. The 'old' experimental one is still around but is deprecated, and is an alias for the new main package one. [@Value documentation](https://projectlombok.org/features/Value.html).
+* FEATURE: {Experimental} `@Builder` support. One of our earliest feature request issues, [Issue #89](https://github.com/rzwitserloot/lombok/issues/89), has finally been addressed. [@Builder documentation](https://projectlombok.org/features/experimental/Builder.html).
+* FEATURE: `@NonNull` on a method or constructor parameter now generates a null-check statement at the start of your method. This nullcheck will throw a `NullPointerException` with the name of the parameter as the message. [Issue #549](https://github.com/rzwitserloot/lombok/issues/549)
+* BUGFIX: Usage of `Lombok.sneakyThrow()` or `@SneakyThrows` would sometimes result in invalid classes (classes which fail with `VerifyError`). [Issue #543](https://github.com/rzwitserloot/lombok/issues/543)
+* BUGFIX: Using `val` in try-with-resources did not work for javac. [Issue #555](https://github.com/rzwitserloot/lombok/issues/555)
+* BUGFIX: When using `@Data`, warnings are not generated if certain aspects are not generated because you wrote explicit versions of them. However, this gets confusing with `equals` / `hashCode` / `canEqual`, as nothing is generated if any one of those methods is present. Now, if one of `equals` or `hashCode` is present but not the other one (or `canEqual` is present but `equals` and/or `hashCode` is missing), a warning is emitted to explain that lombok will not generate any of the equals / hashCode methods, and that you should either write them all yourself or remove them all. [Issue #548](https://github.com/rzwitserloot/lombok/issues/548)
+* BUGFIX: Possibly fixed a race condition in patcher [Issue #566](https://github.com/rzwitserloot/lombok/issues/566).
### v0.11.8 (April 23rd, 2013)
* FEATURE: Major performance improvements in eclipse by profiling the project clean process.
* CHANGE: {Experimental} The experimental `@Value` feature no longer implies the also experimental `@Wither`. If you like your `@Value` classes to make withers, add `@Wither` to the class right next to `@Value`.
-* FEATURE: {Experimental} Reintroduced `onMethod`, `onConstructor` and `onParam` to `@Getter`, `@Setter`, `@Wither`, and `@XArgsConstructor`. These parameters allow you to add annotations to the methods/constructors that lombok will generate. This is a workaround feature: The stability of the feature on future versions of javac is not guaranteed, and if a better way to implement this feature is found, this feature's current incarnation will be removed without a reasonable period of deprecation. [Documentation on the onX feature](http://projectlombok.org/features/experimental/onX.html)
-* FEATURE: Added support for Log4j v2.0 via `@Log4j2` [Issue #432](http://code.google.com/p/projectlombok/issues/detail?id=432)
-* ENHANCEMENT: The Lombok installer can now find and install lombok into [JBoss Developer Studio](http://www.redhat.com/products/jbossenterprisemiddleware/developer-studio/). The installer will now also look for eclipse and eclipse variants in your home directory. [Issue #434](http://code.google.com/p/projectlombok/issues/detail?id=432)
-* BUGFIX: `@ExtensionMethods` no longer causes `VerifyError` exceptions when running eclipse-compiled code if extension methods are called on expressions which are method calls whose return type is a type variable. For example, `someList.get(i).extensionMethod()` would fail that way. [Issue #436](http://code.google.com/p/projectlombok/issues/detail?id=436)
-* BUGFIX: java 7's try-with-resources statement did not delombok correctly. [Issue #459](http://code.google.com/p/projectlombok/issues/detail?id=459)
+* FEATURE: {Experimental} Reintroduced `onMethod`, `onConstructor` and `onParam` to `@Getter`, `@Setter`, `@Wither`, and `@XArgsConstructor`. These parameters allow you to add annotations to the methods/constructors that lombok will generate. This is a workaround feature: The stability of the feature on future versions of javac is not guaranteed, and if a better way to implement this feature is found, this feature's current incarnation will be removed without a reasonable period of deprecation. [Documentation on the onX feature](https://projectlombok.org/features/experimental/onX.html)
+* FEATURE: Added support for Log4j v2.0 via `@Log4j2` [Issue #505](https://github.com/rzwitserloot/lombok/issues/505)
+* ENHANCEMENT: The Lombok installer can now find and install lombok into [JBoss Developer Studio](http://www.redhat.com/products/jbossenterprisemiddleware/developer-studio/). The installer will now also look for eclipse and eclipse variants in your home directory. [Issue #507](https://github.com/rzwitserloot/lombok/issues/507)
+* BUGFIX: `@ExtensionMethods` no longer causes `VerifyError` exceptions when running eclipse-compiled code if extension methods are called on expressions which are method calls whose return type is a type variable. For example, `someList.get(i).extensionMethod()` would fail that way. [Issue #509](https://github.com/rzwitserloot/lombok/issues/509)
+* BUGFIX: java 7's try-with-resources statement did not delombok correctly. [Issue #532](https://github.com/rzwitserloot/lombok/issues/532)
### v0.11.6 (October 30th, 2012)
* FEATURE: Lombok can be disabled entirely for any given compile run by using JVM switch `-Dlombok.disable`. This might be useful for code style checkers and such.
-* FEATURE: Added support for Slf4j extended logger [Issue #421](http://code.google.com/p/projectlombok/issues/detail?id=421)
-* BUGFIX: {Delombok} Running delombok has been causing VerifyError errors when used with javac 1.7 since 0.11.0. [Issue #422](http://code.google.com/p/projectlombok/issues/detail?id=422)
+* FEATURE: Added support for Slf4j extended logger [Issue #494](https://github.com/rzwitserloot/lombok/issues/494)
+* BUGFIX: {Delombok} Running delombok has been causing VerifyError errors when used with javac 1.7 since 0.11.0. [Issue #495](https://github.com/rzwitserloot/lombok/issues/495)
* BUGFIX: A conflict between lombok and certain eclipse plugins would result in NullPointerExceptions in the log when using `@Delegate`.
-* BUGFIX: `NullPointerException in lombok.javac.handlers.JavacHandlerUtil.upToTypeNode(JavacHandlerUtil.java:978)` when compiling with `@ExtensionMethod` in javac and generated constructors are involved. [Issue #423](http://code.google.com/p/projectlombok/issues/detail?id=423)
-* BUGFIX: `@Deprecated` on a field that gets a generated setter in eclipse would result in `IllegalArgumentException`, which you wouldn't see unless you have the error log open. If you have save actions defined, you'd get a popup box with the exception. Now fixed. [Issue #408](http://code.google.com/p/projectlombok/issues/detail?id=408)
+* BUGFIX: `NullPointerException in lombok.&#8203;javac.&#8203;handlers.&#8203;JavacHandlerUtil.&#8203;upToTypeNode&#8203;(JavacHandlerUtil.java:978)` when compiling with `@ExtensionMethod` in javac and generated constructors are involved. [Issue #496](https://github.com/rzwitserloot/lombok/issues/496)
+* BUGFIX: `@Deprecated` on a field that gets a generated setter in eclipse would result in `IllegalArgumentException`, which you wouldn't see unless you have the error log open. If you have save actions defined, you'd get a popup box with the exception. Now fixed. [Issue #481](https://github.com/rzwitserloot/lombok/issues/481)
### v0.11.4 (August 13th, 2012)
-* FEATURE: {Experimental} `@Value`, `@Wither` and `@FieldDefaults` are now available. These are a lot like `@Data` but geared towards immutable classes. [Documentation on @Value](http://projectlombok.org/features/experimental/Value.html), [Documentation on @Wither](http://projectlombok.org/features/experimental/Wither.html) and [Documentation on @FieldDefaults](http://projectlombok.org/features/experimental/FieldDefaults.html).
-* BUGFIX: Eclipse would throw an OOME if using `@ExtensionMethod`. [Issue #390](http://code.google.com/p/projectlombok/issues/detail?id=390)
-* BUGFIX: {Netbeans} `@Cleanup` and `@Synchronized` cause far fewer issues in the netbeans editor. [Issue #393](http://code.google.com/p/projectlombok/issues/detail?id=393)
-* BUGFIX: {Installer} Erroneous messages about the installer complaining about needing root access when installing or removing lombok from eclipse installs has been fixed. The installer edge of this problem was actually already fixed in v0.11.2. [Issue #363](http://code.google.com/p/projectlombok/issues/detail?id=363)
-* BUGFIX: `@ExtensionMethod` had all sorts of issues in javac. [Issue #399](http://code.google.com/p/projectlombok/issues/detail?id=399)
-* BUGFIX: Generating static constructors with javac when you have fields with generics, i.e. `Class<T>`, caused errors. [Issue #396](http://code.google.com/p/projectlombok/issues/detail?id=396)
-* BUGFIX: Minor `@ExtensionMethod` issues in eclipse, such as the ability to call extension methods on a `super` reference which is now no longer possible. [Issue #406](http://code.google.com/p/projectlombok/issues/detail?id=406)
+* FEATURE: {Experimental} `@Value`, `@Wither` and `@FieldDefaults` are now available. These are a lot like `@Data` but geared towards immutable classes. [Documentation on @Value](https://projectlombok.org/features/experimental/Value.html), [Documentation on @Wither](https://projectlombok.org/features/experimental/Wither.html) and [Documentation on @FieldDefaults](https://projectlombok.org/features/experimental/FieldDefaults.html).
+* BUGFIX: Eclipse would throw an OOME if using `@ExtensionMethod`. [Issue #463](https://github.com/rzwitserloot/lombok/issues/463)
+* BUGFIX: {Netbeans} `@Cleanup` and `@Synchronized` cause far fewer issues in the netbeans editor. [Issue #466](https://github.com/rzwitserloot/lombok/issues/466)
+* BUGFIX: {Installer} Erroneous messages about the installer complaining about needing root access when installing or removing lombok from eclipse installs has been fixed. The installer edge of this problem was actually already fixed in v0.11.2. [Issue #436](https://github.com/rzwitserloot/lombok/issues/436)
+* BUGFIX: `@ExtensionMethod` had all sorts of issues in javac. [Issue #472](https://github.com/rzwitserloot/lombok/issues/472)
+* BUGFIX: Generating static constructors with javac when you have fields with generics, i.e. `Class<T>`, caused errors. [Issue #469](https://github.com/rzwitserloot/lombok/issues/469)
+* BUGFIX: Minor `@ExtensionMethod` issues in eclipse, such as the ability to call extension methods on a `super` reference which is now no longer possible. [Issue #479](https://github.com/rzwitserloot/lombok/issues/479)
### v0.11.2 "Dashing Kakapo" (July 3rd, 2012)
* FEATURE: {Experimental} `@ExtensionMethod` is now available to add extensions to
-any type in the form of static methods that take as first parameter an object of that type. [Documentation on @ExtensionMethod](http://projectlombok.org/features/experimental/ExtensionMethod.html)
+any type in the form of static methods that take as first parameter an object of that type. [Documentation on @ExtensionMethod](https://projectlombok.org/features/experimental/ExtensionMethod.html)
* FEATURE: ONGOING: Fix for using lombok together with gwt-designer.
-* ENHANCEMENT: Small performance enhancements in `equals` and `hashCode`. [Issue #366](http://code.google.com/p/projectlombok/issues/detail?id=366)
-* BUGFIX: Eclipse would display an error message regarding an invalid super constructor in the wrong location. [Issue #336](http://code.google.com/p/projectlombok/issues/detail?id=336)
+* ENHANCEMENT: Small performance enhancements in `equals` and `hashCode`. [Issue #439](https://github.com/rzwitserloot/lombok/issues/439)
+* BUGFIX: Eclipse would display an error message regarding an invalid super constructor in the wrong location. [Issue #409](https://github.com/rzwitserloot/lombok/issues/409)
* BUGFIX: Eclipse refactor script 'rename method arguments' should work more often with lombok-affected methods.
* BUGFIX: Using `val` in an enhanced for loop did not work if the iterable was a raw type.
-* BUGFIX: Using `@Getter(lazy=true)` when the data type is boolean, int, array, or some other type that requires special treatment for hashCode/equals, now works properly with `@Data`, `@EqualsHashCode` and `@ToString`. [Issue #376](http://code.google.com/p/projectlombok/issues/detail?id=376)
-* BUGFIX: `SneakyThrows` in constructor should not wrap this/super call in try-block [Issue #381](http://code.google.com/p/projectlombok/issues/detail?id=381)
-* BUGFIX: Setting breakpoints on code above the first generated method was not possible. [Issue #377](http://code.google.com/p/projectlombok/issues/detail?id=377)
+* BUGFIX: Using `@Getter(lazy=true)` when the data type is boolean, int, array, or some other type that requires special treatment for hashCode/equals, now works properly with `@Data`, `@EqualsHashCode` and `@ToString`. [Issue #449](https://github.com/rzwitserloot/lombok/issues/449)
+* BUGFIX: `SneakyThrows` in constructor should not wrap this/super call in try-block [Issue #454](https://github.com/rzwitserloot/lombok/issues/454)
+* BUGFIX: Setting breakpoints on code above the first generated method was not possible. [Issue #450](https://github.com/rzwitserloot/lombok/issues/450)
### v0.11.0 (March 26th, 2012)
-* FEATURE: {Experimental} 'fluent' getters and setters (using just `fieldName` as methodname instead of `getFieldName`), setters that return `this` instead of `void`, and support for fields with prefixes is introduced with this lombok version. Also, the number of parameters of any existing methods with the same name that lombok would generate are now taken into account; previously if you had any method named `setX` regardless of how many parameters it has, lombok would avoid generating a `setX` method. Now lombok generates the method if all present `setX` methods have a number of parameters other than 1. [documentation](http://projectlombok.org/features/experimental/Accessors.html).
-* FEATURE: The combination of `@Delegate` and `@Getter` or `@Data` will now delegate to the result of a generated getter. [Issue #328](http://code.google.com/p/projectlombok/issues/detail?id=328)
-* FEATURE: Developing android apps on eclipse with lombok is now possible by running `java -jar lombok.jar publicApi` and including the generated jar in your project. [Documentation on using lombok for android development](http://projectlombok.org/setup/android.html).
-* BUGFIX: In NetBeans the generated default constructor would still be generated even if Lombok also generated constructors. [Issue #326](http://code.google.com/p/projectlombok/issues/detail?id=326)
-* BUGFIX: Some classes that contain @SneakyThrows would not compile (throw ClassFormatError). [Issue 339](http://code.google.com/p/projectlombok/issues/detail?id=339)
-* BUGFIX: delombok: When `@Delegate` would generate a method with type parameters of the type `T extends package.Class`, a dot would be prepended to the type name. [Issue #341](http://code.google.com/p/projectlombok/issues/detail?id=341)
-* BUGFIX: @Getter and @Setter now generate deprecated methods for deprecated fields. Fixes [Issue #342](http://code.google.com/p/projectlombok/issues/detail?id=342)
-* BUGFIX: @Delegate would not generate @Deprecated on methods marked deprecated in javadoc. Fixes [Issue #348](http://code.google.com/p/projectlombok/issues/detail?id=348)
-* BUGFIX: Using `val` with a type like `Outer<TypeArgs>.Inner` now works. [Issue #343](http://code.google.com/p/projectlombok/issues/detail?id=343)
-* BUGFIX: `@Getter(lazy=true)` where the variable type is a primitive and the initializing expression is of a different primitive type that would type coerce implicitly, i.e. ints can be assigned to longs without a cast, didn't work before. [Issue #345](http://code.google.com/p/projectlombok/issues/detail?id=345)
-* BUGFIX: `val` is no longer legal inside basic for loops (the old kind, not the foreach kind). These variables should rarely be final, and in practice it wasn't possible to delombok this code properly. [Issue #346](http://code.google.com/p/projectlombok/issues/detail?id=346)
-* BUGFIX: PrettyCommentsPrinter now prints default clause of annotation methods. Fixes [Issue #350](http://code.google.com/p/projectlombok/issues/detail?id=350)
+* FEATURE: {Experimental} 'fluent' getters and setters (using just `fieldName` as methodname instead of `getFieldName`), setters that return `this` instead of `void`, and support for fields with prefixes is introduced with this lombok version. Also, the number of parameters of any existing methods with the same name that lombok would generate are now taken into account; previously if you had any method named `setX` regardless of how many parameters it has, lombok would avoid generating a `setX` method. Now lombok generates the method if all present `setX` methods have a number of parameters other than 1. [documentation](https://projectlombok.org/features/experimental/Accessors.html).
+* FEATURE: The combination of `@Delegate` and `@Getter` or `@Data` will now delegate to the result of a generated getter. [Issue #401](https://github.com/rzwitserloot/lombok/issues/401)
+* FEATURE: Developing android apps on eclipse with lombok is now possible by running `java -jar lombok.jar publicApi` and including the generated jar in your project. [Documentation on using lombok for android development](https://projectlombok.org/setup/android.html).
+* BUGFIX: In NetBeans the generated default constructor would still be generated even if Lombok also generated constructors. [Issue #399](https://github.com/rzwitserloot/lombok/issues/399)
+* BUGFIX: Some classes that contain @SneakyThrows would not compile (throw ClassFormatError). [Issue #412](https://github.com/rzwitserloot/lombok/issues/412)
+* BUGFIX: delombok: When `@Delegate` would generate a method with type parameters of the type `T extends package.Class`, a dot would be prepended to the type name. [Issue #414](https://github.com/rzwitserloot/lombok/issues/414)
+* BUGFIX: @Getter and @Setter now generate deprecated methods for deprecated fields. Fixes [Issue #415](https://github.com/rzwitserloot/lombok/issues/415)
+* BUGFIX: @Delegate would not generate @Deprecated on methods marked deprecated in javadoc. Fixes [Issue #421](https://github.com/rzwitserloot/lombok/issues/421)
+* BUGFIX: Using `val` with a type like `Outer<TypeArgs>.Inner` now works. [Issue #416](https://github.com/rzwitserloot/lombok/issues/416)
+* BUGFIX: `@Getter(lazy=true)` where the variable type is a primitive and the initializing expression is of a different primitive type that would type coerce implicitly, i.e. ints can be assigned to longs without a cast, didn't work before. [Issue #418](https://github.com/rzwitserloot/lombok/issues/418)
+* BUGFIX: `val` is no longer legal inside basic for loops (the old kind, not the foreach kind). These variables should rarely be final, and in practice it wasn't possible to delombok this code properly. [Issue #419](https://github.com/rzwitserloot/lombok/issues/419)
+* BUGFIX: PrettyCommentsPrinter now prints default clause of annotation methods. Fixes [Issue #423](https://github.com/rzwitserloot/lombok/issues/423)
### v0.10.8 (January 19th, 2012)
-* FEATURE: `@Delegate` can now be used on a no-argument method, which works similarly to adding it to fields. See [documentation](http://projectlombok.org/features/Delegate.html).
-* BUGFIX: Eclipse refactoring Extract Interface was broken when using lombok annotation to generate methods. [Issue #86](http://code.google.com/p/projectlombok/issues/detail?id=86)
-* BUGFIX: Eclipse action Sort Members was broken when using lombok annotations to generate methods or fields. [Issue #265](http://code.google.com/p/projectlombok/issues/detail?id=265)
-* BUGFIX: Eclipse action Refactor/Rename on an inner type was broken when using lombok annotations. [Issue #316](http://code.google.com/p/projectlombok/issues/detail?id=316)
-* BUGFIX: 0.10.6 causes ClassNotFoundErrors when using ecj (and thus, play framework, gwt, etc). [Issue #320](http://code.google.com/p/projectlombok/issues/detail?id=320)
-* BUGFIX: Eclipse parsing was broken when using lombok annotations with parentheses. [Issue #325](http://code.google.com/p/projectlombok/issues/detail?id=325)
+* FEATURE: `@Delegate` can now be used on a no-argument method, which works similarly to adding it to fields. See [documentation](https://projectlombok.org/features/Delegate.html).
+* BUGFIX: Eclipse refactoring Extract Interface was broken when using lombok annotation to generate methods. [Issue #159](https://github.com/rzwitserloot/lombok/issues/159)
+* BUGFIX: Eclipse action Sort Members was broken when using lombok annotations to generate methods or fields. [Issue #338](https://github.com/rzwitserloot/lombok/issues/338)
+* BUGFIX: Eclipse action Refactor/Rename on an inner type was broken when using lombok annotations. [Issue #389](https://github.com/rzwitserloot/lombok/issues/389)
+* BUGFIX: 0.10.6 causes ClassNotFoundErrors when using ecj (and thus, play framework, gwt, etc). [Issue #393](https://github.com/rzwitserloot/lombok/issues/393)
+* BUGFIX: Eclipse parsing was broken when using lombok annotations with parentheses. [Issue #398](https://github.com/rzwitserloot/lombok/issues/398)
* ENHANCEMENT: Lombok now adds a line to the Eclipse About dialog about itself.
### v0.10.6 (December 19th, 2011)
-* PERFORMANCE: Performance issues (memory leaks) when using lombok in netbeans, introduced in 0.10, have been fixed. [Issue #242](http://code.google.com/p/projectlombok/issues/detail?id=242)
-* BUGFIX: Eclipse quickfix "Add unimplemented methods" would sometimes insert the new method stubs in strange places, especially if `@Data` was present. [Issue #51](http://code.google.com/p/projectlombok/issues/detail?id=51)
-* BUGFIX: Eclipse quickfix "Assign parameter to new field" would insert it outside the class body if `@Data` was present. [Issue #222](http://code.google.com/p/projectlombok/issues/detail?id=222)
-* BUGFIX: Renaming a @Data-annotated class in eclipse using Alt+Shift+R no longer mangles the data annotation. [Issue #286](http://code.google.com/p/projectlombok/issues/detail?id=286)
-* BUGFIX: Using save action 'Use this qualifier for field accesses, only if necessary' did not work together with `@Data` in certain cases. [Issue #301](http://code.google.com/p/projectlombok/issues/detail?id=301)
-* BUGFIX: Organize imports, either run manually or as save action, would throw an exception. [Issue #308](http://code.google.com/p/projectlombok/issues/detail?id=308)
-* BUGFIX: Extracted constants would be placed outside the class body when a logging annotation was present. [Issue #315](http://code.google.com/p/projectlombok/issues/detail?id=315)
+* PERFORMANCE: Performance issues (memory leaks) when using lombok in netbeans, introduced in 0.10, have been fixed. [Issue #315](https://github.com/rzwitserloot/lombok/issues/315)
+* BUGFIX: Eclipse quickfix "Add unimplemented methods" would sometimes insert the new method stubs in strange places, especially if `@Data` was present. [Issue #124](https://github.com/rzwitserloot/lombok/issues/124)
+* BUGFIX: Eclipse quickfix "Assign parameter to new field" would insert it outside the class body if `@Data` was present. [Issue #295](https://github.com/rzwitserloot/lombok/issues/295)
+* BUGFIX: Renaming a @Data-annotated class in eclipse using Alt+Shift+R no longer mangles the data annotation. [Issue #359](https://github.com/rzwitserloot/lombok/issues/359)
+* BUGFIX: Using save action 'Use this qualifier for field accesses, only if necessary' did not work together with `@Data` in certain cases. [Issue #374](https://github.com/rzwitserloot/lombok/issues/374)
+* BUGFIX: Organize imports, either run manually or as save action, would throw an exception. [Issue #381](https://github.com/rzwitserloot/lombok/issues/381)
+* BUGFIX: Extracted constants would be placed outside the class body when a logging annotation was present. [Issue #388](https://github.com/rzwitserloot/lombok/issues/388)
### v0.10.4 (November 21st, 2011)
-* BUGFIX: Using the `log` field from `@Log`, etc, now works in static initializers. [Issue #295](http://code.google.com/p/projectlombok/issues/detail?id=295)
-* BUGFIX: Auto-formatting code containing lombok on eclipse, even via an auto-save action, now works. [Issue #90](http://code.google.com/p/projectlombok/issues/detail?id=90)
-* BUGFIX: Letting eclipse generate various methods when a lombok annotation is present now works. [Issue #138](http://code.google.com/p/projectlombok/issues/detail?id=138)
-* BUGFIX: Renaming a @Data-annotated class in eclipse no longer mangles the data annotation. [Issue #286](http://code.google.com/p/projectlombok/issues/detail?id=286)
-* BUGFIX: Eclipse save action *Add final modifier to private fields* no longer adds final keyword to `@Setter` fields. [Issue #263](http://code.google.com/p/projectlombok/issues/detail?id=263)
-* BUGFIX: Mixing labels and `lombok.val` would cause NPEs in javac. [Issue #299](http://code.google.com/p/projectlombok/issues/detail?id=299)
-* BUGFIX: Writing `lombok.val` out in full (vs. using an import statement) did not work in eclipse. [Issue #300](http://code.google.com/p/projectlombok/issues/detail?id=300)
+* BUGFIX: Using the `log` field from `@Log`, etc, now works in static initializers. [Issue #368](https://github.com/rzwitserloot/lombok/issues/368)
+* BUGFIX: Auto-formatting code containing lombok on eclipse, even via an auto-save action, now works. [Issue #163](https://github.com/rzwitserloot/lombok/issues/163)
+* BUGFIX: Letting eclipse generate various methods when a lombok annotation is present now works. [Issue #211](https://github.com/rzwitserloot/lombok/issues/211)
+* BUGFIX: Renaming a @Data-annotated class in eclipse no longer mangles the data annotation. [Issue #359](https://github.com/rzwitserloot/lombok/issues/359)
+* BUGFIX: Eclipse save action *Add final modifier to private fields* no longer adds final keyword to `@Setter` fields. [Issue #336](https://github.com/rzwitserloot/lombok/issues/336)
+* BUGFIX: Mixing labels and `lombok.val` would cause NPEs in javac. [Issue #372](https://github.com/rzwitserloot/lombok/issues/372)
+* BUGFIX: Writing `lombok.val` out in full (vs. using an import statement) did not work in eclipse. [Issue #373](https://github.com/rzwitserloot/lombok/issues/373)
### v0.10.2 (November 1st, 2011)
-* BUGFIX: Delombok will no longer jumble up comments from different files when using -sourcepath option. [Issue #284](http://code.google.com/p/projectlombok/issues/detail?id=284)
-* BUGFIX: Turns out treating `@NotNull` as an annotation that indicates lombok should generate nullcheck guards causes all sorts of problems. This has been removed again, and documentation has been updated to reflect this. [Issue #287](http://code.google.com/p/projectlombok/issues/detail?id=287)
-* BUGFIX: `@EqualsAndHashCode` or `@Data` did not work on non-static inner classes whose outer class has a type variable. It does now. [Issue #289](http://code.google.com/p/projectlombok/issues/detail?id=289)
+* BUGFIX: Delombok will no longer jumble up comments from different files when using -sourcepath option. [Issue #357](https://github.com/rzwitserloot/lombok/issues/357)
+* BUGFIX: Turns out treating `@NotNull` as an annotation that indicates lombok should generate nullcheck guards causes all sorts of problems. This has been removed again, and documentation has been updated to reflect this. [Issue #360](https://github.com/rzwitserloot/lombok/issues/360)
+* BUGFIX: `@EqualsAndHashCode` or `@Data` did not work on non-static inner classes whose outer class has a type variable. It does now. [Issue #362](https://github.com/rzwitserloot/lombok/issues/362)
### v0.10.1 (October 3rd, 2011)
-* BUGFIX: `@Delegate` in eclipse could cause memory leaks in 0.10.0. [Issue #264](http://code.google.com/p/projectlombok/issues/detail?id=264)
-* BUGFIX: Annotations on enum values were being deleted by delombok. [Issue #269](http://code.google.com/p/projectlombok/issues/detail?id=269)
-* BUGFIX: `@AllArgsConstructor` was erroneously generating a parameter and an assignment for final variables already assigned in their declaration. [Issue #278](http://code.google.com/p/projectlombok/issues/detail?id=278)
-* ENHANCEMENT: `@NotNull` is now also recognized as an annotation indicating that lombok should generate nullcheck guards in generated constructors and setters. [Issue #271](http://code.google.com/p/projectlombok/issues/detail?id=271)
+* BUGFIX: `@Delegate` in eclipse could cause memory leaks in 0.10.0. [Issue #337](https://github.com/rzwitserloot/lombok/issues/337)
+* BUGFIX: Annotations on enum values were being deleted by delombok. [Issue #342](https://github.com/rzwitserloot/lombok/issues/342)
+* BUGFIX: `@AllArgsConstructor` was erroneously generating a parameter and an assignment for final variables already assigned in their declaration. [Issue #351](https://github.com/rzwitserloot/lombok/issues/351)
+* ENHANCEMENT: `@NotNull` is now also recognized as an annotation indicating that lombok should generate nullcheck guards in generated constructors and setters. [Issue #344](https://github.com/rzwitserloot/lombok/issues/344)
### v0.10.0 "Burning Emu" (August 19th, 2011)
-* FEATURE: New annotation: @Delegate. This annotation lets lombok generate delegation methods for a given field. [More&hellip;](http://projectlombok.org/features/Delegate.html)
-* FEATURE: Added support for 'val'. Val is an immutable variable that infers its type from the right hand side of the initializing expression. [More&hellip;](http://projectlombok.org/features/val.html)
-* FEATURE: Added support for several logging frameworks via the `@Log`, `@Slf4j`, etc. annotation. [More&hellip;](http://projectlombok.org/features/Log.html)
-* FEATURE: Lombok now supports post-compile transformers. [Issue #144](http://code.google.com/p/projectlombok/issues/detail?id=144)
+* FEATURE: New annotation: @Delegate. This annotation lets lombok generate delegation methods for a given field. [More&hellip;](https://projectlombok.org/features/Delegate.html)
+* FEATURE: Added support for 'val'. Val is an immutable variable that infers its type from the right hand side of the initializing expression. [More&hellip;](https://projectlombok.org/features/val.html)
+* FEATURE: Added support for several logging frameworks via the `@Log`, `@Slf4j`, etc. annotation. [More&hellip;](https://projectlombok.org/features/Log.html)
+* FEATURE: Lombok now supports post-compile transformers. [Issue #217](https://github.com/rzwitserloot/lombok/issues/217)
* FEATURE: Using `@SneakyThrows` no longer requires a runtime dependency on lombok.jar. In fact, any call to `Lombok.sneakyThrows(ex)` is optimized at the bytecode level and no longer requires you to actually have lombok.jar or lombok-runtime.jar on the classpath.
* FEATURE: @*X*ArgsConstructor, @Getter, and @ToString can now be used on enum declarations. Previously, behaviour of these annotations on enums was undefined.
* FEATURE: @Getter/@Setter (and by extension, @Data) in v0.9.3 and earlier would generate getter and setter method names that did not conform to the beanspec, primarily when faced with boolean properties. This has been fixed. In practice this won't affect you unless you have properties named `isFoo` or `hasFoo`. Now the setter generated for this will be called `setFoo` (as the property name is `foo`) and not `setIsFoo`. Also, `hasFoo` is now no longer special; the names would be `isHasFoo` and `setHasFoo`. The java bean spec does not give `has` special meaning.
-* FEATURE: `@EqualsAndHashCode` (and by extension, `@Data`) now add a `canEqual` method which improves the sanity of equality amongst a hierarchy of classes. [More&hellip;](http://projectlombok.org/features/EqualsAndHashCode.html)
-* FEATURE: `@Getter` now supports a `lazy=true` attribute. [More&hellip;](http://projectlombok.org/features/GetterLazy.html)
-* ENHANCEMENT: The installer will now find Eclipse installations when they are located in a subdirectory of a directory containing the word 'eclipse' . [Issue #210](http://code.google.com/p/projectlombok/issues/detail?id=210)
-* ENHANCEMENT: Add null check for `@Cleanup` [Issue #154](http://code.google.com/p/projectlombok/issues/detail?id=154)
+* FEATURE: `@EqualsAndHashCode` (and by extension, `@Data`) now add a `canEqual` method which improves the sanity of equality amongst a hierarchy of classes. [More&hellip;](https://projectlombok.org/features/EqualsAndHashCode.html)
+* FEATURE: `@Getter` now supports a `lazy=true` attribute. [More&hellip;](https://projectlombok.org/features/GetterLazy.html)
+* ENHANCEMENT: The installer will now find Eclipse installations when they are located in a subdirectory of a directory containing the word 'eclipse' . [Issue #283](https://github.com/rzwitserloot/lombok/issues/283)
+* ENHANCEMENT: Add null check for `@Cleanup` [Issue #227](https://github.com/rzwitserloot/lombok/issues/227)
* BUGFIX: Lombok is now compatible with javac 7.
-* BUGFIX: Hard to reproduce `NullPointerException` in Eclipse on the `getTypeBinding` method in the error log has been fixed. [Issue #164](http://code.google.com/p/projectlombok/issues/detail?id=164)
-* BUGFIX: `@Setter` and `@Getter` can now be applied to static fields again (was broken in v0.9.3 only). [Issue #136](http://code.google.com/p/projectlombok/issues/detail?id=136)
-* BUGFIX: delombok added type parameters to constructors that mirror the type's own type parameters. This resulted in delombok turning any generated constructor that takes at least 1 parameter of type 'T' into something that didn't compile, and to boot, a confusing error message ('T is not compatible with T'). This is now fixed. [Issue #140](http://code.google.com/p/projectlombok/issues/detail?id=140)
-* BUGFIX: The Eclipse source generator would place the generated code outside the class [Issue #155](http://code.google.com/p/projectlombok/issues/detail?id=155)
-* BUGFIX: When using m2eclipse, occasionally you'd see a ClassNotFoundError on JavacProcessingEnvironment. This has been fixed. [Issue #177](http://code.google.com/p/projectlombok/issues/detail?id=177)
-* BUGFIX: Either all or none of `equals`, `hashCode` and `canEqual` will be generated. [Issue #240](http://code.google.com/p/projectlombok/issues/detail?id=240)
-* BUGFIX: Delombok in output-to-directory mode was generating very long paths on mac and linux. [Issue #249](http://code.google.com/p/projectlombok/issues/detail?id=249)
+* BUGFIX: Hard to reproduce `NullPointerException` in Eclipse on the `getTypeBinding` method in the error log has been fixed. [Issue #237](https://github.com/rzwitserloot/lombok/issues/237)
+* BUGFIX: `@Setter` and `@Getter` can now be applied to static fields again (was broken in v0.9.3 only). [Issue #209](https://github.com/rzwitserloot/lombok/issues/209)
+* BUGFIX: delombok added type parameters to constructors that mirror the type's own type parameters. This resulted in delombok turning any generated constructor that takes at least 1 parameter of type 'T' into something that didn't compile, and to boot, a confusing error message ('T is not compatible with T'). This is now fixed. [Issue #213](https://github.com/rzwitserloot/lombok/issues/213)
+* BUGFIX: The Eclipse source generator would place the generated code outside the class [Issue #228](https://github.com/rzwitserloot/lombok/issues/228)
+* BUGFIX: When using m2eclipse, occasionally you'd see a ClassNotFoundError on JavacProcessingEnvironment. This has been fixed. [Issue #250](https://github.com/rzwitserloot/lombok/issues/250)
+* BUGFIX: Either all or none of `equals`, `hashCode` and `canEqual` will be generated. [Issue #313](https://github.com/rzwitserloot/lombok/issues/313)
+* BUGFIX: Delombok in output-to-directory mode was generating very long paths on mac and linux. [Issue #322](https://github.com/rzwitserloot/lombok/issues/322)
* BUGFIX: Various refactor scripts and save actions bugs have been fixed in eclipse, though most remain.
### v0.9.3 "Burrowing Whale" (July 25th, 2010)
-* FEATURE: Adding `@Getter` or `@Setter` to a class is now legal and is like adding those annotations to every non-static field in it. [Issue #129](http://code.google.com/p/projectlombok/issues/detail?id=129)
-* FEATURE: Three new annotations, `@NoArgsConstructor`, `@RequiredArgsConstructor` and `@AllArgsConstructor` have been added. These split off `@Data`'s ability to generate constructors, and also allow you to finetune what kind of constructor you want. In addition, by using these annotations, you can force generation of constructors even if you have your own. [Issue #79](http://code.google.com/p/projectlombok/issues/detail?id=79)
-* FEATURE: Constructors generated by lombok now include a `@java.beans.ConstructorProperties` annotation. This does mean these constructors no longer work in java 1.5, as this is a java 1.6 feature. The annotation can be suppressed by setting `suppressConstructorProperties` to `true` in a `@RequiredArgsConstructor` or `@AllArgsConstructor` annotation. [Issue #122](http://code.google.com/p/projectlombok/issues/detail?id=122)
-* FEATURE: generated `toString`, `equals` and `hashCode` methods will now use `this.getX()` and `other.getX()` instead of `this.x` and `other.x` if a suitable getter is available. This behaviour is useful for proxied classes, such as the POJOs that hibernate makes. Usage of the getters can be suppressed with `@ToString/@EqualsAndHashCode(doNotUseGetters = true)`. [Issue #110](http://code.google.com/p/projectlombok/issues/detail?id=110)
-* ENHANCEMENT: FindBugs' `@CheckForNull` is now copied from a field to a setter's parameter and the getter method just like `@Nullable`. [Issue #128](http://code.google.com/p/projectlombok/issues/detail?id=128)
-* ENHANCEMENT: plugins and `@SneakyThrows`: Resolving types in annotations now works better especially for classes that aren't in the core java libraries. [Issue #88](http://code.google.com/p/projectlombok/issues/detail?id=88)
+* FEATURE: Adding `@Getter` or `@Setter` to a class is now legal and is like adding those annotations to every non-static field in it. [Issue #202](https://github.com/rzwitserloot/lombok/issues/202)
+* FEATURE: Three new annotations, `@NoArgsConstructor`, `@RequiredArgsConstructor` and `@AllArgsConstructor` have been added. These split off `@Data`'s ability to generate constructors, and also allow you to finetune what kind of constructor you want. In addition, by using these annotations, you can force generation of constructors even if you have your own. [Issue #152](https://github.com/rzwitserloot/lombok/issues/152)
+* FEATURE: Constructors generated by lombok now include a `@java.beans.ConstructorProperties` annotation. This does mean these constructors no longer work in java 1.5, as this is a java 1.6 feature. The annotation can be suppressed by setting `suppressConstructorProperties` to `true` in a `@RequiredArgsConstructor` or `@AllArgsConstructor` annotation. [Issue #195](https://github.com/rzwitserloot/lombok/issues/195)
+* FEATURE: generated `toString`, `equals` and `hashCode` methods will now use `this.getX()` and `other.getX()` instead of `this.x` and `other.x` if a suitable getter is available. This behaviour is useful for proxied classes, such as the POJOs that hibernate makes. Usage of the getters can be suppressed with `@ToString/@EqualsAndHashCode(doNotUseGetters = true)`. [Issue #183](https://github.com/rzwitserloot/lombok/issues/183)
+* ENHANCEMENT: FindBugs' `@CheckForNull` is now copied from a field to a setter's parameter and the getter method just like `@Nullable`. [Issue #201](https://github.com/rzwitserloot/lombok/issues/201)
+* ENHANCEMENT: plugins and `@SneakyThrows`: Resolving types in annotations now works better especially for classes that aren't in the core java libraries. [Issue #161](https://github.com/rzwitserloot/lombok/issues/161)
* ENHANCEMENT: If `tools.jar` isn't found (required when running _delombok_), now a useful error message is generated. The search for `tools.jar` now also looks in `JAVA_HOME`.
-* ENHANCEMENT: toString() on inner classes now lists the class name as `Outer.Inner` instead of just `Inner`. [Issue #133](http://code.google.com/p/projectlombok/issues/detail?id=133)
-* ENHANCEMENT: All field accesses generated by lombok are now qualified (like so: `this.fieldName`). For those who have a warning configured for unqualified field access, those should no longer occur. [Issue #48](http://code.google.com/p/projectlombok/issues/detail?id=48)
-* ENHANCEMENT: All fields and methods generated by lombok now get `@SuppressWarnings("all")` attached to avoid such warnings as missing javadoc, for those of you who have that warning enabled. [Issue #47](http://code.google.com/p/projectlombok/issues/detail?id=47)
-* PLATFORMS: Lombok should now run in stand-alone ecj (Eclipse Compiler for Java). This isn't just useful for the few souls actually using this compiler day to day, but various eclipse build tools such as the RCP builder run ecj internally as well. [Issue #72](http://code.google.com/p/projectlombok/issues/detail?id=72)
-* BUGFIX: Eclipse: `@Data` and other annotations now don't throw errors when you include fields with bounded wildcard generics, such as `List<? extends Number>`. [Issue #84](http://code.google.com/p/projectlombok/issues/detail?id=84)
-* BUGFIX: complex enums didn't get delomboked properly. [Issue #96](http://code.google.com/p/projectlombok/issues/detail?id=96)
-* BUGFIX: delombok now no longer forgets to remove `import lombok.AccessLevel;`. In netbeans, that import will no longer be flagged erroneously as being unused. [Issue #100](http://code.google.com/p/projectlombok/issues/detail?id=100) and [Issue #103](http://code.google.com/p/projectlombok/issues/detail?id=103)
-* BUGFIX: While its discouraged, `import lombok.*;` is supposed to work in the vast majority of cases. In eclipse, however, it didn't. Now it does. [Issue #102](http://code.google.com/p/projectlombok/issues/detail?id=102)
-* BUGFIX: When `@Getter` or `@Setter` is applied to a multiple field declaration, such as `@Getter int x, y;`, the annotation now applies to all fields, not just the first. [Issue #54](http://code.google.com/p/projectlombok/issues/detail?id=54)
-* BUGFIX: delombok on most javacs would quit with a NoSuchFieldError if it contains `<?>` style wildcards anywhere in the source, as well as at least 1 lombok annotation. No longer. [Issue #134](http://code.google.com/p/projectlombok/issues/detail?id=134)
+* ENHANCEMENT: toString() on inner classes now lists the class name as `Outer.Inner` instead of just `Inner`. [Issue #206](https://github.com/rzwitserloot/lombok/issues/206)
+* ENHANCEMENT: All field accesses generated by lombok are now qualified (like so: `this.fieldName`). For those who have a warning configured for unqualified field access, those should no longer occur. [Issue #121](https://github.com/rzwitserloot/lombok/issues/121)
+* ENHANCEMENT: All fields and methods generated by lombok now get `@SuppressWarnings("all")` attached to avoid such warnings as missing javadoc, for those of you who have that warning enabled. [Issue #120](https://github.com/rzwitserloot/lombok/issues/120)
+* PLATFORMS: Lombok should now run in stand-alone ecj (Eclipse Compiler for Java). This isn't just useful for the few souls actually using this compiler day to day, but various eclipse build tools such as the RCP builder run ecj internally as well. [Issue #145](https://github.com/rzwitserloot/lombok/issues/145)
+* BUGFIX: Eclipse: `@Data` and other annotations now don't throw errors when you include fields with bounded wildcard generics, such as `List<? extends Number>`. [Issue #157](https://github.com/rzwitserloot/lombok/issues/157)
+* BUGFIX: complex enums didn't get delomboked properly. [Issue #169](https://github.com/rzwitserloot/lombok/issues/169)
+* BUGFIX: delombok now no longer forgets to remove `import lombok.AccessLevel;`. In netbeans, that import will no longer be flagged erroneously as being unused. [Issue #173](https://github.com/rzwitserloot/lombok/issues/173) and [Issue #176](https://github.com/rzwitserloot/lombok/issues/176)
+* BUGFIX: While its discouraged, `import lombok.*;` is supposed to work in the vast majority of cases. In eclipse, however, it didn't. Now it does. [Issue #175](https://github.com/rzwitserloot/lombok/issues/175)
+* BUGFIX: When `@Getter` or `@Setter` is applied to a multiple field declaration, such as `@Getter int x, y;`, the annotation now applies to all fields, not just the first. [Issue #127](https://github.com/rzwitserloot/lombok/issues/127)
+* BUGFIX: delombok on most javacs would quit with a NoSuchFieldError if it contains `<?>` style wildcards anywhere in the source, as well as at least 1 lombok annotation. No longer. [Issue #207](https://github.com/rzwitserloot/lombok/issues/207)
* BUILD: dependencies are now fetched automatically via ivy, and most dependencies now include sources by default, which is particularly handy for those working on the lombok sources themselves.
### v0.9.2 "Hailbunny" (December 15th, 2009)
-* preliminary support for lombok on NetBeans! - thanks go to Jan Lahoda from NetBeans. [Issue #20](http://code.google.com/p/projectlombok/issues/detail?id=20)
-* lombok now ships with the delombok tool, which copies an entire directory filled with sources to a new directory, desugaring any java files to what it would look like without lombok's transformations. Compiling the sources in this new directory without lombok support should result in the same class files as compiling the original with lombok support. Great to double check on what lombok is doing, and for chaining the delombok-ed sources to source-based java tools such as Google Web Toolkit or javadoc. lombok.jar itself also provides an ant task for delombok. [Full documentation of delombok](http://projectlombok.org/features/delombok.html).
-* Lombok now works on openjdk7 (tested with JDK7m5)! For all the folks on the cutting edge, this should be very good news. [Issue #61](http://code.google.com/p/projectlombok/issues/detail?id=61) - thanks go to Jan Lahoda from NetBeans.
+* preliminary support for lombok on NetBeans! - thanks go to Jan Lahoda from NetBeans. [Issue #93](https://github.com/rzwitserloot/lombok/issues/93)
+* lombok now ships with the delombok tool, which copies an entire directory filled with sources to a new directory, desugaring any java files to what it would look like without lombok's transformations. Compiling the sources in this new directory without lombok support should result in the same class files as compiling the original with lombok support. Great to double check on what lombok is doing, and for chaining the delombok-ed sources to source-based java tools such as Google Web Toolkit or javadoc. lombok.jar itself also provides an ant task for delombok. [Full documentation of delombok](https://projectlombok.org/features/delombok.html).
+* Lombok now works on openjdk7 (tested with JDK7m5)! For all the folks on the cutting edge, this should be very good news. [Issue #134](https://github.com/rzwitserloot/lombok/issues/134) - thanks go to Jan Lahoda from NetBeans.
* lombok now has various command-line accessible utilities bundled with it. Run `java -jar lombok.jar --help` to see them. Included (aside from the already mentioned delombok):
* Ability to create a tiny jar named lombok-runtime.jar with runtime dependencies. The lombok transformations that have a runtime dependency on this jar can be listed as well. Run `java -jar lombok.jar createRuntime --help` for more information.
* Scriptable command line install and uninstall options. Run `java -jar lombok.jar install --help` (or `uninstall`, of course) for more information. Technically this support has been there in earlier versions, but the command line options are now much more lenient, not to mention more visible.
-* Lombok now works on Springsource Tool Suite. [Issue #22](http://code.google.com/p/projectlombok/issues/detail?id=22)
-* Lombok now works on JDK 1.6.0_0, for those of us who have really old JDK1.6's installed on their system. [Issue #83](http://code.google.com/p/projectlombok/issues/detail?id=83)
-* Erroneous use of lombok in Eclipse (adding it to a project as an annotation processor, which is not how lombok is to be used on Eclipse) now generates a useful warning message with helpful information, instead of a confusing error hidden in the logs. [Issue #53](http://code.google.com/p/projectlombok/issues/detail?id=53)
-* FIXED: Regression bug where you would occasionally see errors with the gist 'loader constraint violation: when resolving...', such as when opening the help system, starting the diff editor, or, rarely, opening any java source file. [Issue #68](http://code.google.com/p/projectlombok/issues/detail?id=68)
-* FIXED: @SneakyThrows without any parameters should default to `Throwable.class` but it didn't do anything in javac. [Issue #73](http://code.google.com/p/projectlombok/issues/detail?id=73)
-* FIXED: Capitalization is now ignored when scanning for existing methods, so if `setURL` already exists, then a `@Data` annotation on a class with a field named `url` will no longer _also_ generate `setUrl`. [Issue #75](http://code.google.com/p/projectlombok/issues/detail?id=75)
+* Lombok now works on Springsource Tool Suite. [Issue #95](https://github.com/rzwitserloot/lombok/issues/95)
+* Lombok now works on JDK 1.6.0_0, for those of us who have really old JDK1.6's installed on their system. [Issue #156](https://github.com/rzwitserloot/lombok/issues/156)
+* Erroneous use of lombok in Eclipse (adding it to a project as an annotation processor, which is not how lombok is to be used on Eclipse) now generates a useful warning message with helpful information, instead of a confusing error hidden in the logs. [Issue #126](https://github.com/rzwitserloot/lombok/issues/126)
+* FIXED: Regression bug where you would occasionally see errors with the gist 'loader constraint violation: when resolving...', such as when opening the help system, starting the diff editor, or, rarely, opening any java source file. [Issue #141](https://github.com/rzwitserloot/lombok/issues/141)
+* FIXED: @SneakyThrows without any parameters should default to `Throwable.class` but it didn't do anything in javac. [Issue #146](https://github.com/rzwitserloot/lombok/issues/146)
+* FIXED: Capitalization is now ignored when scanning for existing methods, so if `setURL` already exists, then a `@Data` annotation on a class with a field named `url` will no longer _also_ generate `setUrl`. [Issue #148](https://github.com/rzwitserloot/lombok/issues/148)
### v0.9.1 (November 9th, 2009)
* The installer now works much better on linux, in that it auto-finds eclipse in most locations linux users tend to put their eclipse installs, and it can now handle apt-get installed eclipses, which previously didn't work well at all. There's also a hidden feature where the installer can work as a command-line only tool (`java -jar lombok.jar install eclipse path/to/eclipse`) which also supports `uninstall` of course. You can now also point at `eclipse.ini` in case you have a really odd eclipse install, which should always work.
-* For lombok developers, the eclipse launch target now works out-of-the-box on snow leopard. [Issue #66](http://code.google.com/p/projectlombok/issues/detail?id=66)
+* For lombok developers, the eclipse launch target now works out-of-the-box on snow leopard. [Issue #139](https://github.com/rzwitserloot/lombok/issues/139)
### v0.9.0 (November 2nd, 2009)
@@ -233,25 +330,25 @@ any type in the form of static methods that take as first parameter an object of
* Changes to the lombok core API which aren't backwards compatible with lombok series v0.8 but which were necessary to make writing third party processors for lombok a lot easier.
* Minor version number bumped due to the above 3 issues.
* Eclipse's "rename" refactor script, invoked by pressing CMD/CTRL+SHIFT+R, now works on `@Data` annotated classes.
-* The windows installer would fail on boot if you have unformatted drives. [Issue #65](http://code.google.com/p/projectlombok/issues/detail?id=65)
-* The static constructor that `@Data` can make was being generated as package private when compiling with javac. [Issue #63](http://code.google.com/p/projectlombok/issues/detail?id=63)
+* The windows installer would fail on boot if you have unformatted drives. [Issue #138](https://github.com/rzwitserloot/lombok/issues/138)
+* The static constructor that `@Data` can make was being generated as package private when compiling with javac. [Issue #136](https://github.com/rzwitserloot/lombok/issues/136)
### v0.8.5 (September 3rd, 2009)
-* There's now an `AccessLevel.NONE` that you can use for your `@Getter` and `@Setter` annotations to suppress generating setters and getters when you're using the `@Data` annotation. Address [Issue #37](http://code.google.com/p/projectlombok/issues/detail?id=37)
-* Both `@EqualsAndHashCode` and `@ToString` now support explicitly specifying the fields to use, via the new 'of' parameter. Fields that begin with a '$' are now also excluded by default from equals, hashCode, and toString generation, unless of course you explicitly mention them in the 'of' parameter. Addresses [Issue #32](http://code.google.com/p/projectlombok/issues/detail?id=32)
-* There's a commonly used `@NotNull` annotation, from javax.validation (and in earlier versions of hibernate, which is the origin of javax.validation) which does not quite mean what we want it to mean: It is not legal on parameters, and it is checked at runtime after an explicit request for validation. As a workaround, we've removed checking for any annotation named `NotNull` from the nonnull support of lombok's generated Getters, Setters, and constructors. [Issue #43](http://code.google.com/p/projectlombok/issues/detail?id=43)
+* There's now an `AccessLevel.NONE` that you can use for your `@Getter` and `@Setter` annotations to suppress generating setters and getters when you're using the `@Data` annotation. Address [Issue #110](https://github.com/rzwitserloot/lombok/issues/110)
+* Both `@EqualsAndHashCode` and `@ToString` now support explicitly specifying the fields to use, via the new 'of' parameter. Fields that begin with a '$' are now also excluded by default from equals, hashCode, and toString generation, unless of course you explicitly mention them in the 'of' parameter. Addresses [Issue #105](https://github.com/rzwitserloot/lombok/issues/105)
+* There's a commonly used `@NotNull` annotation, from javax.validation (and in earlier versions of hibernate, which is the origin of javax.validation) which does not quite mean what we want it to mean: It is not legal on parameters, and it is checked at runtime after an explicit request for validation. As a workaround, we've removed checking for any annotation named `NotNull` from the nonnull support of lombok's generated Getters, Setters, and constructors. [Issue #116](https://github.com/rzwitserloot/lombok/issues/116)
* Fixed yet another issue with `@SneakyThrows`. This was reported fixed in v0.8.4. but it still didn't work quite as it should. Still falls under the bailiwick of
-[Issue #30](http://code.google.com/p/projectlombok/issues/detail?id=30)
+[Issue #103](https://github.com/rzwitserloot/lombok/issues/103)
### v0.8.4 (September 2nd, 2009)
-* Fixed many issues with `@SneakyThrows` - in previous versions, using it would sometimes confuse the syntax colouring, and various constructs in the annotated method would cause outright eclipse errors, such as beginning the method with a try block. This also fixes [Issue #30](http://code.google.com/p/projectlombok/issues/detail?id=30)
-* Fixed the David Lynch bug - in eclipse, classes with lombok features used in them would sometimes appear invisible from other source files. It's described in more detail on [Issue #41](http://code.google.com/p/projectlombok/issues/detail?id=41). If you suffered from it, you'll know what this is about.
-* Fixed the problem where eclipse's help system did not start up on lombokized eclipses. [Issue #26](http://code.google.com/p/projectlombok/issues/detail?id=26)
-* All generated methods now make their parameters (if they have any) final. This should help avoid problems with the 'make all parameters final' save action in eclipse. [Issue #40](http://code.google.com/p/projectlombok/issues/detail?id=40)
+* Fixed many issues with `@SneakyThrows` - in previous versions, using it would sometimes confuse the syntax colouring, and various constructs in the annotated method would cause outright eclipse errors, such as beginning the method with a try block. This also fixes [Issue #103](https://github.com/rzwitserloot/lombok/issues/103)
+* Fixed the David Lynch bug - in eclipse, classes with lombok features used in them would sometimes appear invisible from other source files. It's described in more detail on [Issue #114](https://github.com/rzwitserloot/lombok/issues/114). If you suffered from it, you'll know what this is about.
+* Fixed the problem where eclipse's help system did not start up on lombokized eclipses. [Issue #99](https://github.com/rzwitserloot/lombok/issues/99)
+* All generated methods now make their parameters (if they have any) final. This should help avoid problems with the 'make all parameters final' save action in eclipse. [Issue #113](https://github.com/rzwitserloot/lombok/issues/113)
* Okay, this time _really_ added support for @NonNull and @NotNull annotations. It was reported for v0.8.3 but it wasn't actually in that release. @Nullable annotations are now also copied over to the getter's return type and the setter and constructor's parameters (but, obviously, no check is added). Any @NonNull annotated non-final fields that are not initialized are now also added to the generated constructor by @Data in order to ensure via an explicit null check that they contain a legal value.
-* @ToString (and hence, @Data) now default to includeFieldNames=true. [Issue #35](http://code.google.com/p/projectlombok/issues/detail?id=35)
+* @ToString (and hence, @Data) now default to includeFieldNames=true. [Issue #108](https://github.com/rzwitserloot/lombok/issues/108)
### v0.8.3 (August 21st, 2009)
@@ -262,16 +359,16 @@ annotation is copied to the setter's parameter, and the getter's method.
### v0.8.2 (July 29th, 2009)
-* @EqualsAndHashCode and @ToString created; these are subsets of what @Data does (namely: generate toString(), and generate equals() and hashCode() implementations). @Data will still generate these methods, but you can now generate them separately if you wish. As part of this split off, you can now specify for toString generation to include the field names in the produced toString method, and for all 3 methods: You can choose to involve the implementation of the superclass, and you can choose to exclude certain fields. [Issue #8](http://code.google.com/p/projectlombok/issues/detail?id=8)
-* when compiling with javac: warnings on specific entries of an annotation parameter (such as non-existent fields in a @EqualsAndHashCode exclude parameter) now show up on the problematic parameter and not on the entire annotation. [Issue #11](http://code.google.com/p/projectlombok/issues/detail?id=11)
+* @EqualsAndHashCode and @ToString created; these are subsets of what @Data does (namely: generate toString(), and generate equals() and hashCode() implementations). @Data will still generate these methods, but you can now generate them separately if you wish. As part of this split off, you can now specify for toString generation to include the field names in the produced toString method, and for all 3 methods: You can choose to involve the implementation of the superclass, and you can choose to exclude certain fields. [Issue #81](https://github.com/rzwitserloot/lombok/issues/81)
+* when compiling with javac: warnings on specific entries of an annotation parameter (such as non-existent fields in a @EqualsAndHashCode exclude parameter) now show up on the problematic parameter and not on the entire annotation. [Issue #84](https://github.com/rzwitserloot/lombok/issues/84)
### v0.8.1 (July 26th, 2009)
* Changelog tracking from this version on.
-* Using eclipse's 'find callers' on a @Data annotation will now find callers of the static constructor if you generated it. If not, it still finds callers to hashCode() as before (it's not possible to make eclipse find callers to the normal constructor, though you can just use 'find callers' on the class name, which works fine). [Issue #5](http://code.google.com/p/projectlombok/issues/detail?id=5)
-* If your field is called 'hasFoo' and its a boolean, and you use @Getter or @Data to generate a getter for it, that getter will now be called 'hasFoo' and not 'isHasFoo' as before. This rule holds for any field prefixed with 'has', 'is', or 'get', AND the character following the prefix is not lowercase (so that 'hashCodeGenerated' is not erroneously identified as already having a prefix!). Similar logic has been added to not generate a getter at all for a field named 'foo' or 'hasFoo' if there is already a method named 'isFoo'. [Issue #4](http://code.google.com/p/projectlombok/issues/detail?id=4)
-* Starting the lombok installer on mac os X using soylatte instead of apple's JVM now correctly detects being on a mac, and using mac-specific code for finding and installing eclipses. [Issue #7](http://code.google.com/p/projectlombok/issues/detail?id=7)
-* For non-mac, non-windows installations, the jar file in the `-javaagent` parameter is now written as an absolute path in `eclipse.ini` instead of a relative one. For some reason, on at least 1 linux installation, an absolute path is required to make javaagent work. This 'fix' has the unfortunate side-effect of making it impossible to move your eclipse installation around without breaking the pointer to the lombok java agent, so this change has only been introduced for non-windows, non-mac. Thanks to WouterS for spotting this one and helping us out with some research on fixing it. [Issue #6](http://code.google.com/p/projectlombok/issues/detail?id=6)
+* Using eclipse's 'find callers' on a @Data annotation will now find callers of the static constructor if you generated it. If not, it still finds callers to hashCode() as before (it's not possible to make eclipse find callers to the normal constructor, though you can just use 'find callers' on the class name, which works fine). [Issue #78](https://github.com/rzwitserloot/lombok/issues/78)
+* If your field is called 'hasFoo' and its a boolean, and you use @Getter or @Data to generate a getter for it, that getter will now be called 'hasFoo' and not 'isHasFoo' as before. This rule holds for any field prefixed with 'has', 'is', or 'get', AND the character following the prefix is not lowercase (so that 'hashCodeGenerated' is not erroneously identified as already having a prefix!). Similar logic has been added to not generate a getter at all for a field named 'foo' or 'hasFoo' if there is already a method named 'isFoo'. [Issue #77](https://github.com/rzwitserloot/lombok/issues/77)
+* Starting the lombok installer on mac os X using soylatte instead of apple's JVM now correctly detects being on a mac, and using mac-specific code for finding and installing eclipses. [Issue #80](https://github.com/rzwitserloot/lombok/issues/80)
+* For non-mac, non-windows installations, the jar file in the `-javaagent` parameter is now written as an absolute path in `eclipse.ini` instead of a relative one. For some reason, on at least 1 linux installation, an absolute path is required to make javaagent work. This 'fix' has the unfortunate side-effect of making it impossible to move your eclipse installation around without breaking the pointer to the lombok java agent, so this change has only been introduced for non-windows, non-mac. Thanks to WouterS for spotting this one and helping us out with some research on fixing it. [Issue #79](https://github.com/rzwitserloot/lombok/issues/79)
### v0.8
diff --git a/doc/maven-pom.xml b/doc/maven-pom.xml
index 34955ab8..baba7ca6 100644
--- a/doc/maven-pom.xml
+++ b/doc/maven-pom.xml
@@ -6,13 +6,13 @@
<packaging>jar</packaging>
<version>@VERSION@</version>
<name>Project Lombok</name>
- <url>http://projectlombok.org</url>
+ <url>https://projectlombok.org</url>
<description>Spice up your java: Automatic Resource Management, automatic generation of getters, setters, equals, hashCode and toString, and more!</description>
<dependencies></dependencies>
<licenses>
<license>
<name>The MIT License</name>
- <url>http://projectlombok.org/LICENSE</url>
+ <url>https://projectlombok.org/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
diff --git a/doc/utils-maven-pom.xml b/doc/utils-maven-pom.xml
index 60df78f0..b3b73c1c 100644
--- a/doc/utils-maven-pom.xml
+++ b/doc/utils-maven-pom.xml
@@ -6,13 +6,13 @@
<packaging>jar</packaging>
<version>@VERSION@</version>
<name>Project Lombok</name>
- <url>http://projectlombok.org</url>
+ <url>https://projectlombok.org</url>
<description>Spice up your java: Automatic Resource Management, automatic generation of getters, setters, equals, hashCode and toString, and more!</description>
<dependencies></dependencies>
<licenses>
<license>
<name>The MIT License</name>
- <url>http://projectlombok.org/LICENSE</url>
+ <url>https://projectlombok.org/LICENSE</url>
<distribution>repo</distribution>
</license>
</licenses>
diff --git a/docker/.dockerignore b/docker/.dockerignore
new file mode 100644
index 00000000..0d79d56d
--- /dev/null
+++ b/docker/.dockerignore
@@ -0,0 +1 @@
+readme.txt \ No newline at end of file
diff --git a/docker/ant/Dockerfile b/docker/ant/Dockerfile
new file mode 100644
index 00000000..32457709
--- /dev/null
+++ b/docker/ant/Dockerfile
@@ -0,0 +1,33 @@
+FROM ubuntu:16.04 as downloader
+
+ARG jdk=9
+ADD provision/jdk/java-${jdk}.sh provision/jdk/java-${jdk}.sh
+RUN provision/jdk/java-${jdk}.sh
+
+ARG ant=1.10.1
+ADD provision/ant/ant-${ant}.sh provision/ant/ant-${ant}.sh
+RUN provision/ant/ant-${ant}.sh
+
+FROM ubuntu:16.04
+
+COPY --from=downloader /usr/local/apache-ant/ /usr/local/apache-ant/
+COPY --from=downloader /opt/jdk/ /opt/jdk/
+
+RUN update-alternatives --install /usr/bin/java java /opt/jdk/bin/java 1000 && update-alternatives --install /usr/bin/javac javac /opt/jdk/bin/javac 1000 && update-alternatives --install /usr/bin/javadoc javadoc /opt/jdk/bin/javadoc 1000 && update-alternatives --install /usr/bin/javap javap /opt/jdk/bin/javap 1000
+
+WORKDIR workspace
+
+ADD shared/ ./
+
+ARG jdk=9
+ADD ant/files/jdk-${jdk} ./
+
+ARG lombokjar=lombok.jar
+ADD https://projectlombok.org/downloads/${lombokjar} lombok.jar
+
+ENV JDK_VERSION=${jdk}
+ENV JAVA_HOME=/opt/jdk
+ENV ANT_HOME=/usr/local/apache-ant/apache-ant
+ENV PATH="${JAVA_HOME}/bin:${ANT_HOME}/bin:${PATH}"
+
+ENTRYPOINT bash
diff --git a/docker/ant/files/jdk-8/build.xml b/docker/ant/files/jdk-8/build.xml
new file mode 100644
index 00000000..2fc38879
--- /dev/null
+++ b/docker/ant/files/jdk-8/build.xml
@@ -0,0 +1,25 @@
+<project name="example" default="dist" basedir=".">
+ <property name="src" location="src/main/java"/>
+ <property name="build" location="build"/>
+ <property name="dist" location="dist"/>
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <target name="init">
+ <tstamp/>
+ <mkdir dir="${build}"/>
+ </target>
+
+ <target name="compile" depends="init" description="compile the source">
+ <javac classpath="lombok.jar" srcdir="${src}" destdir="${build}" fork="true"/>
+ </target>
+
+ <target name="dist" depends="compile" description="generate the distribution">
+ <mkdir dir="${dist}/lib"/>
+ <jar jarfile="${dist}/lib/example-${DSTAMP}.jar" basedir="${build}"/>
+ </target>
+
+ <target name="clean" description="clean up">
+ <delete dir="${build}"/>
+ <delete dir="${dist}"/>
+ </target>
+</project> \ No newline at end of file
diff --git a/docker/ant/files/jdk-9/build.xml b/docker/ant/files/jdk-9/build.xml
new file mode 100644
index 00000000..3f181ed9
--- /dev/null
+++ b/docker/ant/files/jdk-9/build.xml
@@ -0,0 +1,35 @@
+<project name="example" default="dist" basedir=".">
+ <property name="src" location="src/main/java"/>
+ <property name="build" location="build"/>
+ <property name="dist" location="dist"/>
+ <property name="build.sysclasspath" value="ignore"/>
+
+ <target name="init">
+ <tstamp/>
+ <mkdir dir="${build}"/>
+ </target>
+
+ <target name="compile" depends="init" description="compile the source">
+ <javac classpath="lombok.jar" srcdir="${src}" destdir="${build}" fork="true">
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED"/>
+ <compilerarg value="-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED"/>
+ </javac>
+ </target>
+
+ <target name="dist" depends="compile" description="generate the distribution">
+ <mkdir dir="${dist}/lib"/>
+ <jar jarfile="${dist}/lib/example-${DSTAMP}.jar" basedir="${build}"/>
+ </target>
+
+ <target name="clean" description="clean up">
+ <delete dir="${build}"/>
+ <delete dir="${dist}"/>
+ </target>
+</project> \ No newline at end of file
diff --git a/docker/ant/readme.md b/docker/ant/readme.md
new file mode 100644
index 00000000..d6462523
--- /dev/null
+++ b/docker/ant/readme.md
@@ -0,0 +1,33 @@
+## Configuration
+
+[_(general configuration and options)_](../readme.md)
+
+### `ARG ant=1.10.1`
+
+The ant version to be used. Supported values:
+
+- `1.10.1` (default)
+
+## Example build commands:
+
+(To be executed from the `<lombokhome>/docker` directory)
+
+```
+docker build -t lombok-ant-jdk9 -f gradle/Dockerfile .
+
+docker build -t lombok-ant-jdk9 --build-arg lombokjar=lombok-1.16.18.jar -f gradle/Dockerfile .
+```
+
+## Example run commands:
+
+```
+docker run -it lombok-ant-jdk9
+
+docker run --rm -it -v /<lombokhome>/dist/lombok.jar:/workspace/lombok.jar lombok-ant-jdk9
+```
+
+## Example container commands:
+
+```
+ant dist
+```
diff --git a/docker/gradle/Dockerfile b/docker/gradle/Dockerfile
new file mode 100644
index 00000000..938d417e
--- /dev/null
+++ b/docker/gradle/Dockerfile
@@ -0,0 +1,31 @@
+FROM ubuntu:16.04 as downloader
+
+ARG jdk=9
+ADD provision/jdk/java-${jdk}.sh provision/jdk/java-${jdk}.sh
+RUN provision/jdk/java-${jdk}.sh
+
+ARG gradle=4.2.1
+ADD provision/gradle/gradle-${gradle}.sh provision/gradle/gradle-${gradle}.sh
+RUN provision/gradle/gradle-${gradle}.sh
+
+FROM ubuntu:16.04
+
+COPY --from=downloader /opt/gradle/ /opt/gradle/
+COPY --from=downloader /opt/jdk/ /opt/jdk/
+
+RUN update-alternatives --install /usr/bin/java java /opt/jdk/bin/java 1000 && update-alternatives --install /usr/bin/javac javac /opt/jdk/bin/javac 1000 && update-alternatives --install /usr/bin/javadoc javadoc /opt/jdk/bin/javadoc 1000 && update-alternatives --install /usr/bin/javap javap /opt/jdk/bin/javap 1000
+
+WORKDIR workspace
+
+ADD shared/ ./
+ADD gradle/files/ ./
+ARG lombokjar=lombok.jar
+ADD https://projectlombok.org/downloads/${lombokjar} lombok.jar
+
+ARG jdk=9
+ENV JDK_VERSION=${jdk}
+ENV JAVA_HOME=/opt/jdk
+ENV GRADLE_HOME=/opt/gradle/gradle
+ENV PATH="${JAVA_HOME}/bin:${GRADLE_HOME}/bin:${PATH}"
+
+ENTRYPOINT bash
diff --git a/docker/gradle/files/build.gradle b/docker/gradle/files/build.gradle
new file mode 100644
index 00000000..49923f04
--- /dev/null
+++ b/docker/gradle/files/build.gradle
@@ -0,0 +1,5 @@
+apply plugin: 'java'
+
+dependencies {
+ compileOnly files('lombok.jar')
+} \ No newline at end of file
diff --git a/docker/gradle/readme.md b/docker/gradle/readme.md
new file mode 100644
index 00000000..efe4f237
--- /dev/null
+++ b/docker/gradle/readme.md
@@ -0,0 +1,33 @@
+## Configuration
+
+[_(general configuration and options)_](../readme.md)
+
+### `ARG gradle=4.2.1`
+
+The gradle version to be used. Supported values:
+
+- `4.2.1` (default)
+
+## Example build commands:
+
+(To be executed from the `<lombokhome>/docker` directory)
+
+```
+docker build -t lombok-gradle-jdk9 -f gradle/Dockerfile .
+
+docker build -t lombok-gradle-jdk9 --build-arg lombokjar=lombok-1.16.18.jar -f gradle/Dockerfile .
+```
+
+## Example run commands:
+
+```
+docker run -it lombok-gradle-jdk9
+
+docker run --rm -it -v /<lombokhome>/dist/lombok.jar:/workspace/lombok.jar lombok-gradle-jdk9
+```
+
+## Example container commands:
+
+```
+gradle assemble
+```
diff --git a/docker/maven/Dockerfile b/docker/maven/Dockerfile
new file mode 100644
index 00000000..83f124f1
--- /dev/null
+++ b/docker/maven/Dockerfile
@@ -0,0 +1,34 @@
+FROM ubuntu:16.04 as downloader
+
+ARG jdk=9
+ADD provision/jdk/java-${jdk}.sh provision/jdk/java-${jdk}.sh
+RUN provision/jdk/java-${jdk}.sh
+
+ARG maven=3.5.0
+ADD provision/maven/maven-${maven}.sh provision/maven/maven-${maven}.sh
+RUN provision/maven/maven-${maven}.sh
+
+FROM ubuntu:16.04
+
+COPY --from=downloader /usr/local/apache-maven/ /usr/local/apache-maven/
+COPY --from=downloader /opt/jdk/ /opt/jdk/
+
+RUN update-alternatives --install /usr/bin/java java /opt/jdk/bin/java 1000 && update-alternatives --install /usr/bin/javac javac /opt/jdk/bin/javac 1000 && update-alternatives --install /usr/bin/javadoc javadoc /opt/jdk/bin/javadoc 1000 && update-alternatives --install /usr/bin/javap javap /opt/jdk/bin/javap 1000
+
+WORKDIR workspace
+
+ADD shared/ ./
+
+ARG jdk=9
+ADD maven/files/jdk-${jdk} ./
+
+ARG lombokjar=lombok.jar
+ADD https://projectlombok.org/downloads/${lombokjar} lombok.jar
+
+ENV JDK_VERSION=${jdk}
+ENV JAVA_HOME=/opt/jdk
+ENV M2_HOME=/usr/local/apache-maven/apache-maven
+ENV M2=${M2_HOME}/bin
+ENV PATH="${M2}:${JAVA_HOME}/bin:${PATH}"
+
+ENTRYPOINT bash
diff --git a/docker/maven/files/jdk-8/pom.xml b/docker/maven/files/jdk-8/pom.xml
new file mode 100644
index 00000000..87c4a6a8
--- /dev/null
+++ b/docker/maven/files/jdk-8/pom.xml
@@ -0,0 +1,44 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.example</groupId>
+ <artifactId>lombok-jdk-${env.JDK_VERSION}</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <java.version>1.8</java.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.7.0</version>
+ <configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ <showDeprecation>true</showDeprecation>
+ <showWarnings>true</showWarnings>
+ <fork>true</fork>
+ <compilerargs>
+ <arg>-Werror</arg>
+ <arg>-Xlint:all</arg>
+ </compilerargs>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>1.2.3</version>
+ <scope>system</scope>
+ <systemPath>/workspace/lombok.jar</systemPath>
+ </dependency>
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/docker/maven/files/jdk-9/pom.xml b/docker/maven/files/jdk-9/pom.xml
new file mode 100644
index 00000000..dfbb9ad9
--- /dev/null
+++ b/docker/maven/files/jdk-9/pom.xml
@@ -0,0 +1,53 @@
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>com.example</groupId>
+ <artifactId>lombok-jdk-${env.JDK_VERSION}</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <java.version>1.9</java.version>
+ </properties>
+
+ <build>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.7.0</version>
+ <configuration>
+ <source>${java.version}</source>
+ <target>${java.version}</target>
+ <showDeprecation>true</showDeprecation>
+ <showWarnings>true</showWarnings>
+ <fork>true</fork>
+ <compilerargs>
+ <arg>-Werror</arg>
+ <arg>-Xlint:all</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.code=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.comp=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.file=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.main=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.model=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.parser=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.processing=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.tree=ALL-UNNAMED</arg>
+ <arg>-J--add-opens=jdk.compiler/com.sun.tools.javac.util=ALL-UNNAMED</arg>
+ </compilerargs>
+ </configuration>
+ </plugin>
+ </plugins>
+ </build>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>1.2.3</version>
+ <scope>system</scope>
+ <systemPath>/workspace/lombok.jar</systemPath>
+ </dependency>
+ </dependencies>
+
+</project> \ No newline at end of file
diff --git a/docker/maven/readme.md b/docker/maven/readme.md
new file mode 100644
index 00000000..20cf126f
--- /dev/null
+++ b/docker/maven/readme.md
@@ -0,0 +1,33 @@
+## Configuration
+
+[_(general configuration and options)_](../readme.md)
+
+### `ARG maven=3.5.0`
+
+The maven version to be used. Supported values:
+
+- `3.5.0` (default)
+
+## Example build commands:
+
+(To be executed from the `<lombokhome>/docker` directory)
+
+```
+docker build -t lombok-maven-jdk9 -f maven/Dockerfile .
+
+docker build -t lombok-maven-jdk9 --build-arg lombokjar=lombok-1.16.18.jar -f maven/Dockerfile .
+```
+
+## Example run commands:
+
+```
+docker run -it lombok-maven-jdk9
+
+docker run --rm -it -v /<lombokhome>/dist/lombok.jar:/workspace/lombok.jar lombok-maven-jdk9
+```
+
+## Example container commands:
+
+```
+mvn compile
+```
diff --git a/docker/provision/ant/ant-1.10.1.sh b/docker/provision/ant/ant-1.10.1.sh
new file mode 100755
index 00000000..3de7f3d0
--- /dev/null
+++ b/docker/provision/ant/ant-1.10.1.sh
@@ -0,0 +1,4 @@
+apt-get update && apt-get install -y wget
+wget https://archive.apache.org/dist/ant/binaries/apache-ant-1.10.1-bin.tar.gz -O ant.tar.gz
+mkdir /usr/local/apache-ant/ && tar xvf ant.tar.gz -C /usr/local/apache-ant/
+mv /usr/local/apache-ant/apache-ant-1.10.1 /usr/local/apache-ant/apache-ant
diff --git a/docker/provision/gradle/gradle-4.2.1.sh b/docker/provision/gradle/gradle-4.2.1.sh
new file mode 100755
index 00000000..8c300f11
--- /dev/null
+++ b/docker/provision/gradle/gradle-4.2.1.sh
@@ -0,0 +1,4 @@
+apt-get update && apt-get install -y wget unzip
+wget https://services.gradle.org/distributions/gradle-4.2.1-bin.zip -O gradle.zip
+mkdir /opt/gradle && unzip -d /opt/gradle gradle.zip
+mv /opt/gradle/gradle-4.2.1 /opt/gradle/gradle
diff --git a/docker/provision/jdk/java-10.sh b/docker/provision/jdk/java-10.sh
new file mode 100755
index 00000000..9b5f3176
--- /dev/null
+++ b/docker/provision/jdk/java-10.sh
@@ -0,0 +1,4 @@
+apt-get update && apt-get install -y wget
+wget -c --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/10+46/76eac37278c24557a3c4199677f19b62/jdk-10_linux-x64_bin.tar.gz -O jdk.tar.gz
+tar -xzf jdk.tar.gz -C /opt/
+mv /opt/jdk-10 /opt/jdk
diff --git a/docker/provision/jdk/java-8.sh b/docker/provision/jdk/java-8.sh
new file mode 100755
index 00000000..44795c6c
--- /dev/null
+++ b/docker/provision/jdk/java-8.sh
@@ -0,0 +1,6 @@
+apt-get update && apt-get install -y software-properties-common
+echo oracle-java8-installer shared/accepted-oracle-license-v1-1 select true | debconf-set-selections
+add-apt-repository -y ppa:webupd8team/java
+apt-get update && apt-get install -y oracle-java8-installer
+
+mv /usr/lib/jvm/java-8-oracle /opt/jdk
diff --git a/docker/provision/jdk/java-9.sh b/docker/provision/jdk/java-9.sh
new file mode 100755
index 00000000..fd488dc8
--- /dev/null
+++ b/docker/provision/jdk/java-9.sh
@@ -0,0 +1,4 @@
+apt-get update && apt-get install -y wget
+wget --header "Cookie: oraclelicense=accept-securebackup-cookie" http://download.oracle.com/otn-pub/java/jdk/9.0.4+11/c2514751926b4512b076cc82f959763f/jdk-9.0.4_linux-x64_bin.tar.gz -O jdk.tar.gz
+tar -xzf jdk.tar.gz -C /opt/
+mv /opt/jdk-9.0.4 /opt/jdk
diff --git a/docker/provision/maven/maven-3.5.0.sh b/docker/provision/maven/maven-3.5.0.sh
new file mode 100755
index 00000000..3167a964
--- /dev/null
+++ b/docker/provision/maven/maven-3.5.0.sh
@@ -0,0 +1,4 @@
+apt-get update && apt-get install -y wget
+wget https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.5.0/apache-maven-3.5.0-bin.tar.gz -O maven.tar.gz
+mkdir /usr/local/apache-maven/ && tar xvf maven.tar.gz -C /usr/local/apache-maven/
+mv /usr/local/apache-maven/apache-maven-3.5.0 /usr/local/apache-maven/apache-maven
diff --git a/docker/readme.md b/docker/readme.md
new file mode 100644
index 00000000..f6b6e550
--- /dev/null
+++ b/docker/readme.md
@@ -0,0 +1,31 @@
+## Configuration
+
+### `/workspace`
+
+Each docker image contains a `/workspace` where all relevant files are located.
+
+
+### `ARG lombokjar=lombok.jar`
+
+When building the image, a lombok.jar will be downloaded to `/workspace`. By default, this is the latest released version. You
+can download a specific version by adding `--build-arg lombokjar=lombok-<major.minor.build>.jar`
+
+### `ARG jdk=9`
+
+The jdk version to be used. Supported values:
+
+- `9` (default)
+- `8`
+
+The version is also accessible in `JDK_VERSION`.
+
+
+### Use fresh lombok.jar
+If you want to use a lombok.jar from your system, assuming `<lombokhome>` contains the path to the lombok directory (where the .git subdirectory is located)
+you can mount your recently built lombok.jar by providing `-v /<lombokhome>/dist/lombok.jar:/workspace/lombok.jar` to the `docker run` command.
+
+
+## Examples
+
+- [gradle](gradle/readme.md)
+- [maven](maven/readme.md)
diff --git a/docker/shared/lombok.config b/docker/shared/lombok.config
new file mode 100644
index 00000000..62f16b08
--- /dev/null
+++ b/docker/shared/lombok.config
@@ -0,0 +1,4 @@
+lombok.addJavaxGeneratedAnnotation = false
+lombok.anyConstructor.suppressConstructorProperties = true
+
+config.stopBubbling = true \ No newline at end of file
diff --git a/docker/shared/src/main/java/HelloWorld.java b/docker/shared/src/main/java/HelloWorld.java
new file mode 100644
index 00000000..f4c30218
--- /dev/null
+++ b/docker/shared/src/main/java/HelloWorld.java
@@ -0,0 +1,13 @@
+@lombok.Data
+public class HelloWorld {
+ private final int answer;
+
+ public static void main(String... args) {
+ System.out.println(new HelloWorld(42).getAnswer());
+ }
+
+ @FunctionalInterface
+ interface Foo {
+ String name();
+ }
+}
diff --git a/src/core/lombok/AllArgsConstructor.java b/src/core/lombok/AllArgsConstructor.java
index cc494967..c059c65d 100644
--- a/src/core/lombok/AllArgsConstructor.java
+++ b/src/core/lombok/AllArgsConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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,7 @@ import java.lang.annotation.Target;
* Generates an all-args constructor.
* An all-args constructor requires one argument for every field in the class.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Constructor.html">the project lombok features page for &#64;Constructor</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor">the project lombok features page for &#64;Constructor</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
*
@@ -45,31 +45,33 @@ public @interface AllArgsConstructor {
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
- * Any annotations listed here are put on the generated constructor. The syntax for this feature is: {@code @AllArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated constructor.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @AllArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @AllArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
+ *
+ * @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
- */
- AccessLevel access() default lombok.AccessLevel.PUBLIC;
-
- /**
- * Constructors are generated with the {@link java.beans.ConstructorProperties} annotation.
- * However, this annotation is new in 1.6 which means those compiling for 1.5 will need
- * to set this value to true.
*
- * @deprecated THIS FEATURE WILL BE REMOVED after March 31st 2015. Use configuration key {@link ConfigurationKeys#ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES} instead.
+ * @return The constructor will be generated with this access modifier.
*/
- @Deprecated
- boolean suppressConstructorProperties() default false;
+ AccessLevel access() default lombok.AccessLevel.PUBLIC;
/**
* Placeholder annotation to enable the placement of annotations on the generated code.
+ *
* @deprecated Don't use this annotation, ever - Read the documentation.
*/
@Deprecated
diff --git a/src/core/lombok/experimental/Builder.java b/src/core/lombok/Builder.java
index 1300e7d3..a16717cc 100644
--- a/src/core/lombok/experimental/Builder.java
+++ b/src/core/lombok/Builder.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -19,7 +19,7 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-package lombok.experimental;
+package lombok;
import static java.lang.annotation.ElementType.*;
import static java.lang.annotation.RetentionPolicy.*;
@@ -31,25 +31,25 @@ import java.lang.annotation.Target;
* The builder annotation creates a so-called 'builder' aspect to the class that is annotated or the class
* that contains a member which is annotated with {@code @Builder}.
* <p>
- * If a member is annotated, it must be either a constructor or a static method. If a class is annotated,
+ * If a member is annotated, it must be either a constructor or a method. If a class is annotated,
* then a private constructor is generated with all fields as arguments
* (as if {@code @AllArgsConstructor(AccessLevel.PRIVATE)} is present
* on the class), and it is as if this constructor has been annotated with {@code @Builder} instead.
* <p>
* The effect of {@code @Builder} is that an inner class is generated named <code><strong>T</strong>Builder</code>,
- * with a private constructor. Instances of <code><strong>T</strong>Builder</code> are made with the static
+ * with a private constructor. Instances of <code><strong>T</strong>Builder</code> are made with the
* method named {@code builder()} which is also generated for you in the class itself (not in the builder class).
* <p>
* The <code><strong>T</strong>Builder</code> class contains 1 method for each parameter of the annotated
- * constructor / static method (each field, when annotating a class), which returns the builder itself.
+ * constructor / method (each field, when annotating a class), which returns the builder itself.
* The builder also has a <code>build()</code> method which returns a completed instance of the original type,
* created by passing all parameters as set via the various other methods in the builder to the constructor
- * or static method that was annotated with {@code @Builder}. The return type of this method will be the same
- * as the relevant class, unless a static method has been annotated, in which case it'll be equal to the
+ * or method that was annotated with {@code @Builder}. The return type of this method will be the same
+ * as the relevant class, unless a method has been annotated, in which case it'll be equal to the
* return type of that method.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Builder.html">the project lombok features page for &#64;Builder</a>.
- * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Builder">the project lombok features page for &#64;Builder</a>.
+ * <br>
* <p>
* Before:
*
@@ -107,31 +107,65 @@ import java.lang.annotation.Target;
@Target({TYPE, METHOD, CONSTRUCTOR})
@Retention(SOURCE)
public @interface Builder {
- /** Name of the static method that creates a new builder instance. Default: {@code builder}. */
+ /**
+ * The field annotated with {@code @Default} must have an initializing expression; that expression is taken as the default to be used if not explicitly set during building.
+ */
+ @Target(FIELD)
+ @Retention(SOURCE)
+ public @interface Default {}
+
+ /** @return Name of the method that creates a new builder instance. Default: {@code builder}. */
String builderMethodName() default "builder";
- /** Name of the instance method in the builder class that creates an instance of your {@code @Builder}-annotated class. */
+ /** @return Name of the method in the builder class that creates an instance of your {@code @Builder}-annotated class. */
String buildMethodName() default "build";
- /** Name of the builder class.
+ /**
+ * Name of the builder class.
+ *
* Default for {@code @Builder} on types and constructors: {@code (TypeName)Builder}.
- * Default for {@code @Builder} on static methods: {@code (ReturnTypeName)Builder}.
+ * <p>
+ * Default for {@code @Builder} on methods: {@code (ReturnTypeName)Builder}.
+ *
+ * @return Name of the builder class that will be generated (or if it already exists, will be filled with builder elements).
*/
String builderClassName() default "";
/**
- * Normally the builder's 'set' methods are fluent, meaning, they have the same name as the field. Set this
- * to {@code false} to name the setter method for field {@code someField}: {@code setSomeField}.
- * <p>
- * <strong>Default: true</strong>
+ * If true, generate an instance method to obtain a builder that is initialized with the values of this instance.
+ * Legal only if {@code @Builder} is used on a constructor, on the type itself, or on a static method that returns
+ * an instance of the declaring type.
+ *
+ * @return Whether to generate a {@code toBuilder()} method.
*/
- boolean fluent() default true;
+ boolean toBuilder() default false;
/**
- * Normally the builder's 'set' methods are chaining, meaning, they return the builder so that you can chain
- * calls to set methods. Set this to {@code false} to have these 'set' methods return {@code void} instead.
+ * Put on a field (in case of {@code @Builder} on a type) or a parameter (for {@code @Builder} on a constructor or static method) to
+ * indicate how lombok should obtain a value for this field or parameter given an instance; this is only relevant if {@code toBuilder} is {@code true}.
+ *
+ * You do not need to supply an {@code @ObtainVia} annotation unless you wish to change the default behaviour: Use a field with the same name.
+ * <p>
+ * Note that one of {@code field} or {@code method} should be set, or an error is generated.
* <p>
- * <strong>Default: true</strong>
+ * The default behaviour is to obtain a value by referencing the name of the parameter as a field on 'this'.
*/
- boolean chain() default true;
+ @Target({FIELD, PARAMETER})
+ @Retention(SOURCE)
+ public @interface ObtainVia {
+ /**
+ * @return Tells lombok to obtain a value with the expression {@code this.value}.
+ */
+ String field() default "";
+
+ /**
+ * @return Tells lombok to obtain a value with the expression {@code this.method()}.
+ */
+ String method() default "";
+
+ /**
+ * @return Tells lombok to obtain a value with the expression {@code SelfType.method(this)}; requires {@code method} to be set.
+ */
+ boolean isStatic() default false;
+ }
}
diff --git a/src/core/lombok/Cleanup.java b/src/core/lombok/Cleanup.java
index 4b5c6fc2..a3a1c198 100644
--- a/src/core/lombok/Cleanup.java
+++ b/src/core/lombok/Cleanup.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -31,7 +31,7 @@ import java.lang.annotation.Target;
* of what happens. Implemented by wrapping all statements following the local variable declaration to the
* end of your scope into a try block that, as a finally action, closes the resource.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Cleanup.html">the project lombok features page for &#64;Cleanup</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Cleanup">the project lombok features page for &#64;Cleanup</a>.
* <p>
* Example:
* <pre>
@@ -61,10 +61,10 @@ import java.lang.annotation.Target;
* outStream.write(b, 0, r);
* }
* } finally {
- * if (out != null) out.close();
+ * if (outStream != null) outStream.close();
* }
* } finally {
- * if (in != null) in.close();
+ * if (inStream != null) inStream.close();
* }
* }
* </pre>
@@ -72,6 +72,6 @@ import java.lang.annotation.Target;
@Target(ElementType.LOCAL_VARIABLE)
@Retention(RetentionPolicy.SOURCE)
public @interface Cleanup {
- /** The name of the method that cleans up the resource. By default, 'close'. The method must not have any parameters. */
+ /** @return The name of the method that cleans up the resource. By default, 'close'. The method must not have any parameters. */
String value() default "close";
}
diff --git a/src/core/lombok/ConfigurationKeys.java b/src/core/lombok/ConfigurationKeys.java
index 301563b8..29c43d3f 100644
--- a/src/core/lombok/ConfigurationKeys.java
+++ b/src/core/lombok/ConfigurationKeys.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -23,6 +23,7 @@ package lombok;
import java.util.List;
+import lombok.core.configuration.CallSuperType;
import lombok.core.configuration.ConfigurationKey;
import lombok.core.configuration.FlagUsageType;
import lombok.core.configuration.NullCheckExceptionType;
@@ -35,6 +36,47 @@ public class ConfigurationKeys {
// ##### main package features #####
+ // ----- global -----
+
+ /**
+ * lombok configuration: {@code lombok.addGeneratedAnnotation} = {@code true} | {@code false}.
+ *
+ * If {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated, unless {@code lombok.addJavaxGeneratedAnnotation} is set.
+ * <br>
+ * <em>BREAKING CHANGE</em>: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9.
+ *
+ * @see ConfigurationKeys#ADD_JAVAX_GENERATED_ANNOTATIONS
+ * @see ConfigurationKeys#ADD_LOMBOK_GENERATED_ANNOTATIONS
+ * @deprecated Since version 1.16.14, use {@link #ADD_JAVAX_GENERATED_ANNOTATIONS} instead.
+ */
+ @Deprecated
+ public static final ConfigurationKey<Boolean> ADD_GENERATED_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.addGeneratedAnnotation", "Generate @javax.annotation.Generated on all generated code (default: false). Deprecated, use 'lombok.addJavaxGeneratedAnnotation' instead.") {};
+
+ /**
+ * lombok configuration: {@code lombok.addJavaxGeneratedAnnotation} = {@code true} | {@code false}.
+ *
+ * If {@code true}, lombok generates {@code @javax.annotation.Generated("lombok")} on all fields, methods, and types that are generated.
+ * <br>
+ * <em>BREAKING CHANGE</em>: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as this annotation is broken in JDK9.
+ */
+ public static final ConfigurationKey<Boolean> ADD_JAVAX_GENERATED_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.addJavaxGeneratedAnnotation", "Generate @javax.annotation.Generated on all generated code (default: follow lombok.addGeneratedAnnotation).") {};
+
+ /**
+ * lombok configuration: {@code lombok.addLombokGeneratedAnnotation} = {@code true} | {@code false}.
+ *
+ * If {@code true}, lombok generates {@code @lombok.Generated} on all fields, methods, and types that are generated.
+ */
+ public static final ConfigurationKey<Boolean> ADD_LOMBOK_GENERATED_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.addLombokGeneratedAnnotation", "Generate @lombok.Generated on all generated code (default: false).") {};
+
+ /**
+ * lombok configuration: {@code lombok.extern.findbugs.addSuppressFBWarnings} = {@code true} | {@code false}.
+ *
+ * If {@code true}, lombok generates {@code edu.umd.cs.findbugs.annotations.SuppressFBWarnings} on all fields, methods, and types that are generated.
+ *
+ * NB: If you enable this option, findbugs must be on the source or classpath, or you'll get errors that the type {@code SuppressFBWarnings} cannot be found.
+ */
+ public static final ConfigurationKey<Boolean> ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS = new ConfigurationKey<Boolean>("lombok.extern.findbugs.addSuppressFBWarnings", "Generate @edu.umd.cs.findbugs.annotations.SuppressFBWArnings on all generated code (default: false).") {};
+
// ----- *ArgsConstructor -----
/**
@@ -51,10 +93,25 @@ public class ConfigurationKeys {
* To suppress the generation of it, set this configuration to {@code true}.
*
* NB: GWT projects, and probably android projects, should explicitly set this key to {@code true} for the entire project.
+ *
+ * <br>
+ * <em>BREAKING CHANGE</em>: Starting with lombok v2.0.0, defaults to {@code false} instead of {@code true}, as {@code @ConstructorProperties} requires extra modules in JDK9.
+ *
+ * @see ConfigurationKeys#ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES
+ * @deprecated Since version 2.0, use {@link #ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES} instead.
*/
+ @Deprecated
public static final ConfigurationKey<Boolean> ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES = new ConfigurationKey<Boolean>("lombok.anyConstructor.suppressConstructorProperties", "Suppress the generation of @ConstructorProperties for generated constructors (default: false).") {};
/**
+ * lombok configuration: {@code lombok.anyConstructor.addConstructorProperties} = {@code true} | {@code false}.
+ *
+ * If {@code true}, all generated constructors with at least 1 argument get a {@code @ConstructorProperties}.
+ *
+ */
+ public static final ConfigurationKey<Boolean> ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES = new ConfigurationKey<Boolean>("lombok.anyConstructor.addConstructorProperties", "Generate @ConstructorProperties for generated constructors (default: false).") {};
+
+ /**
* lombok configuration: {@code lombok.allArgsConstructor.flagUsage} = {@code WARNING} | {@code ERROR}.
*
* If set, <em>any</em> usage of {@code @AllArgsConstructor} results in a warning / error.
@@ -133,9 +190,16 @@ public class ConfigurationKeys {
/**
* lombok configuration: {@code lombok.equalsAndHashCode.doNotUseGetters} = {@code true} | {@code false}.
*
- * For any class without an {@code @EqualsAndHashCode} that explicitly defines the {@code doNotUseGetters} option, this value is used.
+ * For any class without an {@code @EqualsAndHashCode} that explicitly defines the {@code doNotUseGetters} option, this value is used (default = false).
*/
- public static final ConfigurationKey<Boolean> EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS = new ConfigurationKey<Boolean>("lombok.equalsAndHashCode.doNotUseGetters", "Don't call the getters but use the fields directly in the generated equalsAndHashCode method.") {};
+ public static final ConfigurationKey<Boolean> EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS = new ConfigurationKey<Boolean>("lombok.equalsAndHashCode.doNotUseGetters", "Don't call the getters but use the fields directly in the generated equals and hashCode method (default = false).") {};
+
+ /**
+ * lombok configuration: {@code lombok.equalsAndHashCode.callSuper} = {@code call} | {@code ignore} | {@code warn}.
+ *
+ * For any class with an {@code @EqualsAndHashCode} annotation which extends a class other than {@code java.lang.Object}, should a call to superclass's implementation of {@code equals} and {@code hashCode} be included in the generated methods? (Default = warn)
+ */
+ public static final ConfigurationKey<CallSuperType> EQUALS_AND_HASH_CODE_CALL_SUPER = new ConfigurationKey<CallSuperType>("lombok.equalsAndHashCode.callSuper", "When generating equals and hashCode for classes that don't extend Object, either automatically take into account superclass implementation (call), or don't (skip), or warn and don't (warn). (default = warn).") {};
/**
* lombok configuration: {@code lombok.equalsAndHashCode.flagUsage} = {@code WARNING} | {@code ERROR}.
@@ -149,9 +213,9 @@ public class ConfigurationKeys {
/**
* lombok configuration: {@code lombok.toString.doNotUseGetters} = {@code true} | {@code false}.
*
- * For any class without an {@code @ToString} that explicitly defines the {@code doNotUseGetters} option, this value is used.
+ * For any class without an {@code @ToString} that explicitly defines the {@code doNotUseGetters} option, this value is used (default = false).
*/
- public static final ConfigurationKey<Boolean> TO_STRING_DO_NOT_USE_GETTERS = new ConfigurationKey<Boolean>("lombok.toString.doNotUseGetters", "Don't call the getters but use the fields directly in the generated toString method.") {};
+ public static final ConfigurationKey<Boolean> TO_STRING_DO_NOT_USE_GETTERS = new ConfigurationKey<Boolean>("lombok.toString.doNotUseGetters", "Don't call the getters but use the fields directly in the generated toString method (default = false).") {};
/**
* lombok configuration: {@code lombok.toString.flagUsage} = {@code WARNING} | {@code ERROR}.
@@ -163,9 +227,35 @@ public class ConfigurationKeys {
/**
* lombok configuration: {@code lombok.toString.includeFieldNames} = {@code true} | {@code false}.
*
- * For any class without an {@code @ToString} that explicitly defines the {@code includeFieldNames} option, this value is used.
+ * For any class without an {@code @ToString} that explicitly defines the {@code includeFieldNames} option, this value is used (default = true).
+ */
+ public static final ConfigurationKey<Boolean> TO_STRING_INCLUDE_FIELD_NAMES = new ConfigurationKey<Boolean>("lombok.toString.includeFieldNames", "Include the field names in the generated toString method (default = true).") {};
+
+ // ----- Builder -----
+
+ /**
+ * lombok configuration: {@code lombok.builder.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Builder} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> BUILDER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.builder.flagUsage", "Emit a warning or error if @Builder is used.") {};
+
+ // ----- Singular -----
+
+ /**
+ * lombok configuration: {@code lombok.singular.useGuava} = {@code true} | {@code false}.
+ *
+ * If explicitly set to {@code true}, guava's {@code ImmutableList} etc are used to implement the immutable collection datatypes generated by @Singular @Builder for fields/parameters of type {@code java.util.List} and such.
+ * By default, unmodifiable-wrapped versions of {@code java.util} types are used.
*/
- public static final ConfigurationKey<Boolean> TO_STRING_INCLUDE_FIELD_NAMES = new ConfigurationKey<Boolean>("lombok.toString.includeFieldNames", "Include the field names in the generated toString method.") {};
+ public static final ConfigurationKey<Boolean> SINGULAR_USE_GUAVA = new ConfigurationKey<Boolean>("lombok.singular.useGuava", "Generate backing immutable implementations for @Singular on java.util.* types by using guava's ImmutableList, etc. Normally java.util's mutable types are used and wrapped to make them immutable.") {};
+
+ /**
+ * lombok configuration: {@code lombok.singular.auto} = {@code true} | {@code false}.
+ *
+ * By default or if explicitly set to {@code true}, lombok will attempt to automatically singularize the name of your variable/parameter when using {@code @Singular}; the name is assumed to be written in english, and a plural. If explicitly to {@code false}, you must always specify the singular form; this is especially useful if your identifiers are in a foreign language.
+ */
+ public static final ConfigurationKey<Boolean> SINGULAR_AUTO = new ConfigurationKey<Boolean>("lombok.singular.auto", "If true (default): Automatically singularize the assumed-to-be-plural name of your variable/parameter when using {@code @Singular}.") {};
// ##### Standalones #####
@@ -190,11 +280,11 @@ public class ConfigurationKeys {
// ----- NonNull -----
/**
- * lombok configuration: {@code lombok.nonNull.exceptionType} = &lt;String: <em>a java exception type; either [{@code IllegalArgumentException} or: {@code NullPointerException}].
+ * lombok configuration: {@code lombok.nonNull.exceptionType} = &lt;String: <em>a java exception type</em>; either [{@code IllegalArgumentException} or: {@code NullPointerException}].
*
* Sets the exception to throw if {@code @NonNull} is applied to a method parameter, and a caller passes in {@code null}.
*/
- public static final ConfigurationKey<NullCheckExceptionType> NON_NULL_EXCEPTION_TYPE = new ConfigurationKey<NullCheckExceptionType>("lombok.nonNull.exceptionType", "The type of the exception to throw if a passed-in argument is null. Default: NullPointerException.") {};
+ public static final ConfigurationKey<NullCheckExceptionType> NON_NULL_EXCEPTION_TYPE = new ConfigurationKey<NullCheckExceptionType>("lombok.nonNull.exceptionType", "The type of the exception to throw if a passed-in argument is null (Default: NullPointerException).") {};
/**
* lombok configuration: {@code lombok.nonNull.flagUsage} = {@code WARNING} | {@code ERROR}.
@@ -231,7 +321,8 @@ public class ConfigurationKeys {
* If set, <em>any</em> usage of {@code val} results in a warning / error.
*/
public static final ConfigurationKey<FlagUsageType> VAL_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.val.flagUsage", "Emit a warning or error if 'val' is used.") {};
-
+ public static final ConfigurationKey<FlagUsageType> VAR_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.var.flagUsage", "Emit a warning or error if 'var' is used.") {};
+
// ##### Extern #####
// ----- Logging -----
@@ -285,11 +376,18 @@ public class ConfigurationKeys {
public static final ConfigurationKey<FlagUsageType> LOG_XSLF4J_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.xslf4j.flagUsage", "Emit a warning or error if @XSlf4j is used.") {};
/**
+ * lombok configuration: {@code lombok.log.jbosslog.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @JBossLog} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> LOG_JBOSSLOG_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.log.jbosslog.flagUsage", "Emit a warning or error if @JBossLog is used.") {};
+
+ /**
* lombok configuration: {@code lombok.log.fieldName} = &lt;String: aJavaIdentifier&gt; (Default: {@code log}).
*
* If set the various log annotations (which make a log field) will use the stated identifier instead of {@code log} as a name.
*/
- public static final ConfigurationKey<String> LOG_ANY_FIELD_NAME = new ConfigurationKey<String>("lombok.log.fieldName", "Use this name for the generated logger fields (default: 'log')") {};
+ public static final ConfigurationKey<String> LOG_ANY_FIELD_NAME = new ConfigurationKey<String>("lombok.log.fieldName", "Use this name for the generated logger fields (default: 'log').") {};
/**
* lombok configuration: {@code lombok.log.fieldIsStatic} = {@code true} | {@code false}.
@@ -329,25 +427,16 @@ public class ConfigurationKeys {
/**
* lombok configuration: {@code lombok.accessors.chain} = {@code true} | {@code false}.
*
- * For any class without an {@code @Accessors} that explicitly defines the {@code chain} option, this value is used.
+ * For any class without an {@code @Accessors} that explicitly defines the {@code chain} option, this value is used (default = false).
*/
- public static final ConfigurationKey<Boolean> ACCESSORS_CHAIN = new ConfigurationKey<Boolean>("lombok.accessors.chain", "Generate setters that return 'this' instead of 'void'.") {};
+ public static final ConfigurationKey<Boolean> ACCESSORS_CHAIN = new ConfigurationKey<Boolean>("lombok.accessors.chain", "Generate setters that return 'this' instead of 'void' (default: false).") {};
/**
* lombok configuration: {@code lombok.accessors.fluent} = {@code true} | {@code false}.
*
- * For any class without an {@code @Accessors} that explicitly defines the {@code fluent} option, this value is used.
- */
- public static final ConfigurationKey<Boolean> ACCESSORS_FLUENT = new ConfigurationKey<Boolean>("lombok.accessors.fluent", "Generate getters and setters using only the field name (no get/set prefix).") {};
-
- // ----- Builder -----
-
- /**
- * lombok configuration: {@code lombok.builder.flagUsage} = {@code WARNING} | {@code ERROR}.
- *
- * If set, <em>any</em> usage of {@code @Builder} results in a warning / error.
+ * For any class without an {@code @Accessors} that explicitly defines the {@code fluent} option, this value is used (default = false).
*/
- public static final ConfigurationKey<FlagUsageType> BUILDER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.builder.flagUsage", "Emit a warning or error if @Builder is used.") {};
+ public static final ConfigurationKey<Boolean> ACCESSORS_FLUENT = new ConfigurationKey<Boolean>("lombok.accessors.fluent", "Generate getters and setters using only the field name (no get/set prefix) (default: false).") {};
// ----- ExtensionMethod -----
@@ -361,12 +450,55 @@ public class ConfigurationKeys {
// ----- FieldDefaults -----
/**
+ * lombok configuration: {@code lombok.fieldDefaults.defaultPrivate} = {@code true} | {@code false}.
+ *
+ * If set to <code>true</code> <em>any</em> field without an access modifier or {@code @PackagePrivate} is marked as {@code private} by lombok, in all source files compiled.
+ */
+ public static final ConfigurationKey<Boolean> FIELD_DEFAULTS_PRIVATE_EVERYWHERE = new ConfigurationKey<Boolean>("lombok.fieldDefaults.defaultPrivate", "If true, fields without any access modifier, in any file (lombok annotated or not) are marked as private. Use @PackagePrivate or an explicit modifier to override this.") {};
+
+ /**
+ * lombok configuration: {@code lombok.fieldDefaults.defaultFinal} = {@code true} | {@code false}.
+ *
+ * If set to <code>true</code> <em>any</em> field without {@code @NonFinal} is marked as {@code final} by lombok, in all source files compiled.
+ */
+ public static final ConfigurationKey<Boolean> FIELD_DEFAULTS_FINAL_EVERYWHERE = new ConfigurationKey<Boolean>("lombok.fieldDefaults.defaultFinal", "If true, fields, in any file (lombok annotated or not) are marked as final. Use @NonFinal to override this.") {};
+
+ /**
* lombok configuration: {@code lombok.fieldDefaults.flagUsage} = {@code WARNING} | {@code ERROR}.
*
* If set, <em>any</em> usage of {@code @FieldDefaults} results in a warning / error.
*/
public static final ConfigurationKey<FlagUsageType> FIELD_DEFAULTS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.fieldDefaults.flagUsage", "Emit a warning or error if @FieldDefaults is used.") {};
+ // ----- Helper -----
+
+ /**
+ * lombok configuration: {@code lombok.helper.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @Helper} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> HELPER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.helper.flagUsage", "Emit a warning or error if @Helper is used.") {};
+
+ // ----- onX -----
+
+ /**
+ * lombok configuration: {@code lombok.onX.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code onX} results in a warning / error.
+ * <br>
+ * Specifically, this flags usage of {@code @Getter(onMethod=...)}, {@code @Setter(onParam=...)}, {@code @Setter(onMethod=...)}, {@code @XArgsConstructor(onConstructor=...)}.
+ */
+ public static final ConfigurationKey<FlagUsageType> ON_X_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.onX.flagUsage", "Emit a warning or error if onX is used.") {};
+
+ // ----- UtilityClass -----
+
+ /**
+ * lombok configuration: {@code lombok.utilityClass.flagUsage} = {@code WARNING} | {@code ERROR}.
+ *
+ * If set, <em>any</em> usage of {@code @UtilityClass} results in a warning / error.
+ */
+ public static final ConfigurationKey<FlagUsageType> UTILITY_CLASS_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.utilityClass.flagUsage", "Emit a warning or error if @UtilityClass is used.") {};
+
// ----- Wither -----
/**
@@ -376,7 +508,6 @@ public class ConfigurationKeys {
*/
public static final ConfigurationKey<FlagUsageType> WITHER_FLAG_USAGE = new ConfigurationKey<FlagUsageType>("lombok.wither.flagUsage", "Emit a warning or error if @Wither is used.") {};
-
// ----- Configuration System -----
/**
diff --git a/src/core/lombok/Data.java b/src/core/lombok/Data.java
index bbc8d920..ffa968c1 100644
--- a/src/core/lombok/Data.java
+++ b/src/core/lombok/Data.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -32,7 +32,7 @@ import java.lang.annotation.Target;
* <p>
* Equivalent to {@code @Getter @Setter @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Data.html">the project lombok features page for &#64;Data</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Data">the project lombok features page for &#64;Data</a>.
*
* @see Getter
* @see Setter
@@ -54,6 +54,8 @@ public @interface Data {
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
diff --git a/src/core/lombok/Delegate.java b/src/core/lombok/Delegate.java
index d5b4b48c..0c5a4c2c 100644
--- a/src/core/lombok/Delegate.java
+++ b/src/core/lombok/Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -40,6 +40,8 @@ public @interface Delegate {
* type listed here is used only to determine which delegate methods to generate.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, generate a delegate method.
*/
Class<?>[] types() default {};
@@ -47,6 +49,8 @@ public @interface Delegate {
* Each method in any of the types listed here (include supertypes) will <em>not</em> be delegated.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, skip generating a delegate method (overrides {@code types()}).
*/
Class<?>[] excludes() default {};
}
diff --git a/src/core/lombok/EqualsAndHashCode.java b/src/core/lombok/EqualsAndHashCode.java
index dbce23b8..2f88ac50 100644
--- a/src/core/lombok/EqualsAndHashCode.java
+++ b/src/core/lombok/EqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,15 +29,16 @@ import java.lang.annotation.Target;
/**
* Generates implementations for the {@code equals} and {@code hashCode} methods inherited by all objects, based on relevant fields.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/EqualsAndHashCode.html">the project lombok features page for &#64;EqualsAndHashCode</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/EqualsAndHashCode">the project lombok features page for &#64;EqualsAndHashCode</a>.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
public @interface EqualsAndHashCode {
/**
- * Any fields listed here will not be taken into account in the generated
- * {@code equals} and {@code hashCode} implementations.
+ * Any fields listed here will not be taken into account in the generated {@code equals} and {@code hashCode} implementations.
* Mutually exclusive with {@link #of()}.
+ *
+ * @return A list of fields to exclude.
*/
String[] exclude() default {};
@@ -46,25 +47,37 @@ public @interface EqualsAndHashCode {
* Normally, all non-static, non-transient fields are used for identity.
* <p>
* Mutually exclusive with {@link #exclude()}.
+ *
+ * @return A list of fields to use (<em>default</em>: all of them).
*/
String[] of() default {};
/**
- * Call on the superclass's implementations of {@code equals} and {@code hashCode} before calculating
- * for the fields in this class.
+ * Call on the superclass's implementations of {@code equals} and {@code hashCode} before calculating for the fields in this class.
* <strong>default: false</strong>
+ *
+ * @return Whether to call the superclass's {@code equals} implementation as part of the generated equals algorithm.
*/
boolean callSuper() default false;
/**
* Normally, if getters are available, those are called. To suppress this and let the generated code use the fields directly, set this to {@code true}.
* <strong>default: false</strong>
+ *
+ * @return If {@code true}, always use direct field access instead of calling the getter method.
*/
boolean doNotUseGetters() default false;
/**
- * Any annotations listed here are put on the generated parameter of {@code equals} and {@code canEqual}. The syntax for this feature is: {@code @EqualsAndHashCode(onParam=@__({@AnnotationsGoHere}))}
- * This is useful to add for example a {@code Nullable} annotation.
+ * Any annotations listed here are put on the generated parameter of {@code equals} and {@code canEqual}.
+ * This is useful to add for example a {@code Nullable} annotation.<br>
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @EqualsAndHashCode(onParam=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @EqualsAndHashCode(onParam_={@AnnotationsGohere})} // note the underscore after {@code onParam}.
+ *
+ * @return List of annotations to apply to the generated parameter in the {@code equals()} method.
*/
AnyAnnotation[] onParam() default {};
diff --git a/src/core/lombok/Generated.java b/src/core/lombok/Generated.java
new file mode 100644
index 00000000..b99a1b58
--- /dev/null
+++ b/src/core/lombok/Generated.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015-2016 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;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * Lombok will eventually automatically add this annotation to all generated constructors, methods, fields, and types.
+ *
+ * You can mark the presence of this annotation as 'ignore it' for all code style and bug finding tools.
+ * <p>
+ * NB: As of v1.16.2 which introduces this annotation, lombok doesn't actually add this annotation; we're setting
+ * it up so that lombok jars in widespread use start having this, which will make it easier to actually apply it
+ * later on.
+ */
+@Target({ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.FIELD, ElementType.TYPE})
+@Retention(RetentionPolicy.CLASS)
+public @interface Generated {
+}
diff --git a/src/core/lombok/Getter.java b/src/core/lombok/Getter.java
index 428f53ef..5a23fe30 100644
--- a/src/core/lombok/Getter.java
+++ b/src/core/lombok/Getter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Put on any field to make lombok build a standard getter.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/GetterSetter.html">the project lombok features page for &#64;Getter and &#64;Setter</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/GetterSetter">the project lombok features page for &#64;Getter and &#64;Setter</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onMethod} parameter. See the full documentation for more details.
* <p>
@@ -54,20 +54,29 @@ import java.lang.annotation.Target;
public @interface Getter {
/**
* If you want your getter to be non-public, you can specify an alternate access level here.
+ *
+ * @return The getter method will be generated with this access modifier.
*/
lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
/**
- * Any annotations listed here are put on the generated method. The syntax for this feature is: {@code @Getter(onMethod=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated method.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Getter(onMethod=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @Getter(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
+ *
+ * @return List of annotations to apply to the generated getter method.
*/
- AnyAnnotation[] onMethod() default @AnyAnnotation;
+ AnyAnnotation[] onMethod() default {};
boolean lazy() default false;
/**
- * Placeholder annotation to enable the placement of annotations on the generated code.
- * @deprecated Don't use this annotation, ever - Read the documentation.
- */
+ * Placeholder annotation to enable the placement of annotations on the generated code.
+ * @deprecated Don't use this annotation, ever - Read the documentation.
+ */
@Deprecated
@Retention(RetentionPolicy.SOURCE)
@Target({})
diff --git a/src/core/lombok/Lombok.java b/src/core/lombok/Lombok.java
index 07fd083d..d86b6d1c 100644
--- a/src/core/lombok/Lombok.java
+++ b/src/core/lombok/Lombok.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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 @@ public class Lombok {
* The exception is still thrown - javac will just stop whining about it.
* <p>
* Example usage:
- * <p>
* <pre>public void run() {
* throw sneakyThrow(new IOException("You don't need to catch me!"));
* }</pre>
@@ -49,26 +48,38 @@ public class Lombok {
*/
public static RuntimeException sneakyThrow(Throwable t) {
if (t == null) throw new NullPointerException("t");
- Lombok.<RuntimeException>sneakyThrow0(t);
- return null;
+ return Lombok.<RuntimeException>sneakyThrow0(t);
}
@SuppressWarnings("unchecked")
- private static <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
+ private static <T extends Throwable> T sneakyThrow0(Throwable t) throws T {
throw (T)t;
}
/**
- * Returns the parameter directly. <br />
+ * Returns the parameter directly.
*
- * This method can be used to prevent a static analyzer to determine
- * the nullness of the passed parameter.
+ * This method can be used to prevent a static analyzer to determine the nullness of the passed parameter.
*
- * @param <T> the type of the parameter
- * @param value the value to return
- * @return value
+ * @param <T> the type of the parameter.
+ * @param value the value to return.
+ * @return value (this method just returns the parameter).
*/
public static <T> T preventNullAnalysis(T value) {
return value;
}
+
+ /**
+ * Ensures that the {@code value} is not {@code null}.
+ *
+ * @param <T> Type of the parameter.
+ * @param value the value to test for null.
+ * @param message the message of the {@link NullPointerException}.
+ * @return the value if it is not null.
+ * @throws NullPointerException with the {@code message} if the value is null.
+ */
+ public static <T> T checkNotNull(T value, String message) {
+ if (value == null) throw new NullPointerException(message);
+ return value;
+ }
}
diff --git a/src/core/lombok/NoArgsConstructor.java b/src/core/lombok/NoArgsConstructor.java
index cd3e5568..672cd1c2 100644
--- a/src/core/lombok/NoArgsConstructor.java
+++ b/src/core/lombok/NoArgsConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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,7 @@ import java.lang.annotation.Target;
* Generates a no-args constructor.
* Will generate an error message if such a constructor cannot be written due to the existence of final fields.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Constructor.html">the project lombok features page for &#64;Constructor</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor">the project lombok features page for &#64;Constructor</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
* <p>
@@ -47,20 +47,39 @@ public @interface NoArgsConstructor {
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
- * Any annotations listed here are put on the generated constructor. The syntax for this feature is: {@code @NoArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated constructor.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @NoArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @NoArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
+ *
+ * @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
+ *
+ * @return The constructor will be generated with this access modifier.
*/
AccessLevel access() default lombok.AccessLevel.PUBLIC;
/**
+ * If {@code true}, initializes all final fields to 0 / null / false.
+ * Otherwise, a compile time error occurs.
+ *
+ * @return Return {@code} true to force generation of a no-args constructor, picking defaults if necessary to assign required fields.
+ */
+ boolean force() default false;
+
+ /**
* Placeholder annotation to enable the placement of annotations on the generated code.
* @deprecated Don't use this annotation, ever - Read the documentation.
*/
diff --git a/src/core/lombok/RequiredArgsConstructor.java b/src/core/lombok/RequiredArgsConstructor.java
index 8bb57c1a..f21bd647 100644
--- a/src/core/lombok/RequiredArgsConstructor.java
+++ b/src/core/lombok/RequiredArgsConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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,7 @@ import java.lang.annotation.Target;
* Generates a constructor with required arguments.
* Required arguments are final fields and fields with constraints such as {@code @NonNull}.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Constructor.html">the project lombok features page for &#64;Constructor</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Constructor">the project lombok features page for &#64;Constructor</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onConstructor} parameter. See the full documentation for more details.
*
@@ -45,28 +45,29 @@ public @interface RequiredArgsConstructor {
* is generated with the same argument list that wraps the real constructor.
*
* Such a static 'constructor' is primarily useful as it infers type arguments.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticName() default "";
/**
- * Any annotations listed here are put on the generated constructor. The syntax for this feature is: {@code @RequiredArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated constructor.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @RequiredArgsConstructor(onConstructor=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @RequiredArgsConstructor(onConstructor_={@AnnotationsGohere})} // note the underscore after {@code onConstructor}.
+ *
+ * @return List of annotations to apply to the generated constructor.
*/
AnyAnnotation[] onConstructor() default {};
/**
* Sets the access level of the constructor. By default, generated constructors are {@code public}.
- */
- AccessLevel access() default lombok.AccessLevel.PUBLIC;
-
- /**
- * Constructors are generated with the {@link java.beans.ConstructorProperties} annotation.
- * However, this annotation is new in 1.6 which means those compiling for 1.5 will need
- * to set this value to true.
*
- * @deprecated THIS FEATURE WILL BE REMOVED after March 31st 2015. Use configuration key {@link ConfigurationKeys#ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES} instead.
+ * @return The constructor will be generated with this access modifier.
*/
- @Deprecated
- boolean suppressConstructorProperties() default false;
+ AccessLevel access() default lombok.AccessLevel.PUBLIC;
/**
* Placeholder annotation to enable the placement of annotations on the generated code.
diff --git a/src/core/lombok/Setter.java b/src/core/lombok/Setter.java
index 5e07b802..1b70bac9 100644
--- a/src/core/lombok/Setter.java
+++ b/src/core/lombok/Setter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Put on any field to make lombok build a standard setter.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/GetterSetter.html">the project lombok features page for &#64;Getter and &#64;Setter</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/GetterSetter">the project lombok features page for &#64;Getter and &#64;Setter</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onParam} and {@code onMethod} parameter. See the full documentation for more details.
* <p>
@@ -55,16 +55,32 @@ import java.lang.annotation.Target;
public @interface Setter {
/**
* If you want your setter to be non-public, you can specify an alternate access level here.
+ *
+ * @return The setter method will be generated with this access modifier.
*/
lombok.AccessLevel value() default lombok.AccessLevel.PUBLIC;
/**
- * Any annotations listed here are put on the generated method. The syntax for this feature is: {@code @Setter(onMethod=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated method.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Setter(onMethod=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @Setter(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
+ *
+ * @return List of annotations to apply to the generated setter method.
*/
AnyAnnotation[] onMethod() default {};
/**
- * Any annotations listed here are put on the generated method's parameter. The syntax for this feature is: {@code @Setter(onParam=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated method's parameter.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Setter(onParam=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @Setter(onParam_={@AnnotationsGohere})} // note the underscore after {@code onParam}.
+ *
+ * @return List of annotations to apply to the generated parameter in the setter method.
*/
AnyAnnotation[] onParam() default {};
diff --git a/src/core/lombok/Singular.java b/src/core/lombok/Singular.java
new file mode 100644
index 00000000..67edab96
--- /dev/null
+++ b/src/core/lombok/Singular.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 2015-2017 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;
+
+import static java.lang.annotation.ElementType.*;
+import static java.lang.annotation.RetentionPolicy.*;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+/**
+ * The singular annotation is used together with {@code @Builder} to create single element 'add' methods in the builder for collections.
+ */
+@Target({FIELD, PARAMETER})
+@Retention(SOURCE)
+public @interface Singular {
+ /** @return The singular name of this field. If it's a normal english plural, lombok will figure it out automatically. Otherwise, this parameter is mandatory. */
+ String value() default "";
+}
diff --git a/src/core/lombok/SneakyThrows.java b/src/core/lombok/SneakyThrows.java
index 929b4578..0506d615 100644
--- a/src/core/lombok/SneakyThrows.java
+++ b/src/core/lombok/SneakyThrows.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -34,7 +34,7 @@ import java.lang.annotation.Target;
* checked exception types. The JVM does not check for the consistency of the checked exception system; javac does,
* and this annotation lets you opt out of its mechanism.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/SneakyThrows.html">the project lombok features page for &#64;SneakyThrows</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/SneakyThrows">the project lombok features page for &#64;SneakyThrows</a>.
* <p>
* Example:
* <pre>
@@ -59,8 +59,9 @@ import java.lang.annotation.Target;
@Target({ElementType.METHOD, ElementType.CONSTRUCTOR})
@Retention(RetentionPolicy.SOURCE)
public @interface SneakyThrows {
- /** The exception type(s) you want to sneakily throw onward. */
+ /** @return The exception type(s) you want to sneakily throw onward. */
Class<? extends Throwable>[] value() default java.lang.Throwable.class;
- //The package is mentioned in java.lang due to a bug in javac (presence of an annotation processor throws off the type resolver for some reason).
+ //The fully qualified name is used for java.lang.Throwable in the parameter only. This works around a bug in javac:
+ // presence of an annotation processor throws off the type resolver for some reason.
}
diff --git a/src/core/lombok/Synchronized.java b/src/core/lombok/Synchronized.java
index c5601a0c..5dff0fb2 100644
--- a/src/core/lombok/Synchronized.java
+++ b/src/core/lombok/Synchronized.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,7 +35,7 @@ import java.lang.annotation.Target;
* {@code $LOCK} is used. These will be generated if needed and if they aren't already present. The contents
* of the fields will be serializable.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Synchronized.html">the project lombok features page for &#64;Synchronized</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Synchronized">the project lombok features page for &#64;Synchronized</a>.
*/
@Target(ElementType.METHOD)
@Retention(RetentionPolicy.SOURCE)
@@ -43,6 +43,8 @@ public @interface Synchronized {
/**
* Optional: specify the name of a different field to lock on. It is a compile time error if this field
* doesn't already exist (the fields are automatically generated only if you don't specify a specific name.
+ *
+ * @return Name of the field to lock on (blank = generate one).
*/
String value() default "";
}
diff --git a/src/core/lombok/ToString.java b/src/core/lombok/ToString.java
index e87c71e7..0c43c40b 100644
--- a/src/core/lombok/ToString.java
+++ b/src/core/lombok/ToString.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Generates an implementation for the {@code toString} method inherited by all objects, consisting of printing the values of relevant fields.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/ToString.html">the project lombok features page for &#64;ToString</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/ToString">the project lombok features page for &#64;ToString</a>.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
@@ -37,12 +37,16 @@ public @interface ToString {
/**
* Include the name of each field when printing it.
* <strong>default: true</strong>
+ *
+ * @return Whether or not to include the names of fields in the string produced by the generated {@code toString()}.
*/
boolean includeFieldNames() default true;
/**
* Any fields listed here will not be printed in the generated {@code toString} implementation.
* Mutually exclusive with {@link #of()}.
+ *
+ * @return A list of fields to exclude.
*/
String[] exclude() default {};
@@ -51,18 +55,24 @@ public @interface ToString {
* Normally, all non-static fields are printed.
* <p>
* Mutually exclusive with {@link #exclude()}.
+ *
+ * @return A list of fields to use (<em>default</em>: all of them).
*/
String[] of() default {};
/**
* Include the result of the superclass's implementation of {@code toString} in the output.
* <strong>default: false</strong>
+ *
+ * @return Whether to call the superclass's {@code toString} implementation as part of the generated toString algorithm.
*/
boolean callSuper() default false;
/**
* Normally, if getters are available, those are called. To suppress this and let the generated code use the fields directly, set this to {@code true}.
* <strong>default: false</strong>
+ *
+ * @return If {@code true}, always use direct field access instead of calling the getter method.
*/
boolean doNotUseGetters() default false;
}
diff --git a/src/core/lombok/Value.java b/src/core/lombok/Value.java
index 2cffe15b..562ba0cc 100644
--- a/src/core/lombok/Value.java
+++ b/src/core/lombok/Value.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -29,13 +29,13 @@ import java.lang.annotation.Target;
/**
* Generates a lot of code which fits with a class that is a representation of an immutable entity.
* <p>
- * Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
+ * Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @AllArgsConstructor @ToString @EqualsAndHashCode}.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Value.html">the project lombok features page for &#64;Value</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Value">the project lombok features page for &#64;Value</a>.
*
* @see lombok.Getter
* @see lombok.experimental.FieldDefaults
- * @see lombok.RequiredArgsConstructor
+ * @see lombok.AllArgsConstructor
* @see lombok.ToString
* @see lombok.EqualsAndHashCode
* @see lombok.Data
@@ -49,10 +49,12 @@ public @interface Value {
* We suggest the name: "of", like so:
*
* <pre>
- * public @Data(staticConstructor = "of") class Point { final int x, y; }
+ * public @Value(staticConstructor = "of") class Point { final int x, y; }
* </pre>
*
* Default: No static constructor, instead the normal constructor is public.
+ *
+ * @return Name of static 'constructor' method to generate (blank = generate a normal constructor).
*/
String staticConstructor() default "";
}
diff --git a/src/core/lombok/bytecode/AsmUtil.java b/src/core/lombok/bytecode/AsmUtil.java
index 26e5af1f..e3d33efa 100644
--- a/src/core/lombok/bytecode/AsmUtil.java
+++ b/src/core/lombok/bytecode/AsmUtil.java
@@ -37,7 +37,7 @@ class AsmUtil {
ClassReader reader = new ClassReader(byteCode);
ClassWriter writer = new FixedClassWriter(reader, 0);
- ClassVisitor visitor = new ClassVisitor(Opcodes.ASM5, writer) {
+ ClassVisitor visitor = new ClassVisitor(Opcodes.ASM6, writer) {
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new JSRInlinerAdapter(super.visitMethod(access, name, desc, signature, exceptions), access, name, desc, signature, exceptions);
}
diff --git a/src/core/lombok/bytecode/ClassFileMetaData.java b/src/core/lombok/bytecode/ClassFileMetaData.java
index 68b8bb7d..0dc6a6c8 100644
--- a/src/core/lombok/bytecode/ClassFileMetaData.java
+++ b/src/core/lombok/bytecode/ClassFileMetaData.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -44,6 +44,9 @@ public class ClassFileMetaData {
private static final byte METHOD_HANDLE = 15;
private static final byte METHOD_TYPE = 16;
private static final byte INVOKE_DYNAMIC = 18;
+ // New in java9: support for modules
+ private static final byte MODULE = 19;
+ private static final byte PACKAGE = 20;
private static final int NOT_FOUND = -1;
private static final int START_OF_CONSTANT_POOL = 8;
@@ -79,6 +82,8 @@ public class ClassFileMetaData {
case CLASS:
case STRING:
case METHOD_TYPE:
+ case MODULE:
+ case PACKAGE:
position += 2;
break;
case METHOD_HANDLE:
diff --git a/src/core/lombok/bytecode/PostCompilerApp.java b/src/core/lombok/bytecode/PostCompilerApp.java
index d2c3157c..5f49bd81 100644
--- a/src/core/lombok/bytecode/PostCompilerApp.java
+++ b/src/core/lombok/bytecode/PostCompilerApp.java
@@ -98,7 +98,7 @@ public class PostCompilerApp extends LombokApp {
byte[] original = readFile(file);
byte[] clone = original.clone();
byte[] transformed = PostCompiler.applyTransformations(clone, file.toString(), DiagnosticsReceiver.CONSOLE);
- if (clone != transformed && !Arrays.equals(clone, transformed)) {
+ if (clone != transformed && !Arrays.equals(original, transformed)) {
filesTouched++;
if (args.verbose) System.out.println("Rewriting " + file.getAbsolutePath());
writeFile(file, transformed);
@@ -138,18 +138,24 @@ public class PostCompilerApp extends LombokApp {
byte[] buffer = new byte[1024];
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
FileInputStream fileInputStream = new FileInputStream(file);
- while (true) {
- int read = fileInputStream.read(buffer);
- if (read == -1) break;
- bytes.write(buffer, 0, read);
+ try {
+ while (true) {
+ int read = fileInputStream.read(buffer);
+ if (read == -1) break;
+ bytes.write(buffer, 0, read);
+ }
+ } finally {
+ fileInputStream.close();
}
- fileInputStream.close();
return bytes.toByteArray();
}
static void writeFile(File file, byte[] transformed) throws IOException {
FileOutputStream out = new FileOutputStream(file);
- out.write(transformed);
- out.close();
+ try {
+ out.write(transformed);
+ } finally {
+ out.close();
+ }
}
}
diff --git a/src/core/lombok/bytecode/PreventNullAnalysisRemover.java b/src/core/lombok/bytecode/PreventNullAnalysisRemover.java
index 5f2f5f18..c06f2d7c 100644
--- a/src/core/lombok/bytecode/PreventNullAnalysisRemover.java
+++ b/src/core/lombok/bytecode/PreventNullAnalysisRemover.java
@@ -50,7 +50,7 @@ public class PreventNullAnalysisRemover implements PostCompilerTransformation {
class PreventNullAnalysisVisitor extends MethodVisitor {
PreventNullAnalysisVisitor(MethodVisitor mv) {
- super(Opcodes.ASM5, mv);
+ super(Opcodes.ASM6, mv);
}
@Override public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {
@@ -68,7 +68,7 @@ public class PreventNullAnalysisRemover implements PostCompilerTransformation {
}
}
- reader.accept(new ClassVisitor(Opcodes.ASM5, writer) {
+ reader.accept(new ClassVisitor(Opcodes.ASM6, writer) {
@Override public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {
return new PreventNullAnalysisVisitor(super.visitMethod(access, name, desc, signature, exceptions));
}
diff --git a/src/core/lombok/bytecode/SneakyThrowsRemover.java b/src/core/lombok/bytecode/SneakyThrowsRemover.java
index 8ef64e59..a2ee59ea 100644
--- a/src/core/lombok/bytecode/SneakyThrowsRemover.java
+++ b/src/core/lombok/bytecode/SneakyThrowsRemover.java
@@ -47,12 +47,12 @@ public class SneakyThrowsRemover implements PostCompilerTransformation {
ClassReader reader = new ClassReader(fixedByteCode);
ClassWriter writer = new ClassWriter(reader, 0);
-
+
final AtomicBoolean changesMade = new AtomicBoolean();
class SneakyThrowsRemoverVisitor extends MethodVisitor {
SneakyThrowsRemoverVisitor(MethodVisitor mv) {
- super(Opcodes.ASM5, mv);
+ super(Opcodes.ASM6, mv);
}
private boolean methodInsnQueued = false;
diff --git a/src/core/lombok/core/AST.java b/src/core/lombok/core/AST.java
index e6efe058..1142018f 100644
--- a/src/core/lombok/core/AST.java
+++ b/src/core/lombok/core/AST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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,7 +21,7 @@
*/
package lombok.core;
-import static lombok.Lombok.*;
+import static lombok.Lombok.sneakyThrow;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
@@ -31,10 +31,11 @@ import java.lang.reflect.Type;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
-import java.util.HashMap;
import java.util.IdentityHashMap;
import java.util.List;
import java.util.Map;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import lombok.core.configuration.ConfigurationKey;
import lombok.core.debug.HistogramTracker;
@@ -61,12 +62,18 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
Map<N, N> identityDetector = new IdentityHashMap<N, N>();
private Map<N, L> nodeMap = new IdentityHashMap<N, L>();
private boolean changed = false;
+
+ // The supertypes which are considered AST Node children. Usually, the Statement, and the Expression,
+ // though some platforms (such as Eclipse) group these under one common supertype.
+ private final Collection<Class<? extends N>> statementTypes;
+
private static final HistogramTracker configTracker = System.getProperty("lombok.timeConfig") == null ? null : new HistogramTracker("lombok.config");
- protected AST(String fileName, String packageDeclaration, ImportList imports) {
+ protected AST(String fileName, String packageDeclaration, ImportList imports, Collection<Class<? extends N>> statementTypes) {
this.fileName = fileName == null ? "(unknown).java" : fileName;
this.packageDeclaration = packageDeclaration;
this.imports = imports;
+ this.statementTypes = statementTypes;
}
/**
@@ -209,11 +216,11 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
}
}
- private static Map<Class<?>, Collection<FieldAccess>> fieldsOfASTClasses = new HashMap<Class<?>, Collection<FieldAccess>>();
+ private static final ConcurrentMap<Class<?>, Collection<FieldAccess>> fieldsOfASTClasses = new ConcurrentHashMap<Class<?>, Collection<FieldAccess>>();
/** Returns FieldAccess objects for the stated class. Each field that contains objects of the kind returned by
* {@link #getStatementTypes()}, either directly or inside of an array or java.util.collection (or array-of-arrays,
- * or collection-of-collections, etcetera), is returned.
+ * or collection-of-collections, et cetera), is returned.
*/
protected Collection<FieldAccess> fieldsOf(Class<?> c) {
Collection<FieldAccess> fields = fieldsOfASTClasses.get(c);
@@ -221,8 +228,8 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
fields = new ArrayList<FieldAccess>();
getFields(c, fields);
- fieldsOfASTClasses.put(c, fields);
- return fields;
+ fieldsOfASTClasses.putIfAbsent(c, fields);
+ return fieldsOfASTClasses.get(c);
}
private void getFields(Class<?> c, Collection<FieldAccess> fields) {
@@ -261,13 +268,8 @@ public abstract class AST<A extends AST<A, L, N>, L extends LombokNode<A, L, N>,
return Object.class;
}
- /**
- * The supertypes which are considered AST Node children. Usually, the Statement, and the Expression,
- * though some platforms (such as Eclipse) group these under one common supertype. */
- protected abstract Collection<Class<? extends N>> getStatementTypes();
-
- protected boolean shouldDrill(Class<?> parentType, Class<?> childType, String fieldName) {
- for (Class<?> statementType : getStatementTypes()) {
+ private boolean shouldDrill(Class<?> parentType, Class<?> childType, String fieldName) {
+ for (Class<?> statementType : statementTypes) {
if (statementType.isAssignableFrom(childType)) return true;
}
diff --git a/src/core/lombok/core/Agent.java b/src/core/lombok/core/AgentLauncher.java
index 49c03bf3..1d5ab3e6 100644
--- a/src/core/lombok/core/Agent.java
+++ b/src/core/lombok/core/AgentLauncher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2014 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,45 +21,32 @@
*/
package lombok.core;
-import java.lang.instrument.ClassFileTransformer;
-import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
-import java.security.ProtectionDomain;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
-import javax.swing.JOptionPane;
-import javax.swing.SwingUtilities;
-
-public abstract class Agent {
- protected abstract void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception;
-
- public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Throwable {
- runAgents(agentArgs, instrumentation, true);
+public class AgentLauncher {
+ public interface AgentLaunchable {
+ void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected, Class<?> launchingContext) throws Exception;
}
- public static void premain(String agentArgs, Instrumentation instrumentation) throws Throwable {
- runAgents(agentArgs, instrumentation, false);
- }
-
- private static final List<AgentInfo> AGENTS = Collections.unmodifiableList(Arrays.asList(
- new NetbeansPatcherInfo(),
- new EclipsePatcherInfo()
- ));
-
- private static void runAgents(String agentArgs, Instrumentation instrumentation, boolean injected) throws Throwable {
+ public static void runAgents(String agentArgs, Instrumentation instrumentation, boolean injected, Class<?> launchingContext) throws Throwable {
for (AgentInfo info : AGENTS) {
try {
Class<?> agentClass = Class.forName(info.className());
- Agent agent = (Agent) agentClass.newInstance();
- agent.runAgent(agentArgs, instrumentation, injected);
+ AgentLaunchable agent = (AgentLaunchable) agentClass.newInstance();
+ agent.runAgent(agentArgs, instrumentation, injected, launchingContext);
} catch (Throwable t) {
info.problem(t, instrumentation);
}
}
}
+ private static final List<AgentInfo> AGENTS = Collections.unmodifiableList(Arrays.<AgentInfo>asList(
+ new EclipsePatcherInfo()
+ ));
+
private static abstract class AgentInfo {
abstract String className();
@@ -91,45 +78,6 @@ public abstract class Agent {
}
}
- private static class NetbeansPatcherInfo extends AgentInfo {
- @Override String className() {
- return "lombok.netbeans.agent.NetbeansPatcher";
- }
-
- @Override void problem(Throwable in, Instrumentation instrumentation) throws Throwable {
- try {
- super.problem(in, instrumentation);
- } catch (InternalError ie) {
- throw ie;
- } catch (Throwable t) {
- final String error;
-
- if (t instanceof UnsupportedClassVersionError) {
- error = "Lombok only works on netbeans if you start netbeans using a 1.6 or higher JVM.\n" +
- "Change your platform's default JVM, or edit etc/netbeans.conf\n" +
- "and explicitly tell netbeans your 1.6 JVM's location.";
- } else {
- error = "Lombok disabled due to error: " + t;
- }
-
- instrumentation.addTransformer(new ClassFileTransformer() {
- @Override public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
- if ("org/netbeans/modules/java/source/parsing/JavacParser".equals(className)) {
- //If that class gets loaded, this is definitely a netbeans(-esque) environment, and thus we SHOULD tell the user that lombok is not in fact loaded.
- SwingUtilities.invokeLater(new Runnable() {
- @Override public void run() {
- JOptionPane.showMessageDialog(null, error, "Lombok Disabled", JOptionPane.ERROR_MESSAGE);
- }
- });
- }
-
- return null;
- }
- });
- }
- }
- }
-
private static class EclipsePatcherInfo extends AgentInfo {
@Override String className() {
return "lombok.eclipse.agent.EclipsePatcher";
diff --git a/src/core/lombok/core/AnnotationProcessor.java b/src/core/lombok/core/AnnotationProcessor.java
index eb44811b..5b4ef393 100644
--- a/src/core/lombok/core/AnnotationProcessor.java
+++ b/src/core/lombok/core/AnnotationProcessor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -40,6 +40,7 @@ import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
import javax.lang.model.element.Element;
+import javax.lang.model.element.Name;
import javax.lang.model.element.TypeElement;
import javax.tools.Diagnostic.Kind;
@@ -75,9 +76,9 @@ public class AnnotationProcessor extends AbstractProcessor {
try {
ClassLoader classLoader = findAndPatchClassLoader(procEnv);
- processor = (Processor)Class.forName("lombok.javac.apt.Processor", false, classLoader).newInstance();
+ processor = (Processor) Class.forName("lombok.javac.apt.LombokProcessor", false, classLoader).newInstance();
} catch (Exception e) {
- delayedWarnings.add("You found a bug in lombok; lombok.javac.apt.Processor is not available. Lombok will not run during this compilation: " + trace(e));
+ delayedWarnings.add("You found a bug in lombok; lombok.javac.apt.LombokProcessor is not available. Lombok will not run during this compilation: " + trace(e));
return false;
} catch (NoClassDefFoundError e) {
delayedWarnings.add("Can't load javac processor due to (most likely) a class loader problem: " + trace(e));
@@ -86,7 +87,7 @@ public class AnnotationProcessor extends AbstractProcessor {
try {
processor.init(procEnv);
} catch (Exception e) {
- delayedWarnings.add("lombok.javac.apt.Processor could not be initialized. Lombok will not run during this compilation: " + trace(e));
+ delayedWarnings.add("lombok.javac.apt.LombokProcessor could not be initialized. Lombok will not run during this compilation: " + trace(e));
return false;
} catch (NoClassDefFoundError e) {
delayedWarnings.add("Can't initialize javac processor due to (most likely) a class loader problem: " + trace(e));
@@ -103,7 +104,6 @@ public class AnnotationProcessor extends AbstractProcessor {
URL selfUrl = new File(ClassRootFinder.findClassRootOfClass(AnnotationProcessor.class)).toURI().toURL();
m.invoke(environmentClassLoader, selfUrl);
}
- return environmentClassLoader;
}
ClassLoader ourClassLoader = JavacDescriptor.class.getClassLoader();
@@ -164,7 +164,21 @@ public class AnnotationProcessor extends AbstractProcessor {
for (ProcessorDescriptor proc : active) proc.process(annotations, roundEnv);
- return false;
+ boolean onlyLombok = true;
+ boolean zeroElems = true;
+ for (TypeElement elem : annotations) {
+ zeroElems = false;
+ Name n = elem.getQualifiedName();
+ if (n.length() > 7 && n.subSequence(0, 7).toString().equals("lombok.")) continue;
+ onlyLombok = false;
+ }
+
+ // Normally we rely on the claiming processor to claim away all lombok annotations.
+ // One of the many Java9 oversights is that this 'process' API has not been fixed to address the point that 'files I want to look at' and 'annotations I want to claim' must be one and the same,
+ // and yet in java9 you can no longer have 2 providers for the same service, thus, if you go by module path, lombok no longer loads the ClaimingProcessor.
+ // This doesn't do as good a job, but it'll have to do. The only way to go from here, I think, is either 2 modules, or use reflection hackery to add ClaimingProcessor during our init.
+
+ return onlyLombok && !zeroElems;
}
/**
diff --git a/src/core/lombok/core/GuavaTypeMap.java b/src/core/lombok/core/GuavaTypeMap.java
new file mode 100644
index 00000000..282d5d81
--- /dev/null
+++ b/src/core/lombok/core/GuavaTypeMap.java
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2015 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.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+public final class GuavaTypeMap {
+ private static final Map<String, String> TYPE_TO_GUAVA_TYPE; static {
+ Map<String, String> m = new HashMap<String, String>();
+
+ m.put("java.util.NavigableSet", "ImmutableSortedSet");
+ m.put("java.util.NavigableMap", "ImmutableSortedMap");
+ m.put("java.util.SortedSet", "ImmutableSortedSet");
+ m.put("java.util.SortedMap", "ImmutableSortedMap");
+ m.put("java.util.Set", "ImmutableSet");
+ m.put("java.util.Map", "ImmutableMap");
+ m.put("java.util.Collection", "ImmutableList");
+ m.put("java.util.List", "ImmutableList");
+
+ m.put("com.google.common.collect.ImmutableSet", "ImmutableSet");
+ m.put("com.google.common.collect.ImmutableSortedSet", "ImmutableSortedSet");
+ m.put("com.google.common.collect.ImmutableMap", "ImmutableMap");
+ m.put("com.google.common.collect.ImmutableBiMap", "ImmutableBiMap");
+ m.put("com.google.common.collect.ImmutableSortedMap", "ImmutableSortedMap");
+ m.put("com.google.common.collect.ImmutableList", "ImmutableList");
+ m.put("com.google.common.collect.ImmutableCollection", "ImmutableList");
+ m.put("com.google.common.collect.ImmutableTable", "ImmutableTable");
+
+ TYPE_TO_GUAVA_TYPE = Collections.unmodifiableMap(m);
+ }
+
+ public static String getGuavaTypeName(String fqn) {
+ String target = TYPE_TO_GUAVA_TYPE.get(fqn);
+ return target != null ? target : "ImmutableList";
+ }
+
+ private GuavaTypeMap() {}
+}
diff --git a/src/core/lombok/core/LombokInternalAliasing.java b/src/core/lombok/core/LombokInternalAliasing.java
index 8d6794ae..3dc1bfa2 100644
--- a/src/core/lombok/core/LombokInternalAliasing.java
+++ b/src/core/lombok/core/LombokInternalAliasing.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
@@ -50,6 +50,8 @@ public class LombokInternalAliasing {
Map<String, String> m2 = new HashMap<String, String>();
m2.put("lombok.experimental.Value", "lombok.Value");
+ m2.put("lombok.experimental.Builder", "lombok.Builder");
+ m2.put("lombok.experimental.var", "lombok.var");
m2.put("lombok.Delegate", "lombok.experimental.Delegate");
ALIASES = Collections.unmodifiableMap(m2);
}
diff --git a/src/core/lombok/core/Main.java b/src/core/lombok/core/Main.java
index d62fe3e4..6952ab78 100644
--- a/src/core/lombok/core/Main.java
+++ b/src/core/lombok/core/Main.java
@@ -38,6 +38,7 @@ public class Main {
));
public static void main(String[] args) throws IOException {
+ Thread.currentThread().setContextClassLoader(Main.class.getClassLoader());
int err = new Main(SpiLoadUtil.readAllFromIterator(
SpiLoadUtil.findServices(LombokApp.class)), Arrays.asList(args)).go();
System.exit(err);
@@ -94,7 +95,7 @@ public class Main {
in.close();
}
} catch (Exception e) {
- System.err.println("License file not found. Check http://projectlombok.org/LICENSE");
+ System.err.println("License file not found. Check https://projectlombok.org/LICENSE");
return 1;
}
}
@@ -142,7 +143,7 @@ public class Main {
out.println("------------------------------");
}
out.println("projectlombok.org " + Version.getFullVersion());
- out.println("Copyright (C) 2009-2012 The Project Lombok Authors.");
+ out.println("Copyright (C) 2009-2015 The Project Lombok Authors.");
out.println("Run 'lombok license' to see the lombok license agreement.");
out.println();
out.println("Run lombok without any parameters to start the graphical installer.");
diff --git a/src/core/lombok/core/PostCompiler.java b/src/core/lombok/core/PostCompiler.java
index 11091cb8..237867cb 100644
--- a/src/core/lombok/core/PostCompiler.java
+++ b/src/core/lombok/core/PostCompiler.java
@@ -24,6 +24,8 @@ package lombok.core;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
import java.util.Collections;
import java.util.List;
@@ -55,10 +57,12 @@ public final class PostCompiler {
transformations = SpiLoadUtil.readAllFromIterator(SpiLoadUtil.findServices(PostCompilerTransformation.class, PostCompilerTransformation.class.getClassLoader()));
} catch (IOException e) {
transformations = Collections.emptyList();
- diagnostics.addWarning("Could not load post-compile transformers: " + e.getMessage());
+ StringWriter sw = new StringWriter();
+ e.printStackTrace(new PrintWriter(sw, true));
+ diagnostics.addWarning("Could not load post-compile transformers: " + e.getMessage() + "\n" + sw.toString());
}
}
-
+
public static OutputStream wrapOutputStream(final OutputStream originalStream, final String fileName, final DiagnosticsReceiver diagnostics) throws IOException {
if (System.getProperty("lombok.disablePostCompiler", null) != null) return originalStream;
return new ByteArrayOutputStream() {
diff --git a/src/core/lombok/core/PublicApiCreatorApp.java b/src/core/lombok/core/PublicApiCreatorApp.java
index 178a45e8..c1430c24 100644
--- a/src/core/lombok/core/PublicApiCreatorApp.java
+++ b/src/core/lombok/core/PublicApiCreatorApp.java
@@ -105,7 +105,7 @@ public class PublicApiCreatorApp extends LombokApp {
int firstSlash = subName.indexOf('/');
if (firstSlash == -1) {
// direct member of the lombok package.
- toCopy.add(name);
+ if (!subName.startsWith("ConfigurationKeys")) toCopy.add(name);
continue;
}
String topPkg = subName.substring(0, firstSlash);
diff --git a/src/core/lombok/core/TypeLibrary.java b/src/core/lombok/core/TypeLibrary.java
index c0e9dc43..cdaf7a70 100644
--- a/src/core/lombok/core/TypeLibrary.java
+++ b/src/core/lombok/core/TypeLibrary.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -37,6 +37,7 @@ import java.util.Map;
public class TypeLibrary {
private final Map<String, String> unqualifiedToQualifiedMap;
private final String unqualified, qualified;
+ private boolean locked;
public TypeLibrary() {
unqualifiedToQualifiedMap = new HashMap<String, String>();
@@ -44,15 +45,27 @@ public class TypeLibrary {
qualified = null;
}
+ public void lock() {
+ this.locked = true;
+ }
+
private TypeLibrary(String fqnSingleton) {
- unqualifiedToQualifiedMap = null;
- qualified = fqnSingleton;
- int idx = fqnSingleton.lastIndexOf('.');
- if (idx == -1) {
- unqualified = fqnSingleton;
+ if (fqnSingleton.indexOf("$") != -1) {
+ unqualifiedToQualifiedMap = new HashMap<String, String>();
+ unqualified = null;
+ qualified = null;
+ addType(fqnSingleton);
} else {
- unqualified = fqnSingleton.substring(idx + 1);
+ unqualifiedToQualifiedMap = null;
+ qualified = fqnSingleton;
+ int idx = fqnSingleton.lastIndexOf('.');
+ if (idx == -1) {
+ unqualified = fqnSingleton;
+ } else {
+ unqualified = fqnSingleton.substring(idx + 1);
+ }
}
+ locked = true;
}
public static TypeLibrary createLibraryForSingleType(String fqnSingleton) {
@@ -65,17 +78,29 @@ public class TypeLibrary {
* @param fullyQualifiedTypeName the FQN type name, such as 'java.lang.String'.
*/
public void addType(String fullyQualifiedTypeName) {
- fullyQualifiedTypeName = fullyQualifiedTypeName.replace("$", ".");
+ String dotBased = fullyQualifiedTypeName.replace("$", ".");
+
+ if (locked) throw new IllegalStateException("locked");
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");
- unqualifiedToQualifiedMap.put(unqualified, fullyQualifiedTypeName);
- unqualifiedToQualifiedMap.put(fullyQualifiedTypeName, fullyQualifiedTypeName);
+ unqualifiedToQualifiedMap.put(unqualified.replace("$", "."), dotBased);
+ unqualifiedToQualifiedMap.put(unqualified, dotBased);
+ unqualifiedToQualifiedMap.put(fullyQualifiedTypeName, dotBased);
+ unqualifiedToQualifiedMap.put(dotBased, dotBased);
for (Map.Entry<String, String> e : LombokInternalAliasing.ALIASES.entrySet()) {
- if (fullyQualifiedTypeName.equals(e.getValue())) unqualifiedToQualifiedMap.put(e.getKey(), fullyQualifiedTypeName);
+ if (fullyQualifiedTypeName.equals(e.getValue())) unqualifiedToQualifiedMap.put(e.getKey(), dotBased);
+ }
+
+ int idx2 = fullyQualifiedTypeName.indexOf('$', idx + 1);
+ while (idx2 != -1) {
+ String unq = fullyQualifiedTypeName.substring(idx2 + 1);
+ unqualifiedToQualifiedMap.put(unq.replace("$", "."), dotBased);
+ unqualifiedToQualifiedMap.put(unq, dotBased);
+ idx2 = fullyQualifiedTypeName.indexOf('$', idx2 + 1);
}
}
diff --git a/src/core/lombok/core/TypeResolver.java b/src/core/lombok/core/TypeResolver.java
index 287a085f..60ac6b6a 100644
--- a/src/core/lombok/core/TypeResolver.java
+++ b/src/core/lombok/core/TypeResolver.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -53,10 +53,13 @@ public class TypeResolver {
if (typeRef.equals(qualified)) return typeRef;
// 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);
+ int firstDot = typeRef.indexOf('.');
+ if (firstDot == -1) firstDot = typeRef.length();
+ String firstTypeRef = typeRef.substring(0, firstDot);
+ String fromExplicitImport = imports.getFullyQualifiedNameForSimpleName(firstTypeRef);
if (fromExplicitImport != null) {
// ... and if 'import foobar.Getter;' is in the source file, the answer is no.
- return fromExplicitImport.equals(qualified) ? qualified : null;
+ return (fromExplicitImport + typeRef.substring(firstDot)).equals(qualified) ? qualified : null;
}
// 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.
@@ -68,7 +71,7 @@ public class TypeResolver {
mainLoop:
while (n != null) {
- if (n.getKind() == Kind.TYPE && typeRef.equals(n.getName())) {
+ if (n.getKind() == Kind.TYPE && firstTypeRef.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 null;
}
@@ -81,7 +84,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 null;
+ if (child.getKind() == Kind.TYPE && firstTypeRef.equals(child.getName())) return null;
if (child == n) break;
}
}
@@ -92,14 +95,13 @@ 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 null;
+ if (child.getKind() == Kind.TYPE && firstTypeRef.equals(child.getName())) return null;
}
}
n = n.directUp();
}
-
return qualified;
}
}
diff --git a/src/core/lombok/core/Version.java b/src/core/lombok/core/Version.java
index 9f810525..98f1e575 100644
--- a/src/core/lombok/core/Version.java
+++ b/src/core/lombok/core/Version.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,9 +30,15 @@ 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.14.9";
+ private static final String VERSION = "1.16.21";
private static final String RELEASE_NAME = "Edgy Guinea Pig";
-// private static final String RELEASE_NAME = "Branching Cobra";
+// private static final String RELEASE_NAME = "Dancing Elephant";
+
+ // Named version history:
+ // Angry Butterfly
+ // Branching Cobra
+ // Candid Duck
+ // Dancing Elephant
private Version() {
//Prevent instantiation
@@ -43,7 +49,7 @@ public class Version {
*/
public static void main(String[] args) {
if (args.length > 0) {
- System.out.printf("Lombok %s\n", getFullVersion());
+ System.out.printf("%s\n", getFullVersion());
} else {
System.out.println(VERSION);
}
diff --git a/src/core/lombok/core/configuration/AllowHelper.java b/src/core/lombok/core/configuration/AllowHelper.java
new file mode 100644
index 00000000..1146ccde
--- /dev/null
+++ b/src/core/lombok/core/configuration/AllowHelper.java
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 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
+ * 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.Collection;
+import java.util.Collections;
+
+public final class AllowHelper {
+ private final static Collection<? extends ConfigurationKey<?>> ALLOWABLE = Collections.emptySet();
+
+ private AllowHelper() {
+ // Prevent instantiation
+ }
+
+ public static boolean isAllowable(ConfigurationKey<?> key) {
+ return ALLOWABLE.contains(key);
+ }
+}
diff --git a/src/core/lombok/core/configuration/BubblingConfigurationResolver.java b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
index f96b4468..0849eee2 100644
--- a/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
+++ b/src/core/lombok/core/configuration/BubblingConfigurationResolver.java
@@ -45,32 +45,23 @@ public class BubblingConfigurationResolver implements ConfigurationResolver {
Result result = source.resolve(key);
if (result == null) continue;
if (isList) {
- if (listModificationsList == null) {
- listModificationsList = new ArrayList<List<ListModification>>();
- }
+ if (listModificationsList == null) listModificationsList = new ArrayList<List<ListModification>>();
listModificationsList.add((List<ListModification>)result.getValue());
}
if (result.isAuthoritative()) {
- if (isList) {
- break;
- }
+ if (isList) break;
return (T) result.getValue();
}
}
- if (!isList) {
- return null;
- }
- if (listModificationsList == null) {
- return (T) Collections.emptyList();
- }
+ if (!isList) return null;
+ if (listModificationsList == null) return (T) Collections.emptyList();
+
List<Object> listValues = new ArrayList<Object>();
Collections.reverse(listModificationsList);
for (List<ListModification> listModifications : listModificationsList) {
if (listModifications != null) for (ListModification modification : listModifications) {
listValues.remove(modification.getValue());
- if (modification.isAdded()) {
- listValues.add(modification.getValue());
- }
+ if (modification.isAdded()) listValues.add(modification.getValue());
}
}
return (T) listValues;
diff --git a/src/core/lombok/core/configuration/CallSuperType.java b/src/core/lombok/core/configuration/CallSuperType.java
new file mode 100644
index 00000000..b7152ea4
--- /dev/null
+++ b/src/core/lombok/core/configuration/CallSuperType.java
@@ -0,0 +1,27 @@
+/*
+ * Copyright (C) 2015 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;
+
+/** Used for lombok configuration for configuration whether or not to call the super implementation for certain lombok feature. */
+public enum CallSuperType {
+ CALL, SKIP, WARN;
+}
diff --git a/src/core/lombok/core/configuration/ConfigurationApp.java b/src/core/lombok/core/configuration/ConfigurationApp.java
index e441b4de..efe57e38 100644
--- a/src/core/lombok/core/configuration/ConfigurationApp.java
+++ b/src/core/lombok/core/configuration/ConfigurationApp.java
@@ -198,7 +198,7 @@ public class ConfigurationApp extends LombokApp {
if (paths.size() == 1) {
if (!(argsPaths.size() == 1)) out.printf("Configuration for '%s'.%n%n", paths.iterator().next());
} else {
- out.printf("Configuration for:%n", paths.iterator().next());
+ out.printf("Configuration for:%n");
for (String path : paths) out.printf("- %s%n", path);
out.println();
}
diff --git a/src/core/lombok/core/configuration/ConfigurationParser.java b/src/core/lombok/core/configuration/ConfigurationParser.java
index f0a9e142..e80793c1 100644
--- a/src/core/lombok/core/configuration/ConfigurationParser.java
+++ b/src/core/lombok/core/configuration/ConfigurationParser.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Project Lombok Authors.
+ * Copyright (C) 2014-2016 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
@@ -27,7 +27,7 @@ import java.util.regex.Pattern;
public class ConfigurationParser {
private static final Pattern LINE = Pattern.compile("(?:clear\\s+([^=]+))|(?:(\\S*?)\\s*([-+]?=)\\s*(.*?))");
- private static final Pattern NEWLINE_FINDER = Pattern.compile("^\\s*(.*?)\\s*$", Pattern.MULTILINE);
+ private static final Pattern NEWLINE_FINDER = Pattern.compile("^[\t ]*(.*?)[\t\r ]*$", Pattern.MULTILINE);
private ConfigurationProblemReporter reporter;
diff --git a/src/core/lombok/core/configuration/FileSystemSourceCache.java b/src/core/lombok/core/configuration/FileSystemSourceCache.java
index dc390eb6..8bc5050b 100644
--- a/src/core/lombok/core/configuration/FileSystemSourceCache.java
+++ b/src/core/lombok/core/configuration/FileSystemSourceCache.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Project Lombok Authors.
+ * Copyright (C) 2014-2015 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,41 +38,68 @@ import lombok.core.debug.ProblemReporter;
public class FileSystemSourceCache {
private static final String LOMBOK_CONFIG_FILENAME = "lombok.config";
+ private static final long FULL_CACHE_CLEAR_INTERVAL = TimeUnit.MINUTES.toMillis(30);
private static final long RECHECK_FILESYSTEM = TimeUnit.SECONDS.toMillis(2);
private static final long NEVER_CHECKED = -1;
private static final long MISSING = -88; // Magic value; any lombok.config with this exact epochmillis last modified will never be read, so, let's ensure nobody accidentally has one with that exact last modified stamp.
- private final ConcurrentMap<File, Content> cache = new ConcurrentHashMap<File, Content>();
+ private final ConcurrentMap<File, Content> dirCache = new ConcurrentHashMap<File, Content>(); // caches files (representing dirs) to the content object that tracks content.
+ private final ConcurrentMap<URI, File> uriCache = new ConcurrentHashMap<URI, File>(); // caches URIs of java source files to the dir that contains it.
+ private volatile long lastCacheClear = System.currentTimeMillis();
+
+ private void cacheClear() {
+ // We never clear the caches, generally because it'd be weird if a compile run would continually create an endless stream of new java files.
+ // Still, eventually that's going to cause a bit of a memory leak, so lets just completely clear them out every many minutes.
+ long now = System.currentTimeMillis();
+ long delta = now - lastCacheClear;
+ if (delta > FULL_CACHE_CLEAR_INTERVAL) {
+ lastCacheClear = now;
+ dirCache.clear();
+ uriCache.clear();
+ }
+ }
public Iterable<ConfigurationSource> sourcesForJavaFile(URI javaFile, ConfigurationProblemReporter reporter) {
if (javaFile == null) return Collections.emptyList();
- URI uri = javaFile.normalize();
- if (!uri.isAbsolute()) uri = URI.create("file:" + uri.toString());
-
- File file;
- try {
- file = new File(uri);
- if (!file.exists()) throw new IllegalArgumentException("File does not exist: " + uri);
- return sourcesForDirectory(file.getParentFile(), reporter);
- } catch (IllegalArgumentException e) {
- // This means that the file as passed is not actually a file at all, and some exotic path system is involved.
- // examples: sourcecontrol://jazz stuff, or an actual relative path (uri.isAbsolute() is completely different, that checks presence of schema!),
- // or it's eclipse trying to parse a snippet, which has "/Foo.java" as uri.
- // At some point it might be worth investigating abstracting away the notion of "I can read lombok.config if present in
- // current context, and I can give you may parent context", using ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(javaFile) as basis.
+ cacheClear();
+ File dir = uriCache.get(javaFile);
+ if (dir == null) {
+ URI uri = javaFile.normalize();
+ if (!uri.isAbsolute()) uri = URI.create("file:" + uri.toString());
- // For now, we just carry on as if there is no lombok.config. (intentional fallthrough)
- } catch (Exception e) {
- // Especially for eclipse's sake, exceptions here make eclipse borderline unusable, so let's play nice.
- ProblemReporter.error("Can't find absolute path of file being compiled: " + javaFile, e);
+ try {
+ File file = new File(uri);
+ if (!file.exists()) throw new IllegalArgumentException("File does not exist: " + uri);
+ dir = file.isDirectory() ? file : file.getParentFile();
+ if (dir != null) uriCache.put(javaFile, dir);
+ } catch (IllegalArgumentException e) {
+ // This means that the file as passed is not actually a file at all, and some exotic path system is involved.
+ // examples: sourcecontrol://jazz stuff, or an actual relative path (uri.isAbsolute() is completely different, that checks presence of schema!),
+ // or it's eclipse trying to parse a snippet, which has "/Foo.java" as uri.
+ // At some point it might be worth investigating abstracting away the notion of "I can read lombok.config if present in
+ // current context, and I can give you may parent context", using ResourcesPlugin.getWorkspace().getRoot().findFilesForLocationURI(javaFile) as basis.
+
+ // For now, we just carry on as if there is no lombok.config. (intentional fallthrough)
+ } catch (Exception e) {
+ // Especially for eclipse's sake, exceptions here make eclipse borderline unusable, so let's play nice.
+ ProblemReporter.error("Can't find absolute path of file being compiled: " + javaFile, e);
+ }
+ }
+
+ if (dir != null) {
+ try {
+ return sourcesForDirectory(dir, reporter);
+ } catch (Exception e) {
+ // Especially for eclipse's sake, exceptions here make eclipse borderline unusable, so let's play nice.
+ ProblemReporter.error("Can't resolve config stack for dir: " + dir.getAbsolutePath(), e);
+ }
}
return Collections.emptyList();
}
public Iterable<ConfigurationSource> sourcesForDirectory(URI directory, ConfigurationProblemReporter reporter) {
- if (directory == null) return Collections.emptyList();
- return sourcesForDirectory(new File(directory.normalize()), reporter);
+ return sourcesForJavaFile(directory, reporter);
}
private Iterable<ConfigurationSource> sourcesForDirectory(final File directory, final ConfigurationProblemReporter reporter) {
@@ -139,12 +166,12 @@ public class FileSystemSourceCache {
}
private Content ensureContent(File directory) {
- Content content = cache.get(directory);
+ Content content = dirCache.get(directory);
if (content != null) {
return content;
}
- cache.putIfAbsent(directory, Content.empty());
- return cache.get(directory);
+ dirCache.putIfAbsent(directory, Content.empty());
+ return dirCache.get(directory);
}
private ConfigurationSource parse(File configFile, ConfigurationProblemReporter reporter) {
diff --git a/src/core/lombok/core/configuration/FlagUsageType.java b/src/core/lombok/core/configuration/FlagUsageType.java
index b7053b7c..8717c22b 100644
--- a/src/core/lombok/core/configuration/FlagUsageType.java
+++ b/src/core/lombok/core/configuration/FlagUsageType.java
@@ -23,5 +23,5 @@ package lombok.core.configuration;
/** Used for lombok configuration to flag usages of certain lombok feature. */
public enum FlagUsageType {
- WARNING, ERROR;
+ WARNING, ERROR, ALLOW;
}
diff --git a/src/core/lombok/core/debug/AssertionLogger.java b/src/core/lombok/core/debug/AssertionLogger.java
new file mode 100644
index 00000000..6b2c326d
--- /dev/null
+++ b/src/core/lombok/core/debug/AssertionLogger.java
@@ -0,0 +1,115 @@
+/*
+ * Copyright (C) 2015 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.debug;
+
+import java.io.FileOutputStream;
+import java.io.OutputStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.util.Date;
+import java.util.Random;
+import java.util.concurrent.atomic.AtomicBoolean;
+
+import lombok.core.Version;
+
+/**
+ * We make a number of assumptions in lombok code, and if these assumptions fail, we try to fall back to a 'least bad' scenario. However, we would prefer to
+ * just know about these cases, without confronting our users with error messages. The 'fix' is to log such assertion failures to this logger, which promptly
+ * ignores them, _unless_ you specifically enable logging them to a file. If you'd like to help out or want to assist in debugging, turn this on.
+ */
+public class AssertionLogger {
+ private static final String LOG_PATH;
+
+ static {
+ String log = System.getProperty("lombok.assertion.log", null);
+ if (log != null) {
+ LOG_PATH = log.isEmpty() ? null : log;
+ } else {
+ try {
+ log = System.getenv("LOMBOK_ASSERTION_LOG");
+ } catch (Exception e) {
+ log = null;
+ }
+ LOG_PATH = (log == null || log.isEmpty()) ? null : log;
+ }
+ }
+
+ private static final AtomicBoolean loggedIntro = new AtomicBoolean(false);
+ private static final String PROCESS_ID = generateProcessId();
+
+ private static final String ID_CHARS = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
+
+ private static String generateProcessId() {
+ char[] ID = new char[4];
+ Random r = new Random();
+ for (int i = 0; i < ID.length; i++) ID[i] = ID_CHARS.charAt(r.nextInt(ID_CHARS.length()));
+ return new String(ID);
+ }
+
+ private static synchronized void logToFile(String msg) {
+ if (msg == null) return;
+
+ try {
+ OutputStream out = new FileOutputStream(LOG_PATH, true);
+ out.write(msg.getBytes("UTF-8"));
+ out.close();
+ } catch (Exception e) {
+ throw new RuntimeException("assertion logging can't write to log file", e);
+ }
+ }
+
+ private static void logIntro() {
+ if (loggedIntro.getAndSet(true)) return;
+
+ String version;
+ try {
+ version = Version.getFullVersion();
+ } catch (Exception e) {
+ version = Version.getVersion();
+ }
+
+ logToFile(String.format("{%s} [%s -- START %s]\n", PROCESS_ID, new Date(), version));
+ }
+
+ public static <T extends Throwable> T assertLog(String message, T throwable) {
+ if (LOG_PATH == null) return throwable;
+
+ logIntro();
+
+ if (message == null) message = "(No message)";
+ String stackMsg = "";
+ if (throwable != null) {
+ StringWriter sw = new StringWriter();
+ PrintWriter pw = new PrintWriter(sw);
+ throwable.printStackTrace(pw);
+ pw.close();
+ stackMsg = "\n " + sw.toString().replace("\r", "").replace("\n", "\n ").trim();
+ }
+ logToFile(String.format("{%s} [%ty%<tm%<tdT%<tH%<tM%<tS.%<tL] %s%s\n", PROCESS_ID, new Date(), message, stackMsg));
+ return throwable;
+ }
+
+ public static void assertLog(String message) {
+ if (LOG_PATH == null) return;
+ assertLog(message, null);
+ }
+}
diff --git a/src/core/lombok/core/handlers/HandlerUtil.java b/src/core/lombok/core/handlers/HandlerUtil.java
index 621d8760..6b516904 100644
--- a/src/core/lombok/core/handlers/HandlerUtil.java
+++ b/src/core/lombok/core/handlers/HandlerUtil.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,6 +43,7 @@ import lombok.core.AST;
import lombok.core.AnnotationValues;
import lombok.core.JavaIdentifiers;
import lombok.core.LombokNode;
+import lombok.core.configuration.AllowHelper;
import lombok.core.configuration.ConfigurationKey;
import lombok.core.configuration.FlagUsageType;
import lombok.experimental.Accessors;
@@ -68,6 +69,10 @@ public class HandlerUtil {
return 97;
}
+ public static int primeForNull() {
+ return 43;
+ }
+
/** Checks if the given name is a valid identifier.
*
* If it is, this returns {@code true} and does nothing else.
@@ -87,16 +92,30 @@ public class HandlerUtil {
return true;
}
+ public static String autoSingularize(String plural) {
+ return Singulars.autoSingularize(plural);
+ }
public static void handleFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key, String featureName) {
FlagUsageType fut = node.getAst().readConfiguration(key);
+ if (fut == null && AllowHelper.isAllowable(key)) {
+ node.addError("Use of " + featureName + " is disabled by default. Please add '" + key.getKeyName() + " = " + FlagUsageType.ALLOW + "' to 'lombok.config' if you want to enable is.");
+ }
+
if (fut != null) {
String msg = "Use of " + featureName + " is flagged according to lombok configuration.";
if (fut == FlagUsageType.WARNING) node.addWarning(msg);
- else node.addError(msg);
+ else if (fut == FlagUsageType.ERROR) node.addError(msg);
}
}
+ @SuppressWarnings("deprecation")
+ public static boolean shouldAddGenerated(LombokNode<?, ?, ?> node) {
+ Boolean add = node.getAst().readConfiguration(ConfigurationKeys.ADD_JAVAX_GENERATED_ANNOTATIONS);
+ if (add != null) return add;
+ return Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_GENERATED_ANNOTATIONS));
+ }
+
public static void handleExperimentalFlagUsage(LombokNode<?, ?, ?> node, ConfigurationKey<FlagUsageType> key, String featureName) {
handleFlagUsage(node, key, featureName, ConfigurationKeys.EXPERIMENTAL_FLAG_USAGE, "any lombok.experimental feature");
}
@@ -152,11 +171,12 @@ public class HandlerUtil {
}
@SuppressWarnings({"all", "unchecked", "deprecation"})
- public static final List<Class<? extends java.lang.annotation.Annotation>> INVALID_ON_BUILDERS = Collections.unmodifiableList(
- Arrays.<Class<? extends java.lang.annotation.Annotation>>asList(
- Getter.class, Setter.class, Wither.class, ToString.class, EqualsAndHashCode.class,
- RequiredArgsConstructor.class, AllArgsConstructor.class, NoArgsConstructor.class,
- Data.class, Value.class, lombok.experimental.Value.class, FieldDefaults.class));
+ public static final List<String> INVALID_ON_BUILDERS = Collections.unmodifiableList(
+ Arrays.<String>asList(
+ Getter.class.getName(), Setter.class.getName(), Wither.class.getName(),
+ ToString.class.getName(), EqualsAndHashCode.class.getName(),
+ RequiredArgsConstructor.class.getName(), AllArgsConstructor.class.getName(), NoArgsConstructor.class.getName(),
+ Data.class.getName(), Value.class.getName(), "lombok.experimental.Value", FieldDefaults.class.getName()));
/**
* Given the name of a field, return the 'base name' of that field. For example, {@code fFoobar} becomes {@code foobar} if {@code f} is in the prefix list.
@@ -303,7 +323,7 @@ public class HandlerUtil {
return booleanPrefix + fName.substring(2);
}
- return buildName(isBoolean ? booleanPrefix : normalPrefix, fName);
+ return buildAccessorName(isBoolean ? booleanPrefix : normalPrefix, fName);
}
/**
@@ -375,8 +395,8 @@ public class HandlerUtil {
if (adhereToFluent && fluent) {
names.add(baseName);
} else {
- names.add(buildName(normalPrefix, baseName));
- if (!normalPrefix.equals(booleanPrefix)) names.add(buildName(booleanPrefix, baseName));
+ names.add(buildAccessorName(normalPrefix, baseName));
+ if (!normalPrefix.equals(booleanPrefix)) names.add(buildAccessorName(booleanPrefix, baseName));
}
}
@@ -407,7 +427,7 @@ public class HandlerUtil {
* @param suffix Something like {@code running}.
* @return prefix + smartly title-cased suffix. For example, {@code setRunning}.
*/
- private static String buildName(String prefix, String suffix) {
+ public static String buildAccessorName(String prefix, String suffix) {
if (suffix.length() == 0) return prefix;
if (prefix.length() == 0) return suffix;
diff --git a/src/core/lombok/core/handlers/Singulars.java b/src/core/lombok/core/handlers/Singulars.java
new file mode 100644
index 00000000..87895790
--- /dev/null
+++ b/src/core/lombok/core/handlers/Singulars.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2015 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.handlers;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.util.ArrayList;
+import java.util.List;
+
+public class Singulars {
+ private static final List<String> SINGULAR_STORE; // intended to be immutable.
+
+ static {
+ SINGULAR_STORE = new ArrayList<String>();
+
+ try {
+ InputStream in = Singulars.class.getResourceAsStream("singulars.txt");
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ line = line.trim();
+ if (line.startsWith("#") || line.isEmpty()) continue;
+ if (line.endsWith(" =")) {
+ SINGULAR_STORE.add(line.substring(0, line.length() - 2));
+ SINGULAR_STORE.add("");
+ continue;
+ }
+
+ int idx = line.indexOf(" = ");
+ SINGULAR_STORE.add(line.substring(0, idx));
+ SINGULAR_STORE.add(line.substring(idx + 3));
+ }
+ } finally {
+ try {
+ in.close();
+ } catch (Throwable ignore) {}
+ }
+ } catch (IOException e) {
+ SINGULAR_STORE.clear();
+ }
+ }
+
+ public static String autoSingularize(String in) {
+ final int inLen = in.length();
+ for (int i = 0; i < SINGULAR_STORE.size(); i+= 2) {
+ final String lastPart = SINGULAR_STORE.get(i);
+ final boolean wholeWord = Character.isUpperCase(lastPart.charAt(0));
+ final int endingOnly = lastPart.charAt(0) == '-' ? 1 : 0;
+ final int len = lastPart.length();
+ if (inLen < len) continue;
+ if (!in.regionMatches(true, inLen - len + endingOnly, lastPart, endingOnly, len - endingOnly)) continue;
+ if (wholeWord && inLen != len && !Character.isUpperCase(in.charAt(inLen - len))) continue;
+
+ String replacement = SINGULAR_STORE.get(i + 1);
+ if (replacement.equals("!")) return null;
+
+ boolean capitalizeFirst = !replacement.isEmpty() && Character.isUpperCase(in.charAt(inLen - len + endingOnly));
+ String pre = in.substring(0, inLen - len + endingOnly);
+ String post = capitalizeFirst ? Character.toUpperCase(replacement.charAt(0)) + replacement.substring(1) : replacement;
+ return pre + post;
+ }
+
+ return null;
+ }
+}
diff --git a/src/core/lombok/core/handlers/singulars.txt b/src/core/lombok/core/handlers/singulars.txt
new file mode 100644
index 00000000..d77308cb
--- /dev/null
+++ b/src/core/lombok/core/handlers/singulars.txt
@@ -0,0 +1,56 @@
+#Based on https://github.com/rails/rails/blob/efff6c1fd4b9e2e4c9f705a45879373cb34a5b0e/activesupport/lib/active_support/inflections.rb
+
+quizzes = quiz
+matrices = matrix
+indices = index
+vertices = vertex
+statuses = status
+aliases = alias
+alias = !
+species = !
+Axes = !
+-axes = axe
+sexes = sex
+Testes = testis
+movies = movie
+octopodes = octopus
+buses = bus
+Mice = mouse
+Lice = louse
+News = !
+# We could add more detail (axemen, boatsmen, boogymen, cavemen, gentlemen, etc, but (A) there's stuff like 'cerumen', and (B) the 'men' ending is common in singulars and other languages.)
+# Therefore, the odds of a mistake are too high, so other than these 2 well known cases, force the explicit singular.
+Men = man
+Women = woman
+minutiae = minutia
+shoes = shoe
+synopses = synopsis
+prognoses = prognosis
+theses = thesis
+diagnoses = diagnosis
+bases = base
+analyses = analysis
+Crises = crisis
+children = child
+moves = move
+zombies = zombie
+-quies = quy
+-us = !
+-is = !
+series = !
+-ies = y
+-oes = o
+hives = hive
+-tives = tive
+-sses = ss
+-ches = ch
+-xes = x
+-shes = sh
+-lves = lf
+-rves = rf
+saves = save
+Leaves = leaf
+-ves = !
+-ss = !
+-us = !
+-s =
diff --git a/src/core/lombok/eclipse/EclipseAST.java b/src/core/lombok/eclipse/EclipseAST.java
index 6df5c4d7..dc2c9843 100644
--- a/src/core/lombok/eclipse/EclipseAST.java
+++ b/src/core/lombok/eclipse/EclipseAST.java
@@ -62,7 +62,7 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
* @param ast The compilation unit, which serves as the top level node in the tree to be built.
*/
public EclipseAST(CompilationUnitDeclaration ast) {
- super(toFileName(ast), packageDeclaration(ast), new EclipseImportList(ast));
+ super(toFileName(ast), packageDeclaration(ast), new EclipseImportList(ast), statementTypes());
this.compilationUnitDeclaration = ast;
setTop(buildCompilationUnit(ast));
this.completeParse = isComplete(ast);
@@ -70,7 +70,7 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
}
private static volatile boolean skipEclipseWorkspaceBasedFileResolver = false;
- private static final URI NOT_CALCULATED_MARKER = URI.create("http://projectlombok.org/not/calculated");
+ private static final URI NOT_CALCULATED_MARKER = URI.create("https://projectlombok.org/not/calculated");
private URI memoizedAbsoluteFileLocation = NOT_CALCULATED_MARKER;
public URI getAbsoluteFileLocation() {
@@ -477,9 +477,9 @@ public class EclipseAST extends AST<EclipseAST, EclipseNode, ASTNode> {
return putInMap(new EclipseNode(this, statement, childNodes, Kind.STATEMENT));
}
- /** For Eclipse, only Statement counts, as Expression is a subclass of it, even though this isn't
+ /* For Eclipse, only Statement counts, as Expression is a subclass of it, even though this isn't
* entirely correct according to the JLS spec (only some expressions can be used as statements, not all of them). */
- @Override protected Collection<Class<? extends ASTNode>> getStatementTypes() {
+ private static Collection<Class<? extends ASTNode>> statementTypes() {
return Collections.<Class<? extends ASTNode>>singleton(Statement.class);
}
diff --git a/src/core/lombok/eclipse/EclipseASTVisitor.java b/src/core/lombok/eclipse/EclipseASTVisitor.java
index aa19adc6..f5b49cbb 100644
--- a/src/core/lombok/eclipse/EclipseASTVisitor.java
+++ b/src/core/lombok/eclipse/EclipseASTVisitor.java
@@ -40,7 +40,7 @@ import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
/**
- * Implement so you can ask any JavacAST.Node to traverse depth-first through all children,
+ * Implement so you can ask any EclipseAST.Node to traverse depth-first through all children,
* calling the appropriate visit and endVisit methods.
*/
public interface EclipseASTVisitor {
diff --git a/src/core/lombok/eclipse/EclipseNode.java b/src/core/lombok/eclipse/EclipseNode.java
index 2c970db2..49867e62 100644
--- a/src/core/lombok/eclipse/EclipseNode.java
+++ b/src/core/lombok/eclipse/EclipseNode.java
@@ -54,70 +54,70 @@ public class EclipseNode extends lombok.core.LombokNode<EclipseAST, EclipseNode,
switch (getKind()) {
case COMPILATION_UNIT:
- visitor.visitCompilationUnit(this, (CompilationUnitDeclaration)get());
+ visitor.visitCompilationUnit(this, (CompilationUnitDeclaration) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitCompilationUnit(this, (CompilationUnitDeclaration)get());
+ visitor.endVisitCompilationUnit(this, (CompilationUnitDeclaration) get());
break;
case TYPE:
- visitor.visitType(this, (TypeDeclaration)get());
+ visitor.visitType(this, (TypeDeclaration) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitType(this, (TypeDeclaration)get());
+ visitor.endVisitType(this, (TypeDeclaration) get());
break;
case FIELD:
- visitor.visitField(this, (FieldDeclaration)get());
+ visitor.visitField(this, (FieldDeclaration) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitField(this, (FieldDeclaration)get());
+ visitor.endVisitField(this, (FieldDeclaration) get());
break;
case INITIALIZER:
- visitor.visitInitializer(this, (Initializer)get());
+ visitor.visitInitializer(this, (Initializer) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitInitializer(this, (Initializer)get());
+ visitor.endVisitInitializer(this, (Initializer) get());
break;
case METHOD:
if (get() instanceof Clinit) return;
- visitor.visitMethod(this, (AbstractMethodDeclaration)get());
+ visitor.visitMethod(this, (AbstractMethodDeclaration) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitMethod(this, (AbstractMethodDeclaration)get());
+ visitor.endVisitMethod(this, (AbstractMethodDeclaration) get());
break;
case ARGUMENT:
- AbstractMethodDeclaration method = (AbstractMethodDeclaration)up().get();
- visitor.visitMethodArgument(this, (Argument)get(), method);
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) up().get();
+ visitor.visitMethodArgument(this, (Argument) get(), method);
ast.traverseChildren(visitor, this);
- visitor.endVisitMethodArgument(this, (Argument)get(), method);
+ visitor.endVisitMethodArgument(this, (Argument) get(), method);
break;
case LOCAL:
- visitor.visitLocal(this, (LocalDeclaration)get());
+ visitor.visitLocal(this, (LocalDeclaration) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitLocal(this, (LocalDeclaration)get());
+ visitor.endVisitLocal(this, (LocalDeclaration) get());
break;
case ANNOTATION:
switch (up().getKind()) {
case TYPE:
- visitor.visitAnnotationOnType((TypeDeclaration)up().get(), this, (Annotation)get());
+ visitor.visitAnnotationOnType((TypeDeclaration) up().get(), this, (Annotation) get());
break;
case FIELD:
- visitor.visitAnnotationOnField((FieldDeclaration)up().get(), this, (Annotation)get());
+ visitor.visitAnnotationOnField((FieldDeclaration) up().get(), this, (Annotation) get());
break;
case METHOD:
- visitor.visitAnnotationOnMethod((AbstractMethodDeclaration)up().get(), this, (Annotation)get());
+ visitor.visitAnnotationOnMethod((AbstractMethodDeclaration) up().get(), this, (Annotation) get());
break;
case ARGUMENT:
visitor.visitAnnotationOnMethodArgument(
- (Argument)parent.get(),
- (AbstractMethodDeclaration)parent.directUp().get(),
- this, (Annotation)get());
+ (Argument) parent.get(),
+ (AbstractMethodDeclaration) parent.directUp().get(),
+ this, (Annotation) get());
break;
case LOCAL:
- visitor.visitAnnotationOnLocal((LocalDeclaration)parent.get(), this, (Annotation)get());
+ visitor.visitAnnotationOnLocal((LocalDeclaration) parent.get(), this, (Annotation) get());
break;
default:
throw new AssertionError("Annotation not expected as child of a " + up().getKind());
}
break;
case STATEMENT:
- visitor.visitStatement(this, (Statement)get());
+ visitor.visitStatement(this, (Statement) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitStatement(this, (Statement)get());
+ visitor.endVisitStatement(this, (Statement) get());
break;
default:
throw new AssertionError("Unexpected kind during node traversal: " + getKind());
diff --git a/src/core/lombok/eclipse/TransformEclipseAST.java b/src/core/lombok/eclipse/TransformEclipseAST.java
index e6528178..683465c9 100644
--- a/src/core/lombok/eclipse/TransformEclipseAST.java
+++ b/src/core/lombok/eclipse/TransformEclipseAST.java
@@ -106,7 +106,7 @@ public class TransformEclipseAST {
EclipseAST existing = null;
if (astCacheField != null) {
try {
- existing = (EclipseAST)astCacheField.get(ast);
+ existing = (EclipseAST) astCacheField.get(ast);
} catch (Exception e) {
// existing remains null
}
diff --git a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
index 8326e1d0..6617d21a 100644
--- a/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
+++ b/src/core/lombok/eclipse/handlers/EclipseHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -48,6 +48,7 @@ import lombok.core.TypeResolver;
import lombok.core.configuration.NullCheckExceptionType;
import lombok.core.debug.ProblemReporter;
import lombok.core.handlers.HandlerUtil;
+import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAST;
import lombok.eclipse.EclipseNode;
import lombok.experimental.Accessors;
@@ -143,7 +144,7 @@ public class EclipseHandlerUtil {
return getGeneratedBy(node) != null;
}
- public static ASTNode setGeneratedBy(ASTNode node, ASTNode source) {
+ public static <T extends ASTNode> T setGeneratedBy(T node, ASTNode source) {
ASTNode_generatedBy.set(node, source);
return node;
}
@@ -166,6 +167,7 @@ public class EclipseHandlerUtil {
}
public static boolean isFieldDeprecated(EclipseNode fieldNode) {
+ if (!(fieldNode.get() instanceof FieldDeclaration)) return false;
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
if ((field.modifiers & ClassFileConstants.AccDeprecated) != 0) {
return true;
@@ -195,16 +197,36 @@ public class EclipseHandlerUtil {
TypeResolver resolver = new TypeResolver(node.getImportList());
return resolver.typeMatches(node, type.getName(), typeName);
+ }
+
+ /**
+ * Checks if the given TypeReference node is likely to be a reference to the provided class.
+ *
+ * @param type An actual type. This method checks if {@code typeNode} is likely to be a reference to this type.
+ * @param node A Lombok AST node. Any node in the appropriate compilation unit will do (used to get access to import statements).
+ * @param typeRef A type reference to check.
+ */
+ public static boolean typeMatches(String type, EclipseNode node, TypeReference typeRef) {
+ if (typeRef == null || typeRef.getTypeName() == null || typeRef.getTypeName().length == 0) return false;
+ String lastPartA = new String(typeRef.getTypeName()[typeRef.getTypeName().length -1]);
+ int lastIndex = type.lastIndexOf('.');
+ String lastPartB = lastIndex == -1 ? type : type.substring(lastIndex + 1);
+ if (!lastPartA.equals(lastPartB)) return false;
+ String typeName = toQualifiedName(typeRef.getTypeName());
+ TypeResolver resolver = new TypeResolver(node.getImportList());
+ return resolver.typeMatches(node, type, typeName);
}
public static void sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(EclipseNode typeNode, EclipseNode errorNode) {
List<String> disallowed = null;
for (EclipseNode child : typeNode.down()) {
- for (Class<? extends java.lang.annotation.Annotation> annType : INVALID_ON_BUILDERS) {
+ if (child.getKind() != Kind.ANNOTATION) continue;
+ for (String annType : INVALID_ON_BUILDERS) {
if (annotationTypeMatches(annType, child)) {
if (disallowed == null) disallowed = new ArrayList<String>();
- disallowed.add(annType.getSimpleName());
+ int lastIndex = annType.lastIndexOf('.');
+ disallowed.add(lastIndex == -1 ? annType : annType.substring(lastIndex + 1));
}
}
}
@@ -298,6 +320,10 @@ public class EclipseHandlerUtil {
return new SingleTypeReference(typeName, p);
}
+ public static TypeReference[] copyTypes(TypeReference[] refs) {
+ return copyTypes(refs, null);
+ }
+
/**
* Convenience method that creates a new array and copies each TypeReference in the source array via
* {@link #copyType(TypeReference, ASTNode)}.
@@ -312,6 +338,10 @@ public class EclipseHandlerUtil {
return outs;
}
+ public static TypeReference copyType(TypeReference ref) {
+ return copyType(ref, null);
+ }
+
/**
* You can't share TypeReference objects or subtle errors start happening.
* Unfortunately the TypeReference type hierarchy is complicated and there's no clone
@@ -336,22 +366,23 @@ public class EclipseHandlerUtil {
}
}
}
+
TypeReference typeRef = new ParameterizedQualifiedTypeReference(iRef.tokens, args, iRef.dimensions(), copy(iRef.sourcePositions));
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
if (ref instanceof ArrayQualifiedTypeReference) {
ArrayQualifiedTypeReference iRef = (ArrayQualifiedTypeReference) ref;
TypeReference typeRef = new ArrayQualifiedTypeReference(iRef.tokens, iRef.dimensions(), copy(iRef.sourcePositions));
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
if (ref instanceof QualifiedTypeReference) {
QualifiedTypeReference iRef = (QualifiedTypeReference) ref;
TypeReference typeRef = new QualifiedTypeReference(iRef.tokens, copy(iRef.sourcePositions));
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
@@ -368,14 +399,14 @@ public class EclipseHandlerUtil {
}
TypeReference typeRef = new ParameterizedSingleTypeReference(iRef.token, args, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd);
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
if (ref instanceof ArrayTypeReference) {
ArrayTypeReference iRef = (ArrayTypeReference) ref;
TypeReference typeRef = new ArrayTypeReference(iRef.token, iRef.dimensions(), (long)iRef.sourceStart << 32 | iRef.sourceEnd);
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
@@ -386,14 +417,14 @@ public class EclipseHandlerUtil {
wildcard.sourceStart = original.sourceStart;
wildcard.sourceEnd = original.sourceEnd;
if (original.bound != null) wildcard.bound = copyType(original.bound, source);
- setGeneratedBy(wildcard, source);
+ if (source != null) setGeneratedBy(wildcard, source);
return wildcard;
}
if (ref instanceof SingleTypeReference) {
SingleTypeReference iRef = (SingleTypeReference) ref;
TypeReference typeRef = new SingleTypeReference(iRef.token, (long)iRef.sourceStart << 32 | iRef.sourceEnd);
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
return typeRef;
}
@@ -401,19 +432,17 @@ public class EclipseHandlerUtil {
}
public static Annotation[] copyAnnotations(ASTNode source, Annotation[]... allAnnotations) {
- boolean allNull = true;
-
- List<Annotation> result = new ArrayList<Annotation>();
+ List<Annotation> result = null;
for (Annotation[] annotations : allAnnotations) {
if (annotations != null) {
- allNull = false;
for (Annotation annotation : annotations) {
+ if (result == null) result = new ArrayList<Annotation>();
result.add(copyAnnotation(annotation, source));
}
}
}
- if (allNull) return null;
- return result.toArray(new Annotation[0]);
+
+ return result == null ? null : result.toArray(new Annotation[0]);
}
public static boolean hasAnnotation(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) {
@@ -434,6 +463,42 @@ public class EclipseHandlerUtil {
}
}
+ public static boolean hasAnnotation(String type, EclipseNode node) {
+ if (node == null) return false;
+ if (type == null) return false;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (EclipseNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) return true;
+ }
+ // intentional fallthrough
+ default:
+ return false;
+ }
+ }
+
+ public static EclipseNode findAnnotation(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) {
+ if (node == null) return null;
+ if (type == null) return null;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (EclipseNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) return child;
+ }
+ // intentional fallthrough
+ default:
+ return null;
+ }
+ }
+
/**
* Checks if the provided annotation type is likely to be the intended type for the given annotation node.
*
@@ -441,11 +506,25 @@ public class EclipseHandlerUtil {
*/
public static boolean annotationTypeMatches(Class<? extends java.lang.annotation.Annotation> type, EclipseNode node) {
if (node.getKind() != Kind.ANNOTATION) return false;
- return typeMatches(type, node, ((Annotation)node.get()).type);
+ return typeMatches(type, node, ((Annotation) node.get()).type);
+ }
+
+ /**
+ * Checks if the provided annotation type is likely to be the intended type for the given annotation node.
+ *
+ * This is a guess, but a decent one.
+ */
+ public static boolean annotationTypeMatches(String type, EclipseNode node) {
+ if (node.getKind() != Kind.ANNOTATION) return false;
+ return typeMatches(type, node, ((Annotation) node.get()).type);
+ }
+
+ public static TypeReference cloneSelfType(EclipseNode context) {
+ return cloneSelfType(context, null);
}
public static TypeReference cloneSelfType(EclipseNode context, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
long p = (long)pS << 32 | pE;
EclipseNode type = context;
TypeReference result = null;
@@ -457,7 +536,7 @@ public class EclipseHandlerUtil {
int idx = 0;
for (TypeParameter param : typeDecl.typeParameters) {
TypeReference typeRef = new SingleTypeReference(param.name, (long)param.sourceStart << 32 | param.sourceEnd);
- setGeneratedBy(typeRef, source);
+ if (source != null) setGeneratedBy(typeRef, source);
refs[idx++] = typeRef;
}
result = new ParameterizedSingleTypeReference(typeDecl.name, refs, 0, p);
@@ -465,7 +544,7 @@ public class EclipseHandlerUtil {
result = new SingleTypeReference(((TypeDeclaration)type.get()).name, p);
}
}
- if (result != null) setGeneratedBy(result, source);
+ if (result != null && source != null) setGeneratedBy(result, source);
return result;
}
@@ -668,47 +747,39 @@ public class EclipseHandlerUtil {
*/
public static <A extends java.lang.annotation.Annotation> AnnotationValues<A>
createAnnotation(Class<A> type, final EclipseNode annotationNode) {
+
final Annotation annotation = (Annotation) annotationNode.get();
Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
- final MemberValuePair[] pairs = annotation.memberValuePairs();
- for (Method m : type.getDeclaredMethods()) {
- if (!Modifier.isPublic(m.getModifiers())) continue;
- String name = m.getName();
+ MemberValuePair[] memberValuePairs = annotation.memberValuePairs();
+
+ if (memberValuePairs != null) for (final MemberValuePair pair : memberValuePairs) {
List<String> raws = new ArrayList<String>();
List<Object> expressionValues = new ArrayList<Object>();
List<Object> guesses = new ArrayList<Object>();
- Expression fullExpression = null;
Expression[] expressions = null;
- if (pairs != null) for (MemberValuePair pair : pairs) {
- char[] n = pair.name;
- String mName = n == null ? "value" : new String(pair.name);
- if (mName.equals(name)) fullExpression = pair.value;
+ char[] n = pair.name;
+ String mName = (n == null || n.length == 0) ? "value" : new String(pair.name);
+ final Expression rhs = pair.value;
+ if (rhs instanceof ArrayInitializer) {
+ expressions = ((ArrayInitializer)rhs).expressions;
+ } else if (rhs != null) {
+ expressions = new Expression[] { rhs };
}
-
- boolean isExplicit = fullExpression != null;
-
- if (isExplicit) {
- if (fullExpression instanceof ArrayInitializer) {
- expressions = ((ArrayInitializer)fullExpression).expressions;
- } else expressions = new Expression[] { fullExpression };
- if (expressions != null) for (Expression ex : expressions) {
- StringBuffer sb = new StringBuffer();
- ex.print(0, sb);
- raws.add(sb.toString());
- expressionValues.add(ex);
- guesses.add(calculateValue(ex));
- }
+ if (expressions != null) for (Expression ex : expressions) {
+ StringBuffer sb = new StringBuffer();
+ ex.print(0, sb);
+ raws.add(sb.toString());
+ expressionValues.add(ex);
+ guesses.add(calculateValue(ex));
}
- final Expression fullExpr = fullExpression;
final Expression[] exprs = expressions;
-
- values.put(name, new AnnotationValue(annotationNode, raws, expressionValues, guesses, isExplicit) {
+ values.put(mName, new AnnotationValue(annotationNode, raws, expressionValues, guesses, true) {
@Override public void setError(String message, int valueIdx) {
Expression ex;
- if (valueIdx == -1) ex = fullExpr;
+ if (valueIdx == -1) ex = rhs;
else ex = exprs != null ? exprs[valueIdx] : null;
if (ex == null) ex = annotation;
@@ -721,7 +792,7 @@ public class EclipseHandlerUtil {
@Override public void setWarning(String message, int valueIdx) {
Expression ex;
- if (valueIdx == -1) ex = fullExpr;
+ if (valueIdx == -1) ex = rhs;
else ex = exprs != null ? exprs[valueIdx] : null;
if (ex == null) ex = annotation;
@@ -734,6 +805,21 @@ public class EclipseHandlerUtil {
});
}
+ for (Method m : type.getDeclaredMethods()) {
+ if (!Modifier.isPublic(m.getModifiers())) continue;
+ String name = m.getName();
+ if (!values.containsKey(name)) {
+ values.put(name, new AnnotationValue(annotationNode, new ArrayList<String>(), new ArrayList<Object>(), new ArrayList<Object>(), false) {
+ @Override public void setError(String message, int valueIdx) {
+ annotationNode.addError(message);
+ }
+ @Override public void setWarning(String message, int valueIdx) {
+ annotationNode.addWarning(message);
+ }
+ });
+ }
+ }
+
return new AnnotationValues<A>(type, values, annotationNode);
}
@@ -811,7 +897,7 @@ public class EclipseHandlerUtil {
// Check if the class has a @Getter annotation.
- if (!hasGetterAnnotation && new HandleGetter().fieldQualifiesForGetterGeneration(field)) {
+ if (!hasGetterAnnotation && HandleGetter.fieldQualifiesForGetterGeneration(field)) {
//Check if the class has @Getter or @Data annotation.
EclipseNode containingType = field.up();
@@ -865,7 +951,7 @@ public class EclipseHandlerUtil {
}
static Expression createFieldAccessor(EclipseNode field, FieldAccess fieldAccess, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
long p = (long)pS << 32 | pE;
boolean lookForGetter = lookForGetter(field, fieldAccess);
@@ -881,14 +967,17 @@ public class EclipseHandlerUtil {
ref.receiver = new SingleNameReference(((TypeDeclaration)containerNode.get()).name, p);
} else {
Expression smallRef = new FieldReference(field.getName().toCharArray(), p);
- setGeneratedBy(smallRef, source);
+ if (source != null) setGeneratedBy(smallRef, source);
return smallRef;
}
} else {
ref.receiver = new ThisReference(pS, pE);
}
- setGeneratedBy(ref, source);
- setGeneratedBy(ref.receiver, source);
+
+ if (source != null) {
+ setGeneratedBy(ref, source);
+ setGeneratedBy(ref.receiver, source);
+ }
return ref;
}
@@ -1145,9 +1234,8 @@ public class EclipseHandlerUtil {
if (params < minArgs || params > maxArgs) continue;
}
- if (def.annotations != null) for (Annotation anno : def.annotations) {
- if (typeMatches(Tolerate.class, node, anno.type)) continue top;
- }
+
+ if (isTolerate(node, def)) continue top;
return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
@@ -1158,6 +1246,13 @@ public class EclipseHandlerUtil {
return MemberExistsResult.NOT_EXISTS;
}
+ public static boolean isTolerate(EclipseNode node, AbstractMethodDeclaration def) {
+ if (def.annotations != null) for (Annotation anno : def.annotations) {
+ if (typeMatches(Tolerate.class, node, anno.type)) return true;
+ }
+ return false;
+ }
+
/**
* Checks if there is a (non-default) constructor. In case of multiple constructors (overloading), only
* the first constructor decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned.
@@ -1171,13 +1266,11 @@ public class EclipseHandlerUtil {
if (node != null && node.get() instanceof TypeDeclaration) {
TypeDeclaration typeDecl = (TypeDeclaration)node.get();
- if (typeDecl.methods != null) top: for (AbstractMethodDeclaration def : typeDecl.methods) {
+ if (typeDecl.methods != null) for (AbstractMethodDeclaration def : typeDecl.methods) {
if (def instanceof ConstructorDeclaration) {
if ((def.bits & ASTNode.IsDefaultConstructor) != 0) continue;
- if (def.annotations != null) for (Annotation anno : def.annotations) {
- if (typeMatches(Tolerate.class, node, anno.type)) continue top;
- }
+ if (isTolerate(node, def)) continue;
return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
@@ -1191,8 +1284,9 @@ public class EclipseHandlerUtil {
* Inserts a field into an existing type. The type must represent a {@code TypeDeclaration}.
* The field carries the &#64;{@link SuppressWarnings}("all") annotation.
*/
- public static EclipseNode injectFieldSuppressWarnings(EclipseNode type, FieldDeclaration field) {
- field.annotations = createSuppressWarningsAll(field, field.annotations);
+ public static EclipseNode injectFieldAndMarkGenerated(EclipseNode type, FieldDeclaration field) {
+ field.annotations = addSuppressWarningsAll(type, field, field.annotations);
+ field.annotations = addGenerated(type, field, field.annotations);
return injectField(type, field);
}
@@ -1237,7 +1331,8 @@ public class EclipseHandlerUtil {
* Inserts a method into an existing type. The type must represent a {@code TypeDeclaration}.
*/
public static EclipseNode injectMethod(EclipseNode type, AbstractMethodDeclaration method) {
- method.annotations = createSuppressWarningsAll(method, method.annotations);
+ method.annotations = addSuppressWarningsAll(type, method, method.annotations);
+ method.annotations = addGenerated(type, method, method.annotations);
TypeDeclaration parent = (TypeDeclaration) type.get();
if (parent.methods == null) {
@@ -1279,9 +1374,10 @@ public class EclipseHandlerUtil {
* @param type New type (class, interface, etc) to inject.
*/
public static EclipseNode injectType(final EclipseNode typeNode, final TypeDeclaration type) {
- type.annotations = createSuppressWarningsAll(type, type.annotations);
+ type.annotations = addSuppressWarningsAll(typeNode, type, type.annotations);
+ type.annotations = addGenerated(typeNode, type, type.annotations);
TypeDeclaration parent = (TypeDeclaration) typeNode.get();
-
+
if (parent.memberTypes == null) {
parent.memberTypes = new TypeDeclaration[] { type };
} else {
@@ -1295,32 +1391,82 @@ public class EclipseHandlerUtil {
}
private static final char[] ALL = "all".toCharArray();
+ private static final char[] JUSTIFICATION = "justification".toCharArray();
+ private static final char[] GENERATED_CODE = "generated code".toCharArray();
+ private static final char[] LOMBOK = "lombok".toCharArray();
+ private static final char[][] JAVAX_ANNOTATION_GENERATED = Eclipse.fromQualifiedName("javax.annotation.Generated");
+ private static final char[][] LOMBOK_GENERATED = Eclipse.fromQualifiedName("lombok.Generated");
+ private static final char[][] EDU_UMD_CS_FINDBUGS_ANNOTATIONS_SUPPRESSFBWARNINGS = Eclipse.fromQualifiedName("edu.umd.cs.findbugs.annotations.SuppressFBWarnings");
+
+ public static Annotation[] addSuppressWarningsAll(EclipseNode node, ASTNode source, Annotation[] originalAnnotationArray) {
+ Annotation[] anns = addAnnotation(source, originalAnnotationArray, TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, new StringLiteral(ALL, 0, 0, 0));
+
+ if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS))) {
+ MemberValuePair mvp = new MemberValuePair(JUSTIFICATION, 0, 0, new StringLiteral(GENERATED_CODE, 0, 0, 0));
+ anns = addAnnotation(source, anns, EDU_UMD_CS_FINDBUGS_ANNOTATIONS_SUPPRESSFBWARNINGS, mvp);
+ }
+
+ return anns;
+ }
+
+ public static Annotation[] addGenerated(EclipseNode node, ASTNode source, Annotation[] originalAnnotationArray) {
+ Annotation[] result = originalAnnotationArray;
+ if (HandlerUtil.shouldAddGenerated(node)) {
+ result = addAnnotation(source, result, JAVAX_ANNOTATION_GENERATED, new StringLiteral(LOMBOK, 0, 0, 0));
+ }
+ if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_LOMBOK_GENERATED_ANNOTATIONS))) {
+ result = addAnnotation(source, result, LOMBOK_GENERATED, null);
+ }
+ return result;
+ }
- public static Annotation[] createSuppressWarningsAll(ASTNode source, Annotation[] originalAnnotationArray) {
+ private static Annotation[] addAnnotation(ASTNode source, Annotation[] originalAnnotationArray, char[][] annotationTypeFqn, ASTNode arg) {
+ char[] simpleName = annotationTypeFqn[annotationTypeFqn.length - 1];
+
if (originalAnnotationArray != null) for (Annotation ann : originalAnnotationArray) {
- char[] lastToken = null;
-
if (ann.type instanceof QualifiedTypeReference) {
char[][] t = ((QualifiedTypeReference) ann.type).tokens;
- lastToken = t[t.length - 1];
- } else if (ann.type instanceof SingleTypeReference) {
- lastToken = ((SingleTypeReference) ann.type).token;
+ if (Arrays.deepEquals(t, annotationTypeFqn)) return originalAnnotationArray;
}
- if (lastToken != null && new String(lastToken).equals("SuppressWarnings")) return originalAnnotationArray;
+ if (ann.type instanceof SingleTypeReference) {
+ char[] lastToken = ((SingleTypeReference) ann.type).token;
+ if (Arrays.equals(lastToken, simpleName)) return originalAnnotationArray;
+ }
}
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long)pS << 32 | pE;
- long[] poss = new long[3];
+ long[] poss = new long[annotationTypeFqn.length];
Arrays.fill(poss, p);
- QualifiedTypeReference suppressWarningsType = new QualifiedTypeReference(TypeConstants.JAVA_LANG_SUPPRESSWARNINGS, poss);
- setGeneratedBy(suppressWarningsType, source);
- SingleMemberAnnotation ann = new SingleMemberAnnotation(suppressWarningsType, pS);
- ann.declarationSourceEnd = pE;
- ann.memberValue = new StringLiteral(ALL, pS, pE, 0);
+ QualifiedTypeReference qualifiedType = new QualifiedTypeReference(annotationTypeFqn, poss);
+ setGeneratedBy(qualifiedType, source);
+ Annotation ann;
+ if (arg instanceof Expression) {
+ SingleMemberAnnotation sma = new SingleMemberAnnotation(qualifiedType, pS);
+ sma.declarationSourceEnd = pE;
+ arg.sourceStart = pS;
+ arg.sourceEnd = pE;
+ sma.memberValue = (Expression) arg;
+ setGeneratedBy(sma.memberValue, source);
+ ann = sma;
+ } else if (arg instanceof MemberValuePair) {
+ NormalAnnotation na = new NormalAnnotation(qualifiedType, pS);
+ na.declarationSourceEnd = pE;
+ arg.sourceStart = pS;
+ arg.sourceEnd = pE;
+ na.memberValuePairs = new MemberValuePair[] {(MemberValuePair) arg};
+ setGeneratedBy(na.memberValuePairs[0], source);
+ setGeneratedBy(na.memberValuePairs[0].value, source);
+ na.memberValuePairs[0].value.sourceStart = pS;
+ na.memberValuePairs[0].value.sourceEnd = pE;
+ ann = na;
+ } else {
+ MarkerAnnotation ma = new MarkerAnnotation(qualifiedType, pS);
+ ma.declarationSourceEnd = pE;
+ ann = ma;
+ }
setGeneratedBy(ann, source);
- setGeneratedBy(ann.memberValue, source);
if (originalAnnotationArray == null) return new Annotation[] { ann };
Annotation[] newAnnotationArray = new Annotation[originalAnnotationArray.length + 1];
System.arraycopy(originalAnnotationArray, 0, newAnnotationArray, 0, originalAnnotationArray.length);
@@ -1489,7 +1635,7 @@ public class EclipseHandlerUtil {
* with eclipse versions before 3.7.
*/
public static IntLiteral makeIntLiteral(char[] token, ASTNode source) {
- int pS = source.sourceStart, pE = source.sourceEnd;
+ int pS = source == null ? 0 : source.sourceStart, pE = source == null ? 0 : source.sourceEnd;
IntLiteral result;
try {
if (intLiteralConstructor != null) {
@@ -1504,7 +1650,8 @@ public class EclipseHandlerUtil {
} catch (InstantiationException e) {
throw Lombok.sneakyThrow(e);
}
- setGeneratedBy(result, source);
+
+ if (source != null) setGeneratedBy(result, source);
return result;
}
@@ -1535,6 +1682,14 @@ public class EclipseHandlerUtil {
return true;
}
+ public static void addError(String errorName, EclipseNode node) {
+ if (node.getLatestJavaSpecSupported() < 8) {
+ node.addError("The correct format is " + errorName + "_={@SomeAnnotation, @SomeOtherAnnotation})");
+ } else {
+ node.addError("The correct format is " + errorName + "=@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ }
+ }
+
public static List<Annotation> unboxAndRemoveAnnotationParameter(Annotation annotation, String annotationName, String errorName, EclipseNode errorNode) {
if ("value".equals(annotationName)) {
// We can't unbox this, because SingleMemberAnnotation REQUIRES a value, and this method
@@ -1557,51 +1712,70 @@ public class EclipseHandlerUtil {
char[] nameAsCharArray = annotationName.toCharArray();
+ top:
for (int i = 0; i < pairs.length; i++) {
- if (pairs[i].name == null || !Arrays.equals(nameAsCharArray, pairs[i].name)) continue;
+ boolean allowRaw;
+ char[] name = pairs[i].name;
+ if (name == null) continue;
+ if (name.length < nameAsCharArray.length) continue;
+ for (int j = 0; j < nameAsCharArray.length; j++) {
+ if (name[j] != nameAsCharArray[j]) continue top;
+ }
+ allowRaw = name.length > nameAsCharArray.length;
+ for (int j = nameAsCharArray.length; j < name.length; j++) {
+ if (name[j] != '_') continue top;
+ }
+ // If we're still here it's the targeted annotation param.
Expression value = pairs[i].value;
MemberValuePair[] newPairs = new MemberValuePair[pairs.length - 1];
if (i > 0) System.arraycopy(pairs, 0, newPairs, 0, i);
if (i < pairs.length - 1) System.arraycopy(pairs, i + 1, newPairs, i, pairs.length - i - 1);
normalAnnotation.memberValuePairs = newPairs;
- // We have now removed the annotation parameter and stored '@__({... annotations ...})',
- // which we must now unbox.
- if (!(value instanceof Annotation)) {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- return Collections.emptyList();
- }
-
- Annotation atDummyIdentifier = (Annotation) value;
- if (!(atDummyIdentifier.type instanceof SingleTypeReference) ||
- !isAllValidOnXCharacters(((SingleTypeReference) atDummyIdentifier.type).token)) {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- return Collections.emptyList();
- }
-
- if (atDummyIdentifier instanceof MarkerAnnotation) {
- // It's @Getter(onMethod=@__). This is weird, but fine.
- return Collections.emptyList();
- }
+ // We have now removed the annotation parameter and stored the value,
+ // which we must now unbox. It's either annotations, or @__(annotations).
Expression content = null;
- if (atDummyIdentifier instanceof NormalAnnotation) {
- MemberValuePair[] mvps = ((NormalAnnotation) atDummyIdentifier).memberValuePairs;
- if (mvps == null || mvps.length == 0) {
- // It's @Getter(onMethod=@__()). This is weird, but fine.
+ if (value instanceof ArrayInitializer) {
+ if (!allowRaw) {
+ addError(errorName, errorNode);
return Collections.emptyList();
}
- if (mvps.length == 1 && Arrays.equals("value".toCharArray(), mvps[0].name)) {
- content = mvps[0].value;
+ content = value;
+ } else if (!(value instanceof Annotation)) {
+ addError(errorName, errorNode);
+ return Collections.emptyList();
+ } else {
+ Annotation atDummyIdentifier = (Annotation) value;
+ if (atDummyIdentifier.type instanceof SingleTypeReference && isAllValidOnXCharacters(((SingleTypeReference) atDummyIdentifier.type).token)) {
+ if (atDummyIdentifier instanceof MarkerAnnotation) {
+ return Collections.emptyList();
+ } else if (atDummyIdentifier instanceof NormalAnnotation) {
+ MemberValuePair[] mvps = ((NormalAnnotation) atDummyIdentifier).memberValuePairs;
+ if (mvps == null || mvps.length == 0) {
+ return Collections.emptyList();
+ }
+ if (mvps.length == 1 && Arrays.equals("value".toCharArray(), mvps[0].name)) {
+ content = mvps[0].value;
+ }
+ } else if (atDummyIdentifier instanceof SingleMemberAnnotation) {
+ content = ((SingleMemberAnnotation) atDummyIdentifier).memberValue;
+ } else {
+ addError(errorName, errorNode);
+ return Collections.emptyList();
+ }
+ } else {
+ if (allowRaw) {
+ content = atDummyIdentifier;
+ } else {
+ addError(errorName, errorNode);
+ return Collections.emptyList();
+ }
}
}
- if (atDummyIdentifier instanceof SingleMemberAnnotation) {
- content = ((SingleMemberAnnotation) atDummyIdentifier).memberValue;
- }
-
if (content == null) {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ addError(errorName, errorNode);
return Collections.emptyList();
}
@@ -1613,13 +1787,13 @@ public class EclipseHandlerUtil {
if (expressions != null) for (Expression ex : expressions) {
if (ex instanceof Annotation) result.add((Annotation) ex);
else {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ addError(errorName, errorNode);
return Collections.emptyList();
}
}
return result;
} else {
- errorNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ addError(errorName, errorNode);
return Collections.emptyList();
}
}
diff --git a/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
new file mode 100644
index 00000000..bc779dab
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/EclipseSingularsRecipes.java
@@ -0,0 +1,349 @@
+/*
+ * Copyright (C) 2015-2017 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers;
+
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Wildcard;
+import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+
+import lombok.core.LombokImmutableList;
+import lombok.core.SpiLoadUtil;
+import lombok.core.TypeLibrary;
+import lombok.eclipse.EclipseNode;
+
+public class EclipseSingularsRecipes {
+ private static final EclipseSingularsRecipes INSTANCE = new EclipseSingularsRecipes();
+ private final Map<String, EclipseSingularizer> singularizers = new HashMap<String, EclipseSingularizer>();
+ private final TypeLibrary singularizableTypes = new TypeLibrary();
+
+ private EclipseSingularsRecipes() {
+ try {
+ loadAll(singularizableTypes, singularizers);
+ singularizableTypes.lock();
+ } catch (IOException e) {
+ System.err.println("Lombok's @Singularizable feature is broken due to misconfigured SPI files: " + e);
+ }
+ }
+
+ private static void loadAll(TypeLibrary library, Map<String, EclipseSingularizer> map) throws IOException {
+ for (EclipseSingularizer handler : SpiLoadUtil.findServices(EclipseSingularizer.class, EclipseSingularizer.class.getClassLoader())) {
+ for (String type : handler.getSupportedTypes()) {
+ EclipseSingularizer existingSingularizer = map.get(type);
+ if (existingSingularizer != null) {
+ EclipseSingularizer toKeep = existingSingularizer.getClass().getName().compareTo(handler.getClass().getName()) > 0 ? handler : existingSingularizer;
+ System.err.println("Multiple singularizers found for type " + type + "; the alphabetically first class is used: " + toKeep.getClass().getName());
+ map.put(type, toKeep);
+ } else {
+ map.put(type, handler);
+ library.addType(type);
+ }
+ }
+ }
+ }
+
+ public static EclipseSingularsRecipes get() {
+ return INSTANCE;
+ }
+
+ public String toQualified(String typeReference) {
+ return singularizableTypes.toQualified(typeReference);
+ }
+
+ public EclipseSingularizer getSingularizer(String fqn) {
+ return singularizers.get(fqn);
+ }
+
+ public static final class SingularData {
+ private final EclipseNode annotation;
+ private final char[] singularName;
+ private final char[] pluralName;
+ private final List<TypeReference> typeArgs;
+ private final String targetFqn;
+ private final EclipseSingularizer singularizer;
+ private final ASTNode source;
+
+ public SingularData(EclipseNode annotation, char[] singularName, char[] pluralName, List<TypeReference> typeArgs, String targetFqn, EclipseSingularizer singularizer, ASTNode source) {
+ this.annotation = annotation;
+ this.singularName = singularName;
+ this.pluralName = pluralName;
+ this.typeArgs = typeArgs;
+ this.targetFqn = targetFqn;
+ this.singularizer = singularizer;
+ this.source = source;
+ }
+
+ public void setGeneratedByRecursive(ASTNode target) {
+ SetGeneratedByVisitor visitor = new SetGeneratedByVisitor(source);
+
+ if (target instanceof AbstractMethodDeclaration) {
+ ((AbstractMethodDeclaration) target).traverse(visitor, (ClassScope) null);
+ } else if (target instanceof FieldDeclaration) {
+ ((FieldDeclaration) target).traverse(visitor, (MethodScope) null);
+ } else {
+ target.traverse(visitor, null);
+ }
+ }
+
+ public ASTNode getSource() {
+ return source;
+ }
+
+ public EclipseNode getAnnotation() {
+ return annotation;
+ }
+
+ public char[] getSingularName() {
+ return singularName;
+ }
+
+ public char[] getPluralName() {
+ return pluralName;
+ }
+
+ public List<TypeReference> getTypeArgs() {
+ return typeArgs;
+ }
+
+ public String getTargetFqn() {
+ return targetFqn;
+ }
+
+ public EclipseSingularizer getSingularizer() {
+ return singularizer;
+ }
+
+ public String getTargetSimpleType() {
+ int idx = targetFqn.lastIndexOf(".");
+ return idx == -1 ? targetFqn : targetFqn.substring(idx + 1);
+ }
+ }
+
+ public static abstract class EclipseSingularizer {
+ protected static final long[] NULL_POSS = {0L};
+ public abstract LombokImmutableList<String> getSupportedTypes();
+
+ /** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
+ public boolean checkForAlreadyExistingNodesAndGenerateError(EclipseNode builderType, SingularData data) {
+ for (EclipseNode child : builderType.down()) {
+ switch (child.getKind()) {
+ case FIELD: {
+ FieldDeclaration fd = (FieldDeclaration) child.get();
+ char[] name = fd.name;
+ if (name == null) continue;
+ if (getGeneratedBy(fd) != null) continue;
+ for (char[] fieldToBeGenerated : listFieldsToBeGenerated(data, builderType)) {
+ if (!Arrays.equals(name, fieldToBeGenerated)) continue;
+ child.addError("Manually adding a field that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }
+ case METHOD: {
+ AbstractMethodDeclaration method = (AbstractMethodDeclaration) child.get();
+ char[] name = method.selector;
+ if (name == null) continue;
+ if (getGeneratedBy(method) != null) continue;
+ for (char[] methodToBeGenerated : listMethodsToBeGenerated(data, builderType)) {
+ if (!Arrays.equals(name, methodToBeGenerated)) continue;
+ child.addError("Manually adding a method that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }}
+ }
+
+ return false;
+ }
+
+ public List<char[]> listFieldsToBeGenerated(SingularData data, EclipseNode builderType) {
+ return Collections.singletonList(data.pluralName);
+ }
+
+ public List<char[]> listMethodsToBeGenerated(SingularData data, EclipseNode builderType) {
+ char[] p = data.pluralName;
+ char[] s = data.singularName;
+ if (Arrays.equals(p, s)) return Collections.singletonList(p);
+ return Arrays.asList(p, s);
+ }
+
+ public abstract List<EclipseNode> generateFields(SingularData data, EclipseNode builderType);
+ public abstract void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain);
+ public abstract void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName);
+
+ public boolean requiresCleaning() {
+ try {
+ return !getClass().getMethod("appendCleaningCode", SingularData.class, EclipseNode.class, List.class).getDeclaringClass().equals(EclipseSingularizer.class);
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ public void appendCleaningCode(SingularData data, EclipseNode builderType, List<Statement> statements) {
+ }
+
+ // -- Utility methods --
+
+ /**
+ * Adds the requested number of type arguments to the provided type, copying each argument in {@code typeArgs}. If typeArgs is too long, the extra elements are ignored.
+ * If {@code typeArgs} is null or too short, {@code java.lang.Object} will be substituted for each missing type argument.
+ *
+ * @param count The number of type arguments requested.
+ * @param addExtends If {@code true}, all bounds are either '? extends X' or just '?'. If false, the reverse is applied, and '? extends Foo' is converted to Foo, '?' to Object, etc.
+ * @param node Some node in the same AST. Just used to obtain makers and contexts and such.
+ * @param type The type to add generics to.
+ * @param typeArgs the list of type args to clone.
+ * @param source The source annotation that is the root cause of this code generation.
+ */
+ protected TypeReference addTypeArgs(int count, boolean addExtends, EclipseNode node, TypeReference type, List<TypeReference> typeArgs) {
+ TypeReference[] clonedAndFixedArgs = createTypeArgs(count, addExtends, node, typeArgs);
+ if (type instanceof SingleTypeReference) {
+ type = new ParameterizedSingleTypeReference(((SingleTypeReference) type).token, clonedAndFixedArgs, 0, 0L);
+ } else if (type instanceof QualifiedTypeReference) {
+ QualifiedTypeReference qtr = (QualifiedTypeReference) type;
+ TypeReference[][] trs = new TypeReference[qtr.tokens.length][];
+ trs[qtr.tokens.length - 1] = clonedAndFixedArgs;
+ type = new ParameterizedQualifiedTypeReference(((QualifiedTypeReference) type).tokens, trs, 0, NULL_POSS);
+ } else {
+ node.addError("Don't know how to clone-and-parameterize type: " + type);
+ }
+
+ return type;
+ }
+
+ protected TypeReference[] createTypeArgs(int count, boolean addExtends, EclipseNode node, List<TypeReference> typeArgs) {
+ if (count < 0) throw new IllegalArgumentException("count is negative");
+ if (count == 0) return null;
+ List<TypeReference> arguments = new ArrayList<TypeReference>();
+
+ if (typeArgs != null) for (TypeReference orig : typeArgs) {
+ Wildcard wildcard = orig instanceof Wildcard ? (Wildcard) orig : null;
+ if (!addExtends) {
+ if (wildcard != null && (wildcard.kind == Wildcard.UNBOUND || wildcard.kind == Wildcard.SUPER)) {
+ arguments.add(new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS));
+ } else if (wildcard != null && wildcard.kind == Wildcard.EXTENDS) {
+ try {
+ arguments.add(copyType(wildcard.bound));
+ } catch (Exception e) {
+ arguments.add(new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS));
+ }
+ } else {
+ arguments.add(copyType(orig));
+ }
+ } else {
+ if (wildcard != null && (wildcard.kind == Wildcard.UNBOUND || wildcard.kind == Wildcard.SUPER)) {
+ Wildcard w = new Wildcard(Wildcard.UNBOUND);
+ arguments.add(w);
+ } else if (wildcard != null && wildcard.kind == Wildcard.EXTENDS) {
+ arguments.add(copyType(orig));
+ } else {
+ Wildcard w = new Wildcard(Wildcard.EXTENDS);
+ w.bound = copyType(orig);
+ arguments.add(w);
+ }
+ }
+ if (--count == 0) break;
+ }
+
+ while (count-- > 0) {
+ if (addExtends) {
+ arguments.add(new Wildcard(Wildcard.UNBOUND));
+ } else {
+ arguments.add(new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS));
+ }
+ }
+
+ if (arguments.isEmpty()) return null;
+ return arguments.toArray(new TypeReference[arguments.size()]);
+ }
+
+ private static final char[] SIZE_TEXT = new char[] {'s', 'i', 'z', 'e'};
+
+ /** Generates 'this.<em>name</em>.size()' as an expression; if nullGuard is true, it's this.name == null ? 0 : this.name.size(). */
+ protected Expression getSize(EclipseNode builderType, char[] name, boolean nullGuard) {
+ MessageSend invoke = new MessageSend();
+ ThisReference thisRef = new ThisReference(0, 0);
+ FieldReference thisDotName = new FieldReference(name, 0L);
+ thisDotName.receiver = thisRef;
+ invoke.receiver = thisDotName;
+ invoke.selector = SIZE_TEXT;
+ if (!nullGuard) return invoke;
+
+ ThisReference cdnThisRef = new ThisReference(0, 0);
+ FieldReference cdnThisDotName = new FieldReference(name, 0L);
+ cdnThisDotName.receiver = cdnThisRef;
+ NullLiteral nullLiteral = new NullLiteral(0, 0);
+ EqualExpression isNull = new EqualExpression(cdnThisDotName, nullLiteral, OperatorIds.EQUAL_EQUAL);
+ IntLiteral zeroLiteral = makeIntLiteral(new char[] {'0'}, null);
+ ConditionalExpression conditional = new ConditionalExpression(isNull, zeroLiteral, invoke);
+ return conditional;
+ }
+
+ protected TypeReference cloneParamType(int index, List<TypeReference> typeArgs, EclipseNode builderType) {
+ if (typeArgs != null && typeArgs.size() > index) {
+ TypeReference originalType = typeArgs.get(index);
+ if (originalType instanceof Wildcard) {
+ Wildcard wOriginalType = (Wildcard) originalType;
+ if (wOriginalType.kind == Wildcard.EXTENDS) {
+ try {
+ return copyType(wOriginalType.bound);
+ } catch (Exception e) {
+ // fallthrough
+ }
+ }
+ } else {
+ return copyType(originalType);
+ }
+ }
+
+ return new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, NULL_POSS);
+ }
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilder.java b/src/core/lombok/eclipse/handlers/HandleBuilder.java
index 522501f6..d4cdc654 100644
--- a/src/core/lombok/eclipse/handlers/HandleBuilder.java
+++ b/src/core/lombok/eclipse/handlers/HandleBuilder.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
@@ -32,53 +32,132 @@ import java.util.List;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.AbstractVariableDeclaration;
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.Assignment;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
import org.eclipse.jdt.internal.compiler.ast.MessageSend;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedThisReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeParameter;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.ast.UnaryExpression;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodScope;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.mangosdk.spi.ProviderFor;
import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Builder.ObtainVia;
import lombok.ConfigurationKeys;
+import lombok.Singular;
import lombok.core.AST.Kind;
+import lombok.core.handlers.HandlerUtil;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
import lombok.eclipse.handlers.HandleConstructor.SkipIfConstructorExists;
-import lombok.experimental.Builder;
import lombok.experimental.NonFinal;
@ProviderFor(EclipseAnnotationHandler.class)
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
- @Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
- handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
+ private static final char[] CLEAN_FIELD_NAME = "$lombokUnclean".toCharArray();
+ private static final char[] CLEAN_METHOD_NAME = "$lombokClean".toCharArray();
+
+ private static final boolean toBoolean(Object expr, boolean defaultValue) {
+ if (expr == null) return defaultValue;
+ if (expr instanceof FalseLiteral) return false;
+ if (expr instanceof TrueLiteral) return true;
+ return ((Boolean) expr).booleanValue();
+ }
+
+ private static class BuilderFieldData {
+ TypeReference type;
+ char[] rawName;
+ char[] name;
+ char[] nameOfDefaultProvider;
+ char[] nameOfSetFlag;
+ SingularData singularData;
+ ObtainVia obtainVia;
+ EclipseNode obtainViaNode;
+ EclipseNode originalFieldNode;
+ List<EclipseNode> createdFields = new ArrayList<EclipseNode>();
+ }
+
+ private static boolean equals(String a, char[] b) {
+ if (a.length() != b.length) return false;
+ for (int i = 0; i < b.length; i++) {
+ if (a.charAt(i) != b[i]) return false;
+ }
+ return true;
+ }
+
+ private static boolean equals(String a, char[][] b) {
+ if (a == null || a.isEmpty()) return b.length == 0;
+ String[] aParts = a.split("\\.");
+ if (aParts.length != b.length) return false;
+ for (int i = 0; i < b.length; i++) {
+ if (!equals(aParts[i], b[i])) return false;
+ }
+ return true;
+ }
+
+ private static final char[] DEFAULT_PREFIX = {'$', 'd', 'e', 'f', 'a', 'u', 'l', 't', '$'};
+ private static final char[] SET_PREFIX = {'$', 's', 'e', 't'};
+
+ private static final char[] prefixWith(char[] prefix, char[] name) {
+ char[] out = new char[prefix.length + name.length];
+ System.arraycopy(prefix, 0, out, 0, prefix.length);
+ System.arraycopy(name, 0, out, prefix.length, name.length);
+ return out;
+ }
+
+ @Override public void handle(AnnotationValues<Builder> annotation, Annotation ast, EclipseNode annotationNode) {
long p = (long) ast.sourceStart << 32 | ast.sourceEnd;
Builder builderInstance = annotation.getInstance();
+
+ // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
+ boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
+ boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
+
String builderMethodName = builderInstance.builderMethodName();
String buildMethodName = builderInstance.buildMethodName();
String builderClassName = builderInstance.builderClassName();
+ String toBuilderMethodName = "toBuilder";
+ boolean toBuilder = builderInstance.toBuilder();
+ List<char[]> typeArgsForToBuilder = null;
if (builderMethodName == null) builderMethodName = "builder";
if (buildMethodName == null) builderMethodName = "build";
@@ -92,36 +171,64 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
EclipseNode parent = annotationNode.up();
- List<TypeReference> typesOfParameters = new ArrayList<TypeReference>();
- List<char[]> namesOfParameters = new ArrayList<char[]>();
+ List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
TypeReference returnType;
TypeParameter[] typeParams;
TypeReference[] thrownExceptions;
char[] nameOfStaticBuilderMethod;
EclipseNode tdParent;
- AbstractMethodDeclaration fillParametersFrom = null;
+ EclipseNode fillParametersFrom = parent.get() instanceof AbstractMethodDeclaration ? parent : null;
+ boolean addCleaning = false;
+ boolean isStatic = true;
if (parent.get() instanceof TypeDeclaration) {
tdParent = parent;
TypeDeclaration td = (TypeDeclaration) tdParent.get();
- List<EclipseNode> fields = new ArrayList<EclipseNode>();
- @SuppressWarnings("deprecation")
- boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
- for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
+ List<EclipseNode> allFields = new ArrayList<EclipseNode>();
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (EclipseNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
- // final fields with an initializer cannot be written to, so they can't be 'builderized'. Unfortunately presence of @Value makes
- // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves.
- // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
- if (fd.initialization != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
- namesOfParameters.add(removePrefixFromField(fieldNode));
- typesOfParameters.add(fd.type);
- fields.add(fieldNode);
+ EclipseNode isDefault = findAnnotation(Builder.Default.class, fieldNode);
+ boolean isFinal = ((fd.modifiers & ClassFileConstants.AccFinal) != 0) || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
+
+ BuilderFieldData bfd = new BuilderFieldData();
+ bfd.rawName = fieldNode.getName().toCharArray();
+ bfd.name = removePrefixFromField(fieldNode);
+ bfd.type = fd.type;
+ bfd.singularData = getSingularData(fieldNode, ast);
+ bfd.originalFieldNode = fieldNode;
+
+ if (bfd.singularData != null && isDefault != null) {
+ isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
+ isDefault = null;
+ }
+
+ if (fd.initialization == null && isDefault != null) {
+ isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
+ isDefault = null;
+ }
+
+ if (fd.initialization != null && isDefault == null) {
+ if (isFinal) continue;
+ fieldNode.addWarning("@Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
+ }
+
+ if (isDefault != null) {
+ bfd.nameOfDefaultProvider = prefixWith(DEFAULT_PREFIX, bfd.name);
+ bfd.nameOfSetFlag = prefixWith(bfd.name, SET_PREFIX);
+
+ MethodDeclaration md = generateDefaultProvider(bfd.nameOfDefaultProvider, td.typeParameters, fieldNode, ast);
+ if (md != null) injectMethod(tdParent, md);
+ }
+ addObtainVia(bfd, fieldNode);
+ builderFields.add(bfd);
+ allFields.add(fieldNode);
}
- new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, fields, null, SkipIfConstructorExists.I_AM_BUILDER, null,
- Collections.<Annotation>emptyList(), annotationNode);
+ handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, allFields, false, null, SkipIfConstructorExists.I_AM_BUILDER,
+ Collections.<Annotation>emptyList(), annotationNode);
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
typeParams = td.typeParameters;
@@ -137,7 +244,6 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
tdParent = parent.up();
TypeDeclaration td = (TypeDeclaration) tdParent.get();
- fillParametersFrom = cd;
returnType = namePlusTypeParamsToTypeReference(td.name, td.typeParameters, p);
typeParams = td.typeParameters;
thrownExceptions = cd.thrownExceptions;
@@ -146,11 +252,79 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
} else if (parent.get() instanceof MethodDeclaration) {
MethodDeclaration md = (MethodDeclaration) parent.get();
tdParent = parent.up();
- if (!md.isStatic()) {
- annotationNode.addError("@Builder is only supported on types, constructors, and static methods.");
- return;
+ isStatic = md.isStatic();
+
+ if (toBuilder) {
+ final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+ char[] token;
+ char[][] pkg = null;
+ if (md.returnType.dimensions() > 0) {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ if (md.returnType instanceof SingleTypeReference) {
+ token = ((SingleTypeReference) md.returnType).token;
+ } else if (md.returnType instanceof QualifiedTypeReference) {
+ pkg = ((QualifiedTypeReference) md.returnType).tokens;
+ token = pkg[pkg.length];
+ char[][] pkg_ = new char[pkg.length - 1][];
+ System.arraycopy(pkg, 0, pkg_, 0, pkg_.length);
+ pkg = pkg_;
+ } else {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ if (pkg != null && !equals(parent.getPackageDeclaration(), pkg)) {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ if (tdParent == null || !equals(tdParent.getName(), token)) {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ TypeParameter[] tpOnType = ((TypeDeclaration) tdParent.get()).typeParameters;
+ TypeParameter[] tpOnMethod = md.typeParameters;
+ TypeReference[][] tpOnRet_ = null;
+ if (md.returnType instanceof ParameterizedSingleTypeReference) {
+ tpOnRet_ = new TypeReference[1][];
+ tpOnRet_[0] = ((ParameterizedSingleTypeReference) md.returnType).typeArguments;
+ } else if (md.returnType instanceof ParameterizedQualifiedTypeReference) {
+ tpOnRet_ = ((ParameterizedQualifiedTypeReference) md.returnType).typeArguments;
+ }
+
+ if (tpOnRet_ != null) for (int i = 0; i < tpOnRet_.length - 1; i++) {
+ if (tpOnRet_[i] != null && tpOnRet_[i].length > 0) {
+ annotationNode.addError("@Builder(toBuilder=true) is not supported if returning a type with generics applied to an intermediate.");
+ return;
+ }
+ }
+ TypeReference[] tpOnRet = tpOnRet_ == null ? null : tpOnRet_[tpOnRet_.length - 1];
+ typeArgsForToBuilder = new ArrayList<char[]>();
+
+ // Every typearg on this method needs to be found in the return type, but the reverse is not true.
+ // We also need to 'map' them.
+
+
+ if (tpOnMethod != null) for (TypeParameter onMethod : tpOnMethod) {
+ int pos = -1;
+ if (tpOnRet != null) for (int i = 0; i < tpOnRet.length; i++) {
+ if (tpOnRet[i].getClass() != SingleTypeReference.class) continue;
+ if (!Arrays.equals(((SingleTypeReference) tpOnRet[i]).token, onMethod.name)) continue;
+ pos = i;
+ }
+ if (pos == -1 || tpOnType == null || tpOnType.length <= pos) {
+ annotationNode.addError("@Builder(toBuilder=true) requires that each type parameter on the static method is part of the typeargs of the return value. Type parameter " + new String(onMethod.name) + " is not part of the return type.");
+ return;
+ }
+
+ typeArgsForToBuilder.add(tpOnType[pos].name);
+ }
}
- fillParametersFrom = md;
+
returnType = copyType(md.returnType, ast);
typeParams = md.typeParameters;
thrownExceptions = md.thrownExceptions;
@@ -185,159 +359,373 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
builderClassName = new String(token) + "Builder";
}
} else {
- annotationNode.addError("@Builder is only supported on types, constructors, and static methods.");
+ annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
return;
}
if (fillParametersFrom != null) {
- if (fillParametersFrom.arguments != null) for (Argument a : fillParametersFrom.arguments) {
- namesOfParameters.add(a.name);
- typesOfParameters.add(a.type);
+ for (EclipseNode param : fillParametersFrom.down()) {
+ if (param.getKind() != Kind.ARGUMENT) continue;
+ BuilderFieldData bfd = new BuilderFieldData();
+ Argument arg = (Argument) param.get();
+ bfd.rawName = arg.name;
+ bfd.name = arg.name;
+ bfd.type = arg.type;
+ bfd.singularData = getSingularData(param, ast);
+ bfd.originalFieldNode = param;
+ addObtainVia(bfd, param);
+ builderFields.add(bfd);
}
}
EclipseNode builderType = findInnerClass(tdParent, builderClassName);
if (builderType == null) {
- builderType = makeBuilderClass(tdParent, builderClassName, typeParams, ast);
+ builderType = makeBuilderClass(isStatic, tdParent, builderClassName, typeParams, ast);
} else {
+ TypeDeclaration builderTypeDeclaration = (TypeDeclaration) builderType.get();
+ if (isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) == 0) {
+ annotationNode.addError("Existing Builder must be a static inner class.");
+ return;
+ } else if (!isStatic && (builderTypeDeclaration.modifiers & ClassFileConstants.AccStatic) != 0) {
+ annotationNode.addError("Existing Builder must be a non-static inner class.");
+ return;
+ }
sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ /* generate errors for @Singular BFDs that have one already defined node. */ {
+ for (BuilderFieldData bfd : builderFields) {
+ SingularData sd = bfd.singularData;
+ if (sd == null) continue;
+ EclipseSingularizer singularizer = sd.getSingularizer();
+ if (singularizer == null) continue;
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ bfd.singularData = null;
+ }
+ }
+ }
+ }
+
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ if (bfd.singularData.getSingularizer().requiresCleaning()) {
+ addCleaning = true;
+ break;
+ }
+ }
+ if (bfd.obtainVia != null) {
+ if (bfd.obtainVia.field().isEmpty() == bfd.obtainVia.method().isEmpty()) {
+ bfd.obtainViaNode.addError("The syntax is either @ObtainVia(field = \"fieldName\") or @ObtainVia(method = \"methodName\").");
+ return;
+ }
+ if (bfd.obtainVia.method().isEmpty() && bfd.obtainVia.isStatic()) {
+ bfd.obtainViaNode.addError("@ObtainVia(isStatic = true) is not valid unless 'method' has been set.");
+ return;
+ }
+ }
}
- List<EclipseNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast);
- List<AbstractMethodDeclaration> newMethods = new ArrayList<AbstractMethodDeclaration>();
- for (EclipseNode fieldNode : fieldNodes) {
- MethodDeclaration newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, builderInstance.fluent(), builderInstance.chain());
- if (newMethod != null) newMethods.add(newMethod);
+
+ generateBuilderFields(builderType, builderFields, ast);
+ if (addCleaning) {
+ FieldDeclaration cleanDecl = new FieldDeclaration(CLEAN_FIELD_NAME, 0, -1);
+ cleanDecl.declarationSourceEnd = -1;
+ cleanDecl.modifiers = ClassFileConstants.AccPrivate;
+ cleanDecl.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
+ injectFieldAndMarkGenerated(builderType, cleanDecl);
}
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
ConstructorDeclaration cd = HandleConstructor.createConstructor(
- AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), null,
- annotationNode, Collections.<Annotation>emptyList());
+ AccessLevel.PACKAGE, builderType, Collections.<EclipseNode>emptyList(), false,
+ annotationNode, Collections.<Annotation>emptyList());
if (cd != null) injectMethod(builderType, cd);
}
- for (AbstractMethodDeclaration newMethod : newMethods) injectMethod(builderType, newMethod);
+ for (BuilderFieldData bfd : builderFields) {
+ makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain);
+ }
+
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuildMethod(buildMethodName, nameOfStaticBuilderMethod, returnType, namesOfParameters, builderType, ast, thrownExceptions);
+ MethodDeclaration md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfStaticBuilderMethod, returnType, builderFields, builderType, thrownExceptions, addCleaning, ast);
if (md != null) injectMethod(builderType, md);
}
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ List<EclipseNode> fieldNodes = new ArrayList<EclipseNode>();
+ for (BuilderFieldData bfd : builderFields) {
+ fieldNodes.addAll(bfd.createdFields);
+ }
MethodDeclaration md = HandleToString.createToString(builderType, fieldNodes, true, false, ast, FieldAccess.ALWAYS_FIELD);
if (md != null) injectMethod(builderType, md);
}
+ if (addCleaning) {
+ MethodDeclaration cleanMethod = generateCleanMethod(builderFields, builderType, ast);
+ if (cleanMethod != null) injectMethod(builderType, cleanMethod);
+ }
+
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
- MethodDeclaration md = generateBuilderMethod(builderMethodName, builderClassName, tdParent, typeParams, ast);
+ MethodDeclaration md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, tdParent, typeParams, ast);
+ if (md != null) injectMethod(tdParent, md);
+ }
+
+ if (toBuilder) switch (methodExists(toBuilderMethodName, tdParent, 0)) {
+ case EXISTS_BY_USER:
+ annotationNode.addWarning("Not generating toBuilder() as it already exists.");
+ break;
+ case NOT_EXISTS:
+ TypeParameter[] tps = typeParams;
+ if (typeArgsForToBuilder != null) {
+ tps = new TypeParameter[typeArgsForToBuilder.size()];
+ for (int i = 0; i < tps.length; i++) {
+ tps[i] = new TypeParameter();
+ tps[i].name = typeArgsForToBuilder.get(i);
+ }
+ }
+ MethodDeclaration md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast);
+
if (md != null) injectMethod(tdParent, md);
}
}
- public MethodDeclaration generateBuilderMethod(String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
+ private MethodDeclaration generateToBuilderMethod(String methodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, List<BuilderFieldData> builderFields, boolean fluent, ASTNode source) {
+ // return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
+
int pS = source.sourceStart, pE = source.sourceEnd;
long p = (long) pS << 32 | pE;
MethodDeclaration out = new MethodDeclaration(
((CompilationUnitDeclaration) type.top().get()).compilationResult);
- out.selector = builderMethodName.toCharArray();
- out.modifiers = ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
+ out.selector = methodName.toCharArray();
+ out.modifiers = ClassFileConstants.AccPublic;
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
- out.typeParameters = copyTypeParams(typeParams, source);
AllocationExpression invoke = new AllocationExpression();
invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
- out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
+
+ Expression receiver = invoke;
+ for (BuilderFieldData bfd : builderFields) {
+ char[] setterName = fluent ? bfd.name : HandlerUtil.buildAccessorName("set", new String(bfd.name)).toCharArray();
+ MessageSend ms = new MessageSend();
+ if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
+ char[] fieldName = bfd.obtainVia == null ? bfd.rawName : bfd.obtainVia.field().toCharArray();
+ FieldReference fr = new FieldReference(fieldName, 0);
+ fr.receiver = new ThisReference(0, 0);
+ ms.arguments = new Expression[] {fr};
+ } else {
+ String obtainName = bfd.obtainVia.method();
+ boolean obtainIsStatic = bfd.obtainVia.isStatic();
+ MessageSend obtainExpr = new MessageSend();
+ obtainExpr.receiver = obtainIsStatic ? new SingleNameReference(type.getName().toCharArray(), 0) : new ThisReference(0, 0);
+ obtainExpr.selector = obtainName.toCharArray();
+ if (obtainIsStatic) obtainExpr.arguments = new Expression[] {new ThisReference(0, 0)};
+ ms.arguments = new Expression[] {obtainExpr};
+ }
+ ms.receiver = receiver;
+ ms.selector = setterName;
+ receiver = ms;
+ }
+
+ out.statements = new Statement[] {new ReturnStatement(receiver, pS, pE)};
out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
return out;
+
}
- public MethodDeclaration generateBuildMethod(String name, char[] staticName, TypeReference returnType, List<char[]> fieldNames, EclipseNode type, ASTNode source, TypeReference[] thrownExceptions) {
- int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long) pS << 32 | pE;
+ private MethodDeclaration generateCleanMethod(List<BuilderFieldData> builderFields, EclipseNode builderType, ASTNode source) {
+ List<Statement> statements = new ArrayList<Statement>();
- MethodDeclaration out = new MethodDeclaration(
- ((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, builderType, statements);
+ }
+ }
- out.modifiers = ClassFileConstants.AccPublic;
- TypeDeclaration typeDecl = (TypeDeclaration) type.get();
- out.selector = name.toCharArray();
- out.thrownExceptions = copyTypes(thrownExceptions, source);
+ FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
+ thisUnclean.receiver = new ThisReference(0, 0);
+ statements.add(new Assignment(thisUnclean, new FalseLiteral(0, 0), 0));
+ MethodDeclaration decl = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ decl.selector = CLEAN_METHOD_NAME;
+ decl.modifiers = ClassFileConstants.AccPrivate;
+ decl.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ decl.returnType = TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ decl.statements = statements.toArray(new Statement[0]);
+ decl.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ return decl;
+ }
+
+ public MethodDeclaration generateBuildMethod(EclipseNode tdParent, boolean isStatic, String name, char[] staticName, TypeReference returnType, List<BuilderFieldData> builderFields, EclipseNode type, TypeReference[] thrownExceptions, boolean addCleaning, ASTNode source) {
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- out.returnType = returnType;
+ List<Statement> statements = new ArrayList<Statement>();
+
+ if (addCleaning) {
+ FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
+ thisUnclean.receiver = new ThisReference(0, 0);
+ Expression notClean = new UnaryExpression(thisUnclean, OperatorIds.NOT);
+ MessageSend invokeClean = new MessageSend();
+ invokeClean.selector = CLEAN_METHOD_NAME;
+ statements.add(new IfStatement(notClean, invokeClean, 0, 0));
+ }
+
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, statements, bfd.name);
+ }
+ }
+
+ List<Expression> args = new ArrayList<Expression>();
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.nameOfSetFlag != null) {
+ MessageSend inv = new MessageSend();
+ inv.sourceStart = source.sourceStart;
+ inv.sourceEnd = source.sourceEnd;
+ inv.receiver = new SingleNameReference(((TypeDeclaration) tdParent.get()).name, 0L);
+ inv.selector = bfd.nameOfDefaultProvider;
+ inv.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+
+ args.add(new ConditionalExpression(
+ new SingleNameReference(bfd.nameOfSetFlag, 0L),
+ new SingleNameReference(bfd.name, 0L),
+ inv));
+ } else {
+ args.add(new SingleNameReference(bfd.name, 0L));
+ }
+ }
- List<Expression> assigns = new ArrayList<Expression>();
- for (char[] fieldName : fieldNames) {
- SingleNameReference nameRef = new SingleNameReference(fieldName, p);
- assigns.add(nameRef);
+ if (addCleaning) {
+ FieldReference thisUnclean = new FieldReference(CLEAN_FIELD_NAME, 0);
+ thisUnclean.receiver = new ThisReference(0, 0);
+ statements.add(new Assignment(thisUnclean, new TrueLiteral(0, 0), 0));
}
- Statement statement;
+ out.modifiers = ClassFileConstants.AccPublic;
+ out.selector = name.toCharArray();
+ out.thrownExceptions = copyTypes(thrownExceptions);
+ out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ out.returnType = returnType;
if (staticName == null) {
AllocationExpression allocationStatement = new AllocationExpression();
- allocationStatement.type = copyType(out.returnType, source);
- allocationStatement.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
- statement = new ReturnStatement(allocationStatement, (int)(p >> 32), (int)p);
+ allocationStatement.type = copyType(out.returnType);
+ allocationStatement.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]);
+ statements.add(new ReturnStatement(allocationStatement, 0, 0));
} else {
MessageSend invoke = new MessageSend();
invoke.selector = staticName;
- invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), p);
- TypeParameter[] tps = ((TypeDeclaration) type.get()).typeParameters;
- if (tps != null) {
- TypeReference[] trs = new TypeReference[tps.length];
- for (int i = 0; i < trs.length; i++) {
- trs[i] = new SingleTypeReference(tps[i].name, p);
- }
- invoke.typeArguments = trs;
- }
- invoke.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
+ if (isStatic)
+ invoke.receiver = new SingleNameReference(type.up().getName().toCharArray(), 0);
+ else
+ invoke.receiver = new QualifiedThisReference(new SingleTypeReference(type.up().getName().toCharArray(), 0) , 0, 0);
+
+ invoke.typeArguments = typeParameterNames(((TypeDeclaration) type.get()).typeParameters);
+ invoke.arguments = args.isEmpty() ? null : args.toArray(new Expression[args.size()]);
if (returnType instanceof SingleTypeReference && Arrays.equals(TypeConstants.VOID, ((SingleTypeReference) returnType).token)) {
- statement = invoke;
+ statements.add(invoke);
} else {
- statement = new ReturnStatement(invoke, (int)(p >> 32), (int)p);
+ statements.add(new ReturnStatement(invoke, 0, 0));
}
}
+ out.statements = statements.isEmpty() ? null : statements.toArray(new Statement[statements.size()]);
+ out.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
+ return out;
+ }
+
+ private TypeReference[] typeParameterNames(TypeParameter[] typeParameters) {
+ if (typeParameters == null) return null;
- out.statements = new Statement[] { statement };
+ TypeReference[] trs = new TypeReference[typeParameters.length];
+ for (int i = 0; i < trs.length; i++) {
+ trs[i] = new SingleTypeReference(typeParameters[i].name, 0);
+ }
+ return trs;
+ }
+
+ public MethodDeclaration generateDefaultProvider(char[] methodName, TypeParameter[] typeParameters, EclipseNode fieldNode, ASTNode source) {
+ int pS = source.sourceStart, pE = source.sourceEnd;
+
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) fieldNode.top().get()).compilationResult);
+ out.typeParameters = copyTypeParams(typeParameters, source);
+ out.selector = methodName;
+ out.modifiers = ClassFileConstants.AccPrivate | ClassFileConstants.AccStatic;
+ out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ FieldDeclaration fd = (FieldDeclaration) fieldNode.get();
+ out.returnType = copyType(fd.type, source);
+ out.statements = new Statement[] {new ReturnStatement(fd.initialization, pS, pE)};
+ fd.initialization = null;
- out.traverse(new SetGeneratedByVisitor(source), typeDecl.scope);
+ out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) fieldNode.up().get()).scope);
return out;
}
- public List<EclipseNode> addFieldsToBuilder(EclipseNode builderType, List<char[]> namesOfParameters, List<TypeReference> typesOfParameters, ASTNode source) {
- int len = namesOfParameters.size();
- TypeDeclaration td = (TypeDeclaration) builderType.get();
- FieldDeclaration[] existing = td.fields;
- if (existing == null) existing = new FieldDeclaration[0];
-
- List<EclipseNode> out = new ArrayList<EclipseNode>();
-
- top:
- for (int i = len - 1; i >= 0; i--) {
- char[] name = namesOfParameters.get(i);
- for (FieldDeclaration exists : existing) {
- if (Arrays.equals(exists.name, name)) {
- out.add(builderType.getNodeFor(exists));
- continue top;
- }
- }
- TypeReference fieldReference = copyType(typesOfParameters.get(i), source);
- FieldDeclaration newField = new FieldDeclaration(name, 0, 0);
- newField.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
- newField.modifiers = ClassFileConstants.AccPrivate;
- newField.type = fieldReference;
- out.add(injectField(builderType, newField));
- }
+ public MethodDeclaration generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, EclipseNode type, TypeParameter[] typeParams, ASTNode source) {
+ int pS = source.sourceStart, pE = source.sourceEnd;
+ long p = (long) pS << 32 | pE;
- Collections.reverse(out);
+ MethodDeclaration out = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ out.selector = builderMethodName.toCharArray();
+ out.modifiers = ClassFileConstants.AccPublic;
+ if (isStatic) out.modifiers |= ClassFileConstants.AccStatic;
+ out.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ out.returnType = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
+ out.typeParameters = copyTypeParams(typeParams, source);
+ AllocationExpression invoke = new AllocationExpression();
+ invoke.type = namePlusTypeParamsToTypeReference(builderClassName.toCharArray(), typeParams, p);
+ out.statements = new Statement[] {new ReturnStatement(invoke, pS, pE)};
+ out.traverse(new SetGeneratedByVisitor(source), ((TypeDeclaration) type.get()).scope);
return out;
}
+ public void generateBuilderFields(EclipseNode builderType, List<BuilderFieldData> builderFields, ASTNode source) {
+ List<EclipseNode> existing = new ArrayList<EclipseNode>();
+ for (EclipseNode child : builderType.down()) {
+ if (child.getKind() == Kind.FIELD) existing.add(child);
+ }
+
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType));
+ } else {
+ EclipseNode field = null, setFlag = null;
+ for (EclipseNode exists : existing) {
+ char[] n = ((FieldDeclaration) exists.get()).name;
+ if (Arrays.equals(n, bfd.name)) field = exists;
+ if (bfd.nameOfSetFlag != null && Arrays.equals(n, bfd.nameOfSetFlag)) setFlag = exists;
+ }
+
+ if (field == null) {
+ FieldDeclaration fd = new FieldDeclaration(bfd.name, 0, 0);
+ fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ fd.modifiers = ClassFileConstants.AccPrivate;
+ fd.type = copyType(bfd.type);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
+ field = injectFieldAndMarkGenerated(builderType, fd);
+ }
+ if (setFlag == null && bfd.nameOfSetFlag != null) {
+ FieldDeclaration fd = new FieldDeclaration(bfd.nameOfSetFlag, 0, 0);
+ fd.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+ fd.modifiers = ClassFileConstants.AccPrivate;
+ fd.type = TypeReference.baseTypeReference(TypeIds.T_boolean, 0);
+ fd.traverse(new SetGeneratedByVisitor(source), (MethodScope) null);
+ injectFieldAndMarkGenerated(builderType, fd);
+ }
+ bfd.createdFields.add(field);
+ }
+ }
+ }
+
private static final AbstractMethodDeclaration[] EMPTY = {};
- public MethodDeclaration makeSetterMethodForBuilder(EclipseNode builderType, EclipseNode fieldNode, EclipseNode sourceNode, boolean fluent, boolean chain) {
+ public void makeSetterMethodsForBuilder(EclipseNode builderType, BuilderFieldData bfd, EclipseNode sourceNode, boolean fluent, boolean chain) {
+ boolean deprecate = isFieldDeprecated(bfd.originalFieldNode);
+ if (bfd.singularData == null || bfd.singularData.getSingularizer() == null) {
+ makeSimpleSetterMethodForBuilder(builderType, deprecate, bfd.createdFields.get(0), bfd.nameOfSetFlag, sourceNode, fluent, chain);
+ } else {
+ bfd.singularData.getSingularizer().generateMethods(bfd.singularData, deprecate, builderType, fluent, chain);
+ }
+ }
+
+ private void makeSimpleSetterMethodForBuilder(EclipseNode builderType, boolean deprecate, EclipseNode fieldNode, char[] nameOfSetFlag, EclipseNode sourceNode, boolean fluent, boolean chain) {
TypeDeclaration td = (TypeDeclaration) builderType.get();
AbstractMethodDeclaration[] existing = td.methods;
if (existing == null) existing = EMPTY;
@@ -348,14 +736,14 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
for (int i = 0; i < len; i++) {
if (!(existing[i] instanceof MethodDeclaration)) continue;
char[] existingName = existing[i].selector;
- if (Arrays.equals(name, existingName)) return null;
+ if (Arrays.equals(name, existingName) && !isTolerate(fieldNode, existing[i])) return;
}
- boolean isBoolean = isBoolean(fd.type);
- String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
+ String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
- return HandleSetter.createSetter(td, fieldNode, setterName, chain, ClassFileConstants.AccPublic,
- sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
+ MethodDeclaration setter = HandleSetter.createSetter(td, deprecate, fieldNode, setterName, nameOfSetFlag, chain, ClassFileConstants.AccPublic,
+ sourceNode, Collections.<Annotation>emptyList(), Collections.<Annotation>emptyList());
+ injectMethod(builderType, setter);
}
public EclipseNode findInnerClass(EclipseNode parent, String name) {
@@ -368,14 +756,84 @@ public class HandleBuilder extends EclipseAnnotationHandler<Builder> {
return null;
}
- public EclipseNode makeBuilderClass(EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source) {
+ public EclipseNode makeBuilderClass(boolean isStatic, EclipseNode tdParent, String builderClassName, TypeParameter[] typeParams, ASTNode source) {
TypeDeclaration parent = (TypeDeclaration) tdParent.get();
TypeDeclaration builder = new TypeDeclaration(parent.compilationResult);
builder.bits |= Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
- builder.modifiers |= ClassFileConstants.AccPublic | ClassFileConstants.AccStatic;
+ builder.modifiers |= ClassFileConstants.AccPublic;
+ if (isStatic) builder.modifiers |= ClassFileConstants.AccStatic;
builder.typeParameters = copyTypeParams(typeParams, source);
builder.name = builderClassName.toCharArray();
builder.traverse(new SetGeneratedByVisitor(source), (ClassScope) null);
return injectType(tdParent, builder);
}
+
+ private void addObtainVia(BuilderFieldData bfd, EclipseNode node) {
+ for (EclipseNode child : node.down()) {
+ if (!annotationTypeMatches(ObtainVia.class, child)) continue;
+ AnnotationValues<ObtainVia> ann = createAnnotation(ObtainVia.class, child);
+ bfd.obtainVia = ann.getInstance();
+ bfd.obtainViaNode = child;
+ return;
+ }
+ }
+
+ /**
+ * Returns the explicitly requested singular annotation on this node (field
+ * or parameter), or null if there's no {@code @Singular} annotation on it.
+ *
+ * @param node The node (field or method param) to inspect for its name and potential {@code @Singular} annotation.
+ */
+ private SingularData getSingularData(EclipseNode node, ASTNode source) {
+ for (EclipseNode child : node.down()) {
+ if (!annotationTypeMatches(Singular.class, child)) continue;
+ char[] pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((AbstractVariableDeclaration) node.get()).name;
+ AnnotationValues<Singular> ann = createAnnotation(Singular.class, child);
+ String explicitSingular = ann.getInstance().value();
+ if (explicitSingular.isEmpty()) {
+ if (Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_AUTO))) {
+ node.addError("The singular must be specified explicitly (e.g. @Singular(\"task\")) because auto singularization is disabled.");
+ explicitSingular = new String(pluralName);
+ } else {
+ explicitSingular = autoSingularize(new String(pluralName));
+ if (explicitSingular == null) {
+ node.addError("Can't singularize this name; please specify the singular explicitly (i.e. @Singular(\"sheep\"))");
+ explicitSingular = new String(pluralName);
+ }
+ }
+ }
+ char[] singularName = explicitSingular.toCharArray();
+
+ TypeReference type = ((AbstractVariableDeclaration) node.get()).type;
+ TypeReference[] typeArgs = null;
+ String typeName;
+ if (type instanceof ParameterizedSingleTypeReference) {
+ typeArgs = ((ParameterizedSingleTypeReference) type).typeArguments;
+ typeName = new String(((ParameterizedSingleTypeReference) type).token);
+ } else if (type instanceof ParameterizedQualifiedTypeReference) {
+ TypeReference[][] tr = ((ParameterizedQualifiedTypeReference) type).typeArguments;
+ if (tr != null) typeArgs = tr[tr.length - 1];
+ char[][] tokens = ((ParameterizedQualifiedTypeReference) type).tokens;
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < tokens.length; i++) {
+ if (i > 0) sb.append(".");
+ sb.append(tokens[i]);
+ }
+ typeName = sb.toString();
+ } else {
+ typeName = type.toString();
+ }
+
+ String targetFqn = EclipseSingularsRecipes.get().toQualified(typeName);
+ EclipseSingularizer singularizer = EclipseSingularsRecipes.get().getSingularizer(targetFqn);
+ if (singularizer == null) {
+ node.addError("Lombok does not know how to create the singular-form builder methods for type '" + typeName + "'; they won't be generated.");
+ return null;
+ }
+
+ return new SingularData(child, singularName, pluralName, typeArgs == null ? Collections.<TypeReference>emptyList() : Arrays.asList(typeArgs), targetFqn, singularizer, source);
+ }
+
+ return null;
+ }
}
diff --git a/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
new file mode 100644
index 00000000..be2b986d
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleBuilderDefault.java
@@ -0,0 +1,46 @@
+/*
+ * Copyright (C) 2017-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
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers;
+
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.Builder;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+
+@ProviderFor(EclipseAnnotationHandler.class)
+@HandlerPriority(-1025) //HandleBuilder's level, minus one.
+public class HandleBuilderDefault extends EclipseAnnotationHandler<Builder.Default> {
+ @Override public void handle(AnnotationValues<Builder.Default> annotation, Annotation ast, EclipseNode annotationNode) {
+ EclipseNode annotatedField = annotationNode.up();
+ if (annotatedField.getKind() != Kind.FIELD) return;
+ EclipseNode classWithAnnotatedField = annotatedField.up();
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField) && !hasAnnotation("lombok.experimental.Builder", classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder on the class for it to mean anything.");
+ }
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleConstructor.java b/src/core/lombok/eclipse/handlers/HandleConstructor.java
index b72d000f..62e2c18c 100644
--- a/src/core/lombok/eclipse/handlers/HandleConstructor.java
+++ b/src/core/lombok/eclipse/handlers/HandleConstructor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,10 +29,12 @@ import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.ConfigurationKeys;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
@@ -40,21 +42,28 @@ import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
-import lombok.experimental.Builder;
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.Argument;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
+import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.CharLiteral;
import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
import org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.DoubleLiteral;
import org.eclipse.jdt.internal.compiler.ast.ExplicitConstructorCall;
import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FalseLiteral;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.FloatLiteral;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.jdt.internal.compiler.ast.LongLiteral;
import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleMemberAnnotation;
@@ -63,12 +72,16 @@ import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.StringLiteral;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.mangosdk.spi.ProviderFor;
public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleNoArgsConstructor extends EclipseAnnotationHandler<NoArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NO_ARGS_CONSTRUCTOR_FLAG_USAGE, "@NoArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -78,16 +91,20 @@ public class HandleConstructor {
AccessLevel level = ann.access();
String staticName = ann.staticName();
if (level == AccessLevel.NONE) return;
- List<EclipseNode> fields = new ArrayList<EclipseNode>();
- List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode);
+ boolean force = ann.force();
+
+ List<EclipseNode> fields = force ? findFinalFields(typeNode) : Collections.<EclipseNode>emptyList();
+ List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode);
- new HandleConstructor().generateConstructor(typeNode, level, fields, staticName, SkipIfConstructorExists.NO, null, onConstructor, annotationNode);
+ handleConstructor.generateConstructor(typeNode, level, fields, force, staticName, SkipIfConstructorExists.NO, onConstructor, annotationNode);
}
}
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleRequiredArgsConstructor extends EclipseAnnotationHandler<RequiredArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -97,43 +114,51 @@ public class HandleConstructor {
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- Boolean suppressConstructorProperties = null;
if (annotation.isExplicit("suppressConstructorProperties")) {
- @SuppressWarnings("deprecation")
- boolean suppress = ann.suppressConstructorProperties();
- suppressConstructorProperties = suppress;
+ annotationNode.addError("This deprecated feature is no longer supported. Remove it; you can create a lombok.config file with 'lombok.anyConstructor.suppressConstructorProperties = true'.");
}
- List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode);
+ List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor", annotationNode);
- new HandleConstructor().generateConstructor(
- typeNode, level, findRequiredFields(typeNode), staticName, SkipIfConstructorExists.NO,
- suppressConstructorProperties, onConstructor, annotationNode);
+ handleConstructor.generateConstructor(
+ typeNode, level, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO,
+ onConstructor, annotationNode);
}
}
private static List<EclipseNode> findRequiredFields(EclipseNode typeNode) {
+ return findFields(typeNode, true);
+ }
+
+ private static List<EclipseNode> findFinalFields(EclipseNode typeNode) {
+ return findFields(typeNode, false);
+ }
+
+ private static List<EclipseNode> findFields(EclipseNode typeNode, boolean nullMarked) {
List<EclipseNode> fields = new ArrayList<EclipseNode>();
for (EclipseNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
if (!filterField(fieldDecl)) continue;
boolean isFinal = (fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0;
- boolean isNonNull = findAnnotations(fieldDecl, NON_NULL_PATTERN).length != 0;
+ boolean isNonNull = nullMarked && findAnnotations(fieldDecl, NON_NULL_PATTERN).length != 0;
if ((isFinal || isNonNull) && fieldDecl.initialization == null) fields.add(child);
}
return fields;
}
static List<EclipseNode> findAllFields(EclipseNode typeNode) {
+ return findAllFields(typeNode, false);
+ }
+
+ static List<EclipseNode> findAllFields(EclipseNode typeNode, boolean evenFinalInitialized) {
List<EclipseNode> fields = new ArrayList<EclipseNode>();
for (EclipseNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
FieldDeclaration fieldDecl = (FieldDeclaration) child.get();
if (!filterField(fieldDecl)) continue;
- // Skip initialized final fields.
- if (((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) continue;
+ if (!evenFinalInitialized && ((fieldDecl.modifiers & ClassFileConstants.AccFinal) != 0) && fieldDecl.initialization != null) continue;
fields.add(child);
}
@@ -142,6 +167,8 @@ public class HandleConstructor {
@ProviderFor(EclipseAnnotationHandler.class)
public static class HandleAllArgsConstructor extends EclipseAnnotationHandler<AllArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -151,18 +178,15 @@ public class HandleConstructor {
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- Boolean suppressConstructorProperties = null;
if (annotation.isExplicit("suppressConstructorProperties")) {
- @SuppressWarnings("deprecation")
- boolean suppress = ann.suppressConstructorProperties();
- suppressConstructorProperties = suppress;
+ annotationNode.addError("This deprecated feature is no longer supported. Remove it; you can create a lombok.config file with 'lombok.anyConstructor.suppressConstructorProperties = true'.");
}
- List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode);
+ List<Annotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor", annotationNode);
- new HandleConstructor().generateConstructor(
- typeNode, level, findAllFields(typeNode), staticName, SkipIfConstructorExists.NO,
- suppressConstructorProperties, onConstructor, annotationNode);
+ handleConstructor.generateConstructor(
+ typeNode, level, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO,
+ onConstructor, annotationNode);
}
}
@@ -184,14 +208,14 @@ public class HandleConstructor {
EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists,
List<Annotation> onConstructor, EclipseNode sourceNode) {
- generateConstructor(typeNode, level, findRequiredFields(typeNode), staticName, skipIfConstructorExists, null, onConstructor, sourceNode);
+ generateConstructor(typeNode, level, findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode);
}
public void generateAllArgsConstructor(
EclipseNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists,
List<Annotation> onConstructor, EclipseNode sourceNode) {
- generateConstructor(typeNode, level, findAllFields(typeNode), staticName, skipIfConstructorExists, null, onConstructor, sourceNode);
+ generateConstructor(typeNode, level, findAllFields(typeNode), false, staticName, skipIfConstructorExists, onConstructor, sourceNode);
}
public enum SkipIfConstructorExists {
@@ -199,8 +223,8 @@ public class HandleConstructor {
}
public void generateConstructor(
- EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, String staticName, SkipIfConstructorExists skipIfConstructorExists,
- Boolean suppressConstructorProperties, List<Annotation> onConstructor, EclipseNode sourceNode) {
+ EclipseNode typeNode, AccessLevel level, List<EclipseNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists,
+ List<Annotation> onConstructor, EclipseNode sourceNode) {
ASTNode source = sourceNode.get();
boolean staticConstrRequired = staticName != null && !staticName.equals("");
@@ -210,8 +234,8 @@ public class HandleConstructor {
for (EclipseNode child : typeNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
boolean skipGeneration = (annotationTypeMatches(NoArgsConstructor.class, child) ||
- annotationTypeMatches(AllArgsConstructor.class, child) ||
- annotationTypeMatches(RequiredArgsConstructor.class, child));
+ annotationTypeMatches(AllArgsConstructor.class, child) ||
+ annotationTypeMatches(RequiredArgsConstructor.class, child));
if (!skipGeneration && skipIfConstructorExists == SkipIfConstructorExists.YES) {
skipGeneration = annotationTypeMatches(Builder.class, child);
@@ -224,8 +248,8 @@ public class HandleConstructor {
// the 'staticName' parameter of the @XArgsConstructor you've stuck on your type.
// We should warn that we're ignoring @Data's 'staticConstructor' param.
typeNode.addWarning(
- "Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.",
- source.sourceStart, source.sourceEnd);
+ "Ignoring static constructor name: explicit @XxxArgsConstructor annotation present; its `staticName` parameter will be used.",
+ source.sourceStart, source.sourceEnd);
}
return;
}
@@ -234,11 +258,11 @@ public class HandleConstructor {
}
ConstructorDeclaration constr = createConstructor(
- staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields,
- suppressConstructorProperties, sourceNode, onConstructor);
+ staticConstrRequired ? AccessLevel.PRIVATE : level, typeNode, fields, allToDefault,
+ sourceNode, onConstructor);
injectMethod(typeNode, constr);
if (staticConstrRequired) {
- MethodDeclaration staticConstr = createStaticConstructor(level, staticName, typeNode, fields, source);
+ MethodDeclaration staticConstr = createStaticConstructor(level, staticName, typeNode, allToDefault ? Collections.<EclipseNode>emptyList() : fields, source);
injectMethod(typeNode, staticConstr);
}
}
@@ -248,7 +272,7 @@ public class HandleConstructor {
if (fields.isEmpty()) return null;
int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long)pS << 32 | pE;
+ long p = (long) pS << 32 | pE;
long[] poss = new long[3];
Arrays.fill(poss, p);
QualifiedTypeReference constructorPropertiesType = new QualifiedTypeReference(JAVA_BEANS_CONSTRUCTORPROPERTIES, poss);
@@ -275,28 +299,28 @@ public class HandleConstructor {
return new Annotation[] { ann };
}
- public static ConstructorDeclaration createConstructor(
- AccessLevel level, EclipseNode type, Collection<EclipseNode> fields,
- Boolean suppressConstructorProperties, EclipseNode sourceNode, List<Annotation> onConstructor) {
+ @SuppressWarnings("deprecation") public static ConstructorDeclaration createConstructor(
+ AccessLevel level, EclipseNode type, Collection<EclipseNode> fields, boolean allToDefault,
+ EclipseNode sourceNode, List<Annotation> onConstructor) {
ASTNode source = sourceNode.get();
- TypeDeclaration typeDeclaration = ((TypeDeclaration)type.get());
- long p = (long)source.sourceStart << 32 | source.sourceEnd;
+ TypeDeclaration typeDeclaration = ((TypeDeclaration) type.get());
+ long p = (long) source.sourceStart << 32 | source.sourceEnd;
- boolean isEnum = (((TypeDeclaration)type.get()).modifiers & ClassFileConstants.AccEnum) != 0;
+ boolean isEnum = (((TypeDeclaration) type.get()).modifiers & ClassFileConstants.AccEnum) != 0;
if (isEnum) level = AccessLevel.PRIVATE;
- if (suppressConstructorProperties == null) {
- if (fields.isEmpty()) {
- suppressConstructorProperties = false;
- } else {
- suppressConstructorProperties = Boolean.TRUE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
- }
+ boolean addConstructorProperties;
+ if (fields.isEmpty()) {
+ addConstructorProperties = false;
+ } else {
+ Boolean v = type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES);
+ addConstructorProperties = v != null ? v.booleanValue() :
+ Boolean.FALSE.equals(type.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
}
- ConstructorDeclaration constructor = new ConstructorDeclaration(
- ((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(level);
constructor.selector = typeDeclaration.name;
@@ -319,23 +343,27 @@ public class HandleConstructor {
char[] rawName = field.name;
char[] fieldName = removePrefixFromField(fieldNode);
FieldReference thisX = new FieldReference(rawName, p);
- thisX.receiver = new ThisReference((int)(p >> 32), (int)p);
+ int s = (int) (p >> 32);
+ int e = (int) p;
+ thisX.receiver = new ThisReference(s, e);
+
+ Expression assignmentExpr = allToDefault ? getDefaultExpr(field.type, s, e) : new SingleNameReference(fieldName, p);
- SingleNameReference assignmentNameRef = new SingleNameReference(fieldName, p);
- Assignment assignment = new Assignment(thisX, assignmentNameRef, (int)p);
- assignment.sourceStart = (int)(p >> 32); assignment.sourceEnd = assignment.statementEnd = (int)(p >> 32);
+ Assignment assignment = new Assignment(thisX, assignmentExpr, (int) p);
+ assignment.sourceStart = (int) (p >> 32); assignment.sourceEnd = assignment.statementEnd = (int) (p >> 32);
assigns.add(assignment);
- long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd;
- Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source), Modifier.FINAL);
- Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
- Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
- if (nonNulls.length != 0) {
- Statement nullCheck = generateNullCheck(field, sourceNode);
- if (nullCheck != null) nullChecks.add(nullCheck);
+ if (!allToDefault) {
+ long fieldPos = (((long) field.sourceStart) << 32) | field.sourceEnd;
+ Argument parameter = new Argument(fieldName, fieldPos, copyType(field.type, source), Modifier.FINAL);
+ Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
+ Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
+ if (nonNulls.length != 0) {
+ Statement nullCheck = generateNullCheck(parameter, sourceNode);
+ if (nullCheck != null) nullChecks.add(nullCheck);
+ }
+ parameter.annotations = copyAnnotations(source, nonNulls, nullables);
+ params.add(parameter);
}
- Annotation[] copiedAnnotations = copyAnnotations(source, nonNulls, nullables);
- if (copiedAnnotations.length != 0) parameter.annotations = copiedAnnotations;
- params.add(parameter);
}
nullChecks.addAll(assigns);
@@ -344,20 +372,34 @@ public class HandleConstructor {
/* Generate annotations that must be put on the generated method, and attach them. */ {
Annotation[] constructorProperties = null;
- if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(type)) {
+ if (!allToDefault && addConstructorProperties && !isLocalType(type)) {
constructorProperties = createConstructorProperties(source, fields);
}
- Annotation[] copiedAnnotations = copyAnnotations(source,
- onConstructor.toArray(new Annotation[0]),
- constructorProperties);
- if (copiedAnnotations.length != 0) constructor.annotations = copiedAnnotations;
+ constructor.annotations = copyAnnotations(source,
+ onConstructor.toArray(new Annotation[0]),
+ constructorProperties);
}
constructor.traverse(new SetGeneratedByVisitor(source), typeDeclaration.scope);
return constructor;
}
+ private static Expression getDefaultExpr(TypeReference type, int s, int e) {
+ boolean array = type instanceof ArrayTypeReference;
+ if (array) return new NullLiteral(s, e);
+ char[] lastToken = type.getLastToken();
+ if (Arrays.equals(TypeConstants.BOOLEAN, lastToken)) return new FalseLiteral(s, e);
+ if (Arrays.equals(TypeConstants.CHAR, lastToken)) return new CharLiteral(new char[] {'\'', '\\', '0', '\''}, s, e);
+ if (Arrays.equals(TypeConstants.BYTE, lastToken) || Arrays.equals(TypeConstants.SHORT, lastToken) ||
+ Arrays.equals(TypeConstants.INT, lastToken)) return IntLiteral.buildIntLiteral(new char[] {'0'}, s, e);
+ if (Arrays.equals(TypeConstants.LONG, lastToken)) return LongLiteral.buildLongLiteral(new char[] {'0', 'L'}, s, e);
+ if (Arrays.equals(TypeConstants.FLOAT, lastToken)) return new FloatLiteral(new char[] {'0', 'F'}, s, e);
+ if (Arrays.equals(TypeConstants.DOUBLE, lastToken)) return new DoubleLiteral(new char[] {'0', 'D'}, s, e);
+
+ return new NullLiteral(s, e);
+ }
+
public static boolean isLocalType(EclipseNode type) {
Kind kind = type.up().getKind();
if (kind == Kind.COMPILATION_UNIT) return false;
@@ -367,10 +409,9 @@ public class HandleConstructor {
public MethodDeclaration createStaticConstructor(AccessLevel level, String name, EclipseNode type, Collection<EclipseNode> fields, ASTNode source) {
int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long)pS << 32 | pE;
+ long p = (long) pS << 32 | pE;
- MethodDeclaration constructor = new MethodDeclaration(
- ((CompilationUnitDeclaration) type.top().get()).compilationResult);
+ MethodDeclaration constructor = new MethodDeclaration(((CompilationUnitDeclaration) type.top().get()).compilationResult);
constructor.modifiers = toEclipseModifier(level) | ClassFileConstants.AccStatic;
TypeDeclaration typeDecl = (TypeDeclaration) type.get();
@@ -378,7 +419,7 @@ public class HandleConstructor {
constructor.annotations = null;
constructor.selector = name.toCharArray();
constructor.thrownExceptions = null;
- constructor.typeParameters = copyTypeParams(((TypeDeclaration)type.get()).typeParameters, source);
+ constructor.typeParameters = copyTypeParams(((TypeDeclaration) type.get()).typeParameters, source);
constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
@@ -391,20 +432,18 @@ public class HandleConstructor {
for (EclipseNode fieldNode : fields) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
- long fieldPos = (((long)field.sourceStart) << 32) | field.sourceEnd;
+ long fieldPos = (((long) field.sourceStart) << 32) | field.sourceEnd;
SingleNameReference nameRef = new SingleNameReference(field.name, fieldPos);
assigns.add(nameRef);
Argument parameter = new Argument(field.name, fieldPos, copyType(field.type, source), Modifier.FINAL);
-
- Annotation[] copiedAnnotations = copyAnnotations(source, findAnnotations(field, NON_NULL_PATTERN), findAnnotations(field, NULLABLE_PATTERN));
- if (copiedAnnotations.length != 0) parameter.annotations = copiedAnnotations;
+ parameter.annotations = copyAnnotations(source, findAnnotations(field, NON_NULL_PATTERN), findAnnotations(field, NULLABLE_PATTERN));
params.add(parameter);
}
statement.arguments = assigns.isEmpty() ? null : assigns.toArray(new Expression[assigns.size()]);
constructor.arguments = params.isEmpty() ? null : params.toArray(new Argument[params.size()]);
- constructor.statements = new Statement[] { new ReturnStatement(statement, (int)(p >> 32), (int)p) };
+ constructor.statements = new Statement[] { new ReturnStatement(statement, (int) (p >> 32), (int)p) };
constructor.traverse(new SetGeneratedByVisitor(source), typeDecl.scope);
return constructor;
diff --git a/src/core/lombok/eclipse/handlers/HandleData.java b/src/core/lombok/eclipse/handlers/HandleData.java
index 0ff65a47..025ceefd 100644
--- a/src/core/lombok/eclipse/handlers/HandleData.java
+++ b/src/core/lombok/eclipse/handlers/HandleData.java
@@ -43,6 +43,12 @@ import org.mangosdk.spi.ProviderFor;
*/
@ProviderFor(EclipseAnnotationHandler.class)
public class HandleData extends EclipseAnnotationHandler<Data> {
+ private HandleGetter handleGetter = new HandleGetter();
+ private HandleSetter handleSetter = new HandleSetter();
+ private HandleEqualsAndHashCode handleEqualsAndHashCode = new HandleEqualsAndHashCode();
+ private HandleToString handleToString = new HandleToString();
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<Data> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data");
@@ -66,11 +72,11 @@ public class HandleData extends EclipseAnnotationHandler<Data> {
//for whatever reason, though you can find callers of that one by focusing on the class name itself
//and hitting 'find callers'.
- new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
- new HandleToString().generateToStringForType(typeNode, annotationNode);
- new HandleConstructor().generateRequiredArgsConstructor(
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleSetter.generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
+ handleToString.generateToStringForType(typeNode, annotationNode);
+ handleConstructor.generateRequiredArgsConstructor(
typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
Collections.<Annotation>emptyList(), annotationNode);
}
diff --git a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
index e1b02051..75339f7c 100644
--- a/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/eclipse/handlers/HandleEqualsAndHashCode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -39,6 +39,7 @@ import lombok.EqualsAndHashCode;
import lombok.core.AST.Kind;
import lombok.core.handlers.HandlerUtil;
import lombok.core.AnnotationValues;
+import lombok.core.configuration.CallSuperType;
import lombok.eclipse.Eclipse;
import lombok.eclipse.EclipseAnnotationHandler;
import lombok.eclipse.EclipseNode;
@@ -66,6 +67,7 @@ import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
import org.eclipse.jdt.internal.compiler.ast.NameReference;
import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.ParameterizedQualifiedTypeReference;
import org.eclipse.jdt.internal.compiler.ast.ParameterizedSingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
@@ -116,7 +118,10 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
return;
}
- generateMethods(typeNode, errorNode, null, null, null, false, FieldAccess.GETTER, new ArrayList<Annotation>());
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateMethods(typeNode, errorNode, null, null, null, false, access, new ArrayList<Annotation>());
}
@Override public void handle(AnnotationValues<EqualsAndHashCode> annotation, Annotation ast, EclipseNode annotationNode) {
@@ -127,7 +132,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
List<String> includes = Arrays.asList(ann.of());
EclipseNode typeNode = annotationNode.up();
- List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam=", annotationNode);
+ List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
checkForBogusFieldNames(typeNode, annotation);
Boolean callSuper = ann.callSuper();
@@ -185,8 +190,23 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
return;
}
- if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) {
- errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
+ if (implicitCallSuper && !isDirectDescendantOfObject) {
+ CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
+ if (cst == null) cst = CallSuperType.WARN;
+
+ switch (cst) {
+ default:
+ case WARN:
+ errorNode.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
+ callSuper = false;
+ break;
+ case SKIP:
+ callSuper = false;
+ break;
+ case CALL:
+ callSuper = true;
+ break;
+ }
}
List<EclipseNode> nodesForEquality = new ArrayList<EclipseNode>();
@@ -279,7 +299,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
/* final int PRIME = X; */ {
/* Without fields, PRIME isn't used, and that would trigger a 'local variable not used' warning. */
- if (!isEmpty || callSuper) {
+ if (!isEmpty) {
LocalDeclaration primeDecl = new LocalDeclaration(PRIME, pS, pE);
setGeneratedBy(primeDecl, source);
primeDecl.modifiers |= Modifier.FINAL;
@@ -291,26 +311,30 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
}
}
- /* int result = 1; */ {
- LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
+ /*int result = ... */{
+ LocalDeclaration resultDecl = new LocalDeclaration(RESULT, pS, pE);
setGeneratedBy(resultDecl, source);
- resultDecl.initialization = makeIntLiteral("1".toCharArray(), source);
+ final Expression init;
+ if (callSuper) {
+ /* ... super.hashCode(); */
+ MessageSend callToSuper = new MessageSend();
+ setGeneratedBy(callToSuper, source);
+ callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
+ callToSuper.receiver = new SuperReference(pS, pE);
+ setGeneratedBy(callToSuper.receiver, source);
+ callToSuper.selector = "hashCode".toCharArray();
+ init = callToSuper;
+ } else {
+ /* ... 1; */
+ init = makeIntLiteral("1".toCharArray(), source);
+ }
+ resultDecl.initialization = init;
resultDecl.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
resultDecl.type.sourceStart = pS; resultDecl.type.sourceEnd = pE;
setGeneratedBy(resultDecl.type, source);
statements.add(resultDecl);
}
- if (callSuper) {
- MessageSend callToSuper = new MessageSend();
- setGeneratedBy(callToSuper, source);
- callToSuper.sourceStart = pS; callToSuper.sourceEnd = pE;
- callToSuper.receiver = new SuperReference(pS, pE);
- setGeneratedBy(callToSuper.receiver, source);
- callToSuper.selector = "hashCode".toCharArray();
- statements.add(createResultCalculation(source, callToSuper));
- }
-
for (EclipseNode field : fields) {
TypeReference fType = getFieldType(field, fieldAccess);
char[] dollarFieldName = ("$" + field.getName()).toCharArray();
@@ -358,7 +382,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
statements.add(createResultCalculation(source, fieldAccessor));
} else /* objects */ {
/* final java.lang.Object $fieldName = this.fieldName; */
- /* $fieldName == null ? 0 : $fieldName.hashCode() */
+ /* $fieldName == null ? NULL_PRIME : $fieldName.hashCode() */
statements.add(createLocalDeclaration(source, dollarFieldName, generateQualifiedTypeRef(source, TypeConstants.JAVA_LANG_OBJECT), fieldAccessor));
SingleNameReference copy1 = new SingleNameReference(dollarFieldName, p);
@@ -375,8 +399,8 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
setGeneratedBy(nullLiteral, source);
EqualExpression objIsNull = new EqualExpression(copy2, nullLiteral, OperatorIds.EQUAL_EQUAL);
setGeneratedBy(objIsNull, source);
- IntLiteral int0 = makeIntLiteral("0".toCharArray(), source);
- ConditionalExpression nullOrHashCode = new ConditionalExpression(objIsNull, int0, hashCodeCall);
+ IntLiteral intMagic = makeIntLiteral(String.valueOf(HandlerUtil.primeForNull()).toCharArray(), source);
+ ConditionalExpression nullOrHashCode = new ConditionalExpression(objIsNull, intMagic, hashCodeCall);
nullOrHashCode.sourceStart = pS; nullOrHashCode.sourceEnd = pE;
setGeneratedBy(nullOrHashCode, source);
statements.add(createResultCalculation(source, nullOrHashCode));
@@ -442,17 +466,44 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
return assignment;
}
- public TypeReference createTypeReference(EclipseNode type, long p) {
+ /**
+ * @param type Type to 'copy' into a typeref
+ * @param p position
+ * @param addWildcards If false, all generics are cut off. If true, replaces all genericparams with a ?.
+ * @return
+ */
+ public TypeReference createTypeReference(EclipseNode type, long p, ASTNode source, boolean addWildcards) {
+ int pS = source.sourceStart; int pE = source.sourceEnd;
List<String> list = new ArrayList<String>();
+ List<Integer> genericsCount = addWildcards ? new ArrayList<Integer>() : null;
+
list.add(type.getName());
+ if (addWildcards) genericsCount.add(arraySizeOf(((TypeDeclaration) type.get()).typeParameters));
+ boolean staticContext = (((TypeDeclaration) type.get()).modifiers & Modifier.STATIC) != 0;
EclipseNode tNode = type.up();
+
while (tNode != null && tNode.getKind() == Kind.TYPE) {
list.add(tNode.getName());
+ if (addWildcards) genericsCount.add(staticContext ? 0 : arraySizeOf(((TypeDeclaration) tNode.get()).typeParameters));
+ if (!staticContext) staticContext = (((TypeDeclaration) tNode.get()).modifiers & Modifier.STATIC) != 0;
tNode = tNode.up();
}
Collections.reverse(list);
+ if (addWildcards) Collections.reverse(genericsCount);
+
+ if (list.size() == 1) {
+ if (!addWildcards || genericsCount.get(0) == 0) {
+ return new SingleTypeReference(list.get(0).toCharArray(), p);
+ } else {
+ return new ParameterizedSingleTypeReference(list.get(0).toCharArray(), wildcardify(pS, pE, source, genericsCount.get(0)), 0, p);
+ }
+ }
+
+ if (addWildcards) {
+ addWildcards = false;
+ for (int i : genericsCount) if (i > 0) addWildcards = true;
+ }
- if (list.size() == 1) return new SingleTypeReference(list.get(0).toCharArray(), p);
long[] ps = new long[list.size()];
char[][] tokens = new char[list.size()][];
for (int i = 0; i < list.size(); i++) {
@@ -460,13 +511,31 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
tokens[i] = list.get(i).toCharArray();
}
- return new QualifiedTypeReference(tokens, ps);
+ if (!addWildcards) return new QualifiedTypeReference(tokens, ps);
+ TypeReference[][] typeArgs2 = new TypeReference[tokens.length][];
+ for (int i = 0; i < tokens.length; i++) typeArgs2[i] = wildcardify(pS, pE, source, genericsCount.get(i));
+ return new ParameterizedQualifiedTypeReference(tokens, typeArgs2, 0, ps);
+ }
+
+ private TypeReference[] wildcardify(int pS, int pE, ASTNode source, int count) {
+ if (count == 0) return null;
+ TypeReference[] typeArgs = new TypeReference[count];
+ for (int i = 0; i < count; i++) {
+ typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
+ typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE;
+ setGeneratedBy(typeArgs[i], source);
+ }
+
+ return typeArgs;
+ }
+
+ private int arraySizeOf(Object[] arr) {
+ return arr == null ? 0 : arr.length;
}
public MethodDeclaration createEquals(EclipseNode type, Collection<EclipseNode> fields, boolean callSuper, ASTNode source, FieldAccess fieldAccess, boolean needsCanEqual, List<Annotation> onParam) {
int pS = source.sourceStart; int pE = source.sourceEnd;
long p = (long)pS << 32 | pE;
- TypeDeclaration typeDecl = (TypeDeclaration)type.get();
MethodDeclaration method = new MethodDeclaration(
((CompilationUnitDeclaration) type.top().get()).compilationResult);
@@ -512,7 +581,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
SingleNameReference oRef = new SingleNameReference(new char[] { 'o' }, p);
setGeneratedBy(oRef, source);
- TypeReference typeReference = createTypeReference(type, p);
+ TypeReference typeReference = createTypeReference(type, p, source, false);
setGeneratedBy(typeReference, source);
InstanceOfExpression instanceOf = new InstanceOfExpression(oRef, typeReference);
@@ -535,33 +604,17 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
char[] otherName = "other".toCharArray();
- /* MyType<?> other = (MyType<?>) o; */ {
+ /* Outer.Inner.MyType<?> other = (Outer.Inner.MyType<?>) o; */ {
if (!fields.isEmpty() || needsCanEqual) {
LocalDeclaration other = new LocalDeclaration(otherName, pS, pE);
other.modifiers |= ClassFileConstants.AccFinal;
setGeneratedBy(other, source);
- char[] typeName = typeDecl.name;
- TypeReference targetType;
- if (typeDecl.typeParameters == null || typeDecl.typeParameters.length == 0) {
- targetType = new SingleTypeReference(typeName, p);
- setGeneratedBy(targetType, source);
- other.type = new SingleTypeReference(typeName, p);
- setGeneratedBy(other.type, source);
- } else {
- TypeReference[] typeArgs = new TypeReference[typeDecl.typeParameters.length];
- for (int i = 0; i < typeArgs.length; i++) {
- typeArgs[i] = new Wildcard(Wildcard.UNBOUND);
- typeArgs[i].sourceStart = pS; typeArgs[i].sourceEnd = pE;
- setGeneratedBy(typeArgs[i], source);
- }
- targetType = new ParameterizedSingleTypeReference(typeName, typeArgs, 0, p);
- setGeneratedBy(targetType, source);
- other.type = new ParameterizedSingleTypeReference(typeName, copyTypes(typeArgs, source), 0, p);
- setGeneratedBy(other.type, source);
- }
+ TypeReference targetType = createTypeReference(type, p, source, true);
+ setGeneratedBy(targetType, source);
+ other.type = createTypeReference(type, p, source, true);
+ setGeneratedBy(other.type, source);
NameReference oRef = new SingleNameReference(new char[] { 'o' }, p);
setGeneratedBy(oRef, source);
- other.annotations = createSuppressWarningsAll(source, null);
other.initialization = makeCastExpression(oRef, targetType, source);
statements.add(other);
}
@@ -645,7 +698,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
} else /* objects */ {
/* final java.lang.Object this$fieldName = this.fieldName; */
/* final java.lang.Object other$fieldName = other.fieldName; */
- /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false;; */
+ /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
char[] thisDollarFieldName = ("this$" + field.getName()).toCharArray();
char[] otherDollarFieldName = ("other$" + field.getName()).toCharArray();
@@ -725,7 +778,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
public MethodDeclaration createCanEqual(EclipseNode type, ASTNode source, List<Annotation> onParam) {
- /* public boolean canEqual(final java.lang.Object other) {
+ /* protected boolean canEqual(final java.lang.Object other) {
* return other instanceof Outer.Inner.MyType;
* }
*/
@@ -757,7 +810,7 @@ public class HandleEqualsAndHashCode extends EclipseAnnotationHandler<EqualsAndH
SingleNameReference otherRef = new SingleNameReference(otherName, p);
setGeneratedBy(otherRef, source);
- TypeReference typeReference = createTypeReference(type, p);
+ TypeReference typeReference = createTypeReference(type, p, source, false);
setGeneratedBy(typeReference, source);
InstanceOfExpression instanceOf = new InstanceOfExpression(otherRef, typeReference);
diff --git a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
index 7d0702db..702713fe 100644
--- a/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/eclipse/handlers/HandleFieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2012-2016 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
@@ -23,12 +23,17 @@ package lombok.eclipse.handlers;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.Arrays;
+
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
-import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.Eclipse;
+import lombok.eclipse.EclipseASTAdapter;
+import lombok.eclipse.EclipseASTVisitor;
import lombok.eclipse.EclipseNode;
import lombok.experimental.FieldDefaults;
import lombok.experimental.NonFinal;
@@ -37,16 +42,19 @@ import lombok.experimental.PackagePrivate;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.mangosdk.spi.ProviderFor;
/**
* Handles the {@code lombok.FieldDefaults} annotation for eclipse.
*/
-@ProviderFor(EclipseAnnotationHandler.class)
+@ProviderFor(EclipseASTVisitor.class)
@HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier.
-public class HandleFieldDefaults extends EclipseAnnotationHandler<FieldDefaults> {
+public class HandleFieldDefaults extends EclipseASTAdapter {
public boolean generateFieldDefaultsForType(EclipseNode typeNode, EclipseNode pos, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) {
if (checkForTypeLevelFieldDefaults) {
if (hasAnnotation(FieldDefaults.class, typeNode)) {
@@ -89,43 +97,78 @@ public class HandleFieldDefaults extends EclipseAnnotationHandler<FieldDefaults>
if (level != null && level != AccessLevel.NONE) {
if ((field.modifiers & (ClassFileConstants.AccPublic | ClassFileConstants.AccPrivate | ClassFileConstants.AccProtected)) == 0) {
if (!hasAnnotation(PackagePrivate.class, fieldNode)) {
- field.modifiers |= EclipseHandlerUtil.toEclipseModifier(level);
+ if ((field.modifiers & ClassFileConstants.AccStatic) == 0) {
+ field.modifiers |= EclipseHandlerUtil.toEclipseModifier(level);
+ }
}
}
}
if (makeFinal && (field.modifiers & ClassFileConstants.AccFinal) == 0) {
if (!hasAnnotation(NonFinal.class, fieldNode)) {
- field.modifiers |= ClassFileConstants.AccFinal;
+ if ((field.modifiers & ClassFileConstants.AccStatic) == 0) {
+ field.modifiers |= ClassFileConstants.AccFinal;
+ }
}
}
fieldNode.rebuild();
}
- public void handle(AnnotationValues<FieldDefaults> annotation, Annotation ast, EclipseNode annotationNode) {
- handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_DEFAULTS_FLAG_USAGE, "@FieldDefaults");
-
- EclipseNode node = annotationNode.up();
- FieldDefaults instance = annotation.getInstance();
- AccessLevel level = instance.level();
- boolean makeFinal = instance.makeFinal();
+ private static final char[] FIELD_DEFAULTS = "FieldDefaults".toCharArray();
+
+ @Override public void visitType(EclipseNode typeNode, TypeDeclaration type) {
+ AnnotationValues<FieldDefaults> fieldDefaults = null;
+ EclipseNode source = typeNode;
- if (level == AccessLevel.NONE && !makeFinal) {
- annotationNode.addError("This does nothing; provide either level or makeFinal or both.");
- return;
+ boolean levelIsExplicit = false;
+ boolean makeFinalIsExplicit = false;
+ FieldDefaults fd = null;
+ for (EclipseNode jn : typeNode.down()) {
+ if (jn.getKind() != Kind.ANNOTATION) continue;
+ Annotation ann = (Annotation) jn.get();
+ TypeReference typeTree = ann.type;
+ if (typeTree == null) continue;
+ if (typeTree instanceof SingleTypeReference) {
+ char[] t = ((SingleTypeReference) typeTree).token;
+ if (!Arrays.equals(t, FIELD_DEFAULTS)) continue;
+ } else if (typeTree instanceof QualifiedTypeReference) {
+ char[][] t = ((QualifiedTypeReference) typeTree).tokens;
+ if (!Eclipse.nameEquals(t, "lombok.experimental.FieldDefaults")) continue;
+ } else {
+ continue;
+ }
+
+ if (!typeMatches(FieldDefaults.class, jn, typeTree)) continue;
+
+ source = jn;
+ fieldDefaults = createAnnotation(FieldDefaults.class, jn);
+ levelIsExplicit = fieldDefaults.isExplicit("level");
+ makeFinalIsExplicit = fieldDefaults.isExplicit("makeFinal");
+
+ handleExperimentalFlagUsage(jn, ConfigurationKeys.FIELD_DEFAULTS_FLAG_USAGE, "@FieldDefaults");
+
+ fd = fieldDefaults.getInstance();
+ if (!levelIsExplicit && !makeFinalIsExplicit) {
+ jn.addError("This does nothing; provide either level or makeFinal or both.");
+ }
+
+ if (levelIsExplicit && fd.level() == AccessLevel.NONE) {
+ jn.addError("AccessLevel.NONE doesn't mean anything here. Pick another value.");
+ levelIsExplicit = false;
+ }
+ break;
}
- if (level == AccessLevel.PACKAGE) {
- annotationNode.addError("Setting 'level' to PACKAGE does nothing. To force fields as package private, use the @PackagePrivate annotation on the field.");
- }
+ if (fd == null && (type.modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation)) != 0) return;
- if (!makeFinal && annotation.isExplicit("makeFinal")) {
- annotationNode.addError("Setting 'makeFinal' to false does nothing. To force fields to be non-final, use the @NonFinal annotation on the field.");
- }
+ boolean defaultToPrivate = levelIsExplicit ? false : Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.FIELD_DEFAULTS_PRIVATE_EVERYWHERE));
+ boolean defaultToFinal = makeFinalIsExplicit ? false : Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.FIELD_DEFAULTS_FINAL_EVERYWHERE));
- if (node == null) return;
+ if (!defaultToPrivate && !defaultToFinal && fieldDefaults == null) return;
+ AccessLevel fdAccessLevel = (fieldDefaults != null && levelIsExplicit) ? fd.level() : defaultToPrivate ? AccessLevel.PRIVATE : null;
+ boolean fdToFinal = (fieldDefaults != null && makeFinalIsExplicit) ? fd.makeFinal() : defaultToFinal;
- generateFieldDefaultsForType(node, annotationNode, level, makeFinal, false);
+ generateFieldDefaultsForType(typeNode, source, fdAccessLevel, fdToFinal, false);
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleGetter.java b/src/core/lombok/eclipse/handlers/HandleGetter.java
index 031fff82..f417aca5 100644
--- a/src/core/lombok/eclipse/handlers/HandleGetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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
@@ -105,7 +105,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
return true;
}
- public boolean fieldQualifiesForGetterGeneration(EclipseNode field) {
+ public static boolean fieldQualifiesForGetterGeneration(EclipseNode field) {
if (field.getKind() != Kind.FIELD) return false;
FieldDeclaration fieldDecl = (FieldDeclaration) field.get();
return filterField(fieldDecl);
@@ -148,7 +148,7 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
if (node == null) return;
- List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod=", annotationNode);
+ List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -183,6 +183,10 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
errorNode.addError("'lazy' requires the field to be private and final.");
return;
}
+ if ((field.modifiers & ClassFileConstants.AccTransient) != 0) {
+ errorNode.addError("'lazy' is not supported on transient fields.");
+ return;
+ }
if (field.initialization == null) {
errorNode.addError("'lazy' requires field initialization.");
return;
@@ -270,14 +274,12 @@ public class HandleGetter extends EclipseAnnotationHandler<Getter> {
deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
}
- Annotation[] copiedAnnotations = copyAnnotations(source,
+ method.annotations = copyAnnotations(source,
onMethod.toArray(new Annotation[0]),
findAnnotations(field, NON_NULL_PATTERN),
findAnnotations(field, NULLABLE_PATTERN),
findDelegatesAndMarkAsHandled(fieldNode),
deprecated);
-
- if (copiedAnnotations.length != 0) method.annotations = copiedAnnotations;
}
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
diff --git a/src/core/lombok/eclipse/handlers/HandleHelper.java b/src/core/lombok/eclipse/handlers/HandleHelper.java
new file mode 100644
index 00000000..4f06bdfd
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleHelper.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright (C) 2015-2016 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers;
+
+import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+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.Block;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.ConfigurationKeys;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+import lombok.experimental.Helper;
+
+/**
+ * Handles the {@code lombok.Cleanup} annotation for eclipse.
+ */
+@ProviderFor(EclipseAnnotationHandler.class)
+public class HandleHelper extends EclipseAnnotationHandler<Helper> {
+ private Statement[] getStatementsFromAstNode(ASTNode node) {
+ if (node instanceof Block) return ((Block) node).statements;
+ if (node instanceof AbstractMethodDeclaration) return ((AbstractMethodDeclaration) node).statements;
+ if (node instanceof SwitchStatement) return ((SwitchStatement) node).statements;
+ return null;
+ }
+
+ private void setStatementsOfAstNode(ASTNode node, Statement[] statements) {
+ if (node instanceof Block) ((Block) node).statements = statements;
+ else if (node instanceof AbstractMethodDeclaration) ((AbstractMethodDeclaration) node).statements = statements;
+ else if (node instanceof SwitchStatement) ((SwitchStatement) node).statements = statements;
+ else throw new IllegalArgumentException("Can't set statements on node type: " + node.getClass());
+ }
+
+ @Override public void handle(AnnotationValues<Helper> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
+
+ EclipseNode annotatedType = annotationNode.up();
+ EclipseNode containingBlock = annotatedType == null ? null : annotatedType.directUp();
+ Statement[] origStatements = getStatementsFromAstNode(containingBlock == null ? null : containingBlock.get());
+
+ if (annotatedType == null || annotatedType.getKind() != Kind.TYPE || origStatements == null) {
+ annotationNode.addError("@Helper is legal only on method-local classes.");
+ return;
+ }
+
+ TypeDeclaration annotatedType_ = (TypeDeclaration) annotatedType.get();
+ int indexOfType = -1;
+ for (int i = 0; i < origStatements.length; i++) {
+ if (origStatements[i] == annotatedType_) {
+ indexOfType = i;
+ break;
+ }
+ }
+
+ final List<String> knownMethodNames = new ArrayList<String>();
+
+ for (AbstractMethodDeclaration methodOfHelper : annotatedType_.methods) {
+ if (!(methodOfHelper instanceof MethodDeclaration)) continue;
+ char[] name = methodOfHelper.selector;
+ if (name != null && name.length > 0 && name[0] != '<') knownMethodNames.add(new String(name));
+ }
+
+ Collections.sort(knownMethodNames);
+ final String[] knownMethodNames_ = knownMethodNames.toArray(new String[knownMethodNames.size()]);
+
+ final char[] helperName = new char[annotatedType_.name.length + 1];
+ final boolean[] helperUsed = new boolean[1];
+ helperName[0] = '$';
+ System.arraycopy(annotatedType_.name, 0, helperName, 1, helperName.length - 1);
+
+ ASTVisitor visitor = new ASTVisitor() {
+ @Override public boolean visit(MessageSend messageSend, BlockScope scope) {
+ if (messageSend.receiver instanceof ThisReference) {
+ if ((((ThisReference) messageSend.receiver).bits & ASTNode.IsImplicitThis) == 0) return true;
+ } else if (messageSend.receiver != null) return true;
+
+ char[] name = messageSend.selector;
+ if (name == null || name.length == 0 || name[0] == '<') return true;
+ String n = new String(name);
+ if (Arrays.binarySearch(knownMethodNames_, n) < 0) return true;
+ messageSend.receiver = new SingleNameReference(helperName, messageSend.nameSourcePosition);
+ helperUsed[0] = true;
+ return true;
+ }
+ };
+
+ for (int i = indexOfType + 1; i < origStatements.length; i++) {
+ origStatements[i].traverse(visitor, null);
+ }
+
+ if (!helperUsed[0]) {
+ annotationNode.addWarning("No methods of this helper class are ever used.");
+ return;
+ }
+
+ Statement[] newStatements = new Statement[origStatements.length + 1];
+ System.arraycopy(origStatements, 0, newStatements, 0, indexOfType + 1);
+ System.arraycopy(origStatements, indexOfType + 1, newStatements, indexOfType + 2, origStatements.length - indexOfType - 1);
+ LocalDeclaration decl = new LocalDeclaration(helperName, 0, 0);
+ decl.modifiers |= ClassFileConstants.AccFinal;
+ AllocationExpression alloc = new AllocationExpression();
+ alloc.type = new SingleTypeReference(annotatedType_.name, 0L);
+ decl.initialization = alloc;
+ decl.type = new SingleTypeReference(annotatedType_.name, 0L);
+ SetGeneratedByVisitor sgbvVisitor = new SetGeneratedByVisitor(annotationNode.get());
+ decl.traverse(sgbvVisitor, null);
+ newStatements[indexOfType + 1] = decl;
+ setStatementsOfAstNode(containingBlock.get(), newStatements);
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleLog.java b/src/core/lombok/eclipse/handlers/HandleLog.java
index 830190a2..c49030d8 100644
--- a/src/core/lombok/eclipse/handlers/HandleLog.java
+++ b/src/core/lombok/eclipse/handlers/HandleLog.java
@@ -229,6 +229,17 @@ public class HandleLog {
}
}
+ /**
+ * Handles the {@link lombok.extern.jbosslog.JBossLog} annotation for Eclipse.
+ */
+ @ProviderFor(EclipseAnnotationHandler.class)
+ public static class HandleJBossLog extends EclipseAnnotationHandler<lombok.extern.jbosslog.JBossLog> {
+ @Override public void handle(AnnotationValues<lombok.extern.jbosslog.JBossLog> annotation, Annotation source, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
+ processAnnotation(LoggingFramework.JBOSSLOG, annotation, source, annotationNode, annotation.getInstance().topic());
+ }
+ }
+
enum LoggingFramework {
// private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class);
COMMONS("org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory", "getLog", "@CommonsLog"),
@@ -264,7 +275,9 @@ public class HandleLog {
// private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(TargetType.class);
XSLF4J("org.slf4j.ext.XLogger", "org.slf4j.ext.XLoggerFactory", "getXLogger", "@XSlf4j"),
-
+
+ // private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(TargetType.class);
+ JBOSSLOG("org.jboss.logging.Logger", "org.jboss.logging.Logger", "getLogger", "@JBossLog"),
;
private final String loggerTypeName;
diff --git a/src/core/lombok/eclipse/handlers/HandleNonNull.java b/src/core/lombok/eclipse/handlers/HandleNonNull.java
index d904de2f..d09993ed 100644
--- a/src/core/lombok/eclipse/handlers/HandleNonNull.java
+++ b/src/core/lombok/eclipse/handlers/HandleNonNull.java
@@ -91,7 +91,7 @@ public class HandleNonNull extends EclipseAnnotationHandler<NonNull> {
if (isGenerated(declaration)) return;
if (declaration.isAbstract()) {
- annotationNode.addWarning("@NonNull is meaningless on a parameter of an abstract method.");
+ // This used to be a warning, but as @NonNull also has a documentary purpose, better to not warn about this. Since 1.16.7
return;
}
diff --git a/src/core/lombok/eclipse/handlers/HandlePrintAST.java b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
index 0b61bc4d..234e29b8 100644
--- a/src/core/lombok/eclipse/handlers/HandlePrintAST.java
+++ b/src/core/lombok/eclipse/handlers/HandlePrintAST.java
@@ -59,7 +59,7 @@ public class HandlePrintAST extends EclipseAnnotationHandler<PrintAST> {
try {
stream.close();
} catch (Exception e) {
- Lombok.sneakyThrow(e);
+ throw Lombok.sneakyThrow(e);
}
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleSetter.java b/src/core/lombok/eclipse/handlers/HandleSetter.java
index c22af676..6a9a5123 100644
--- a/src/core/lombok/eclipse/handlers/HandleSetter.java
+++ b/src/core/lombok/eclipse/handlers/HandleSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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 org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
import org.eclipse.jdt.internal.compiler.ast.Statement;
import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TrueLiteral;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
@@ -125,8 +126,8 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
AccessLevel level = annotation.getInstance().value();
if (level == AccessLevel.NONE || node == null) return;
- List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode);
- List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode);
+ List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod", annotationNode);
+ List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -192,11 +193,11 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
}
}
- MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), fieldNode, setterName, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
+ MethodDeclaration method = createSetter((TypeDeclaration) fieldNode.up().get(), false, fieldNode, setterName, null, shouldReturnThis, modifier, sourceNode, onMethod, onParam);
injectMethod(fieldNode.up(), method);
}
- static MethodDeclaration createSetter(TypeDeclaration parent, EclipseNode fieldNode, String name, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
+ static MethodDeclaration createSetter(TypeDeclaration parent, boolean deprecate, EclipseNode fieldNode, String name, char[] booleanFieldToSet, boolean shouldReturnThis, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
ASTNode source = sourceNode.get();
int pS = source.sourceStart, pE = source.sourceEnd;
@@ -213,13 +214,10 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
shouldReturnThis = false;
}
Annotation[] deprecated = null;
- if (isFieldDeprecated(fieldNode)) {
+ if (isFieldDeprecated(fieldNode) || deprecate) {
deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
}
- Annotation[] copiedAnnotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
- if (copiedAnnotations.length != 0) {
- method.annotations = copiedAnnotations;
- }
+ method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL);
param.sourceStart = pS; param.sourceEnd = pE;
method.arguments = new Argument[] { param };
@@ -246,15 +244,17 @@ public class HandleSetter extends EclipseAnnotationHandler<Setter> {
statements.add(assignment);
}
+ if (booleanFieldToSet != null) {
+ statements.add(new Assignment(new SingleNameReference(booleanFieldToSet, p), new TrueLiteral(pS, pE), pE));
+ }
+
if (shouldReturnThis) {
ThisReference thisRef = new ThisReference(pS, pE);
ReturnStatement returnThis = new ReturnStatement(thisRef, pS, pE);
statements.add(returnThis);
}
method.statements = statements.toArray(new Statement[0]);
-
- Annotation[] copiedAnnotationsParam = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0]));
- if (copiedAnnotationsParam.length != 0) param.annotations = copiedAnnotationsParam;
+ param.annotations = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0]));
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
return method;
diff --git a/src/core/lombok/eclipse/handlers/HandleToString.java b/src/core/lombok/eclipse/handlers/HandleToString.java
index a4ed254a..d8f4c569 100644
--- a/src/core/lombok/eclipse/handlers/HandleToString.java
+++ b/src/core/lombok/eclipse/handlers/HandleToString.java
@@ -94,7 +94,11 @@ public class HandleToString extends EclipseAnnotationHandler<ToString> {
Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
- generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
+
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, access);
}
public void handle(AnnotationValues<ToString> annotation, Annotation ast, EclipseNode annotationNode) {
diff --git a/src/core/lombok/eclipse/handlers/HandleUtilityClass.java b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java
new file mode 100644
index 00000000..959c1d20
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/HandleUtilityClass.java
@@ -0,0 +1,194 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers;
+
+import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.Arrays;
+
+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.Clinit;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+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.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+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.ThrowStatement;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.ConfigurationKeys;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.core.AST.Kind;
+import lombok.eclipse.EclipseAnnotationHandler;
+import lombok.eclipse.EclipseNode;
+import lombok.experimental.UtilityClass;
+
+/**
+ * Handles the {@code lombok.experimental.UtilityClass} annotation for eclipse.
+ */
+@HandlerPriority(-4096) //-2^12; to ensure @FieldDefaults picks up on the 'static' we set here.
+@ProviderFor(EclipseAnnotationHandler.class)
+public class HandleUtilityClass extends EclipseAnnotationHandler<UtilityClass> {
+ @Override public void handle(AnnotationValues<UtilityClass> annotation, Annotation ast, EclipseNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.UTILITY_CLASS_FLAG_USAGE, "@UtilityClass");
+
+ EclipseNode typeNode = annotationNode.up();
+ if (!checkLegality(typeNode, annotationNode)) return;
+ changeModifiersAndGenerateConstructor(annotationNode.up(), annotationNode);
+ }
+
+ private static boolean checkLegality(EclipseNode typeNode, EclipseNode errorNode) {
+ TypeDeclaration typeDecl = null;
+ if (typeNode.get() instanceof TypeDeclaration) typeDecl = (TypeDeclaration) typeNode.get();
+ int modifiers = typeDecl == null ? 0 : typeDecl.modifiers;
+ boolean notAClass = (modifiers & (ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0;
+
+ if (typeDecl == null || notAClass) {
+ errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation).");
+ return false;
+ }
+
+ // It might be an inner class. This is okay, but only if it is / can be a static inner class. Thus, all of its parents have to be static inner classes until the top-level.
+ EclipseNode typeWalk = typeNode;
+ while (true) {
+ typeWalk = typeWalk.up();
+ switch (typeWalk.getKind()) {
+ case TYPE:
+ if ((((TypeDeclaration) typeWalk.get()).modifiers & (ClassFileConstants.AccStatic | ClassFileConstants.AccInterface | ClassFileConstants.AccAnnotation | ClassFileConstants.AccEnum)) != 0) continue;
+ if (typeWalk.up().getKind() == Kind.COMPILATION_UNIT) return true;
+ errorNode.addError("@UtilityClass automatically makes the class static, however, this class cannot be made static.");
+ return false;
+ case COMPILATION_UNIT:
+ return true;
+ default:
+ errorNode.addError("@UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class.");
+ return false;
+ }
+ }
+ }
+
+ private void changeModifiersAndGenerateConstructor(EclipseNode typeNode, EclipseNode annotationNode) {
+ TypeDeclaration classDecl = (TypeDeclaration) typeNode.get();
+
+ boolean makeConstructor = true;
+
+ classDecl.modifiers |= ClassFileConstants.AccFinal;
+
+ boolean markStatic = true;
+ boolean requiresClInit = false;
+ boolean alreadyHasClinit = false;
+
+ if (typeNode.up().getKind() == Kind.COMPILATION_UNIT) markStatic = false;
+ if (markStatic && typeNode.up().getKind() == Kind.TYPE) {
+ TypeDeclaration typeDecl = (TypeDeclaration) typeNode.up().get();
+ if ((typeDecl.modifiers & ClassFileConstants.AccInterface) != 0) markStatic = false;
+ }
+
+ if (markStatic) classDecl.modifiers |= ClassFileConstants.AccStatic;
+
+ for (EclipseNode element : typeNode.down()) {
+ if (element.getKind() == Kind.FIELD) {
+ FieldDeclaration fieldDecl = (FieldDeclaration) element.get();
+ if ((fieldDecl.modifiers & ClassFileConstants.AccStatic) == 0) {
+ requiresClInit = true;
+ fieldDecl.modifiers |= ClassFileConstants.AccStatic;
+ }
+ } else if (element.getKind() == Kind.METHOD) {
+ AbstractMethodDeclaration amd = (AbstractMethodDeclaration) element.get();
+ if (amd instanceof ConstructorDeclaration) {
+ ConstructorDeclaration constrDecl = (ConstructorDeclaration) element.get();
+ if (getGeneratedBy(constrDecl) == null && (constrDecl.bits & ASTNode.IsDefaultConstructor) == 0) {
+ element.addError("@UtilityClasses cannot have declared constructors.");
+ makeConstructor = false;
+ continue;
+ }
+ } else if (amd instanceof MethodDeclaration) {
+ amd.modifiers |= ClassFileConstants.AccStatic;
+ } else if (amd instanceof Clinit) {
+ alreadyHasClinit = true;
+ }
+ } else if (element.getKind() == Kind.TYPE) {
+ ((TypeDeclaration) element.get()).modifiers |= ClassFileConstants.AccStatic;
+ }
+ }
+
+ if (makeConstructor) createPrivateDefaultConstructor(typeNode, annotationNode);
+ if (requiresClInit && !alreadyHasClinit) classDecl.addClinit();
+ }
+
+ private static final char[][] JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION = new char[][] {
+ TypeConstants.JAVA, TypeConstants.LANG, "UnsupportedOperationException".toCharArray()
+ };
+
+ private static final char[] UNSUPPORTED_MESSAGE = "This is a utility class and cannot be instantiated".toCharArray();
+
+ private void createPrivateDefaultConstructor(EclipseNode typeNode, EclipseNode sourceNode) {
+ ASTNode source = sourceNode.get();
+
+ TypeDeclaration typeDeclaration = ((TypeDeclaration) typeNode.get());
+ long p = (long) source.sourceStart << 32 | source.sourceEnd;
+
+ ConstructorDeclaration constructor = new ConstructorDeclaration(((CompilationUnitDeclaration) typeNode.top().get()).compilationResult);
+
+ constructor.modifiers = ClassFileConstants.AccPrivate;
+ constructor.selector = typeDeclaration.name;
+ constructor.constructorCall = new ExplicitConstructorCall(ExplicitConstructorCall.ImplicitSuper);
+ constructor.constructorCall.sourceStart = source.sourceStart;
+ constructor.constructorCall.sourceEnd = source.sourceEnd;
+ constructor.thrownExceptions = null;
+ constructor.typeParameters = null;
+ constructor.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ constructor.bodyStart = constructor.declarationSourceStart = constructor.sourceStart = source.sourceStart;
+ constructor.bodyEnd = constructor.declarationSourceEnd = constructor.sourceEnd = source.sourceEnd;
+ constructor.arguments = null;
+
+ AllocationExpression exception = new AllocationExpression();
+ setGeneratedBy(exception, source);
+ long[] ps = new long[JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION.length];
+ Arrays.fill(ps, p);
+ exception.type = new QualifiedTypeReference(JAVA_LANG_UNSUPPORTED_OPERATION_EXCEPTION, ps);
+ setGeneratedBy(exception.type, source);
+ exception.arguments = new Expression[] {
+ new StringLiteral(UNSUPPORTED_MESSAGE, source.sourceStart, source.sourceEnd, 0)
+ };
+ setGeneratedBy(exception.arguments[0], source);
+ ThrowStatement throwStatement = new ThrowStatement(exception, source.sourceStart, source.sourceEnd);
+ setGeneratedBy(throwStatement, source);
+
+ constructor.statements = new Statement[] {throwStatement};
+
+ injectMethod(typeNode, constructor);
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/HandleVal.java b/src/core/lombok/eclipse/handlers/HandleVal.java
index d4ae417c..3742ac00 100644
--- a/src/core/lombok/eclipse/handlers/HandleVal.java
+++ b/src/core/lombok/eclipse/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-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,19 +21,24 @@
*/
package lombok.eclipse.handlers;
-import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.typeMatches;
import lombok.ConfigurationKeys;
import lombok.val;
+import lombok.var;
import lombok.core.HandlerPriority;
import lombok.eclipse.DeferUntilPostDiet;
import lombok.eclipse.EclipseASTAdapter;
import lombok.eclipse.EclipseASTVisitor;
import lombok.eclipse.EclipseNode;
+import org.eclipse.jdt.internal.compiler.ast.ASTNode;
import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
import org.eclipse.jdt.internal.compiler.ast.ForStatement;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.mangosdk.spi.ProviderFor;
/*
@@ -44,8 +49,13 @@ import org.mangosdk.spi.ProviderFor;
@HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated.
public class HandleVal extends EclipseASTAdapter {
@Override public void visitLocal(EclipseNode localNode, LocalDeclaration local) {
- if (!EclipseHandlerUtil.typeMatches(val.class, localNode, local.type)) return;
- handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
+ TypeReference type = local.type;
+ boolean isVal = typeMatches(val.class, localNode, type);
+ boolean isVar = typeMatches(var.class, localNode, type);
+ if (!(isVal || isVar)) return;
+
+ if (isVal) handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
+ if (isVar) handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var");
boolean variableOfForEach = false;
@@ -54,23 +64,37 @@ public class HandleVal extends EclipseASTAdapter {
variableOfForEach = fs.elementVariable == local;
}
+ String annotation = isVal ? "val" : "var";
if (local.initialization == null && !variableOfForEach) {
- localNode.addError("'val' on a local variable requires an initializer expression");
+ localNode.addError("'" + annotation + "' on a local variable requires an initializer expression");
return;
}
if (local.initialization instanceof ArrayInitializer) {
- localNode.addError("'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
+ localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
return;
}
- if (localNode.directUp().get() instanceof ForStatement) {
+ ASTNode parentRaw = localNode.directUp().get();
+
+ if (isVal && parentRaw instanceof ForStatement) {
localNode.addError("'val' is not allowed in old-style for loops");
return;
}
+ if (parentRaw instanceof ForStatement && ((ForStatement) parentRaw).initializations != null && ((ForStatement) parentRaw).initializations.length > 1) {
+ localNode.addError("'var' is not allowed in old-style for loops if there is more than 1 initializer");
+ return;
+ }
+
if (local.initialization != null && local.initialization.getClass().getName().equals("org.eclipse.jdt.internal.compiler.ast.LambdaExpression")) {
- localNode.addError("'val' is not allowed with lambda expressions.");
+ localNode.addError("'" + annotation + "' is not allowed with lambda expressions.");
+ return;
+ }
+
+ if(isVar && local.initialization instanceof NullLiteral) {
+ localNode.addError("variable initializer is 'null'");
+ return;
}
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleValue.java b/src/core/lombok/eclipse/handlers/HandleValue.java
index 79c11771..a61ca6c3 100644
--- a/src/core/lombok/eclipse/handlers/HandleValue.java
+++ b/src/core/lombok/eclipse/handlers/HandleValue.java
@@ -47,6 +47,12 @@ import org.mangosdk.spi.ProviderFor;
@ProviderFor(EclipseAnnotationHandler.class)
@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends EclipseAnnotationHandler<Value> {
+ private HandleFieldDefaults handleFieldDefaults = new HandleFieldDefaults();
+ private HandleGetter handleGetter = new HandleGetter();
+ private HandleEqualsAndHashCode handleEqualsAndHashCode = new HandleEqualsAndHashCode();
+ private HandleToString handleToString = new HandleToString();
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
public void handle(AnnotationValues<Value> annotation, Annotation ast, EclipseNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
@@ -72,7 +78,7 @@ public class HandleValue extends EclipseAnnotationHandler<Value> {
}
}
- new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
+ handleFieldDefaults.generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
//Careful: Generate the public static constructor (if there is one) LAST, so that any attempt to
//'find callers' on the annotation node will find callers of the constructor, which is by far the
@@ -80,10 +86,10 @@ public class HandleValue extends EclipseAnnotationHandler<Value> {
//for whatever reason, though you can find callers of that one by focusing on the class name itself
//and hitting 'find callers'.
- new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
- new HandleToString().generateToStringForType(typeNode, annotationNode);
- new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
+ handleToString.generateToStringForType(typeNode, annotationNode);
+ handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, ann.staticConstructor(), SkipIfConstructorExists.YES,
Collections.<Annotation>emptyList(), annotationNode);
}
}
diff --git a/src/core/lombok/eclipse/handlers/HandleWither.java b/src/core/lombok/eclipse/handlers/HandleWither.java
index 8b038676..200ebde7 100644
--- a/src/core/lombok/eclipse/handlers/HandleWither.java
+++ b/src/core/lombok/eclipse/handlers/HandleWither.java
@@ -25,7 +25,6 @@ import static lombok.core.handlers.HandlerUtil.*;
import static lombok.eclipse.Eclipse.*;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import java.lang.reflect.Modifier;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
@@ -57,6 +56,7 @@ import org.eclipse.jdt.internal.compiler.ast.ThisReference;
import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.ExtraCompilerModifiers;
import org.mangosdk.spi.ProviderFor;
@ProviderFor(EclipseAnnotationHandler.class)
@@ -127,8 +127,8 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
AccessLevel level = annotation.getInstance().value();
if (level == AccessLevel.NONE || node == null) return;
- List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode);
- List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode);
+ List<Annotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Wither(onMethod", annotationNode);
+ List<Annotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Wither(onParam", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -163,6 +163,9 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
return;
}
+ EclipseNode typeNode = fieldNode.up();
+ boolean makeAbstract = typeNode != null && typeNode.getKind() == Kind.TYPE && (((TypeDeclaration) typeNode.get()).modifiers & ClassFileConstants.AccAbstract) != 0;
+
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
TypeReference fieldType = copyType(field.type, source);
boolean isBoolean = isBoolean(fieldType);
@@ -208,17 +211,18 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
int modifier = toEclipseModifier(level);
- MethodDeclaration method = createWither((TypeDeclaration) fieldNode.up().get(), fieldNode, witherName, modifier, sourceNode, onMethod, onParam);
+ MethodDeclaration method = createWither((TypeDeclaration) fieldNode.up().get(), fieldNode, witherName, modifier, sourceNode, onMethod, onParam, makeAbstract);
injectMethod(fieldNode.up(), method);
}
- public MethodDeclaration createWither(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam) {
+ public MethodDeclaration createWither(TypeDeclaration parent, EclipseNode fieldNode, String name, int modifier, EclipseNode sourceNode, List<Annotation> onMethod, List<Annotation> onParam, boolean makeAbstract ) {
ASTNode source = sourceNode.get();
if (name == null) return null;
FieldDeclaration field = (FieldDeclaration) fieldNode.get();
int pS = source.sourceStart, pE = source.sourceEnd;
- long p = (long)pS << 32 | pE;
+ long p = (long) pS << 32 | pE;
MethodDeclaration method = new MethodDeclaration(parent.compilationResult);
+ if (makeAbstract) modifier = modifier | ClassFileConstants.AccAbstract | ExtraCompilerModifiers.AccSemicolonBody;
method.modifiers = modifier;
method.returnType = cloneSelfType(fieldNode, source);
if (method.returnType == null) return null;
@@ -227,11 +231,8 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
if (isFieldDeprecated(fieldNode)) {
deprecated = new Annotation[] { generateDeprecatedAnnotation(source) };
}
- Annotation[] copiedAnnotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
- if (copiedAnnotations.length != 0) {
- method.annotations = copiedAnnotations;
- }
- Argument param = new Argument(field.name, p, copyType(field.type, source), Modifier.FINAL);
+ method.annotations = copyAnnotations(source, onMethod.toArray(new Annotation[0]), deprecated);
+ Argument param = new Argument(field.name, p, copyType(field.type, source), ClassFileConstants.AccFinal);
param.sourceStart = pS; param.sourceEnd = pE;
method.arguments = new Argument[] { param };
method.selector = name.toCharArray();
@@ -240,51 +241,52 @@ public class HandleWither extends EclipseAnnotationHandler<Wither> {
method.typeParameters = null;
method.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
- List<Expression> args = new ArrayList<Expression>();
- for (EclipseNode child : fieldNode.up().down()) {
- if (child.getKind() != Kind.FIELD) continue;
- FieldDeclaration childDecl = (FieldDeclaration) child.get();
- // Skip fields that start with $
- if (childDecl.name != null && childDecl.name.length > 0 && childDecl.name[0] == '$') continue;
- long fieldFlags = childDecl.modifiers;
- // Skip static fields.
- if ((fieldFlags & ClassFileConstants.AccStatic) != 0) continue;
- // Skip initialized final fields.
- if (((fieldFlags & ClassFileConstants.AccFinal) != 0) && childDecl.initialization != null) continue;
- if (child.get() == fieldNode.get()) {
- args.add(new SingleNameReference(field.name, p));
- } else {
- args.add(createFieldAccessor(child, FieldAccess.ALWAYS_FIELD, source));
- }
- }
-
- AllocationExpression constructorCall = new AllocationExpression();
- constructorCall.arguments = args.toArray(new Expression[0]);
- constructorCall.type = cloneSelfType(fieldNode, source);
-
- Expression identityCheck = new EqualExpression(
- createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source),
- new SingleNameReference(field.name, p),
- OperatorIds.EQUAL_EQUAL);
- ThisReference thisRef = new ThisReference(pS, pE);
- Expression conditional = new ConditionalExpression(identityCheck, thisRef, constructorCall);
- Statement returnStatement = new ReturnStatement(conditional, pS, pE);
- method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
- method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
-
Annotation[] nonNulls = findAnnotations(field, NON_NULL_PATTERN);
Annotation[] nullables = findAnnotations(field, NULLABLE_PATTERN);
- List<Statement> statements = new ArrayList<Statement>(5);
- if (nonNulls.length > 0) {
- Statement nullCheck = generateNullCheck(field, sourceNode);
- if (nullCheck != null) statements.add(nullCheck);
- }
- statements.add(returnStatement);
-
- method.statements = statements.toArray(new Statement[0]);
- Annotation[] copiedAnnotationsParam = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0]));
- if (copiedAnnotationsParam.length != 0) param.annotations = copiedAnnotationsParam;
+ if (!makeAbstract) {
+ List<Expression> args = new ArrayList<Expression>();
+ for (EclipseNode child : fieldNode.up().down()) {
+ if (child.getKind() != Kind.FIELD) continue;
+ FieldDeclaration childDecl = (FieldDeclaration) child.get();
+ // Skip fields that start with $
+ if (childDecl.name != null && childDecl.name.length > 0 && childDecl.name[0] == '$') continue;
+ long fieldFlags = childDecl.modifiers;
+ // Skip static fields.
+ if ((fieldFlags & ClassFileConstants.AccStatic) != 0) continue;
+ // Skip initialized final fields.
+ if (((fieldFlags & ClassFileConstants.AccFinal) != 0) && childDecl.initialization != null) continue;
+ if (child.get() == fieldNode.get()) {
+ args.add(new SingleNameReference(field.name, p));
+ } else {
+ args.add(createFieldAccessor(child, FieldAccess.ALWAYS_FIELD, source));
+ }
+ }
+
+ AllocationExpression constructorCall = new AllocationExpression();
+ constructorCall.arguments = args.toArray(new Expression[0]);
+ constructorCall.type = cloneSelfType(fieldNode, source);
+
+ Expression identityCheck = new EqualExpression(
+ createFieldAccessor(fieldNode, FieldAccess.ALWAYS_FIELD, source),
+ new SingleNameReference(field.name, p),
+ OperatorIds.EQUAL_EQUAL);
+ ThisReference thisRef = new ThisReference(pS, pE);
+ Expression conditional = new ConditionalExpression(identityCheck, thisRef, constructorCall);
+ Statement returnStatement = new ReturnStatement(conditional, pS, pE);
+ method.bodyStart = method.declarationSourceStart = method.sourceStart = source.sourceStart;
+ method.bodyEnd = method.declarationSourceEnd = method.sourceEnd = source.sourceEnd;
+
+ List<Statement> statements = new ArrayList<Statement>(5);
+ if (nonNulls.length > 0) {
+ Statement nullCheck = generateNullCheck(field, sourceNode);
+ if (nullCheck != null) statements.add(nullCheck);
+ }
+ statements.add(returnStatement);
+
+ method.statements = statements.toArray(new Statement[0]);
+ }
+ param.annotations = copyAnnotations(source, nonNulls, nullables, onParam.toArray(new Annotation[0]));
method.traverse(new SetGeneratedByVisitor(source), parent.scope);
return method;
diff --git a/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java b/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
index 7217a396..89964914 100644
--- a/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
+++ b/src/core/lombok/eclipse/handlers/SetGeneratedByVisitor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2013 The Project Lombok Authors.
+ * Copyright (C) 2011-2015 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
@@ -23,6 +23,8 @@ package lombok.eclipse.handlers;
import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+import java.util.Arrays;
+
import org.eclipse.jdt.internal.compiler.ASTVisitor;
import org.eclipse.jdt.internal.compiler.ast.AND_AND_Expression;
import org.eclipse.jdt.internal.compiler.ast.ASTNode;
@@ -128,881 +130,816 @@ public final class SetGeneratedByVisitor extends ASTVisitor {
private static final long INT_TO_LONG_MASK = 0x00000000FFFFFFFFL;
private final ASTNode source;
- private final int newSourceStart;
- private final int newSourceEnd;
+ private final int sourceStart;
+ private final int sourceEnd;
+ private final long sourcePos;
public SetGeneratedByVisitor(ASTNode source) {
this.source = source;
- this.newSourceStart = this.source.sourceStart;
- this.newSourceEnd = this.source.sourceEnd;
+ this.sourceStart = this.source.sourceStart;
+ this.sourceEnd = this.source.sourceEnd;
+ this.sourcePos = (long)sourceStart << 32 | (sourceEnd & INT_TO_LONG_MASK);
}
- private void applyOffset(JavadocAllocationExpression node) {
- applyOffsetExpression(node);
- node.memberStart = newSourceStart;
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+ private void fixPositions(JavadocAllocationExpression node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.memberStart = sourceStart;
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
}
- private void applyOffset(JavadocMessageSend node) {
- applyOffsetMessageSend(node);
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+ private void fixPositions(JavadocMessageSend node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.nameSourcePosition = sourcePos;
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
}
- private void applyOffset(JavadocSingleNameReference node) {
- applyOffsetExpression(node);
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+ private void fixPositions(JavadocSingleNameReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
}
- private void applyOffset(JavadocSingleTypeReference node) {
- applyOffsetExpression(node);
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+ private void fixPositions(JavadocSingleTypeReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
}
- private void applyOffset(JavadocFieldReference node) {
- applyOffsetFieldReference(node);
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+ private void fixPositions(JavadocFieldReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.nameSourcePosition = sourcePos;
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
+ }
+
+ private void fixPositions(JavadocArrayQualifiedTypeReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ if (node.sourcePositions == null || node.sourcePositions.length != node.tokens.length) node.sourcePositions = new long[node.tokens.length];
+ Arrays.fill(node.sourcePositions, sourcePos);
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
+ }
+
+ private void fixPositions(JavadocQualifiedTypeReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ if (node.sourcePositions == null || node.sourcePositions.length != node.tokens.length) node.sourcePositions = new long[node.tokens.length];
+ Arrays.fill(node.sourcePositions, sourcePos);
+ node.tagSourceEnd = sourceEnd;
+ node.tagSourceStart = sourceStart;
+ }
+
+ private void fixPositions(Annotation node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.declarationSourceEnd = sourceEnd;
}
-
- private void applyOffset(JavadocArrayQualifiedTypeReference node) {
- applyOffsetQualifiedTypeReference(node);
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+
+ private void fixPositions(ArrayTypeReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.originalSourceEnd = sourceEnd;
}
- private void applyOffset(JavadocQualifiedTypeReference node) {
- applyOffsetQualifiedTypeReference(node);
- node.tagSourceEnd = newSourceEnd;
- node.tagSourceStart = newSourceStart;
+ private void fixPositions(AbstractMethodDeclaration node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.bodyEnd = sourceEnd;
+ node.bodyStart = sourceStart;
+ node.declarationSourceEnd = sourceEnd;
+ node.declarationSourceStart = sourceStart;
+ node.modifiersSourceStart = sourceStart;
}
- private void applyOffset(Annotation node) {
- applyOffsetExpression(node);
- node.declarationSourceEnd = newSourceEnd;
+ private void fixPositions(Javadoc node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.valuePositions = sourceStart;
}
- private void applyOffset(ArrayTypeReference node) {
- applyOffsetExpression(node);
- node.originalSourceEnd = newSourceEnd;
+ private void fixPositions(Initializer node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.declarationEnd = sourceEnd;
+ node.declarationSourceEnd = sourceEnd;
+ node.declarationSourceStart = sourceStart;
+ node.modifiersSourceStart = sourceStart;
+ node.endPart1Position = sourceEnd;
+ node.endPart2Position = sourceEnd;
+ node.bodyStart = sourceStart;
+ node.bodyEnd = sourceEnd;
}
-
- private void applyOffset(AbstractMethodDeclaration node) {
- applyOffsetASTNode(node);
- node.bodyEnd = newSourceEnd;
- node.bodyStart = newSourceStart;
- node.declarationSourceEnd = newSourceEnd;
- node.declarationSourceStart = newSourceStart;
- node.modifiersSourceStart = newSourceStart;
+
+ private void fixPositions(TypeDeclaration node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.bodyEnd = sourceEnd;
+ node.bodyStart = sourceStart;
+ node.declarationSourceEnd = sourceEnd;
+ node.declarationSourceStart = sourceStart;
+ node.modifiersSourceStart = sourceStart;
}
- private void applyOffset(Javadoc node) {
- applyOffsetASTNode(node);
- node.valuePositions = newSourceStart;
- for (int i = 0; i < node.inheritedPositions.length; i++) {
- node.inheritedPositions[i] = recalcSourcePosition(node.inheritedPositions[i]);
- }
+ private void fixPositions(ImportReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.declarationEnd = sourceEnd;
+ node.declarationSourceEnd = sourceEnd;
+ node.declarationSourceStart = sourceStart;
+ if (node.sourcePositions == null || node.sourcePositions.length != node.tokens.length) node.sourcePositions = new long[node.tokens.length];
+ Arrays.fill(node.sourcePositions, sourcePos);
}
-
- private void applyOffset(Initializer node) {
- applyOffsetFieldDeclaration(node);
- node.bodyStart = newSourceStart;
- node.bodyEnd = newSourceEnd;
- }
-
- private void applyOffset(TypeDeclaration node) {
- applyOffsetASTNode(node);
- node.bodyEnd = newSourceEnd;
- node.bodyStart = newSourceStart;
- node.declarationSourceEnd = newSourceEnd;
- node.declarationSourceStart = newSourceStart;
- node.modifiersSourceStart = newSourceStart;
- }
-
- private void applyOffset(ImportReference node) {
- applyOffsetASTNode(node);
- node.declarationEnd = newSourceEnd;
- node.declarationSourceEnd = newSourceEnd;
- node.declarationSourceStart = newSourceStart;
- for (int i = 0; i < node.sourcePositions.length; i++) {
- node.sourcePositions[i] = recalcSourcePosition(node.sourcePositions[i]);
- }
+
+ private void fixPositions(ASTNode node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
}
-
- private void applyOffsetASTNode(ASTNode node) {
- node.sourceEnd = newSourceEnd;
- node.sourceStart = newSourceStart;
+
+ private void fixPositions(SwitchStatement node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.blockStart = sourceStart;
}
-
- private void applyOffsetExpression(Expression node) {
- applyOffsetASTNode(node);
-// if (node.statementEnd != -1) {
- node.statementEnd = newSourceEnd;
-// }
+
+ private void fixPositions(Expression node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
}
-
- private void applyOffsetVariable(AbstractVariableDeclaration node) {
- applyOffsetASTNode(node);
- node.declarationEnd = newSourceEnd;
- node.declarationSourceEnd = newSourceEnd;
- node.declarationSourceStart = newSourceStart;
- node.modifiersSourceStart = newSourceStart;
+
+ private void fixPositions(AbstractVariableDeclaration node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.declarationEnd = sourceEnd;
+ node.declarationSourceEnd = sourceEnd;
+ node.declarationSourceStart = sourceStart;
+ node.modifiersSourceStart = sourceStart;
}
- private void applyOffsetFieldDeclaration(FieldDeclaration node) {
- applyOffsetVariable(node);
- node.endPart1Position = newSourceEnd;
- node.endPart2Position = newSourceEnd;
+ private void fixPositions(FieldDeclaration node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.declarationEnd = sourceEnd;
+ node.declarationSourceEnd = sourceEnd;
+ node.declarationSourceStart = sourceStart;
+ node.modifiersSourceStart = sourceStart;
+ node.endPart1Position = sourceEnd;
+ node.endPart2Position = sourceEnd;
}
- private void applyOffsetFieldReference(FieldReference node) {
- applyOffsetExpression(node);
- node.nameSourcePosition = recalcSourcePosition(node.nameSourcePosition);
+ private void fixPositions(FieldReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.nameSourcePosition = sourcePos;
}
- private void applyOffsetMessageSend(MessageSend node) {
- applyOffsetExpression(node);
- node.nameSourcePosition = recalcSourcePosition(node.nameSourcePosition);
+ private void fixPositions(MessageSend node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ node.nameSourcePosition = sourcePos;
}
- private void applyOffsetQualifiedNameReference(QualifiedNameReference node) {
- applyOffsetExpression(node);
- for (int i = 0; i < node.sourcePositions.length; i++) {
- node.sourcePositions[i] = recalcSourcePosition(node.sourcePositions[i]);
- }
+ private void fixPositions(QualifiedNameReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ if (node.sourcePositions == null || node.sourcePositions.length != node.tokens.length) node.sourcePositions = new long[node.tokens.length];
+ Arrays.fill(node.sourcePositions, sourcePos);
}
- private void applyOffsetQualifiedTypeReference(QualifiedTypeReference node) {
- applyOffsetExpression(node);
- for (int i = 0; i < node.sourcePositions.length; i++) {
- node.sourcePositions[i] = recalcSourcePosition(node.sourcePositions[i]);
- }
- }
-
- /** See {@link FieldReference#nameSourcePosition} for explanation */
- private long recalcSourcePosition(long sourcePosition) {
-// long start = (sourcePosition >>> 32);
-// long end = (sourcePosition & 0x00000000FFFFFFFFL);
-// start = newSourceStart;
-// end = newSourceStart;
-// return ((start<<32)+end);
- return ((long)newSourceStart << 32) | (newSourceEnd & INT_TO_LONG_MASK);
+ private void fixPositions(QualifiedTypeReference node) {
+ node.sourceEnd = sourceEnd;
+ node.sourceStart = sourceStart;
+ node.statementEnd = sourceEnd;
+ if (node.sourcePositions == null || node.sourcePositions.length != node.tokens.length) node.sourcePositions = new long[node.tokens.length];
+ Arrays.fill(node.sourcePositions, sourcePos);
}
@Override public boolean visit(AllocationExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
-
+
@Override public boolean visit(AND_AND_Expression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(AnnotationMethodDeclaration node, ClassScope classScope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, classScope);
}
@Override public boolean visit(Argument node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetVariable(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Argument node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetVariable(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayAllocationExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayInitializer node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayQualifiedTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedTypeReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayQualifiedTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedTypeReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ArrayTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(AssertStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Assignment node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(BinaryExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Block node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(BreakStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(CaseStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(CastExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(CharLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ClassLiteralAccess node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Clinit node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(CompilationUnitDeclaration node, CompilationUnitScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(CompoundAssignment node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ConditionalExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ConstructorDeclaration node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ContinueStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(DoStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(DoubleLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(EmptyStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(EqualExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ExplicitConstructorCall node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ExtendedStringLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(FalseLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(FieldDeclaration node, MethodScope scope) {
- setGeneratedBy(node, source);
- applyOffsetFieldDeclaration(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(FieldReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetFieldReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(FieldReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetFieldReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(FloatLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ForeachStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ForStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(IfStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ImportReference node, CompilationUnitScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Initializer node, MethodScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(InstanceOfExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(IntLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Javadoc node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Javadoc node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocAllocationExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocAllocationExpression node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocArgumentExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocArgumentExpression node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocArrayQualifiedTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocArrayQualifiedTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocArraySingleTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocArraySingleTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocFieldReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocFieldReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocImplicitTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocImplicitTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocMessageSend node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocMessageSend node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocQualifiedTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocQualifiedTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocReturnStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocReturnStatement node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocSingleNameReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocSingleNameReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocSingleTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(JavadocSingleTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(LabeledStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(LocalDeclaration node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetVariable(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(LongLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(MarkerAnnotation node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(MemberValuePair node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(MessageSend node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetMessageSend(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(MethodDeclaration node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(StringLiteralConcatenation node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(NormalAnnotation node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(NullLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(OR_OR_Expression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ParameterizedQualifiedTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedTypeReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ParameterizedQualifiedTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedTypeReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ParameterizedSingleTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ParameterizedSingleTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(PostfixExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(PrefixExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedAllocationExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedNameReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedNameReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedNameReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedSuperReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedSuperReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedThisReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedThisReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedTypeReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(QualifiedTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetQualifiedTypeReference(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ReturnStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SingleMemberAnnotation node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SingleNameReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SingleNameReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SingleTypeReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SingleTypeReference node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(StringLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SuperReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SwitchStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
- node.blockStart = newSourceStart;
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(SynchronizedStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ThisReference node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ThisReference node, ClassScope scope) {
- setGeneratedBy(node, source);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(ThrowStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TrueLiteral node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TryStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TypeDeclaration node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TypeDeclaration node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TypeDeclaration node, CompilationUnitScope scope) {
- setGeneratedBy(node, source);
- applyOffset(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TypeParameter node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetVariable(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(TypeParameter node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetVariable(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(UnaryExpression node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(WhileStatement node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetASTNode(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Wildcard node, BlockScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
@Override public boolean visit(Wildcard node, ClassScope scope) {
- setGeneratedBy(node, source);
- applyOffsetExpression(node);
+ fixPositions(setGeneratedBy(node, source));
return super.visit(node, scope);
}
+
+// missing methods
+// public boolean visit(MarkerAnnotation node, ClassScope scope){ return true;}
+// public boolean visit(MemberValuePair node, ClassScope scope){ return true;}
+// public boolean visit(NormalAnnotation node, ClassScope scope){ return true;}
+// public boolean visit(SingleMemberAnnotation node, ClassScope scope){ return true;}
+
+// missing methods from later versions
+// public boolean visit(UnionTypeReference node, BlockScope scope){ return true;}
+// public boolean visit(UnionTypeReference node, ClassScope scope){ return true;}
+// public boolean visit(LambdaExpression node, BlockScope scope){ return true;}
+// public boolean visit(ReferenceExpression node, BlockScope scope){ return true;}
+// public boolean visit(IntersectionCastTypeReference node, ClassScope scope){ return true;}
+// public boolean visit(IntersectionCastTypeReference node, BlockScope scope){ return true;}
} \ No newline at end of file
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
new file mode 100644
index 00000000..5956c01b
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaMapSingularizer.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseGuavaMapSingularizer extends EclipseGuavaSingularizer {
+ // TODO cgcc.ImmutableMultimap, cgcc.ImmutableListMultimap, cgcc.ImmutableSetMultimap
+ // TODO cgcc.ImmutableClassToInstanceMap
+ // TODO cgcc.ImmutableRangeMap
+
+ private static final LombokImmutableList<String> SUFFIXES =
+ LombokImmutableList.of("key", "value");
+ private static final LombokImmutableList<String> SUPPORTED_TYPES = LombokImmutableList.of(
+ "com.google.common.collect.ImmutableMap",
+ "com.google.common.collect.ImmutableBiMap",
+ "com.google.common.collect.ImmutableSortedMap"
+ );
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return SUPPORTED_TYPES;
+ }
+
+ @Override protected LombokImmutableList<String> getArgumentSuffixes() {
+ return SUFFIXES;
+ }
+
+ @Override protected String getAddMethodName() {
+ return "put";
+ }
+
+ @Override protected String getAddAllTypeName() {
+ return "java.util.Map";
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
new file mode 100644
index 00000000..326a9179
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSetListSingularizer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseGuavaSetListSingularizer extends EclipseGuavaSingularizer {
+ // TODO com.google.common.collect.ImmutableRangeSet
+ // TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset
+ private static final LombokImmutableList<String> SUFFIXES = LombokImmutableList.of("");
+ private static final LombokImmutableList<String> SUPPORTED_TYPES = LombokImmutableList.of(
+ "com.google.common.collect.ImmutableCollection",
+ "com.google.common.collect.ImmutableList",
+ "com.google.common.collect.ImmutableSet",
+ "com.google.common.collect.ImmutableSortedSet"
+ );
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return SUPPORTED_TYPES;
+ }
+
+ @Override protected LombokImmutableList<String> getArgumentSuffixes() {
+ return SUFFIXES;
+ }
+
+ @Override protected String getAddMethodName() {
+ return "add";
+ }
+
+ @Override protected String getAddAllTypeName() {
+ return "java.lang.Iterable";
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
new file mode 100644
index 00000000..8e925b3f
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaSingularizer.java
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2015-2017 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.core.GuavaTypeMap;
+import lombok.core.LombokImmutableList;
+import lombok.core.handlers.HandlerUtil;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+
+abstract class EclipseGuavaSingularizer extends EclipseSingularizer {
+ protected String getSimpleTargetTypeName(SingularData data) {
+ return GuavaTypeMap.getGuavaTypeName(data.getTargetFqn());
+ }
+
+ protected char[] getBuilderMethodName(SingularData data) {
+ String simpleTypeName = getSimpleTargetTypeName(data);
+ if ("ImmutableSortedSet".equals(simpleTypeName) || "ImmutableSortedMap".equals(simpleTypeName)) return "naturalOrder".toCharArray();
+ return "builder".toCharArray();
+ }
+
+ protected char[][] makeGuavaTypeName(String simpleName, boolean addBuilder) {
+ char[][] tokenizedName = new char[addBuilder ? 6 : 5][];
+ tokenizedName[0] = new char[] {'c', 'o', 'm'};
+ tokenizedName[1] = new char[] {'g', 'o', 'o', 'g', 'l', 'e'};
+ tokenizedName[2] = new char[] {'c', 'o', 'm', 'm', 'o', 'n'};
+ tokenizedName[3] = new char[] {'c', 'o', 'l', 'l', 'e', 'c', 't'};
+ tokenizedName[4] = simpleName.toCharArray();
+ if (addBuilder) tokenizedName[5] = new char[] { 'B', 'u', 'i', 'l', 'd', 'e', 'r'};
+ return tokenizedName;
+ }
+
+ @Override public List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
+ String simpleTypeName = getSimpleTargetTypeName(data);
+ char[][] tokenizedName = makeGuavaTypeName(simpleTypeName, true);
+ TypeReference type = new QualifiedTypeReference(tokenizedName, NULL_POSS);
+ type = addTypeArgs(getTypeArgumentsCount(), false, builderType, type, data.getTypeArgs());
+
+ FieldDeclaration buildField = new FieldDeclaration(data.getPluralName(), 0, -1);
+ buildField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ buildField.modifiers = ClassFileConstants.AccPrivate;
+ buildField.declarationSourceEnd = -1;
+ buildField.type = type;
+ data.setGeneratedByRecursive(buildField);
+ return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
+ }
+
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
+ TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateSingularMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generatePluralMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
+ }
+
+ void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ Assignment a = new Assignment(thisDotField, new NullLiteral(0, 0), 0);
+ md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray();
+ md.statements = returnStatement != null ? new Statement[] {a, returnStatement} : new Statement[] {a};
+ md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ injectMethod(builderType, md);
+ }
+
+ void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ LombokImmutableList<String> suffixes = getArgumentSuffixes();
+ char[][] names = new char[suffixes.size()][];
+ for (int i = 0; i < suffixes.size(); i++) {
+ String s = suffixes.get(i);
+ char[] n = data.getSingularName();
+ names[i] = s.isEmpty() ? n : s.toCharArray();
+ }
+
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType));
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldDotAdd = new MessageSend();
+ thisDotFieldDotAdd.arguments = new Expression[suffixes.size()];
+ for (int i = 0; i < suffixes.size(); i++) {
+ thisDotFieldDotAdd.arguments[i] = new SingleNameReference(names[i], 0L);
+ }
+ thisDotFieldDotAdd.receiver = thisDotField;
+ thisDotFieldDotAdd.selector = getAddMethodName().toCharArray();
+ statements.add(thisDotFieldDotAdd);
+ if (returnStatement != null) statements.add(returnStatement);
+ md.statements = statements.toArray(new Statement[statements.size()]);
+ md.arguments = new Argument[suffixes.size()];
+ for (int i = 0; i < suffixes.size(); i++) {
+ TypeReference tr = cloneParamType(i, data.getTypeArgs(), builderType);
+ md.arguments[i] = new Argument(names[i], 0, tr, 0);
+ }
+ md.returnType = returnType;
+ md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName(getAddMethodName(), new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType));
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldDotAddAll = new MessageSend();
+ thisDotFieldDotAddAll.arguments = new Expression[] {new SingleNameReference(data.getPluralName(), 0L)};
+ thisDotFieldDotAddAll.receiver = thisDotField;
+ thisDotFieldDotAddAll.selector = (getAddMethodName() + "All").toCharArray();
+ statements.add(thisDotFieldDotAddAll);
+ if (returnStatement != null) statements.add(returnStatement);
+
+ md.statements = statements.toArray(new Statement[statements.size()]);
+
+ TypeReference paramType;
+ paramType = new QualifiedTypeReference(fromQualifiedName(getAddAllTypeName()), NULL_POSS);
+ paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs());
+ Argument param = new Argument(data.getPluralName(), 0, paramType, 0);
+ md.arguments = new Argument[] {param};
+ md.returnType = returnType;
+ md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName(getAddMethodName() + "All", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
+ TypeReference varType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
+ String simpleTypeName = getSimpleTargetTypeName(data);
+ int agrumentsCount = getTypeArgumentsCount();
+ varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs());
+
+ MessageSend emptyInvoke; {
+ //ImmutableX.of()
+ emptyInvoke = new MessageSend();
+ emptyInvoke.selector = new char[] {'o', 'f'};
+ emptyInvoke.receiver = new QualifiedNameReference(makeGuavaTypeName(simpleTypeName, false), NULL_POSS, 0, 0);
+ emptyInvoke.typeArguments = createTypeArgs(agrumentsCount, false, builderType, data.getTypeArgs());
+ }
+
+ MessageSend invokeBuild; {
+ //this.pluralName.build();
+ invokeBuild = new MessageSend();
+ invokeBuild.selector = new char[] {'b', 'u', 'i', 'l', 'd'};
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ invokeBuild.receiver = thisDotField;
+ }
+
+ Expression isNull; {
+ //this.pluralName == null
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ isNull = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+ }
+
+ Expression init = new ConditionalExpression(isNull, emptyInvoke, invokeBuild);
+ LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0);
+ varDefStat.type = varType;
+ varDefStat.initialization = init;
+ statements.add(varDefStat);
+ }
+
+ protected Statement createConstructBuilderVarIfNeeded(SingularData data, EclipseNode builderType) {
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ FieldReference thisDotField2 = new FieldReference(data.getPluralName(), 0L);
+ thisDotField2.receiver = new ThisReference(0, 0);
+ Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+
+ MessageSend createBuilderInvoke = new MessageSend();
+ char[][] tokenizedName = makeGuavaTypeName(getSimpleTargetTypeName(data), false);
+ createBuilderInvoke.receiver = new QualifiedNameReference(tokenizedName, NULL_POSS, 0, 0);
+ createBuilderInvoke.selector = getBuilderMethodName(data);
+ return new IfStatement(cond, new Assignment(thisDotField2, createBuilderInvoke, 0), 0, 0);
+ }
+
+ protected abstract LombokImmutableList<String> getArgumentSuffixes();
+ protected abstract String getAddMethodName();
+ protected abstract String getAddAllTypeName();
+
+ protected int getTypeArgumentsCount() {
+ return getArgumentSuffixes().size();
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java
new file mode 100644
index 00000000..4d25811b
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseGuavaTableSingularizer.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseGuavaTableSingularizer extends EclipseGuavaSingularizer {
+ private static final LombokImmutableList<String> SUFFIXES =
+ LombokImmutableList.of("rowKey", "columnKey", "value");
+ private static final LombokImmutableList<String> SUPPORTED_TYPES =
+ LombokImmutableList.of("com.google.common.collect.ImmutableTable");
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return SUPPORTED_TYPES;
+ }
+
+ @Override protected LombokImmutableList<String> getArgumentSuffixes() {
+ return SUFFIXES;
+ }
+
+ @Override protected String getAddMethodName() {
+ return "put";
+ }
+
+ @Override protected String getAddAllTypeName() {
+ return "com.google.common.collect.Table";
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
new file mode 100644
index 00000000..cfa48eaf
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSetSingularizer.java
@@ -0,0 +1,189 @@
+/*
+ * Copyright (C) 2015-2017 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import static lombok.eclipse.Eclipse.ECLIPSE_DO_NOT_TOUCH_FLAG;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
+import lombok.core.handlers.HandlerUtil;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+
+abstract class EclipseJavaUtilListSetSingularizer extends EclipseJavaUtilSingularizer {
+ @Override public List<char[]> listFieldsToBeGenerated(SingularData data, EclipseNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaListSetSingularizer.listFieldsToBeGenerated(data, builderType);
+ }
+
+ return super.listFieldsToBeGenerated(data, builderType);
+ }
+
+ @Override public List<char[]> listMethodsToBeGenerated(SingularData data, EclipseNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaListSetSingularizer.listMethodsToBeGenerated(data, builderType);
+ }
+
+ return super.listMethodsToBeGenerated(data, builderType);
+ }
+
+ @Override public List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaListSetSingularizer.generateFields(data, builderType);
+ }
+
+ TypeReference type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
+ type = addTypeArgs(1, false, builderType, type, data.getTypeArgs());
+
+ FieldDeclaration buildField = new FieldDeclaration(data.getPluralName(), 0, -1);
+ buildField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ buildField.modifiers = ClassFileConstants.AccPrivate;
+ buildField.declarationSourceEnd = -1;
+ buildField.type = type;
+ data.setGeneratedByRecursive(buildField);
+ return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
+ }
+
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
+ if (useGuavaInstead(builderType)) {
+ guavaListSetSingularizer.generateMethods(data, deprecate, builderType, fluent, chain);
+ return;
+ }
+
+ TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateSingularMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generatePluralMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
+ }
+
+ private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ FieldReference thisDotField2 = new FieldReference(data.getPluralName(), 0L);
+ thisDotField2.receiver = new ThisReference(0, 0);
+ md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray();
+ MessageSend clearMsg = new MessageSend();
+ clearMsg.receiver = thisDotField2;
+ clearMsg.selector = "clear".toCharArray();
+ Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsg, 0, 0);
+ md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
+ md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+ injectMethod(builderType, md);
+ }
+
+ void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType, false));
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldDotAdd = new MessageSend();
+ thisDotFieldDotAdd.arguments = new Expression[] {new SingleNameReference(data.getSingularName(), 0L)};
+ thisDotFieldDotAdd.receiver = thisDotField;
+ thisDotFieldDotAdd.selector = "add".toCharArray();
+ statements.add(thisDotFieldDotAdd);
+ if (returnStatement != null) statements.add(returnStatement);
+
+ md.statements = statements.toArray(new Statement[statements.size()]);
+ TypeReference paramType = cloneParamType(0, data.getTypeArgs(), builderType);
+ Argument param = new Argument(data.getSingularName(), 0, paramType, 0);
+ md.arguments = new Argument[] {param};
+ md.returnType = returnType;
+ md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("add", new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType, false));
+
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldDotAddAll = new MessageSend();
+ thisDotFieldDotAddAll.arguments = new Expression[] {new SingleNameReference(data.getPluralName(), 0L)};
+ thisDotFieldDotAddAll.receiver = thisDotField;
+ thisDotFieldDotAddAll.selector = "addAll".toCharArray();
+ statements.add(thisDotFieldDotAddAll);
+ if (returnStatement != null) statements.add(returnStatement);
+
+ md.statements = statements.toArray(new Statement[statements.size()]);
+
+ TypeReference paramType = new QualifiedTypeReference(TypeConstants.JAVA_UTIL_COLLECTION, NULL_POSS);
+ paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs());
+ Argument param = new Argument(data.getPluralName(), 0, paramType, 0);
+ md.arguments = new Argument[] {param};
+ md.returnType = returnType;
+ md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("addAll", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java
new file mode 100644
index 00000000..576115b0
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilListSingularizer.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import static lombok.eclipse.handlers.EclipseHandlerUtil.makeIntLiteral;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.Eclipse;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
+import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.mangosdk.spi.ProviderFor;
+
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseJavaUtilListSingularizer extends EclipseJavaUtilListSetSingularizer {
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of("java.util.List", "java.util.Collection", "java.lang.Iterable");
+ }
+
+ @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
+ if (useGuavaInstead(builderType)) {
+ guavaListSetSingularizer.appendBuildCode(data, builderType, statements, targetVariableName);
+ return;
+ }
+
+ List<Statement> switchContents = new ArrayList<Statement>();
+
+ /* case 0: (empty) break; */ {
+ switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'0'}, null), 0, 0));
+ MessageSend invoke = new MessageSend();
+ invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
+ invoke.selector = "emptyList".toCharArray();
+ switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), invoke, 0));
+ switchContents.add(new BreakStatement(null, 0, 0));
+ }
+
+ /* case 1: (singleton) break; */ {
+ switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'1'}, null), 0, 0));
+ FieldReference thisDotField = new FieldReference(data.getPluralName(), 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotFieldGet0 = new MessageSend();
+ thisDotFieldGet0.receiver = thisDotField;
+ thisDotFieldGet0.selector = new char[] {'g', 'e', 't'};
+ thisDotFieldGet0.arguments = new Expression[] {makeIntLiteral(new char[] {'0'}, null)};
+
+ Expression[] args = new Expression[] {thisDotFieldGet0};
+ MessageSend invoke = new MessageSend();
+ invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
+ invoke.selector = "singletonList".toCharArray();
+ invoke.arguments = args;
+ switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), invoke, 0));
+ switchContents.add(new BreakStatement(null, 0, 0));
+ }
+
+ /* default: Create by passing builder field to constructor. */ {
+ switchContents.add(new CaseStatement(null, 0, 0));
+
+ Expression argToUnmodifiable;
+ /* new j.u.ArrayList<Generics>(this.pluralName); */ {
+ FieldReference thisDotPluralName = new FieldReference(data.getPluralName(), 0L);
+ thisDotPluralName.receiver = new ThisReference(0, 0);
+ TypeReference targetTypeExpr = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
+ targetTypeExpr = addTypeArgs(1, false, builderType, targetTypeExpr, data.getTypeArgs());
+ AllocationExpression constructorCall = new AllocationExpression();
+ constructorCall.type = targetTypeExpr;
+ constructorCall.arguments = new Expression[] {thisDotPluralName};
+ argToUnmodifiable = constructorCall;
+ }
+
+ /* pluralname = Collections.unmodifiableList(-newlist-); */ {
+ MessageSend unmodInvoke = new MessageSend();
+ unmodInvoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
+ unmodInvoke.selector = "unmodifiableList".toCharArray();
+ unmodInvoke.arguments = new Expression[] {argToUnmodifiable};
+ switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), unmodInvoke, 0));
+ }
+ }
+
+ SwitchStatement switchStat = new SwitchStatement();
+ switchStat.statements = switchContents.toArray(new Statement[switchContents.size()]);
+ switchStat.expression = getSize(builderType, data.getPluralName(), true);
+
+ TypeReference localShadowerType = new QualifiedTypeReference(Eclipse.fromQualifiedName(data.getTargetFqn()), NULL_POSS);
+ localShadowerType = addTypeArgs(1, false, builderType, localShadowerType, data.getTypeArgs());
+ LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0);
+ varDefStat.type = localShadowerType;
+ statements.add(varDefStat);
+ statements.add(switchStat);
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
new file mode 100644
index 00000000..9aac32a3
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilMapSingularizer.java
@@ -0,0 +1,313 @@
+/*
+ * Copyright (C) 2015-2017 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.Argument;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.ReturnStatement;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.core.handlers.HandlerUtil;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseJavaUtilMapSingularizer extends EclipseJavaUtilSingularizer {
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
+ }
+
+ @Override public List<char[]> listFieldsToBeGenerated(SingularData data, EclipseNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaMapSingularizer.listFieldsToBeGenerated(data, builderType);
+ }
+
+ char[] p = data.getPluralName();
+ int len = p.length;
+ char[] k = new char[len + 4];
+ char[] v = new char[len + 6];
+ System.arraycopy(p, 0, k, 0, len);
+ System.arraycopy(p, 0, v, 0, len);
+ k[len] = '$';
+ k[len + 1] = 'k';
+ k[len + 2] = 'e';
+ k[len + 3] = 'y';
+ v[len] = '$';
+ v[len + 1] = 'v';
+ v[len + 2] = 'a';
+ v[len + 3] = 'l';
+ v[len + 4] = 'u';
+ v[len + 5] = 'e';
+ return Arrays.asList(k, v);
+ }
+
+ @Override public List<char[]> listMethodsToBeGenerated(SingularData data, EclipseNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaMapSingularizer.listFieldsToBeGenerated(data, builderType);
+ } else {
+ return super.listMethodsToBeGenerated(data, builderType);
+ }
+ }
+
+ @Override public List<EclipseNode> generateFields(SingularData data, EclipseNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaMapSingularizer.generateFields(data, builderType);
+ }
+
+ char[] keyName = (new String(data.getPluralName()) + "$key").toCharArray();
+ char[] valueName = (new String(data.getPluralName()) + "$value").toCharArray();
+ FieldDeclaration buildKeyField; {
+ TypeReference type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
+ type = addTypeArgs(1, false, builderType, type, data.getTypeArgs());
+ buildKeyField = new FieldDeclaration(keyName, 0, -1);
+ buildKeyField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ buildKeyField.modifiers = ClassFileConstants.AccPrivate;
+ buildKeyField.declarationSourceEnd = -1;
+ buildKeyField.type = type;
+ }
+ FieldDeclaration buildValueField; {
+ TypeReference type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
+ List<TypeReference> tArgs = data.getTypeArgs();
+ if (tArgs != null && tArgs.size() > 1) tArgs = Collections.singletonList(tArgs.get(1));
+ else tArgs = Collections.emptyList();
+ type = addTypeArgs(1, false, builderType, type, tArgs);
+ buildValueField = new FieldDeclaration(valueName, 0, -1);
+ buildValueField.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ buildValueField.modifiers = ClassFileConstants.AccPrivate;
+ buildValueField.declarationSourceEnd = -1;
+ buildValueField.type = type;
+ }
+ data.setGeneratedByRecursive(buildKeyField);
+ data.setGeneratedByRecursive(buildValueField);
+ EclipseNode keyFieldNode = injectFieldAndMarkGenerated(builderType, buildKeyField);
+ EclipseNode valueFieldNode = injectFieldAndMarkGenerated(builderType, buildValueField);
+ return Arrays.asList(keyFieldNode, valueFieldNode);
+ }
+
+ @Override public void generateMethods(SingularData data, boolean deprecate, EclipseNode builderType, boolean fluent, boolean chain) {
+ if (useGuavaInstead(builderType)) {
+ guavaMapSingularizer.generateMethods(data, deprecate, builderType, fluent, chain);
+ return;
+ }
+
+ TypeReference returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ Statement returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateSingularMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generatePluralMethod(deprecate, returnType, returnStatement, data, builderType, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : TypeReference.baseTypeReference(TypeIds.T_void, 0);
+ returnStatement = chain ? new ReturnStatement(new ThisReference(0, 0), 0, 0) : null;
+ generateClearMethod(deprecate, returnType, returnStatement, data, builderType);
+ }
+
+ private void generateClearMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ String pN = new String(data.getPluralName());
+ char[] keyFieldName = (pN + "$key").toCharArray();
+ char[] valueFieldName = (pN + "$value").toCharArray();
+
+ FieldReference thisDotField = new FieldReference(keyFieldName, 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ FieldReference thisDotField2 = new FieldReference(keyFieldName, 0L);
+ thisDotField2.receiver = new ThisReference(0, 0);
+ FieldReference thisDotField3 = new FieldReference(valueFieldName, 0L);
+ thisDotField3.receiver = new ThisReference(0, 0);
+ md.selector = HandlerUtil.buildAccessorName("clear", new String(data.getPluralName())).toCharArray();
+ MessageSend clearMsg1 = new MessageSend();
+ clearMsg1.receiver = thisDotField2;
+ clearMsg1.selector = "clear".toCharArray();
+ MessageSend clearMsg2 = new MessageSend();
+ clearMsg2.receiver = thisDotField3;
+ clearMsg2.selector = "clear".toCharArray();
+ Block clearMsgs = new Block(2);
+ clearMsgs.statements = new Statement[] {clearMsg1, clearMsg2};
+ Statement clearStatement = new IfStatement(new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL), clearMsgs, 0, 0);
+ md.statements = returnStatement != null ? new Statement[] {clearStatement, returnStatement} : new Statement[] {clearStatement};
+ md.returnType = returnType;
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ injectMethod(builderType, md);
+ }
+
+ private void generateSingularMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType, true));
+
+ String sN = new String(data.getSingularName());
+ String pN = new String(data.getPluralName());
+ char[] keyParamName = (sN + "Key").toCharArray();
+ char[] valueParamName = (sN + "Value").toCharArray();
+ char[] keyFieldName = (pN + "$key").toCharArray();
+ char[] valueFieldName = (pN + "$value").toCharArray();
+
+ /* this.pluralname$key.add(singularnameKey); */ {
+ FieldReference thisDotKeyField = new FieldReference(keyFieldName, 0L);
+ thisDotKeyField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotKeyFieldDotAdd = new MessageSend();
+ thisDotKeyFieldDotAdd.arguments = new Expression[] {new SingleNameReference(keyParamName, 0L)};
+ thisDotKeyFieldDotAdd.receiver = thisDotKeyField;
+ thisDotKeyFieldDotAdd.selector = "add".toCharArray();
+ statements.add(thisDotKeyFieldDotAdd);
+ }
+
+ /* this.pluralname$value.add(singularnameValue); */ {
+ FieldReference thisDotValueField = new FieldReference(valueFieldName, 0L);
+ thisDotValueField.receiver = new ThisReference(0, 0);
+ MessageSend thisDotValueFieldDotAdd = new MessageSend();
+ thisDotValueFieldDotAdd.arguments = new Expression[] {new SingleNameReference(valueParamName, 0L)};
+ thisDotValueFieldDotAdd.receiver = thisDotValueField;
+ thisDotValueFieldDotAdd.selector = "add".toCharArray();
+ statements.add(thisDotValueFieldDotAdd);
+ }
+ if (returnStatement != null) statements.add(returnStatement);
+
+ md.statements = statements.toArray(new Statement[statements.size()]);
+ TypeReference keyParamType = cloneParamType(0, data.getTypeArgs(), builderType);
+ Argument keyParam = new Argument(keyParamName, 0, keyParamType, 0);
+ TypeReference valueParamType = cloneParamType(1, data.getTypeArgs(), builderType);
+ Argument valueParam = new Argument(valueParamName, 0, valueParamType, 0);
+ md.arguments = new Argument[] {keyParam, valueParam};
+ md.returnType = returnType;
+ md.selector = fluent ? data.getSingularName() : HandlerUtil.buildAccessorName("put", new String(data.getSingularName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ private void generatePluralMethod(boolean deprecate, TypeReference returnType, Statement returnStatement, SingularData data, EclipseNode builderType, boolean fluent) {
+ MethodDeclaration md = new MethodDeclaration(((CompilationUnitDeclaration) builderType.top().get()).compilationResult);
+ md.bits |= ECLIPSE_DO_NOT_TOUCH_FLAG;
+ md.modifiers = ClassFileConstants.AccPublic;
+
+ String pN = new String(data.getPluralName());
+ char[] keyFieldName = (pN + "$key").toCharArray();
+ char[] valueFieldName = (pN + "$value").toCharArray();
+
+ List<Statement> statements = new ArrayList<Statement>();
+ statements.add(createConstructBuilderVarIfNeeded(data, builderType, true));
+
+ char[] entryName = "$lombokEntry".toCharArray();
+
+ TypeReference forEachType = new QualifiedTypeReference(JAVA_UTIL_MAP_ENTRY, NULL_POSS);
+ forEachType = addTypeArgs(2, true, builderType, forEachType, data.getTypeArgs());
+
+ MessageSend keyArg = new MessageSend();
+ keyArg.receiver = new SingleNameReference(entryName, 0L);
+ keyArg.selector = "getKey".toCharArray();
+ MessageSend addKey = new MessageSend();
+ FieldReference thisDotKeyField = new FieldReference(keyFieldName, 0L);
+ thisDotKeyField.receiver = new ThisReference(0, 0);
+ addKey.receiver = thisDotKeyField;
+ addKey.selector = new char[] {'a', 'd', 'd'};
+ addKey.arguments = new Expression[] {keyArg};
+
+ MessageSend valueArg = new MessageSend();
+ valueArg.receiver = new SingleNameReference(entryName, 0L);
+ valueArg.selector = "getValue".toCharArray();
+ MessageSend addValue = new MessageSend();
+ FieldReference thisDotValueField = new FieldReference(valueFieldName, 0L);
+ thisDotValueField.receiver = new ThisReference(0, 0);
+ addValue.receiver = thisDotValueField;
+ addValue.selector = new char[] {'a', 'd', 'd'};
+ addValue.arguments = new Expression[] {valueArg};
+
+ LocalDeclaration elementVariable = new LocalDeclaration(entryName, 0, 0);
+ elementVariable.type = forEachType;
+ ForeachStatement forEach = new ForeachStatement(elementVariable, 0);
+ MessageSend invokeEntrySet = new MessageSend();
+ invokeEntrySet.selector = new char[] { 'e', 'n', 't', 'r', 'y', 'S', 'e', 't'};
+ invokeEntrySet.receiver = new SingleNameReference(data.getPluralName(), 0L);
+ forEach.collection = invokeEntrySet;
+ Block forEachContent = new Block(0);
+ forEachContent.statements = new Statement[] {addKey, addValue};
+ forEach.action = forEachContent;
+ statements.add(forEach);
+ if (returnStatement != null) statements.add(returnStatement);
+
+ md.statements = statements.toArray(new Statement[statements.size()]);
+
+ TypeReference paramType = new QualifiedTypeReference(JAVA_UTIL_MAP, NULL_POSS);
+ paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs());
+ Argument param = new Argument(data.getPluralName(), 0, paramType, 0);
+ md.arguments = new Argument[] {param};
+ md.returnType = returnType;
+ md.selector = fluent ? data.getPluralName() : HandlerUtil.buildAccessorName("putAll", new String(data.getPluralName())).toCharArray();
+ md.annotations = deprecate ? new Annotation[] { generateDeprecatedAnnotation(data.getSource()) } : null;
+
+ data.setGeneratedByRecursive(md);
+ injectMethod(builderType, md);
+ }
+
+ @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
+ if (useGuavaInstead(builderType)) {
+ guavaMapSingularizer.appendBuildCode(data, builderType, statements, targetVariableName);
+ return;
+ }
+
+ if (data.getTargetFqn().equals("java.util.Map")) {
+ statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, true, "emptyMap", "singletonMap", "LinkedHashMap"));
+ } else {
+ statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, true, true, false, true, "TreeMap"));
+ }
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java
new file mode 100644
index 00000000..2d16eae0
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSetSingularizer.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import java.util.List;
+
+import lombok.core.LombokImmutableList;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.mangosdk.spi.ProviderFor;
+
+@ProviderFor(EclipseSingularizer.class)
+public class EclipseJavaUtilSetSingularizer extends EclipseJavaUtilListSetSingularizer {
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of("java.util.Set", "java.util.SortedSet", "java.util.NavigableSet");
+ }
+
+ @Override public void appendBuildCode(SingularData data, EclipseNode builderType, List<Statement> statements, char[] targetVariableName) {
+ if (useGuavaInstead(builderType)) {
+ guavaListSetSingularizer.appendBuildCode(data, builderType, statements, targetVariableName);
+ return;
+ }
+
+ if (data.getTargetFqn().equals("java.util.Set")) {
+ statements.addAll(createJavaUtilSetMapInitialCapacitySwitchStatements(data, builderType, false, "emptySet", "singleton", "LinkedHashSet"));
+ } else {
+ statements.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, false, true, false, true, "TreeSet"));
+ }
+ }
+}
diff --git a/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java
new file mode 100644
index 00000000..6661f4af
--- /dev/null
+++ b/src/core/lombok/eclipse/handlers/singulars/EclipseJavaUtilSingularizer.java
@@ -0,0 +1,300 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.handlers.singulars;
+
+import static lombok.eclipse.Eclipse.*;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.List;
+
+import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
+import org.eclipse.jdt.internal.compiler.ast.Assignment;
+import org.eclipse.jdt.internal.compiler.ast.BinaryExpression;
+import org.eclipse.jdt.internal.compiler.ast.Block;
+import org.eclipse.jdt.internal.compiler.ast.BreakStatement;
+import org.eclipse.jdt.internal.compiler.ast.CaseStatement;
+import org.eclipse.jdt.internal.compiler.ast.ConditionalExpression;
+import org.eclipse.jdt.internal.compiler.ast.EqualExpression;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldReference;
+import org.eclipse.jdt.internal.compiler.ast.ForStatement;
+import org.eclipse.jdt.internal.compiler.ast.IfStatement;
+import org.eclipse.jdt.internal.compiler.ast.IntLiteral;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.ast.NullLiteral;
+import org.eclipse.jdt.internal.compiler.ast.OperatorIds;
+import org.eclipse.jdt.internal.compiler.ast.PostfixExpression;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedNameReference;
+import org.eclipse.jdt.internal.compiler.ast.QualifiedTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.SingleNameReference;
+import org.eclipse.jdt.internal.compiler.ast.Statement;
+import org.eclipse.jdt.internal.compiler.ast.SwitchStatement;
+import org.eclipse.jdt.internal.compiler.ast.ThisReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
+import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
+import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+
+import lombok.ConfigurationKeys;
+import lombok.eclipse.EclipseNode;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.EclipseSingularizer;
+import lombok.eclipse.handlers.EclipseSingularsRecipes.SingularData;
+
+abstract class EclipseJavaUtilSingularizer extends EclipseSingularizer {
+ protected static final char[][] JAVA_UTIL_ARRAYLIST = {
+ {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'A', 'r', 'r', 'a', 'y', 'L', 'i', 's', 't'}
+ };
+
+ protected static final char[][] JAVA_UTIL_LIST = {
+ {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'L', 'i', 's', 't'}
+ };
+
+ protected static final char[][] JAVA_UTIL_MAP = {
+ {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'}
+ };
+
+ protected static final char[][] JAVA_UTIL_MAP_ENTRY = {
+ {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'M', 'a', 'p'}, {'E', 'n', 't', 'r', 'y'}
+ };
+
+ protected static final char[][] JAVA_UTIL_COLLECTIONS = {
+ {'j', 'a', 'v', 'a'}, {'u', 't', 'i', 'l'}, {'C', 'o', 'l', 'l', 'e', 'c', 't', 'i', 'o', 'n', 's'}
+ };
+
+ protected final EclipseSingularizer guavaListSetSingularizer = new EclipseGuavaSetListSingularizer();
+ protected final EclipseSingularizer guavaMapSingularizer = new EclipseGuavaMapSingularizer();
+
+ protected boolean useGuavaInstead(EclipseNode node) {
+ return Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_USE_GUAVA));
+ }
+
+ protected List<Statement> createJavaUtilSetMapInitialCapacitySwitchStatements(SingularData data, EclipseNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType) {
+ List<Statement> switchContents = new ArrayList<Statement>();
+ char[] keyName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName();
+
+ if (emptyCollectionMethod != null) { // case 0: (empty); break;
+ switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'0'}, null), 0, 0));
+
+ /* pluralName = java.util.Collections.emptyCollectionMethod(); */ {
+ MessageSend invoke = new MessageSend();
+ invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
+ invoke.selector = emptyCollectionMethod.toCharArray();
+ switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), invoke, 0));
+ }
+
+ switchContents.add(new BreakStatement(null, 0, 0));
+ }
+
+ if (singletonCollectionMethod != null) { // case 1: (singleton); break;
+ switchContents.add(new CaseStatement(makeIntLiteral(new char[] {'1'}, null), 0, 0));
+ /* !mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName.get(0));
+ mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName$key.get(0), this.pluralName$value.get(0)); */ {
+ FieldReference thisDotKey = new FieldReference(keyName, 0L);
+ thisDotKey.receiver = new ThisReference(0, 0);
+ MessageSend thisDotKeyGet0 = new MessageSend();
+ thisDotKeyGet0.receiver = thisDotKey;
+ thisDotKeyGet0.selector = new char[] {'g', 'e', 't'};
+ thisDotKeyGet0.arguments = new Expression[] {makeIntLiteral(new char[] {'0'}, null)};
+
+ Expression[] args;
+ if (mapMode) {
+ char[] valueName = (new String(data.getPluralName()) + "$value").toCharArray();
+ FieldReference thisDotValue = new FieldReference(valueName, 0L);
+ thisDotValue.receiver = new ThisReference(0, 0);
+ MessageSend thisDotValueGet0 = new MessageSend();
+ thisDotValueGet0.receiver = thisDotValue;
+ thisDotValueGet0.selector = new char[] {'g', 'e', 't'};
+ thisDotValueGet0.arguments = new Expression[] {makeIntLiteral(new char[] {'0'}, null)};
+ args = new Expression[] {thisDotKeyGet0, thisDotValueGet0};
+ } else {
+ args = new Expression[] {thisDotKeyGet0};
+ }
+
+ MessageSend invoke = new MessageSend();
+ invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
+ invoke.selector = singletonCollectionMethod.toCharArray();
+ invoke.arguments = args;
+ switchContents.add(new Assignment(new SingleNameReference(data.getPluralName(), 0), invoke, 0));
+ }
+ switchContents.add(new BreakStatement(null, 0, 0));
+ }
+
+ { // default:
+ switchContents.add(new CaseStatement(null, 0, 0));
+ switchContents.addAll(createJavaUtilSimpleCreationAndFillStatements(data, builderType, mapMode, false, true, emptyCollectionMethod == null, targetType));
+ }
+
+ SwitchStatement switchStat = new SwitchStatement();
+ switchStat.statements = switchContents.toArray(new Statement[switchContents.size()]);
+ switchStat.expression = getSize(builderType, keyName, true);
+
+ TypeReference localShadowerType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
+ localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs());
+ LocalDeclaration varDefStat = new LocalDeclaration(data.getPluralName(), 0, 0);
+ varDefStat.type = localShadowerType;
+ return Arrays.asList(varDefStat, switchStat);
+ }
+
+ protected List<Statement> createJavaUtilSimpleCreationAndFillStatements(SingularData data, EclipseNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType) {
+ char[] varName = mapMode ? (new String(data.getPluralName()) + "$key").toCharArray() : data.getPluralName();
+
+ Statement createStat; {
+ // pluralName = new java.util.TargetType(initialCap);
+ Expression[] constructorArgs = null;
+ if (addInitialCapacityArg) {
+ // this.varName.size() < MAX_POWER_OF_2 ? 1 + this.varName.size() + (this.varName.size() - 3) / 3 : Integer.MAX_VALUE;
+ // lessThanCutOff = this.varName.size() < MAX_POWER_OF_2
+ Expression lessThanCutoff = new BinaryExpression(getSize(builderType, varName, nullGuard), makeIntLiteral("0x40000000".toCharArray(), null), OperatorIds.LESS);
+ FieldReference integerMaxValue = new FieldReference("MAX_VALUE".toCharArray(), 0L);
+ integerMaxValue.receiver = new QualifiedNameReference(TypeConstants.JAVA_LANG_INTEGER, NULL_POSS, 0, 0);
+ Expression sizeFormulaLeft = new BinaryExpression(makeIntLiteral(new char[] {'1'}, null), getSize(builderType, varName, nullGuard), OperatorIds.PLUS);
+ Expression sizeFormulaRightLeft = new BinaryExpression(getSize(builderType, varName, nullGuard), makeIntLiteral(new char[] {'3'}, null), OperatorIds.MINUS);
+ Expression sizeFormulaRight = new BinaryExpression(sizeFormulaRightLeft, makeIntLiteral(new char[] {'3'}, null), OperatorIds.DIVIDE);
+ Expression sizeFormula = new BinaryExpression(sizeFormulaLeft, sizeFormulaRight, OperatorIds.PLUS);
+ Expression cond = new ConditionalExpression(lessThanCutoff, sizeFormula, integerMaxValue);
+ constructorArgs = new Expression[] {cond};
+ }
+
+ TypeReference targetTypeRef = new QualifiedTypeReference(new char[][] {TypeConstants.JAVA, TypeConstants.UTIL, targetType.toCharArray()}, NULL_POSS);
+ targetTypeRef = addTypeArgs(mapMode ? 2 : 1, false, builderType, targetTypeRef, data.getTypeArgs());
+ AllocationExpression constructorCall = new AllocationExpression();
+ constructorCall.type = targetTypeRef;
+ constructorCall.arguments = constructorArgs;
+
+ if (defineVar) {
+ TypeReference localShadowerType = new QualifiedTypeReference(fromQualifiedName(data.getTargetFqn()), NULL_POSS);
+ localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs());
+ LocalDeclaration localShadowerDecl = new LocalDeclaration(data.getPluralName(), 0, 0);
+ localShadowerDecl.type = localShadowerType;
+ localShadowerDecl.initialization = constructorCall;
+ createStat = localShadowerDecl;
+ } else {
+ createStat = new Assignment(new SingleNameReference(data.getPluralName(), 0L), constructorCall, 0);
+ }
+ }
+
+ Statement fillStat; {
+ if (mapMode) {
+ // for (int $i = 0; $i < this.pluralname$key.size(); i++) pluralname.put(this.pluralname$key.get($i), this.pluralname$value.get($i));
+ char[] iVar = new char[] {'$', 'i'};
+ MessageSend pluralnameDotPut = new MessageSend();
+ pluralnameDotPut.selector = new char[] {'p', 'u', 't'};
+ pluralnameDotPut.receiver = new SingleNameReference(data.getPluralName(), 0L);
+ FieldReference thisDotKey = new FieldReference(varName, 0L);
+ thisDotKey.receiver = new ThisReference(0, 0);
+ FieldReference thisDotValue = new FieldReference((new String(data.getPluralName()) + "$value").toCharArray(), 0L);
+ thisDotValue.receiver = new ThisReference(0, 0);
+ MessageSend keyArg = new MessageSend();
+ keyArg.receiver = thisDotKey;
+ keyArg.arguments = new Expression[] {new SingleNameReference(iVar, 0L)};
+ keyArg.selector = new char[] {'g', 'e', 't'};
+ MessageSend valueArg = new MessageSend();
+ valueArg.receiver = thisDotValue;
+ valueArg.arguments = new Expression[] {new SingleNameReference(iVar, 0L)};
+ valueArg.selector = new char[] {'g', 'e', 't'};
+ pluralnameDotPut.arguments = new Expression[] {keyArg, valueArg};
+
+ LocalDeclaration forInit = new LocalDeclaration(iVar, 0, 0);
+ forInit.type = TypeReference.baseTypeReference(TypeIds.T_int, 0);
+ forInit.initialization = makeIntLiteral(new char[] {'0'}, null);
+ Expression checkExpr = new BinaryExpression(new SingleNameReference(iVar, 0L), getSize(builderType, varName, nullGuard), OperatorIds.LESS);
+ Expression incrementExpr = new PostfixExpression(new SingleNameReference(iVar, 0L), IntLiteral.One, OperatorIds.PLUS, 0);
+ fillStat = new ForStatement(new Statement[] {forInit}, checkExpr, new Statement[] {incrementExpr}, pluralnameDotPut, true, 0, 0);
+ } else {
+ // pluralname.addAll(this.pluralname);
+ MessageSend pluralnameDotAddAll = new MessageSend();
+ pluralnameDotAddAll.selector = new char[] {'a', 'd', 'd', 'A', 'l', 'l'};
+ pluralnameDotAddAll.receiver = new SingleNameReference(data.getPluralName(), 0L);
+ FieldReference thisDotPluralname = new FieldReference(varName, 0L);
+ thisDotPluralname.receiver = new ThisReference(0, 0);
+ pluralnameDotAddAll.arguments = new Expression[] {thisDotPluralname};
+ fillStat = pluralnameDotAddAll;
+ }
+
+ if (nullGuard) {
+ FieldReference thisDotField = new FieldReference(varName, 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.NOT_EQUAL);
+ fillStat = new IfStatement(cond, fillStat, 0, 0);
+ }
+ }
+
+ Statement unmodifiableStat; {
+ // pluralname = Collections.unmodifiableInterfaceType(pluralname);
+ Expression arg = new SingleNameReference(data.getPluralName(), 0L);
+ MessageSend invoke = new MessageSend();
+ invoke.arguments = new Expression[] {arg};
+ invoke.selector = ("unmodifiable" + data.getTargetSimpleType()).toCharArray();
+ invoke.receiver = new QualifiedNameReference(JAVA_UTIL_COLLECTIONS, NULL_POSS, 0, 0);
+ unmodifiableStat = new Assignment(new SingleNameReference(data.getPluralName(), 0L), invoke, 0);
+ }
+
+ return Arrays.asList(createStat, fillStat, unmodifiableStat);
+ }
+
+ protected Statement createConstructBuilderVarIfNeeded(SingularData data, EclipseNode builderType, boolean mapMode) {
+ char[] v1Name, v2Name;
+ if (mapMode) {
+ String n = new String(data.getPluralName());
+ v1Name = (n + "$key").toCharArray();
+ v2Name = (n + "$value").toCharArray();
+ } else {
+ v1Name = data.getPluralName();
+ v2Name = null;
+ }
+
+ FieldReference thisDotField = new FieldReference(v1Name, 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ Expression cond = new EqualExpression(thisDotField, new NullLiteral(0, 0), OperatorIds.EQUAL_EQUAL);
+
+ thisDotField = new FieldReference(v1Name, 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ TypeReference v1Type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
+ v1Type = addTypeArgs(1, false, builderType, v1Type, data.getTypeArgs());
+ AllocationExpression constructArrayList = new AllocationExpression();
+ constructArrayList.type = v1Type;
+ Assignment initV1 = new Assignment(thisDotField, constructArrayList, 0);
+ Statement thenPart;
+ if (mapMode) {
+ thisDotField = new FieldReference(v2Name, 0L);
+ thisDotField.receiver = new ThisReference(0, 0);
+ TypeReference v2Type = new QualifiedTypeReference(JAVA_UTIL_ARRAYLIST, NULL_POSS);
+ List<TypeReference> tArgs = data.getTypeArgs();
+ if (tArgs != null && tArgs.size() > 1) tArgs = Collections.singletonList(tArgs.get(1));
+ else tArgs = Collections.emptyList();
+ v2Type = addTypeArgs(1, false, builderType, v2Type, tArgs);
+ constructArrayList = new AllocationExpression();
+ constructArrayList.type = v2Type;
+ Assignment initV2 = new Assignment(thisDotField, constructArrayList, 0);
+ Block b = new Block(0);
+ b.statements = new Statement[] {initV1, initV2};
+ thenPart = b;
+ } else {
+ thenPart = initV1;
+ }
+
+ return new IfStatement(cond, thenPart, 0, 0);
+ }
+}
diff --git a/src/core/lombok/experimental/Accessors.java b/src/core/lombok/experimental/Accessors.java
index c2a0ca16..dc9ae4b0 100644
--- a/src/core/lombok/experimental/Accessors.java
+++ b/src/core/lombok/experimental/Accessors.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* A container for settings for the generation of getters and setters.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Accessors.html">the project lombok features page for &#64;Accessors</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Accessors">the project lombok features page for &#64;Accessors</a>.
* <p>
* Using this annotation does nothing by itself; an annotation that makes lombok generate getters and setters,
* such as {@link lombok.Setter} or {@link lombok.Data} is also required.
@@ -38,15 +38,19 @@ import java.lang.annotation.Target;
@Retention(RetentionPolicy.SOURCE)
public @interface Accessors {
/**
- * If true, accessors will be named after the field and not include a <code>get</code> or <code>set</code>
- * prefix. If true and <code>chain</code> is omitted, <code>chain</code> defaults to <code>true</code>.
+ * If true, accessors will be named after the field and not include a {@code get} or {@code set}
+ * prefix. If true and {@code chain} is omitted, {@code chain} defaults to {@code true}.
* <strong>default: false</strong>
+ *
+ * @return Whether or not to make fluent methods (named {@code fieldName()}, not for example {@code setFieldName}).
*/
boolean fluent() default false;
/**
- * If true, setters return <code>this</code> instead of <code>void</code>.
- * <strong>default: false</strong>, unless <code>fluent=true</code>, then <strong>default: true</code>
+ * If true, setters return {@code this} instead of {@code void}.
+ * <strong>default: false</strong>, unless {@code fluent=true}, then <strong>default: true</strong>
+ *
+ * @return Whether or not setters should return themselves (chaining) or {@code void} (no chaining).
*/
boolean chain() default false;
@@ -55,6 +59,8 @@ public @interface Accessors {
* Note that a prefix only counts if the next character is NOT a lowercase character or the last
* letter of the prefix is not a letter (for instance an underscore). If multiple fields
* all turn into the same name when the prefix is stripped, an error will be generated.
+ *
+ * @return If you are in the habit of prefixing your fields (for example, you name them {@code fFieldName}, specify such prefixes here).
*/
String[] prefix() default {};
}
diff --git a/src/core/lombok/experimental/Delegate.java b/src/core/lombok/experimental/Delegate.java
index 806d5871..cc844526 100644
--- a/src/core/lombok/experimental/Delegate.java
+++ b/src/core/lombok/experimental/Delegate.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -40,7 +40,7 @@ import java.lang.annotation.Target;
* that exist in {@link Object}, the {@code canEqual(Object)} method, and any methods that appear in types
* that are listed in the {@code excludes} property.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Delegate.html">the project lombok features page for &#64;Delegate</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Delegate">the project lombok features page for &#64;Delegate</a>.
*/
@Target({ElementType.FIELD, ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
@@ -52,6 +52,8 @@ public @interface Delegate {
* type listed here is used only to determine which delegate methods to generate.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, generate a delegate method.
*/
Class<?>[] types() default {};
@@ -59,6 +61,8 @@ public @interface Delegate {
* Each method in any of the types listed here (include supertypes) will <em>not</em> be delegated.
*
* NB: All methods in {@code Object}, as well as {@code canEqual(Object other)} will never be delegated.
+ *
+ * @return For each method (not already in {@code java.lang.Object}) in these types, skip generating a delegate method (overrides {@code types()}).
*/
Class<?>[] excludes() default {};
}
diff --git a/src/core/lombok/experimental/ExtensionMethod.java b/src/core/lombok/experimental/ExtensionMethod.java
index 7de8a136..af38f6ed 100644
--- a/src/core/lombok/experimental/ExtensionMethod.java
+++ b/src/core/lombok/experimental/ExtensionMethod.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,8 +31,8 @@ import java.lang.annotation.*;
* otherwise modifying the original type. Extension methods are a special kind of static method, but they are called as
* if they were instance methods on the extended type.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/ExtensionMethod.html">the project lombok features page for &#64;ExtensionMethod</a>.
- * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/ExtensionMethod">the project lombok features page for &#64;ExtensionMethod</a>.
+ * <br>
* <p>
* Before:
*
@@ -60,12 +60,14 @@ import java.lang.annotation.*;
@Target(TYPE)
@Retention(SOURCE)
public @interface ExtensionMethod {
- /** All types whose static methods will be exposed as extension methods. */
+ /** @return All types whose static methods will be exposed as extension methods. */
Class<?>[] value();
/**
* If {@code true}, an applicable extension method is used (if found) even if the method call already was compilable (this is the default).
* If {@code false}, an extension method is only used if the method call is not also defined by the type itself.
+ *
+ * @return Whether or not to override already existing methods with the extension.
*/
boolean suppressBaseMethods() default true;
}
diff --git a/src/core/lombok/experimental/FieldDefaults.java b/src/core/lombok/experimental/FieldDefaults.java
index 1c621f3c..5c387bb6 100644
--- a/src/core/lombok/experimental/FieldDefaults.java
+++ b/src/core/lombok/experimental/FieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,11 +31,11 @@ import lombok.AccessLevel;
/**
* Adds modifiers to each field in the type with this annotation.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/FieldDefaults.html">the project lombok features page for &#64;FieldDefaults</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/FieldDefaults">the project lombok features page for &#64;FieldDefaults</a>.
* <p>
- * If {@code makeFinal} is {@code true}, then each field that is not annotated with {@code @NonFinal} will have the {@code final} modifier added.
+ * If {@code makeFinal} is {@code true}, then each (instance) field that is not annotated with {@code @NonFinal} will have the {@code final} modifier added.
* <p>
- * If {@code level} is set, then each field that is package private (i.e. no access modifier) and does not have the {@code @PackagePrivate} annotation will
+ * If {@code level} is set, then each (instance) field that is package private (i.e. no access modifier) and does not have the {@code @PackagePrivate} annotation will
* have the appropriate access level modifier added.
*/
@Target(ElementType.TYPE)
diff --git a/src/core/lombok/experimental/Value.java b/src/core/lombok/experimental/Helper.java
index b7700bb5..34745cbe 100644
--- a/src/core/lombok/experimental/Value.java
+++ b/src/core/lombok/experimental/Helper.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2015 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
@@ -27,34 +27,9 @@ import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
- * Generates a lot of code which fits with a class that is a representation of an immutable entity.
- * <p>
- * Equivalent to {@code @Getter @FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE) @RequiredArgsConstructor @ToString @EqualsAndHashCode}.
- * <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Value.html">the project lombok features page for &#64;Value</a>.
- *
- * @see lombok.Getter
- * @see Wither
- * @see lombok.RequiredArgsConstructor
- * @see lombok.ToString
- * @see lombok.EqualsAndHashCode
- * @see lombok.Data
- * @deprecated {@link lombok.Value} has been promoted to the main package, so use that one instead.
+ * Use on a method local class to indicate that all methods inside should be exposed to the rest of
+ * the method as if they were helper methods.
*/
@Target(ElementType.TYPE)
@Retention(RetentionPolicy.SOURCE)
-@Deprecated
-public @interface Value {
- /**
- * If you specify a static constructor name, then the generated constructor will be private, and
- * instead a static factory method is created that other classes can use to create instances.
- * We suggest the name: "of", like so:
- *
- * <pre>
- * public @Data(staticConstructor = "of") class Point { final int x, y; }
- * </pre>
- *
- * Default: No static constructor, instead the normal constructor is public.
- */
- String staticConstructor() default "";
-}
+public @interface Helper {}
diff --git a/src/core/lombok/experimental/NonFinal.java b/src/core/lombok/experimental/NonFinal.java
index 0c31dd2a..12a45d22 100644
--- a/src/core/lombok/experimental/NonFinal.java
+++ b/src/core/lombok/experimental/NonFinal.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
/**
* Used to indicate the explicit intention for the annotated entity to <em>not</em> be {@code final}.
- * Currently used by {@code FieldDefaults} to avoid having it make a field final.
+ * Currently used by {@code FieldDefaults} and {@code Value} to avoid having it make a field final.
*/
@Target({ElementType.FIELD, ElementType.PARAMETER, ElementType.LOCAL_VARIABLE, ElementType.ANNOTATION_TYPE, ElementType.TYPE, ElementType.METHOD})
@Retention(RetentionPolicy.SOURCE)
diff --git a/src/core/lombok/experimental/PackagePrivate.java b/src/core/lombok/experimental/PackagePrivate.java
index bfe5638b..42002818 100644
--- a/src/core/lombok/experimental/PackagePrivate.java
+++ b/src/core/lombok/experimental/PackagePrivate.java
@@ -28,7 +28,7 @@ import java.lang.annotation.Target;
/**
* Used to indicate the explicit intention for the annotated entity to have the <em>package private</em> access level.
- * Currently used by {@code FieldDefaults} to avoid having it make a field one of {@code public}, {@code protected}, or {@code private}.
+ * Currently used by {@code FieldDefaults} and {@code Value} to avoid having it make a field one of {@code public}, {@code protected}, or {@code private}.
*/
@Target({ElementType.TYPE, ElementType.FIELD, ElementType.CONSTRUCTOR, ElementType.METHOD, ElementType.ANNOTATION_TYPE})
@Retention(RetentionPolicy.SOURCE)
diff --git a/src/core/lombok/experimental/UtilityClass.java b/src/core/lombok/experimental/UtilityClass.java
new file mode 100644
index 00000000..80f3eee9
--- /dev/null
+++ b/src/core/lombok/experimental/UtilityClass.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2015 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.experimental;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * An annotation to create utility classes.
+ *
+ * If a class is annotated with {@code @UtilityClass}, the following things happen to it:<ul>
+ * <li>It is marked final.</li>
+ * <li>If any constructors are declared in it, an error is generated. Otherwise, a private no-args constructor is generated; it throws a {@code UnsupportedOperationException}.</li>
+ * <li>All methods, inner classes, and fields in the class are marked static.</li>
+ * </ul>
+ */
+@Target({ElementType.TYPE})
+@Retention(RetentionPolicy.SOURCE)
+public @interface UtilityClass {
+}
diff --git a/src/core/lombok/experimental/Wither.java b/src/core/lombok/experimental/Wither.java
index fe113bb0..3df546d0 100644
--- a/src/core/lombok/experimental/Wither.java
+++ b/src/core/lombok/experimental/Wither.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -31,7 +31,7 @@ import lombok.AccessLevel;
/**
* Put on any field to make lombok build a 'wither' - a withX method which produces a clone of this object (except for 1 field which gets a new value).
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/experimental/Wither.html">the project lombok features page for &#64;Wither</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/experimental/Wither">the project lombok features page for &#64;Wither</a>.
* <p>
* Even though it is not listed, this annotation also has the {@code onParam} and {@code onMethod} parameter. See the full documentation for more details.
* <p>
@@ -56,16 +56,32 @@ import lombok.AccessLevel;
public @interface Wither {
/**
* If you want your wither to be non-public, you can specify an alternate access level here.
+ *
+ * @return The method will be generated with this access modifier.
*/
AccessLevel value() default AccessLevel.PUBLIC;
/**
- * Any annotations listed here are put on the generated method. The syntax for this feature is: {@code @Setter(onMethod=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated method.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Wither(onMethod=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @Wither(onMethod_={@AnnotationsGohere})} // note the underscore after {@code onMethod}.
+ *
+ * @return List of annotations to apply to the generated method.
*/
AnyAnnotation[] onMethod() default {};
/**
- * Any annotations listed here are put on the generated method's parameter. The syntax for this feature is: {@code @Setter(onParam=@__({@AnnotationsGoHere}))}
+ * Any annotations listed here are put on the generated method's parameter.
+ * The syntax for this feature depends on JDK version (nothing we can do about that; it's to work around javac bugs).<br>
+ * up to JDK7:<br>
+ * {@code @Wither(onParam=@__({@AnnotationsGoHere}))}<br>
+ * from JDK8:<br>
+ * {@code @Wither(onParam_={@AnnotationsGohere})} // note the underscore after {@code onParam}.
+ *
+ * @return List of annotations to apply to the generated parameter in the method.
*/
AnyAnnotation[] onParam() default {};
diff --git a/src/core/lombok/experimental/package-info.java b/src/core/lombok/experimental/package-info.java
index 776f2c27..22b23a52 100644
--- a/src/core/lombok/experimental/package-info.java
+++ b/src/core/lombok/experimental/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -28,6 +28,6 @@
* to the official feature documentation.
*
* @see lombok
- * @see <a href="http://projectlombok.org/features/experimental/index.html">Lombok features (experimental)</a>
+ * @see <a href="https://projectlombok.org/features/experimental/all">Lombok features (experimental)</a>
*/
package lombok.experimental;
diff --git a/src/core/lombok/experimental/var.java b/src/core/lombok/experimental/var.java
new file mode 100644
index 00000000..71cc141a
--- /dev/null
+++ b/src/core/lombok/experimental/var.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2010-2017 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.experimental;
+
+/**
+ * like val but not final
+ *
+ * @deprecated {@code var} has been promoted to the main package; use {@link lombok.var} instead.
+ */
+@Deprecated
+public @interface var {
+}
diff --git a/src/core/lombok/extern/apachecommons/CommonsLog.java b/src/core/lombok/extern/apachecommons/CommonsLog.java
index 45345098..04d5ef93 100644
--- a/src/core/lombok/extern/apachecommons/CommonsLog.java
+++ b/src/core/lombok/extern/apachecommons/CommonsLog.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,21 +46,20 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
+ * This annotation is valid for classes and enumerations.<br>
*
- * @see org.apache.commons.logging.Log org.apache.commons.logging.Log
- * @see org.apache.commons.logging.LogFactory#getLog(java.lang.Class) org.apache.commons.logging.LogFactory.getLog(Class target)
+ * @see <a href="https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/Log.html">org.apache.commons.logging.Log</a>
+ * @see <a href="https://commons.apache.org/proper/commons-logging/apidocs/org/apache/commons/logging/LogFactory.html#getLog(java.lang.Class)">org.apache.commons.logging.LogFactory#getLog(java.lang.Class)</a>
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface CommonsLog {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/java/Log.java b/src/core/lombok/extern/java/Log.java
index bac2742e..553b7c4a 100644
--- a/src/core/lombok/extern/java/Log.java
+++ b/src/core/lombok/extern/java/Log.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,20 +46,19 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see java.util.logging.Logger java.util.logging.Logger
- * @see java.util.logging.Logger#getLogger(java.lang.String) java.util.logging.Logger.getLogger(String name)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html">java.util.logging.Logger</a>
+ * @see <a href="https://docs.oracle.com/javase/8/docs/api/java/util/logging/Logger.html#getLogger-java.lang.String-">java.util.logging.Logger#getLogger(java.lang.String)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Log {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/jbosslog/JBossLog.java b/src/core/lombok/extern/jbosslog/JBossLog.java
new file mode 100644
index 00000000..ea520aea
--- /dev/null
+++ b/src/core/lombok/extern/jbosslog/JBossLog.java
@@ -0,0 +1,64 @@
+/*
+ * Copyright (C) 2016-2017 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.jbosslog;
+
+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.
+ * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
+ * <p>
+ * Example:
+ * <pre>
+ * &#64;JBossLog
+ * public class LogExample {
+ * }
+ * </pre>
+ *
+ * will generate:
+ *
+ * <pre>
+ * public class LogExample {
+ * private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LogExample.class);
+ * }
+ * </pre>
+ *
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html">org.jboss.logging.Logger</a>
+ * @see <a href="https://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html#getLogger(java.lang.Class)">org.jboss.logging.Logger#getLogger(java.lang.Class)</a>
+ * @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
+ * @see lombok.extern.java.Log &#64;Log
+ * @see lombok.extern.log4j.Log4j &#64;Log4j
+ * @see lombok.extern.log4j.Log4j2 &#64;Log4j2
+ * @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
+ * */
+@Retention(RetentionPolicy.SOURCE)
+@Target(ElementType.TYPE)
+public @interface JBossLog {
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
+ String topic() default "";
+}
diff --git a/src/core/lombok/extern/log4j/Log4j.java b/src/core/lombok/extern/log4j/Log4j.java
index 9490acb8..ee719407 100644
--- a/src/core/lombok/extern/log4j/Log4j.java
+++ b/src/core/lombok/extern/log4j/Log4j.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,21 +46,20 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
+ * This annotation is valid for classes and enumerations.<br>
*
- * @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 <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html">org.apache.log4j.Logger</a>
+ * @see <a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.Class)">org.apache.log4j.Logger#getLogger(java.lang.Class)</a>
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Log4j {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/log4j/Log4j2.java b/src/core/lombok/extern/log4j/Log4j2.java
index 43125e6b..4a5b166c 100644
--- a/src/core/lombok/extern/log4j/Log4j2.java
+++ b/src/core/lombok/extern/log4j/Log4j2.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -42,25 +42,24 @@ import java.lang.annotation.Target;
*
* <pre>
* public class LogExample {
- * private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.Logger.getLogger(LogExample.class);
+ * private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger(LogExample.class);
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
+ * This annotation is valid for classes and enumerations.<br>
*
- * @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 <a href="https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/Logger.html">org.apache.logging.log4j.Logger</a>
+ * @see <a href="https://logging.apache.org/log4j/2.x/log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger-java.lang.Class-">org.apache.logging.log4j.LogManager#getLogger(java.lang.Class)</a>
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Log4j2 {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/slf4j/Slf4j.java b/src/core/lombok/extern/slf4j/Slf4j.java
index 04df6498..24586d43 100644
--- a/src/core/lombok/extern/slf4j/Slf4j.java
+++ b/src/core/lombok/extern/slf4j/Slf4j.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,21 +46,20 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see org.slf4j.Logger org.slf4j.Logger
- * @see org.slf4j.LoggerFactory#getLogger(java.lang.Class) org.slf4j.LoggerFactory.getLogger(Class target)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/Logger.html">org.slf4j.Logger</a>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/LoggerFactory.html#getLogger(java.lang.Class)">org.slf4j.LoggerFactory#getLogger(java.lang.Class)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
* @see lombok.extern.slf4j.XSlf4j &#64;XSlf4j
- * */
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
+ */
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface Slf4j {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/extern/slf4j/XSlf4j.java b/src/core/lombok/extern/slf4j/XSlf4j.java
index 8a311c79..85a0fdd8 100644
--- a/src/core/lombok/extern/slf4j/XSlf4j.java
+++ b/src/core/lombok/extern/slf4j/XSlf4j.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2013 The Project Lombok Authors.
+ * Copyright (C) 2012-2017 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
@@ -29,7 +29,7 @@ import java.lang.annotation.Target;
/**
* Causes lombok to generate a logger field.
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/Log.html">the project lombok features page for lombok log annotations</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/Log">the project lombok features page for lombok log annotations</a>.
* <p>
* Example:
* <pre>
@@ -46,20 +46,19 @@ import java.lang.annotation.Target;
* }
* </pre>
*
- * This annotation is valid for classes and enumerations.<br />
- * @see org.slf4j.ext.XLogger org.slf4j.ext.XLogger
- * @see org.slf4j.ext.XLoggerFactory#getLogger(java.lang.Class) org.slf4j.ext.XLoggerFactory.getXLogger(Class target)
+ * This annotation is valid for classes and enumerations.<br>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/ext/XLogger.html">org.slf4j.ext.XLogger</a>
+ * @see <a href="https://www.slf4j.org/api/org/slf4j/ext/XLoggerFactory.html#getXLogger(java.lang.Class)">org.slf4j.ext.XLoggerFactory#getLogger(java.lang.Class)</a>
* @see lombok.extern.apachecommons.CommonsLog &#64;CommonsLog
* @see lombok.extern.java.Log &#64;Log
* @see lombok.extern.log4j.Log4j &#64;Log4j
* @see lombok.extern.log4j.Log4j2 &#64;Log4j2
* @see lombok.extern.slf4j.Slf4j &#64;Slf4j
+ * @see lombok.extern.jbosslog.JBossLog &#64;JBossLog
*/
@Retention(RetentionPolicy.SOURCE)
@Target(ElementType.TYPE)
public @interface XSlf4j {
- /**
- * Sets the category of the constructed Logger. By default, it will use the type where the annotation is placed.
- */
+ /** @return The category of the constructed Logger. By default, it will use the type where the annotation is placed. */
String topic() default "";
}
diff --git a/src/core/lombok/javac/CapturingDiagnosticListener.java b/src/core/lombok/javac/CapturingDiagnosticListener.java
index a0ac6adc..0e64ed8d 100644
--- a/src/core/lombok/javac/CapturingDiagnosticListener.java
+++ b/src/core/lombok/javac/CapturingDiagnosticListener.java
@@ -52,6 +52,10 @@ public class CapturingDiagnosticListener implements DiagnosticListener<JavaFileO
"^" + Pattern.quote(file.getAbsolutePath()) +
"\\s*:\\s*\\d+\\s*:\\s*(?:warning:\\s*)?(.*)$", Pattern.DOTALL).matcher(msg);
if (m.matches()) msg = m.group(1);
+ if (msg.equals("deprecated item is not annotated with @Deprecated")) {
+ // This is new in JDK9; prior to that you don't see this. We shall ignore these.
+ return;
+ }
messages.add(new CompilerMessage(d.getLineNumber(), d.getStartPosition(), d.getKind() == Kind.ERROR, msg));
}
diff --git a/src/core/lombok/javac/CompilerMessageSuppressor.java b/src/core/lombok/javac/CompilerMessageSuppressor.java
index a17e0c62..391ec64a 100644
--- a/src/core/lombok/javac/CompilerMessageSuppressor.java
+++ b/src/core/lombok/javac/CompilerMessageSuppressor.java
@@ -26,6 +26,7 @@ import java.io.OutputStream;
import java.io.PrintWriter;
import java.lang.reflect.Field;
import java.util.LinkedList;
+import java.util.Map;
import java.util.Queue;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ConcurrentMap;
@@ -43,38 +44,40 @@ import com.sun.tools.javac.util.Log;
* then they will be generated AGAIN, this time with proper names and line numbers, at the end. Therefore, we want to suppress the logger.
*/
public final class CompilerMessageSuppressor {
+
private final Log log;
- private static final Field errWriterField, warnWriterField, noticeWriterField, dumpOnErrorField, promptOnErrorField, diagnosticListenerField;
+ private static final WriterField errWriterField, warnWriterField, noticeWriterField;
+ private static final Field dumpOnErrorField, promptOnErrorField, diagnosticListenerField;
private static final Field deferDiagnosticsField, deferredDiagnosticsField, diagnosticHandlerField;
private static final ConcurrentMap<Class<?>, Field> handlerDeferredFields = new ConcurrentHashMap<Class<?>, Field>();
private static final Field NULL_FIELD;
- private PrintWriter errWriter, warnWriter, noticeWriter;
private Boolean dumpOnError, promptOnError;
private DiagnosticListener<?> contextDiagnosticListener, logDiagnosticListener;
private final Context context;
- // If this is true, the fields changed. Better to print weird error messages than to fail outright.
- private static final boolean dontBother;
-
private static final ThreadLocal<Queue<?>> queueCache = new ThreadLocal<Queue<?>>();
+ enum Writers {
+ ERROR("errWriter", "ERROR"),
+ WARNING("warnWriter", "WARNING"),
+ NOTICE("noticeWriter", "NOTICE");
+
+ final String fieldName;
+ final String keyName;
+
+ Writers(String fieldName, String keyName) {
+ this.fieldName = fieldName;
+ this.keyName = keyName;
+ }
+ }
+
static {
- errWriterField = getDeclaredField(Log.class, "errWriter");
- warnWriterField = getDeclaredField(Log.class, "warnWriter");
- noticeWriterField = getDeclaredField(Log.class, "noticeWriter");
+ errWriterField = createWriterField(Writers.ERROR);
+ warnWriterField = createWriterField(Writers.WARNING);
+ noticeWriterField = createWriterField(Writers.NOTICE);
dumpOnErrorField = getDeclaredField(Log.class, "dumpOnError");
promptOnErrorField = getDeclaredField(Log.class, "promptOnError");
diagnosticListenerField = getDeclaredField(Log.class, "diagListener");
-
- dontBother =
- errWriterField == null ||
- warnWriterField == null ||
- noticeWriterField == null ||
- dumpOnErrorField == null ||
- promptOnErrorField == null ||
- diagnosticListenerField == null;
-
-
deferDiagnosticsField = getDeclaredField(Log.class, "deferDiagnostics");
deferredDiagnosticsField = getDeclaredField(Log.class, "deferredDiagnostics");
@@ -100,17 +103,13 @@ public final class CompilerMessageSuppressor {
this.context = context;
}
- public boolean disableLoggers() {
+ public void disableLoggers() {
contextDiagnosticListener = context.get(DiagnosticListener.class);
context.put(DiagnosticListener.class, (DiagnosticListener<?>) null);
- if (dontBother) return false;
- boolean dontBotherInstance = false;
-
- PrintWriter dummyWriter = new PrintWriter(new OutputStream() {
- @Override public void write(int b) throws IOException {
- // Do nothing on purpose
- }
- });
+
+ errWriterField.pauze(log);
+ warnWriterField.pauze(log);
+ noticeWriterField.pauze(log);
if (deferDiagnosticsField != null) try {
if (Boolean.TRUE.equals(deferDiagnosticsField.get(log))) {
@@ -130,50 +129,23 @@ public final class CompilerMessageSuppressor {
}
} catch (Exception e) {}
- if (!dontBotherInstance) try {
- errWriter = (PrintWriter) errWriterField.get(log);
- errWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
- warnWriter = (PrintWriter) warnWriterField.get(log);
- warnWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
- noticeWriter = (PrintWriter) noticeWriterField.get(log);
- noticeWriterField.set(log, dummyWriter);
- } catch (Exception e) {
- dontBotherInstance = true;
- }
-
- if (!dontBotherInstance) try {
+ if (dumpOnErrorField != null) try {
dumpOnError = (Boolean) dumpOnErrorField.get(log);
dumpOnErrorField.set(log, false);
} catch (Exception e) {
- dontBotherInstance = true;
}
- if (!dontBotherInstance) try {
+ if (promptOnErrorField != null) try {
promptOnError = (Boolean) promptOnErrorField.get(log);
promptOnErrorField.set(log, false);
} catch (Exception e) {
- dontBotherInstance = true;
}
- if (!dontBotherInstance) try {
+ if (diagnosticListenerField != null) try {
logDiagnosticListener = (DiagnosticListener<?>) diagnosticListenerField.get(log);
diagnosticListenerField.set(log, null);
} catch (Exception e) {
- dontBotherInstance = true;
}
-
- if (dontBotherInstance) enableLoggers();
- return !dontBotherInstance;
}
private static Field getDeferredField(Object handler) {
@@ -193,20 +165,9 @@ public final class CompilerMessageSuppressor {
contextDiagnosticListener = null;
}
- if (errWriter != null) try {
- errWriterField.set(log, errWriter);
- errWriter = null;
- } catch (Exception e) {}
-
- if (warnWriter != null) try {
- warnWriterField.set(log, warnWriter);
- warnWriter = null;
- } catch (Exception e) {}
-
- if (noticeWriter != null) try {
- noticeWriterField.set(log, noticeWriter);
- noticeWriter = null;
- } catch (Exception e) {}
+ errWriterField.resume(log);
+ warnWriterField.resume(log);
+ noticeWriterField.resume(log);
if (dumpOnError != null) try {
dumpOnErrorField.set(log, dumpOnError);
@@ -283,4 +244,107 @@ public final class CompilerMessageSuppressor {
// javac will contain rather a lot of messages, but this is a lot better than just crashing during compilation!
}
}
+
+ private static WriterField createWriterField(Writers w) {
+ // jdk9
+ try {
+ Field writers = getDeclaredField(Log.class, "writer");
+ if (writers != null) {
+ Class<?> kindsClass = Class.forName("com.sun.tools.javac.util.Log$WriterKind");
+ for (Object enumConstant : kindsClass.getEnumConstants()) {
+ if (enumConstant.toString().equals(w.keyName)) {
+ return new Java9WriterField(writers, enumConstant);
+ }
+ }
+ return WriterField.NONE;
+ }
+ } catch (Exception e) {
+ }
+
+ // jdk8
+ Field writerField = getDeclaredField(Log.class, w.fieldName);
+ if (writerField != null) return new Java8WriterField(writerField);
+
+ // other jdk
+ return WriterField.NONE;
+ }
+
+ interface WriterField {
+ final PrintWriter NO_WRITER = new PrintWriter(new OutputStream() {
+ @Override public void write(int b) throws IOException {
+ // Do nothing on purpose
+ }
+ });
+
+ final WriterField NONE = new WriterField() {
+ @Override public void pauze(Log log) {
+ // do nothing
+ }
+ @Override public void resume(Log log) {
+ // no nothing
+ }
+ };
+
+ void pauze(Log log);
+ void resume(Log log);
+ }
+
+ static class Java8WriterField implements WriterField {
+ private final Field field;
+ private PrintWriter writer;
+
+ public Java8WriterField(Field field) {
+ this.field = field;
+ }
+
+ @Override public void pauze(Log log) {
+ try {
+ writer = (PrintWriter) field.get(log);
+ field.set(log, NO_WRITER);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override public void resume(Log log) {
+ if (writer != null) {
+ try {
+ field.set(log, writer);
+ } catch (Exception e) {
+ }
+ }
+ writer = null;
+ }
+ }
+
+
+ static class Java9WriterField implements WriterField {
+ private final Field field;
+ private final Object key;
+ private PrintWriter writer;
+
+ public Java9WriterField(Field field, Object key) {
+ this.field = field;
+ this.key = key;
+ }
+
+ @Override public void pauze(Log log) {
+ try {
+ @SuppressWarnings("unchecked") Map<Object,PrintWriter> map = (Map<Object,PrintWriter>)field.get(log);
+ writer = map.get(key);
+ map.put(key, NO_WRITER);
+ } catch (Exception e) {
+ }
+ }
+
+ @Override public void resume(Log log) {
+ if (writer != null) {
+ try {
+ @SuppressWarnings("unchecked") Map<Object,PrintWriter> map = (Map<Object,PrintWriter>)field.get(log);
+ map.put(key, writer);
+ } catch (Exception e) {
+ }
+ }
+ writer = null;
+ }
+ }
} \ No newline at end of file
diff --git a/src/core/lombok/javac/HandlerLibrary.java b/src/core/lombok/javac/HandlerLibrary.java
index 30aeff73..3c61696b 100644
--- a/src/core/lombok/javac/HandlerLibrary.java
+++ b/src/core/lombok/javac/HandlerLibrary.java
@@ -44,6 +44,7 @@ import lombok.core.TypeResolver;
import lombok.core.configuration.ConfigurationKeysLoader;
import lombok.javac.handlers.JavacHandlerUtil;
+import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -148,12 +149,12 @@ public class HandlerLibrary {
* then uses SPI discovery to load all annotation and visitor based handlers so that future calls
* to the handle methods will defer to these handlers.
*/
- public static HandlerLibrary load(Messager messager) {
+ public static HandlerLibrary load(Messager messager, Trees trees) {
HandlerLibrary library = new HandlerLibrary(messager);
try {
- loadAnnotationHandlers(library);
- loadVisitorHandlers(library);
+ loadAnnotationHandlers(library, trees);
+ loadVisitorHandlers(library, trees);
} catch (IOException e) {
System.err.println("Lombok isn't running due to misconfigured SPI files: " + e);
}
@@ -165,9 +166,10 @@ public class HandlerLibrary {
/** Uses SPI Discovery to find implementations of {@link JavacAnnotationHandler}. */
@SuppressWarnings({"rawtypes", "unchecked"})
- private static void loadAnnotationHandlers(HandlerLibrary lib) throws IOException {
+ private static void loadAnnotationHandlers(HandlerLibrary lib, Trees trees) throws IOException {
//No, that seemingly superfluous reference to JavacAnnotationHandler's classloader is not in fact superfluous!
for (JavacAnnotationHandler handler : SpiLoadUtil.findServices(JavacAnnotationHandler.class, JavacAnnotationHandler.class.getClassLoader())) {
+ handler.setTrees(trees);
Class<? extends Annotation> annotationClass = handler.getAnnotationHandledByThisHandler();
AnnotationHandlerContainer<?> container = new AnnotationHandlerContainer(handler, annotationClass);
String annotationClassName = container.annotationClass.getName().replace("$", ".");
@@ -179,9 +181,10 @@ public class HandlerLibrary {
}
/** Uses SPI Discovery to find implementations of {@link JavacASTVisitor}. */
- private static void loadVisitorHandlers(HandlerLibrary lib) throws IOException {
+ private static void loadVisitorHandlers(HandlerLibrary lib, Trees trees) throws IOException {
//No, that seemingly superfluous reference to JavacASTVisitor's classloader is not in fact superfluous!
for (JavacASTVisitor visitor : SpiLoadUtil.findServices(JavacASTVisitor.class, JavacASTVisitor.class.getClassLoader())) {
+ visitor.setTrees(trees);
lib.visitorHandlers.add(new VisitorContainer(visitor));
}
}
diff --git a/src/core/lombok/javac/Javac8BasedLombokOptions.java b/src/core/lombok/javac/Javac8BasedLombokOptions.java
index 3fdea890..9a662490 100644
--- a/src/core/lombok/javac/Javac8BasedLombokOptions.java
+++ b/src/core/lombok/javac/Javac8BasedLombokOptions.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2013-2017 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
@@ -28,7 +28,7 @@ import com.sun.tools.javac.util.Options;
public class Javac8BasedLombokOptions extends LombokOptions {
public static Javac8BasedLombokOptions replaceWithDelombokOptions(Context context) {
Options options = Options.instance(context);
- context.put(optionsKey, (Options)null);
+ context.put(optionsKey, (Options) null);
Javac8BasedLombokOptions result = new Javac8BasedLombokOptions(context);
result.putAll(options);
return result;
diff --git a/src/core/lombok/javac/Javac9BasedLombokOptions.java b/src/core/lombok/javac/Javac9BasedLombokOptions.java
new file mode 100644
index 00000000..e786346d
--- /dev/null
+++ b/src/core/lombok/javac/Javac9BasedLombokOptions.java
@@ -0,0 +1,48 @@
+/*
+ * Copyright (C) 2017 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.javac;
+
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Options;
+
+public class Javac9BasedLombokOptions extends LombokOptions {
+ public static Javac9BasedLombokOptions replaceWithDelombokOptions(Context context) {
+ Options options = Options.instance(context);
+ context.put(optionsKey, (Options) null);
+ Javac9BasedLombokOptions result = new Javac9BasedLombokOptions(context);
+ result.putAll(options);
+ return result;
+ }
+
+ private Javac9BasedLombokOptions(Context context) {
+ super(context);
+ }
+
+ @Override public void putJavacOption(String optionName, String value) {
+ if (optionName.equals("CLASSPATH")) optionName = "CLASS_PATH";
+ if (optionName.equals("SOURCEPATH")) optionName = "SOURCE_PATH";
+ if (optionName.equals("BOOTCLASSPATH")) optionName = "BOOT_CLASS_PATH";
+ String optionText = Option.valueOf(optionName).primaryName;
+ put(optionText, value);
+ }
+}
diff --git a/src/core/lombok/javac/JavacAST.java b/src/core/lombok/javac/JavacAST.java
index 4e553063..12d919af 100644
--- a/src/core/lombok/javac/JavacAST.java
+++ b/src/core/lombok/javac/JavacAST.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -22,52 +22,54 @@
package lombok.javac;
import java.lang.reflect.Field;
+import java.lang.reflect.Method;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
import javax.annotation.processing.Messager;
import javax.tools.Diagnostic;
import javax.tools.JavaFileObject;
+import com.sun.tools.javac.util.JCDiagnostic;
import lombok.core.AST;
-import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.model.JavacElements;
import com.sun.tools.javac.model.JavacTypes;
import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCCatch;
-import com.sun.tools.javac.tree.JCTree.JCTry;
-import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
+import com.sun.tools.javac.tree.JCTree.JCCatch;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.tree.JCTree.JCExpression;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCTry;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
import com.sun.tools.javac.util.Log;
import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
* Wraps around javac's internal AST view to add useful features as well as the ability to visit parents from children,
* something javac's own AST system does not offer.
*/
public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
- private final Messager messager;
private final JavacElements elements;
private final JavacTreeMaker treeMaker;
private final Symtab symtab;
private final JavacTypes javacTypes;
private final Log log;
+ private final ErrorLog errorLogger;
private final Context context;
/**
@@ -78,11 +80,11 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
* @param top The compilation unit, which serves as the top level node in the tree to be built.
*/
public JavacAST(Messager messager, Context context, JCCompilationUnit top) {
- super(sourceName(top), packageDeclaration(top), new JavacImportList(top));
+ super(sourceName(top), PackageName.getPackageName(top), new JavacImportList(top), statementTypes());
setTop(buildCompilationUnit(top));
this.context = context;
- this.messager = messager;
this.log = Log.instance(context);
+ this.errorLogger = ErrorLog.create(messager, log);
this.elements = JavacElements.instance(context);
this.treeMaker = new JavacTreeMaker(TreeMaker.instance(context));
this.symtab = Symtab.instance(context);
@@ -103,10 +105,6 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return cu.sourcefile == null ? null : cu.sourcefile.toString();
}
- private static String packageDeclaration(JCCompilationUnit cu) {
- return (cu.pid instanceof JCFieldAccess || cu.pid instanceof JCIdent) ? cu.pid.toString() : null;
- }
-
public Context getContext() {
return context;
}
@@ -128,6 +126,8 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
String nm = Source.instance(context).name();
int underscoreIdx = nm.indexOf('_');
if (underscoreIdx > -1) return Integer.parseInt(nm.substring(underscoreIdx + 1));
+ // assume java9+
+ return Integer.parseInt(nm);
} catch (Exception ignore) {}
return 6;
}
@@ -189,7 +189,7 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
List<JavacNode> childNodes = new ArrayList<JavacNode>();
for (JCTree s : top.defs) {
if (s instanceof JCClassDecl) {
- addIfNotNull(childNodes, buildType((JCClassDecl)s));
+ addIfNotNull(childNodes, buildType((JCClassDecl) s));
} // else they are import statements, which we don't care about. Or Skip objects, whatever those are.
}
@@ -208,10 +208,10 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
* JCVariableDecl for fields
* JCBlock for (static) initializers
*/
- if (def instanceof JCMethodDecl) addIfNotNull(childNodes, buildMethod((JCMethodDecl)def));
- else if (def instanceof JCClassDecl) addIfNotNull(childNodes, buildType((JCClassDecl)def));
- else if (def instanceof JCVariableDecl) addIfNotNull(childNodes, buildField((JCVariableDecl)def));
- else if (def instanceof JCBlock) addIfNotNull(childNodes, buildInitializer((JCBlock)def));
+ if (def instanceof JCMethodDecl) addIfNotNull(childNodes, buildMethod((JCMethodDecl) def));
+ else if (def instanceof JCClassDecl) addIfNotNull(childNodes, buildType((JCClassDecl) def));
+ else if (def instanceof JCVariableDecl) addIfNotNull(childNodes, buildField((JCVariableDecl) def));
+ else if (def instanceof JCBlock) addIfNotNull(childNodes, buildInitializer((JCBlock) def));
}
return putInMap(new JavacNode(this, type, childNodes, Kind.TYPE));
@@ -297,7 +297,6 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
// @Foo int x, y; is handled in javac by putting the same annotation node on 2 JCVariableDecls.
return null;
}
-
return putInMap(new JavacNode(this, annotation, null, Kind.ANNOTATION));
}
@@ -315,12 +314,40 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
if (statement instanceof JCClassDecl) return buildType((JCClassDecl)statement);
if (statement instanceof JCVariableDecl) return buildLocalVar((JCVariableDecl)statement, Kind.LOCAL);
if (statement instanceof JCTry) return buildTry((JCTry) statement);
-
+ if (statement.getClass().getSimpleName().equals("JCLambda")) return buildLambda(statement);
if (setAndGetAsHandled(statement)) return null;
return drill(statement);
}
+ private JavacNode buildLambda(JCTree jcTree) {
+ return buildStatementOrExpression(getBody(jcTree));
+ }
+
+ private JCTree getBody(JCTree jcTree) {
+ try {
+ return (JCTree) getBodyMethod(jcTree.getClass()).invoke(jcTree);
+ } catch (Exception e) {
+ throw Javac.sneakyThrow(e);
+ }
+ }
+
+ private final static ConcurrentMap<Class<?>, Method> getBodyMethods = new ConcurrentHashMap<Class<?>, Method>();
+
+ private Method getBodyMethod(Class<?> c) {
+ Method m = getBodyMethods.get(c);
+ if (m != null) {
+ return m;
+ }
+ try {
+ m = c.getMethod("getBody");
+ } catch (NoSuchMethodException e) {
+ throw Javac.sneakyThrow(e);
+ }
+ getBodyMethods.putIfAbsent(c, m);
+ return getBodyMethods.get(c);
+ }
+
private JavacNode drill(JCTree statement) {
try {
List<JavacNode> childNodes = new ArrayList<JavacNode>();
@@ -336,9 +363,8 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
}
}
- /** For javac, both JCExpression and JCStatement are considered as valid children types. */
- @Override
- protected Collection<Class<? extends JCTree>> getStatementTypes() {
+ /* For javac, both JCExpression and JCStatement are considered as valid children types. */
+ private static Collection<Class<? extends JCTree>> statementTypes() {
Collection<Class<? extends JCTree>> collection = new ArrayList<Class<? extends JCTree>>(3);
collection.add(JCStatement.class);
collection.add(JCExpression.class);
@@ -376,22 +402,21 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
try {
switch (kind) {
case ERROR:
- increaseErrorCount(messager);
- boolean prev = log.multipleErrors;
- log.multipleErrors = true;
- try {
- log.error(pos, "proc.messager", message);
- } finally {
- log.multipleErrors = prev;
- }
+ errorLogger.error(pos, message);
+ break;
+ case MANDATORY_WARNING:
+ errorLogger.mandatoryWarning(pos, message);
break;
- default:
case WARNING:
- log.warning(pos, "proc.messager", message);
+ errorLogger.warning(pos, message);
+ break;
+ default:
+ case NOTE:
+ errorLogger.note(pos, message);
break;
}
} finally {
- if (oldSource != null) log.useSource(oldSource);
+ if (newSource != null) log.useSource(oldSource);
}
}
@@ -429,16 +454,183 @@ public class JavacAST extends AST<JavacAST, JavacNode, JCTree> {
return oldL;
}
- private void increaseErrorCount(Messager m) {
- try {
- Field f = m.getClass().getDeclaredField("errorCount");
- f.setAccessible(true);
- if (f.getType() == int.class) {
- int val = ((Number)f.get(m)).intValue();
- f.set(m, val +1);
+ abstract static class ErrorLog {
+ final Log log;
+ private final Messager messager;
+ private final Field errorCount;
+ private final Field warningCount;
+
+ private ErrorLog(Log log, Messager messager, Field errorCount, Field warningCount) {
+ this.log = log;
+ this.messager = messager;
+ this.errorCount = errorCount;
+ this.warningCount = warningCount;
+ }
+
+ final void error(DiagnosticPosition pos, String message) {
+ increment(errorCount);
+ error1(pos, message);
+ }
+
+ final void warning(DiagnosticPosition pos, String message) {
+ increment(warningCount);
+ warning1(pos, message);
+ }
+
+ final void mandatoryWarning(DiagnosticPosition pos, String message) {
+ increment(warningCount);
+ mandatoryWarning1(pos, message);
+ }
+
+ abstract void error1(DiagnosticPosition pos, String message);
+ abstract void warning1(DiagnosticPosition pos, String message);
+ abstract void mandatoryWarning1(DiagnosticPosition pos, String message);
+ abstract void note(DiagnosticPosition pos, String message);
+
+ private void increment(Field field) {
+ if (field == null) return;
+ try {
+ int val = ((Number)field.get(messager)).intValue();
+ field.set(messager, val +1);
+ } catch (Throwable t) {
+ //Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
+ }
+ }
+
+ static ErrorLog create(Messager messager, Log log) {
+ Field errorCount = null;
+ try {
+ Field f = messager.getClass().getDeclaredField("errorCount");
+ f.setAccessible(true);
+ errorCount = f;
+ } catch (Throwable t) {}
+ boolean hasMultipleErrors = false;
+ for (Field field : log.getClass().getFields()) {
+ if (field.getName().equals("multipleErrors")) {
+ hasMultipleErrors = true;
+ break;
+ }
+ }
+ if (hasMultipleErrors) return new JdkBefore9(log, messager, errorCount);
+
+ Field warningCount = null;
+ try {
+ Field f = messager.getClass().getDeclaredField("warningCount");
+ f.setAccessible(true);
+ warningCount = f;
+ } catch (Throwable t) {}
+
+ return new Jdk9Plus(log, messager, errorCount, warningCount);
+ }
+ }
+
+ static class JdkBefore9 extends ErrorLog {
+ private JdkBefore9(Log log, Messager messager, Field errorCount) {
+ super(log, messager, errorCount, null);
+ }
+
+ @Override void error1(DiagnosticPosition pos, String message) {
+ boolean prev = log.multipleErrors;
+ log.multipleErrors = true;
+ try {
+ log.error(pos, "proc.messager", message);
+ } finally {
+ log.multipleErrors = prev;
+ }
+ }
+
+ @Override void warning1(DiagnosticPosition pos, String message) {
+ log.warning(pos, "proc.messager", message);
+ }
+
+ @Override void mandatoryWarning1(DiagnosticPosition pos, String message) {
+ log.mandatoryWarning(pos, "proc.messager", message);
+ }
+
+ @Override void note(DiagnosticPosition pos, String message) {
+ log.note(pos, "proc.messager", message);
+ }
+ }
+
+ static class Jdk9Plus extends ErrorLog {
+ private static final String PROC_MESSAGER = "proc.messager";
+ private Object multiple;
+ private Method errorMethod, warningMethod, mandatoryWarningMethod, noteMethod;
+ private Method errorKey, warningKey, noteKey;
+ private JCDiagnostic.Factory diags;
+
+ private Jdk9Plus(Log log, Messager messager, Field errorCount, Field warningCount) {
+ super(log, messager, errorCount, warningCount);
+
+ try {
+ final String jcd = "com.sun.tools.javac.util.JCDiagnostic";
+ Class<?> df = Class.forName(jcd + "$DiagnosticFlag");
+ for (Object constant : df.getEnumConstants()) {
+ if (constant.toString().equals("MULTIPLE")) this.multiple = constant;
+ }
+
+ Class<?> errorCls = Class.forName(jcd + "$Error");
+ Class<?> warningCls = Class.forName(jcd + "$Warning");
+ Class<?> noteCls = Class.forName(jcd + "$Note");
+
+ Class<?> lc = log.getClass();
+ this.errorMethod = lc.getMethod("error", df, DiagnosticPosition.class, errorCls);
+ this.warningMethod = lc.getMethod("warning", DiagnosticPosition.class, warningCls);
+ this.mandatoryWarningMethod = lc.getMethod("mandatoryWarning", DiagnosticPosition.class, warningCls);
+ this.noteMethod = lc.getMethod("note", DiagnosticPosition.class, noteCls);
+
+ Field diagsField = lc.getSuperclass().getDeclaredField("diags");
+ diagsField.setAccessible(true);
+ this.diags = (JCDiagnostic.Factory)diagsField.get(log);
+
+ Class<?> dc = this.diags.getClass();
+ this.errorKey = dc.getMethod("errorKey", String.class, Object[].class);
+ this.warningKey = dc.getDeclaredMethod("warningKey", String.class, Object[].class);
+ this.warningKey.setAccessible(true);
+ this.noteKey = dc.getDeclaredMethod("noteKey", String.class, Object[].class);
+ this.noteKey.setAccessible(true);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override void error1(DiagnosticPosition pos, String message) {
+ try {
+ Object error = this.errorKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ errorMethod.invoke(log, multiple, pos, error);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override
+ void warning1(DiagnosticPosition pos, String message) {
+ try {
+ Object warning = this.warningKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ warningMethod.invoke(log, pos, warning);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override
+ void mandatoryWarning1(DiagnosticPosition pos, String message) {
+ try {
+ Object warning = this.warningKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ mandatoryWarningMethod.invoke(log, pos, warning);
+ } catch (Throwable t) {
+ //t.printStackTrace();
+ }
+ }
+
+ @Override
+ void note(DiagnosticPosition pos, String message) {
+ try {
+ Object note = this.noteKey.invoke(diags, PROC_MESSAGER, new Object[] { message });
+ noteMethod.invoke(log, pos, note);
+ } catch (Throwable t) {
+ //t.printStackTrace();
}
- } catch (Throwable t) {
- //Very unfortunate, but in most cases it still works fine, so we'll silently swallow it.
}
}
}
diff --git a/src/core/lombok/javac/JavacASTAdapter.java b/src/core/lombok/javac/JavacASTAdapter.java
index 5d120a77..6af53e3d 100644
--- a/src/core/lombok/javac/JavacASTAdapter.java
+++ b/src/core/lombok/javac/JavacASTAdapter.java
@@ -21,6 +21,7 @@
*/
package lombok.javac;
+import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
@@ -35,6 +36,9 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
*/
public class JavacASTAdapter implements JavacASTVisitor {
/** {@inheritDoc} */
+ @Override public void setTrees(Trees trees) {}
+
+ /** {@inheritDoc} */
@Override public void visitCompilationUnit(JavacNode top, JCCompilationUnit unit) {}
/** {@inheritDoc} */
diff --git a/src/core/lombok/javac/JavacASTVisitor.java b/src/core/lombok/javac/JavacASTVisitor.java
index c57e657a..565980f9 100644
--- a/src/core/lombok/javac/JavacASTVisitor.java
+++ b/src/core/lombok/javac/JavacASTVisitor.java
@@ -23,6 +23,7 @@ package lombok.javac;
import java.io.PrintStream;
+import com.sun.source.util.Trees;
import com.sun.tools.javac.code.Flags;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
@@ -37,6 +38,8 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
* calling the appropriate visit and endVisit methods.
*/
public interface JavacASTVisitor {
+ void setTrees(Trees trees);
+
/**
* Called at the very beginning and end.
*/
@@ -121,6 +124,8 @@ public interface JavacASTVisitor {
this.out = out;
}
+ @Override public void setTrees(Trees trees) {}
+
private void forcePrint(String text, Object... params) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < indent; i++) sb.append(" ");
diff --git a/src/core/lombok/javac/JavacAnnotationHandler.java b/src/core/lombok/javac/JavacAnnotationHandler.java
index a86aa6c6..dd4e7098 100644
--- a/src/core/lombok/javac/JavacAnnotationHandler.java
+++ b/src/core/lombok/javac/JavacAnnotationHandler.java
@@ -26,6 +26,7 @@ import java.lang.annotation.Annotation;
import lombok.core.AnnotationValues;
import lombok.core.SpiLoadUtil;
+import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
/**
@@ -40,6 +41,8 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation;
* You also need to register yourself via SPI discovery as being an implementation of {@code JavacAnnotationHandler}.
*/
public abstract class JavacAnnotationHandler<T extends Annotation> {
+ protected Trees trees;
+
/**
* Called when an annotation is found that is likely to match the annotation you're interested in.
*
@@ -63,4 +66,8 @@ public abstract class JavacAnnotationHandler<T extends Annotation> {
@SuppressWarnings("unchecked") public Class<T> getAnnotationHandledByThisHandler() {
return (Class<T>) SpiLoadUtil.findAnnotationClass(getClass(), JavacAnnotationHandler.class);
}
+
+ public void setTrees(Trees trees) {
+ this.trees = trees;
+ }
}
diff --git a/src/core/lombok/javac/JavacImportList.java b/src/core/lombok/javac/JavacImportList.java
index 2665ca7c..468d8c7b 100644
--- a/src/core/lombok/javac/JavacImportList.java
+++ b/src/core/lombok/javac/JavacImportList.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013-2014 The Project Lombok Authors.
+ * Copyright (C) 2013-2015 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
@@ -24,22 +24,21 @@ package lombok.javac;
import java.util.ArrayList;
import java.util.Collection;
+import lombok.core.ImportList;
+import lombok.core.LombokInternalAliasing;
+
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCImport;
import com.sun.tools.javac.util.List;
-import lombok.core.ImportList;
-import lombok.core.LombokInternalAliasing;
-
public class JavacImportList implements ImportList {
- private final JCExpression pkg;
+ private final String pkgStr;
private final List<JCTree> defs;
public JavacImportList(JCCompilationUnit cud) {
- this.pkg = cud.pid;
+ this.pkgStr = PackageName.getPackageName(cud);
this.defs = cud.defs;
}
@@ -58,7 +57,6 @@ public class JavacImportList implements ImportList {
}
@Override public boolean hasStarImport(String packageName) {
- String pkgStr = pkg == null ? null : pkg.toString();
if (pkgStr != null && pkgStr.equals(packageName)) return true;
if ("java.lang".equals(packageName)) return true;
@@ -86,7 +84,7 @@ public class JavacImportList implements ImportList {
@Override public Collection<String> applyNameToStarImports(String startsWith, String name) {
ArrayList<String> out = new ArrayList<String>();
- if (pkg != null && topLevelName(pkg).equals(startsWith)) out.add(pkg.toString() + "." + name);
+ if (pkgStr != null && topLevelName(pkgStr).equals(startsWith)) out.add(pkgStr + "." + name);
for (JCTree def : defs) {
if (!(def instanceof JCImport)) continue;
@@ -110,8 +108,14 @@ public class JavacImportList implements ImportList {
return tree.toString();
}
+ private String topLevelName(String packageName) {
+ int idx = packageName.indexOf(".");
+ if (idx == -1) return packageName;
+ return packageName.substring(0, idx);
+ }
+
@Override public String applyUnqualifiedNameToPackage(String unqualified) {
- if (pkg == null) return unqualified;
- return pkg.toString() + "." + unqualified;
+ if (pkgStr == null) return unqualified;
+ return pkgStr + "." + unqualified;
}
}
diff --git a/src/core/lombok/javac/JavacNode.java b/src/core/lombok/javac/JavacNode.java
index 6eef36eb..fa24c2f9 100644
--- a/src/core/lombok/javac/JavacNode.java
+++ b/src/core/lombok/javac/JavacNode.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2013 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -23,6 +23,7 @@ package lombok.javac;
import java.util.List;
+import javax.lang.model.element.Element;
import javax.tools.Diagnostic;
import lombok.core.AST.Kind;
@@ -51,6 +52,13 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
super(ast, node, children, kind);
}
+ public Element getElement() {
+ if (node instanceof JCClassDecl) return ((JCClassDecl) node).sym;
+ if (node instanceof JCMethodDecl) return ((JCMethodDecl) node).sym;
+ if (node instanceof JCVariableDecl) return ((JCVariableDecl) node).sym;
+ return null;
+ }
+
public int getEndPosition(DiagnosticPosition pos) {
JCCompilationUnit cu = (JCCompilationUnit) top().get();
return Javac.getEndPosition(pos, cu);
@@ -66,40 +74,40 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
public void traverse(JavacASTVisitor visitor) {
switch (this.getKind()) {
case COMPILATION_UNIT:
- visitor.visitCompilationUnit(this, (JCCompilationUnit)get());
+ visitor.visitCompilationUnit(this, (JCCompilationUnit) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitCompilationUnit(this, (JCCompilationUnit)get());
+ visitor.endVisitCompilationUnit(this, (JCCompilationUnit) get());
break;
case TYPE:
- visitor.visitType(this, (JCClassDecl)get());
+ visitor.visitType(this, (JCClassDecl) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitType(this, (JCClassDecl)get());
+ visitor.endVisitType(this, (JCClassDecl) get());
break;
case FIELD:
- visitor.visitField(this, (JCVariableDecl)get());
+ visitor.visitField(this, (JCVariableDecl) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitField(this, (JCVariableDecl)get());
+ visitor.endVisitField(this, (JCVariableDecl) get());
break;
case METHOD:
- visitor.visitMethod(this, (JCMethodDecl)get());
+ visitor.visitMethod(this, (JCMethodDecl) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitMethod(this, (JCMethodDecl)get());
+ visitor.endVisitMethod(this, (JCMethodDecl) get());
break;
case INITIALIZER:
- visitor.visitInitializer(this, (JCBlock)get());
+ visitor.visitInitializer(this, (JCBlock) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitInitializer(this, (JCBlock)get());
+ visitor.endVisitInitializer(this, (JCBlock) get());
break;
case ARGUMENT:
JCMethodDecl parentMethod = (JCMethodDecl) up().get();
- visitor.visitMethodArgument(this, (JCVariableDecl)get(), parentMethod);
+ visitor.visitMethodArgument(this, (JCVariableDecl) get(), parentMethod);
ast.traverseChildren(visitor, this);
- visitor.endVisitMethodArgument(this, (JCVariableDecl)get(), parentMethod);
+ visitor.endVisitMethodArgument(this, (JCVariableDecl) get(), parentMethod);
break;
case LOCAL:
- visitor.visitLocal(this, (JCVariableDecl)get());
+ visitor.visitLocal(this, (JCVariableDecl) get());
ast.traverseChildren(visitor, this);
- visitor.endVisitLocal(this, (JCVariableDecl)get());
+ visitor.endVisitLocal(this, (JCVariableDecl) get());
break;
case STATEMENT:
visitor.visitStatement(this, get());
@@ -109,21 +117,21 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
case ANNOTATION:
switch (up().getKind()) {
case TYPE:
- visitor.visitAnnotationOnType((JCClassDecl)up().get(), this, (JCAnnotation)get());
+ visitor.visitAnnotationOnType((JCClassDecl) up().get(), this, (JCAnnotation) get());
break;
case FIELD:
- visitor.visitAnnotationOnField((JCVariableDecl)up().get(), this, (JCAnnotation)get());
+ visitor.visitAnnotationOnField((JCVariableDecl) up().get(), this, (JCAnnotation) get());
break;
case METHOD:
- visitor.visitAnnotationOnMethod((JCMethodDecl)up().get(), this, (JCAnnotation)get());
+ visitor.visitAnnotationOnMethod((JCMethodDecl) up().get(), this, (JCAnnotation) get());
break;
case ARGUMENT:
- JCVariableDecl argument = (JCVariableDecl)up().get();
- JCMethodDecl method = (JCMethodDecl)up().up().get();
- visitor.visitAnnotationOnMethodArgument(argument, method, this, (JCAnnotation)get());
+ JCVariableDecl argument = (JCVariableDecl) up().get();
+ JCMethodDecl method = (JCMethodDecl) up().up().get();
+ visitor.visitAnnotationOnMethodArgument(argument, method, this, (JCAnnotation) get());
break;
case LOCAL:
- visitor.visitAnnotationOnLocal((JCVariableDecl)up().get(), this, (JCAnnotation)get());
+ visitor.visitAnnotationOnLocal((JCVariableDecl) up().get(), this, (JCAnnotation) get());
break;
default:
throw new AssertionError("Annotion not expected as child of a " + up().getKind());
@@ -138,9 +146,9 @@ public class JavacNode extends lombok.core.LombokNode<JavacAST, JavacNode, JCTre
@Override public String getName() {
final Name n;
- if (node instanceof JCClassDecl) n = ((JCClassDecl)node).name;
- else if (node instanceof JCMethodDecl) n = ((JCMethodDecl)node).name;
- else if (node instanceof JCVariableDecl) n = ((JCVariableDecl)node).name;
+ if (node instanceof JCClassDecl) n = ((JCClassDecl) node).name;
+ else if (node instanceof JCMethodDecl) n = ((JCMethodDecl) node).name;
+ else if (node instanceof JCVariableDecl) n = ((JCVariableDecl) node).name;
else n = null;
return n == null ? null : n.toString();
diff --git a/src/core/lombok/javac/JavacResolution.java b/src/core/lombok/javac/JavacResolution.java
index 23d7d482..8cc239e1 100644
--- a/src/core/lombok/javac/JavacResolution.java
+++ b/src/core/lombok/javac/JavacResolution.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 The Project Lombok Authors.
+ * Copyright (C) 2011-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
@@ -24,14 +24,17 @@ package lombok.javac;
import static lombok.javac.Javac.*;
import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.ArrayDeque;
import java.util.Map;
import javax.lang.model.type.TypeKind;
+import javax.tools.JavaFileObject;
import lombok.Lombok;
+import lombok.core.debug.AssertionLogger;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Symbol.TypeSymbol;
@@ -57,6 +60,7 @@ import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Log;
public class JavacResolution {
private final Attr attr;
@@ -98,7 +102,7 @@ public class JavacResolution {
@Override public void visitClassDef(JCClassDecl tree) {
if (copyAt != null) return;
- env = enter.getClassEnv(tree.sym);
+ if (tree.sym != null) env = enter.getClassEnv(tree.sym);
}
@Override public void visitMethodDef(JCMethodDecl tree) {
@@ -138,16 +142,70 @@ public class JavacResolution {
EnvFinder finder = new EnvFinder(node.getContext());
while (!stack.isEmpty()) stack.pop().accept(finder);
- TreeMirrorMaker mirrorMaker = new TreeMirrorMaker(node.getTreeMaker());
+ TreeMirrorMaker mirrorMaker = new TreeMirrorMaker(node.getTreeMaker(), node.getContext());
JCTree copy = mirrorMaker.copy(finder.copyAt());
-
- attrib(copy, finder.get());
- return mirrorMaker.getOriginalToCopyMap();
+ Log log = Log.instance(node.getContext());
+ JavaFileObject oldFileObject = log.useSource(((JCCompilationUnit) node.top().get()).getSourceFile());
+ try {
+ memberEnterAndAttribute(copy, finder.get(), node.getContext());
+ return mirrorMaker.getOriginalToCopyMap();
+ } finally {
+ log.useSource(oldFileObject);
+ }
} finally {
messageSuppressor.enableLoggers();
}
}
+ private static Field memberEnterDotEnv;
+
+ private static Field getMemberEnterDotEnv() {
+ if (memberEnterDotEnv != null) return memberEnterDotEnv;
+ try {
+ Field f = MemberEnter.class.getDeclaredField("env");
+ f.setAccessible(true);
+ memberEnterDotEnv = f;
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+
+ return memberEnterDotEnv;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static Env<AttrContext> getEnvOfMemberEnter(MemberEnter memberEnter) {
+ Field f = getMemberEnterDotEnv();
+ try {
+ return (Env<AttrContext>) f.get(memberEnter);
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private static void setEnvOfMemberEnter(MemberEnter memberEnter, Env<AttrContext> env) {
+ Field f = getMemberEnterDotEnv();
+ try {
+ f.set(memberEnter, env);
+ } catch (Exception e) {
+ return;
+ }
+ }
+
+ private void memberEnterAndAttribute(JCTree copy, Env<AttrContext> env, Context context) {
+ MemberEnter memberEnter = MemberEnter.instance(context);
+ Env<AttrContext> oldEnv = getEnvOfMemberEnter(memberEnter);
+ setEnvOfMemberEnter(memberEnter, env);
+ try {
+ copy.accept(memberEnter);
+ } catch (Exception ignore) {
+ // intentionally ignored; usually even if this step fails, val will work (but not for val in method local inner classes and anonymous inner classes).
+ AssertionLogger.assertLog("member enter failed.", ignore);
+ } finally {
+ setEnvOfMemberEnter(memberEnter, oldEnv);
+ }
+ attrib(copy, env);
+ }
+
public void resolveClassMember(JavacNode node) {
ArrayDeque<JCTree> stack = new ArrayDeque<JCTree>();
@@ -171,8 +229,13 @@ public class JavacResolution {
}
private void attrib(JCTree tree, Env<AttrContext> env) {
+ if (env.enclClass.type == null) try {
+ env.enclClass.type = Type.noType;
+ } catch (Throwable ignore) {
+ // This addresses issue #1553 which involves JDK9; if it doesn't exist, we probably don't need to set it.
+ }
if (tree instanceof JCBlock) attr.attribStat(tree, env);
- else if (tree instanceof JCMethodDecl) attr.attribStat(((JCMethodDecl)tree).body, env);
+ else if (tree instanceof JCMethodDecl) attr.attribStat(((JCMethodDecl) tree).body, env);
else if (tree instanceof JCVariableDecl) attr.attribStat(tree, env);
else throw new IllegalStateException("Called with something that isn't a block, method decl, or variable decl");
}
@@ -210,6 +273,7 @@ public class JavacResolution {
}
public static Type ifTypeIsIterableToComponent(Type type, JavacAST ast) {
+ if (type == null) return null;
Types types = Types.instance(ast.getContext());
Symtab syms = Symtab.instance(ast.getContext());
Type boundType = ReflectiveAccess.Types_upperBound(types, type);
@@ -241,7 +305,7 @@ public class JavacResolution {
Type type0 = type;
while (type0 instanceof ArrayType) {
dims++;
- type0 = ((ArrayType)type0).elemtype;
+ type0 = ((ArrayType) type0).elemtype;
}
JCExpression result = typeToJCTree0(type0, ast, allowCompound, allowVoid);
diff --git a/src/core/lombok/javac/JavacTransformer.java b/src/core/lombok/javac/JavacTransformer.java
index 004a6035..54977a59 100644
--- a/src/core/lombok/javac/JavacTransformer.java
+++ b/src/core/lombok/javac/JavacTransformer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -26,6 +26,7 @@ import java.util.SortedSet;
import javax.annotation.processing.Messager;
+import com.sun.source.util.Trees;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
@@ -38,9 +39,9 @@ public class JavacTransformer {
private final HandlerLibrary handlers;
private final Messager messager;
- public JavacTransformer(Messager messager) {
+ public JavacTransformer(Messager messager, Trees trees) {
this.messager = messager;
- this.handlers = HandlerLibrary.load(messager);
+ this.handlers = HandlerLibrary.load(messager, trees);
}
public SortedSet<Long> getPriorities() {
@@ -54,7 +55,7 @@ public class JavacTransformer {
public void transform(long priority, Context context, java.util.List<JCCompilationUnit> compilationUnitsRaw) {
List<JCCompilationUnit> compilationUnits;
if (compilationUnitsRaw instanceof List<?>) {
- compilationUnits = (List<JCCompilationUnit>)compilationUnitsRaw;
+ compilationUnits = (List<JCCompilationUnit>) compilationUnitsRaw;
} else {
compilationUnits = List.nil();
for (int i = compilationUnitsRaw.size() -1; i >= 0; i--) {
diff --git a/src/core/lombok/javac/apt/EmptyLombokFileObject.java b/src/core/lombok/javac/apt/EmptyLombokFileObject.java
index 7298e920..5a3a7def 100644
--- a/src/core/lombok/javac/apt/EmptyLombokFileObject.java
+++ b/src/core/lombok/javac/apt/EmptyLombokFileObject.java
@@ -19,7 +19,6 @@
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/
-
package lombok.javac.apt;
import java.io.ByteArrayInputStream;
diff --git a/src/core/lombok/javac/apt/InterceptingJavaFileManager.java b/src/core/lombok/javac/apt/InterceptingJavaFileManager.java
index 303bdc2f..9b58d111 100644
--- a/src/core/lombok/javac/apt/InterceptingJavaFileManager.java
+++ b/src/core/lombok/javac/apt/InterceptingJavaFileManager.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -42,14 +42,14 @@ final class InterceptingJavaFileManager extends ForwardingJavaFileManager<JavaFi
}
@Override public JavaFileObject getJavaFileForOutput(Location location, String className, final Kind kind, FileObject sibling) throws IOException {
- if (className.startsWith("lombok.dummy.ForceNewRound")) {
+ if (className.contains("lombok.dummy.ForceNewRound")) {
final String name = className.replace(".", "/") + kind.extension;
return LombokFileObjects.createEmpty(compiler, name, kind);
}
+
JavaFileObject fileObject = fileManager.getJavaFileForOutput(location, className, kind, sibling);
- if (kind != Kind.CLASS) {
- return fileObject;
- }
+ if (kind != Kind.CLASS) return fileObject;
+
return LombokFileObjects.createIntercepting(compiler, fileObject, className, diagnostics);
}
} \ No newline at end of file
diff --git a/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java b/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java
new file mode 100644
index 00000000..f9fe2a7d
--- /dev/null
+++ b/src/core/lombok/javac/apt/Javac9BaseFileObjectWrapper.java
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2010-2017 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.javac.apt;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.Writer;
+import java.net.URI;
+import java.nio.file.Path;
+
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+
+import com.sun.tools.javac.file.BaseFileManager;
+
+class Javac9BaseFileObjectWrapper extends com.sun.tools.javac.file.PathFileObject {
+ private final LombokFileObject delegate;
+
+ public Javac9BaseFileObjectWrapper(BaseFileManager fileManager, Path path, LombokFileObject delegate) {
+ super(fileManager, path);
+ this.delegate = delegate;
+ }
+
+ @Override public boolean isNameCompatible(String simpleName, Kind kind) {
+ return delegate.isNameCompatible(simpleName, kind);
+ }
+
+ @Override public URI toUri() {
+ return delegate.toUri();
+ }
+
+ @SuppressWarnings("all")
+ @Override public String getName() {
+ return delegate.getName();
+ }
+
+ @Override public CharSequence getCharContent(boolean ignoreEncodingErrors) throws IOException {
+ return delegate.getCharContent(ignoreEncodingErrors);
+ }
+
+ @Override public InputStream openInputStream() throws IOException {
+ return delegate.openInputStream();
+ }
+
+ @Override public Reader openReader(boolean ignoreEncodingErrors) throws IOException {
+ return delegate.openReader(ignoreEncodingErrors);
+ }
+
+ @Override public Writer openWriter() throws IOException {
+ return delegate.openWriter();
+ }
+
+ @Override public OutputStream openOutputStream() throws IOException {
+ return delegate.openOutputStream();
+ }
+
+ @Override public long getLastModified() {
+ return delegate.getLastModified();
+ }
+
+ @Override public boolean delete() {
+ return delegate.delete();
+ }
+
+ @Override public Kind getKind() {
+ return delegate.getKind();
+ }
+
+ @Override public NestingKind getNestingKind() {
+ return delegate.getNestingKind();
+ }
+
+ @Override public Modifier getAccessLevel() {
+ return delegate.getAccessLevel();
+ }
+
+ @Override public boolean equals(Object obj) {
+ if (!(obj instanceof Javac9BaseFileObjectWrapper)) {
+ return false;
+ }
+ return delegate.equals(((Javac9BaseFileObjectWrapper)obj).delegate);
+ }
+
+ @Override public int hashCode() {
+ return delegate.hashCode();
+ }
+
+ @Override public String toString() {
+ return delegate.toString();
+ }
+} \ No newline at end of file
diff --git a/src/core/lombok/javac/apt/LombokFileObjects.java b/src/core/lombok/javac/apt/LombokFileObjects.java
index 412e449b..aba10540 100644
--- a/src/core/lombok/javac/apt/LombokFileObjects.java
+++ b/src/core/lombok/javac/apt/LombokFileObjects.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -22,20 +22,32 @@
package lombok.javac.apt;
+import java.io.IOException;
import java.lang.reflect.Method;
+import java.net.URI;
+import java.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Arrays;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean;
+import javax.tools.FileObject;
import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import javax.tools.JavaFileObject.Kind;
import lombok.core.DiagnosticsReceiver;
+import com.sun.tools.javac.file.BaseFileManager;
+
//Can't use SimpleJavaFileObject so we copy/paste most of its content here, because javac doesn't follow the interface,
//and casts to its own BaseFileObject type. D'oh!
final class LombokFileObjects {
- enum Compiler {
- JAVAC6 {
+
+ interface Compiler {
+ Compiler JAVAC6 = new Compiler() {
private Method decoderMethod = null;
private final AtomicBoolean decoderIsSet = new AtomicBoolean();
@@ -46,13 +58,13 @@ final class LombokFileObjects {
@Override public Method getDecoderMethod() {
synchronized (decoderIsSet) {
if (decoderIsSet.get()) return decoderMethod;
- decoderMethod = getDecoderMethod("com.sun.tools.javac.util.BaseFileObject");
+ decoderMethod = LombokFileObjects.getDecoderMethod("com.sun.tools.javac.util.BaseFileObject");
decoderIsSet.set(true);
return decoderMethod;
}
}
- },
- JAVAC7 {
+ };
+ Compiler JAVAC7 = new Compiler() {
private Method decoderMethod = null;
private final AtomicBoolean decoderIsSet = new AtomicBoolean();
@@ -63,46 +75,82 @@ final class LombokFileObjects {
@Override public Method getDecoderMethod() {
synchronized (decoderIsSet) {
if (decoderIsSet.get()) return decoderMethod;
- decoderMethod = getDecoderMethod("com.sun.tools.javac.file.BaseFileObject");
+ decoderMethod = LombokFileObjects.getDecoderMethod("com.sun.tools.javac.file.BaseFileObject");
decoderIsSet.set(true);
return decoderMethod;
}
}
};
- static Method getDecoderMethod(String className) {
- Method m = null;
- try {
- m = Class.forName(className).getDeclaredMethod("getDecoder", boolean.class);
- m.setAccessible(true);
- } catch (NoSuchMethodException e) {
- // Intentional fallthrough - getDecoder(boolean) is not always present.
- } catch (ClassNotFoundException e) {
- // Intentional fallthrough - getDecoder(boolean) is not always present.
- }
- return m;
- }
+ JavaFileObject wrap(LombokFileObject fileObject);
+ Method getDecoderMethod();
+ }
- abstract JavaFileObject wrap(LombokFileObject fileObject);
- abstract Method getDecoderMethod();
+ static Method getDecoderMethod(String className) {
+ Method m = null;
+ try {
+ m = Class.forName(className).getDeclaredMethod("getDecoder", boolean.class);
+ m.setAccessible(true);
+ } catch (NoSuchMethodException e) {
+ // Intentional fallthrough - getDecoder(boolean) is not always present.
+ } catch (ClassNotFoundException e) {
+ // Intentional fallthrough - getDecoder(boolean) is not always present.
+ }
+ return m;
}
private LombokFileObjects() {}
+ private static final List<String> KNOWN_JAVA9_FILE_MANAGERS = Arrays.asList(
+ "com.google.errorprone.MaskedClassLoader$MaskedFileManager",
+ "com.google.devtools.build.buildjar.javac.BlazeJavacMain$ClassloaderMaskingFileManager",
+ "com.google.devtools.build.java.turbine.javac.JavacTurbineCompiler$ClassloaderMaskingFileManager",
+ "org.netbeans.modules.java.source.parsing.ProxyFileManager",
+ "com.sun.tools.javac.api.ClientCodeWrapper$WrappedStandardJavaFileManager",
+ "com.sun.tools.javac.main.DelegatingJavaFileManager$DelegatingSJFM" // IntelliJ + JDK10
+ );
+
static Compiler getCompiler(JavaFileManager jfm) {
String jfmClassName = jfm != null ? jfm.getClass().getName() : "null";
if (jfmClassName.equals("com.sun.tools.javac.util.DefaultFileManager")) return Compiler.JAVAC6;
if (jfmClassName.equals("com.sun.tools.javac.util.JavacFileManager")) return Compiler.JAVAC6;
- if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) return Compiler.JAVAC7;
+ if (jfmClassName.equals("com.sun.tools.javac.file.JavacFileManager")) {
+ try {
+ Class<?> superType = Class.forName("com.sun.tools.javac.file.BaseFileManager");
+ if (superType.isInstance(jfm)) {
+ return new Java9Compiler(jfm);
+ }
+ }
+ catch (Throwable e) {}
+ return Compiler.JAVAC7;
+ }
+ if (KNOWN_JAVA9_FILE_MANAGERS.contains(jfmClassName)) {
+ try {
+ return new Java9Compiler(jfm);
+ }
+ catch (Throwable e) {}
+ }
+ try {
+ if (Class.forName("com.sun.tools.javac.file.PathFileObject") == null) throw new NullPointerException();
+ return new Java9Compiler(jfm);
+ } catch (Throwable e) {}
try {
if (Class.forName("com.sun.tools.javac.file.BaseFileObject") == null) throw new NullPointerException();
return Compiler.JAVAC7;
- } catch (Exception e) {}
+ } catch (Throwable e) {}
try {
if (Class.forName("com.sun.tools.javac.util.BaseFileObject") == null) throw new NullPointerException();
return Compiler.JAVAC6;
- } catch (Exception e) {}
- return null;
+ } catch (Throwable e) {}
+
+ StringBuilder sb = new StringBuilder(jfmClassName);
+ if (jfm != null) {
+ sb.append(" extends ").append(jfm.getClass().getSuperclass().getName());
+ for (Class<?> cls : jfm.getClass().getInterfaces()) {
+ sb.append(" implements ").append(cls.getName());
+ }
+ }
+ throw new IllegalArgumentException(sb.toString());
}
static JavaFileObject createEmpty(Compiler compiler, String name, Kind kind) {
@@ -112,4 +160,113 @@ final class LombokFileObjects {
static JavaFileObject createIntercepting(Compiler compiler, JavaFileObject delegate, String fileName, DiagnosticsReceiver diagnostics) {
return compiler.wrap(new InterceptingJavaFileObject(delegate, fileName, diagnostics, compiler.getDecoderMethod()));
}
+
+ static class Java9Compiler implements Compiler {
+ private final BaseFileManager fileManager;
+
+ public Java9Compiler(JavaFileManager jfm) {
+ fileManager = asBaseFileManager(jfm);
+ }
+
+ @Override public JavaFileObject wrap(LombokFileObject fileObject) {
+ return new Javac9BaseFileObjectWrapper(fileManager, toPath(fileObject), fileObject);
+ }
+
+ @Override public Method getDecoderMethod() {
+ return null;
+ }
+
+ private static Path toPath(LombokFileObject fileObject) {
+ URI uri = fileObject.toUri();
+ if (uri.getScheme() == null) {
+ uri = URI.create("file:///" + uri);
+ }
+ try {
+ return Paths.get(uri);
+ } catch (IllegalArgumentException e) {
+ throw new IllegalArgumentException("Problems in URI '" + uri + "' (" + fileObject.toUri() + ")", e);
+ }
+ }
+
+ private static BaseFileManager asBaseFileManager(JavaFileManager jfm) {
+ if (jfm instanceof BaseFileManager) {
+ return (BaseFileManager) jfm;
+ }
+ return new FileManagerWrapper(jfm);
+ }
+
+ static class FileManagerWrapper extends BaseFileManager {
+ JavaFileManager manager;
+
+ public FileManagerWrapper(JavaFileManager manager) {
+ super(null);
+ this.manager = manager;
+ }
+
+ @Override
+ public int isSupportedOption(String option) {
+ return manager.isSupportedOption(option);
+ }
+
+ @Override
+ public ClassLoader getClassLoader(Location location) {
+ return manager.getClassLoader(location);
+ }
+
+ @Override
+ public Iterable<JavaFileObject> list(Location location, String packageName, Set<Kind> kinds, boolean recurse) throws IOException {
+ return manager.list(location, packageName, kinds, recurse);
+ }
+
+ @Override
+ public String inferBinaryName(Location location, JavaFileObject file) {
+ return manager.inferBinaryName(location, file);
+ }
+
+ @Override
+ public boolean isSameFile(FileObject a, FileObject b) {
+ return manager.isSameFile(a, b);
+ }
+
+ @Override
+ public boolean handleOption(String current, Iterator<String> remaining) {
+ return manager.handleOption(current, remaining);
+ }
+
+ @Override
+ public boolean hasLocation(Location location) {
+ return manager.hasLocation(location);
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForInput(Location location, String className, Kind kind) throws IOException {
+ return manager.getJavaFileForInput(location, className, kind);
+ }
+
+ @Override
+ public JavaFileObject getJavaFileForOutput(Location location, String className, Kind kind, FileObject sibling) throws IOException {
+ return manager.getJavaFileForOutput(location, className, kind, sibling);
+ }
+
+ @Override
+ public FileObject getFileForInput(Location location, String packageName, String relativeName) throws IOException {
+ return manager.getFileForInput(location, packageName, relativeName);
+ }
+
+ @Override
+ public FileObject getFileForOutput(Location location, String packageName, String relativeName, FileObject sibling) throws IOException {
+ return manager.getFileForOutput(location, packageName, relativeName, sibling);
+ }
+
+ @Override
+ public void flush() throws IOException {
+ manager.flush();
+ }
+
+ @Override
+ public void close() throws IOException {
+ manager.close();
+ }
+ }
+ }
}
diff --git a/src/core/lombok/javac/apt/LombokProcessor.java b/src/core/lombok/javac/apt/LombokProcessor.java
new file mode 100644
index 00000000..9c0a2dfa
--- /dev/null
+++ b/src/core/lombok/javac/apt/LombokProcessor.java
@@ -0,0 +1,402 @@
+/*
+ * 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
+ * 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.javac.apt;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Messager;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.TypeElement;
+import javax.tools.Diagnostic.Kind;
+import javax.tools.JavaFileManager;
+import javax.tools.JavaFileObject;
+
+import lombok.Lombok;
+import lombok.core.DiagnosticsReceiver;
+import lombok.javac.JavacTransformer;
+
+import com.sun.source.util.TreePath;
+import com.sun.source.util.Trees;
+import com.sun.tools.javac.jvm.ClassWriter;
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.processing.JavacFiler;
+import com.sun.tools.javac.processing.JavacProcessingEnvironment;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Context;
+
+/**
+ * This Annotation Processor is the standard injection mechanism for lombok-enabling the javac compiler.
+ *
+ * To actually enable lombok in a javac compilation run, this class should be in the classpath when
+ * running javac; that's the only requirement.
+ */
+@SupportedAnnotationTypes("*")
+public class LombokProcessor extends AbstractProcessor {
+ private JavacProcessingEnvironment processingEnv;
+ private JavacTransformer transformer;
+ private Trees trees;
+ private boolean lombokDisabled = false;
+
+ /** {@inheritDoc} */
+ @Override public void init(ProcessingEnvironment procEnv) {
+ super.init(procEnv);
+ if (System.getProperty("lombok.disable") != null) {
+ lombokDisabled = true;
+ return;
+ }
+
+ this.processingEnv = (JavacProcessingEnvironment) procEnv;
+
+ placePostCompileAndDontMakeForceRoundDummiesHook();
+ trees = Trees.instance(procEnv);
+ transformer = new JavacTransformer(procEnv.getMessager(), trees);
+ SortedSet<Long> p = transformer.getPriorities();
+ if (p.isEmpty()) {
+ this.priorityLevels = new long[] {0L};
+ this.priorityLevelsRequiringResolutionReset = new HashSet<Long>();
+ } else {
+ this.priorityLevels = new long[p.size()];
+ int i = 0;
+ for (Long prio : p) this.priorityLevels[i++] = prio;
+ this.priorityLevelsRequiringResolutionReset = transformer.getPrioritiesRequiringResolutionReset();
+ }
+ }
+
+ private static final String JPE = "com.sun.tools.javac.processing.JavacProcessingEnvironment";
+ private static final Field javacProcessingEnvironment_discoveredProcs = getFieldAccessor(JPE, "discoveredProcs");
+ private static final Field discoveredProcessors_procStateList = getFieldAccessor(JPE + "$DiscoveredProcessors", "procStateList");
+ private static final Field processorState_processor = getFieldAccessor(JPE + "$processor", "processor");
+
+ private static final Field getFieldAccessor(String typeName, String fieldName) {
+ try {
+ Class<?> c = Class.forName(typeName);
+ Field f = c.getDeclaredField(fieldName);
+ f.setAccessible(true);
+ return f;
+ } catch (ClassNotFoundException e) {
+ return null;
+ } catch (NoSuchFieldException e) {
+ return null;
+ }
+ }
+
+ // The intent of this method is to have lombok emit a warning if it's not 'first in line'. However, pragmatically speaking, you're always looking at one of two cases:
+ // (A) The other processor(s) running before lombok require lombok to have run or they crash. So, they crash, and unfortunately we are never even init-ed; the warning is never emitted.
+ // (B) The other processor(s) don't care about it at all. So, it doesn't actually matter that lombok isn't first.
+ // Hence, for now, no warnings.
+ @SuppressWarnings("unused")
+ private String listAnnotationProcessorsBeforeOurs() {
+ try {
+ Object discoveredProcessors = javacProcessingEnvironment_discoveredProcs.get(this.processingEnv);
+ ArrayList<?> states = (ArrayList<?>) discoveredProcessors_procStateList.get(discoveredProcessors);
+ if (states == null || states.isEmpty()) return null;
+ if (states.size() == 1) return processorState_processor.get(states.get(0)).getClass().getName();
+
+ int idx = 0;
+ StringBuilder out = new StringBuilder();
+ for (Object processState : states) {
+ idx++;
+ String name = processorState_processor.get(processState).getClass().getName();
+ if (out.length() > 0) out.append(", ");
+ out.append("[").append(idx).append("] ").append(name);
+ }
+ return out.toString();
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ private void placePostCompileAndDontMakeForceRoundDummiesHook() {
+ stopJavacProcessingEnvironmentFromClosingOurClassloader();
+
+ forceMultipleRoundsInNetBeansEditor();
+ Context context = processingEnv.getContext();
+ disablePartialReparseInNetBeansEditor(context);
+ try {
+ Method keyMethod = Context.class.getDeclaredMethod("key", Class.class);
+ keyMethod.setAccessible(true);
+ Object key = keyMethod.invoke(context, JavaFileManager.class);
+ Field htField = Context.class.getDeclaredField("ht");
+ htField.setAccessible(true);
+ @SuppressWarnings("unchecked")
+ Map<Object,Object> ht = (Map<Object,Object>) htField.get(context);
+ final JavaFileManager originalFiler = (JavaFileManager) ht.get(key);
+ if (!(originalFiler instanceof InterceptingJavaFileManager)) {
+ final Messager messager = processingEnv.getMessager();
+ DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager);
+
+ JavaFileManager newFiler = new InterceptingJavaFileManager(originalFiler, receiver);
+ ht.put(key, newFiler);
+ Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager");
+ filerFileManagerField.setAccessible(true);
+ filerFileManagerField.set(processingEnv.getFiler(), newFiler);
+
+ replaceFileManagerJdk9(context, newFiler);
+ }
+ } catch (Exception e) {
+ throw Lombok.sneakyThrow(e);
+ }
+ }
+
+ private void replaceFileManagerJdk9(Context context, JavaFileManager newFiler) {
+ try {
+ JavaCompiler compiler = (JavaCompiler) JavaCompiler.class.getDeclaredMethod("instance", Context.class).invoke(null, context);
+ try {
+ Field fileManagerField = JavaCompiler.class.getDeclaredField("fileManager");
+ fileManagerField.setAccessible(true);
+ fileManagerField.set(compiler, newFiler);
+ }
+ catch (Exception e) {}
+
+ try {
+ Field writerField = JavaCompiler.class.getDeclaredField("writer");
+ writerField.setAccessible(true);
+ ClassWriter writer = (ClassWriter) writerField.get(compiler);
+ Field fileManagerField = ClassWriter.class.getDeclaredField("fileManager");
+ fileManagerField.setAccessible(true);
+ fileManagerField.set(writer, newFiler);
+ }
+ catch (Exception e) {}
+ }
+ catch (Exception e) {
+ }
+ }
+
+ private void forceMultipleRoundsInNetBeansEditor() {
+ try {
+ Field f = JavacProcessingEnvironment.class.getDeclaredField("isBackgroundCompilation");
+ f.setAccessible(true);
+ f.set(processingEnv, true);
+ } catch (NoSuchFieldException e) {
+ // only NetBeans has it
+ } catch (Throwable t) {
+ throw Lombok.sneakyThrow(t);
+ }
+ }
+
+ private void disablePartialReparseInNetBeansEditor(Context context) {
+ try {
+ Class<?> cancelServiceClass = Class.forName("com.sun.tools.javac.util.CancelService");
+ Method cancelServiceInstace = cancelServiceClass.getDeclaredMethod("instance", Context.class);
+ Object cancelService = cancelServiceInstace.invoke(null, context);
+ if (cancelService == null) return;
+ Field parserField = cancelService.getClass().getDeclaredField("parser");
+ parserField.setAccessible(true);
+ Object parser = parserField.get(cancelService);
+ Field supportsReparseField = parser.getClass().getDeclaredField("supportsReparse");
+ supportsReparseField.setAccessible(true);
+ supportsReparseField.set(parser, false);
+ } catch (ClassNotFoundException e) {
+ // only NetBeans has it
+ } catch (NoSuchFieldException e) {
+ // only NetBeans has it
+ } catch (Throwable t) {
+ throw Lombok.sneakyThrow(t);
+ }
+ }
+
+ private static ClassLoader wrapClassLoader(final ClassLoader parent) {
+ return new ClassLoader() {
+
+ public Class<?> loadClass(String name) throws ClassNotFoundException {
+ return parent.loadClass(name);
+ }
+
+ public String toString() {
+ return parent.toString();
+ }
+
+ public URL getResource(String name) {
+ return parent.getResource(name);
+ }
+
+ public Enumeration<URL> getResources(String name) throws IOException {
+ return parent.getResources(name);
+ }
+
+ public InputStream getResourceAsStream(String name) {
+ return parent.getResourceAsStream(name);
+ }
+
+ public void setDefaultAssertionStatus(boolean enabled) {
+ parent.setDefaultAssertionStatus(enabled);
+ }
+
+ public void setPackageAssertionStatus(String packageName, boolean enabled) {
+ parent.setPackageAssertionStatus(packageName, enabled);
+ }
+
+ public void setClassAssertionStatus(String className, boolean enabled) {
+ parent.setClassAssertionStatus(className, enabled);
+ }
+
+ public void clearAssertionStatus() {
+ parent.clearAssertionStatus();
+ }
+ };
+ }
+
+ private void stopJavacProcessingEnvironmentFromClosingOurClassloader() {
+ try {
+ Field f = JavacProcessingEnvironment.class.getDeclaredField("processorClassLoader");
+ f.setAccessible(true);
+ ClassLoader unwrapped = (ClassLoader) f.get(processingEnv);
+ if (unwrapped == null) return;
+ ClassLoader wrapped = wrapClassLoader(unwrapped);
+ f.set(processingEnv, wrapped);
+ } catch (NoSuchFieldException e) {
+ // Some versions of javac have this (and call close on it), some don't. I guess this one doesn't have it.
+ } catch (Throwable t) {
+ throw Lombok.sneakyThrow(t);
+ }
+ }
+
+ private final IdentityHashMap<JCCompilationUnit, Long> roots = new IdentityHashMap<JCCompilationUnit, Long>();
+ private long[] priorityLevels;
+ private Set<Long> priorityLevelsRequiringResolutionReset;
+
+ /** {@inheritDoc} */
+ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (lombokDisabled) return false;
+ if (roundEnv.processingOver()) return false;
+
+ // We have: A sorted set of all priority levels: 'priorityLevels'
+
+ // Step 1: Take all CUs which aren't already in the map. Give them the first priority level.
+
+ String randomModuleName = null;
+
+ for (Element element : roundEnv.getRootElements()) {
+ if (randomModuleName == null) randomModuleName = getModuleNameFor(element);
+ JCCompilationUnit unit = toUnit(element);
+ if (unit == null) continue;
+ if (roots.containsKey(unit)) continue;
+ roots.put(unit, priorityLevels[0]);
+ }
+
+ while (true) {
+ // Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level.
+
+ for (long prio : priorityLevels) {
+ List<JCCompilationUnit> cusForThisRound = new ArrayList<JCCompilationUnit>();
+ for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
+ Long prioOfCu = entry.getValue();
+ if (prioOfCu == null || prioOfCu != prio) continue;
+ cusForThisRound.add(entry.getKey());
+ }
+ transformer.transform(prio, processingEnv.getContext(), cusForThisRound);
+ }
+
+ // Step 3: Push up all CUs to the next level. Set level to null if there is no next level.
+
+ Set<Long> newLevels = new HashSet<Long>();
+ for (int i = priorityLevels.length - 1; i >= 0; i--) {
+ Long curLevel = priorityLevels[i];
+ Long nextLevel = (i == priorityLevels.length - 1) ? null : priorityLevels[i + 1];
+ List<JCCompilationUnit> cusToAdvance = new ArrayList<JCCompilationUnit>();
+ for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
+ if (curLevel.equals(entry.getValue())) {
+ cusToAdvance.add(entry.getKey());
+ newLevels.add(nextLevel);
+ }
+ }
+ for (JCCompilationUnit unit : cusToAdvance) {
+ roots.put(unit, nextLevel);
+ }
+ }
+ newLevels.remove(null);
+
+ // Step 4: If ALL values are null, quit. Else, either do another loop right now or force a resolution reset by forcing a new round in the annotation processor.
+
+ if (newLevels.isEmpty()) return false;
+ newLevels.retainAll(priorityLevelsRequiringResolutionReset);
+ if (!newLevels.isEmpty()) {
+ // Force a new round to reset resolution. The next round will cause this method (process) to be called again.
+ forceNewRound(randomModuleName, (JavacFiler) processingEnv.getFiler());
+ return false;
+ }
+ // None of the new levels need resolution, so just keep going.
+ }
+ }
+
+ private int dummyCount = 0;
+ private void forceNewRound(String randomModuleName, JavacFiler filer) {
+ if (!filer.newFiles()) {
+ try {
+ String name = "lombok.dummy.ForceNewRound" + (dummyCount++);
+ if (randomModuleName != null) name = randomModuleName + "/" + name;
+ JavaFileObject dummy = filer.createSourceFile(name);
+ Writer w = dummy.openWriter();
+ w.close();
+ } catch (Exception e) {
+ e.printStackTrace();
+ processingEnv.getMessager().printMessage(Kind.WARNING,
+ "Can't force a new processing round. Lombok won't work.");
+ }
+ }
+ }
+
+ private String getModuleNameFor(Element element) {
+ while (element != null) {
+ if (element.getKind().name().equals("MODULE")) {
+ String n = element.getSimpleName().toString().trim();
+ return n.isEmpty() ? null : n;
+ }
+ Element n = element.getEnclosingElement();
+ if (n == element) return null;
+ element = n;
+ }
+ return null;
+ }
+
+ private JCCompilationUnit toUnit(Element element) {
+ TreePath path = trees == null ? null : trees.getPath(element);
+ if (path == null) return null;
+
+ return (JCCompilationUnit) path.getCompilationUnit();
+ }
+
+ /**
+ * We just return the latest version of whatever JDK we run on. Stupid? Yeah, but it's either that or warnings on all versions but 1.
+ */
+ @Override public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+}
diff --git a/src/core/lombok/javac/apt/Processor.java b/src/core/lombok/javac/apt/Processor.java
index ce4d75ff..7a187148 100644
--- a/src/core/lombok/javac/apt/Processor.java
+++ b/src/core/lombok/javac/apt/Processor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2015 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,295 +21,211 @@
*/
package lombok.javac.apt;
+import static javax.tools.StandardLocation.*;
+
+import java.io.File;
+import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
-import java.io.Writer;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.StringWriter;
import java.lang.reflect.Field;
-import java.lang.reflect.Method;
import java.net.URL;
import java.util.ArrayList;
+import java.util.Collections;
import java.util.Enumeration;
-import java.util.HashSet;
-import java.util.IdentityHashMap;
-import java.util.List;
import java.util.Map;
+import java.util.Properties;
import java.util.Set;
-import java.util.SortedSet;
import javax.annotation.processing.AbstractProcessor;
-import javax.annotation.processing.Messager;
+import javax.annotation.processing.Filer;
import javax.annotation.processing.ProcessingEnvironment;
import javax.annotation.processing.RoundEnvironment;
import javax.annotation.processing.SupportedAnnotationTypes;
import javax.lang.model.SourceVersion;
-import javax.lang.model.element.Element;
import javax.lang.model.element.TypeElement;
-import javax.tools.Diagnostic.Kind;
+import javax.tools.Diagnostic;
import javax.tools.JavaFileManager;
-import javax.tools.JavaFileObject;
-
-import lombok.Lombok;
-import lombok.core.DiagnosticsReceiver;
-import lombok.javac.JavacTransformer;
-import com.sun.source.util.TreePath;
-import com.sun.source.util.Trees;
import com.sun.tools.javac.processing.JavacFiler;
import com.sun.tools.javac.processing.JavacProcessingEnvironment;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.Options;
/**
- * This Annotation Processor is the standard injection mechanism for lombok-enabling the javac compiler.
- *
- * To actually enable lombok in a javac compilation run, this class should be in the classpath when
- * running javac; that's the only requirement.
+ * This processor should not be used. It used to be THE processor. This class is only there to warn people that something went wrong, and for the
+ * lombok developers to see if what the reason for those failures is.
*/
+@Deprecated
@SupportedAnnotationTypes("*")
public class Processor extends AbstractProcessor {
-
- private JavacProcessingEnvironment processingEnv;
- private JavacTransformer transformer;
- private Trees trees;
- private boolean lombokDisabled = false;
/** {@inheritDoc} */
@Override public void init(ProcessingEnvironment procEnv) {
super.init(procEnv);
if (System.getProperty("lombok.disable") != null) {
- lombokDisabled = true;
return;
}
-
- this.processingEnv = (JavacProcessingEnvironment) procEnv;
- placePostCompileAndDontMakeForceRoundDummiesHook();
- transformer = new JavacTransformer(procEnv.getMessager());
- trees = Trees.instance(procEnv);
- SortedSet<Long> p = transformer.getPriorities();
- if (p.isEmpty()) {
- this.priorityLevels = new long[] {0L};
- this.priorityLevelsRequiringResolutionReset = new HashSet<Long>();
- } else {
- this.priorityLevels = new long[p.size()];
- int i = 0;
- for (Long prio : p) this.priorityLevels[i++] = prio;
- this.priorityLevelsRequiringResolutionReset = transformer.getPrioritiesRequiringResolutionReset();
- }
+ procEnv.getMessager().printMessage(Diagnostic.Kind.WARNING, "Wrong usage of 'lombok.javac.apt.Processor'. " + report(procEnv));
}
- private void placePostCompileAndDontMakeForceRoundDummiesHook() {
- stopJavacProcessingEnvironmentFromClosingOurClassloader();
-
- forceMultipleRoundsInNetBeansEditor();
- Context context = processingEnv.getContext();
- disablePartialReparseInNetBeansEditor(context);
+ private String report(ProcessingEnvironment procEnv) {
+ String data = collectData(procEnv);
try {
- Method keyMethod = Context.class.getDeclaredMethod("key", Class.class);
- keyMethod.setAccessible(true);
- Object key = keyMethod.invoke(context, JavaFileManager.class);
- Field htField = Context.class.getDeclaredField("ht");
- htField.setAccessible(true);
- @SuppressWarnings("unchecked")
- Map<Object,Object> ht = (Map<Object,Object>) htField.get(context);
- final JavaFileManager originalFiler = (JavaFileManager) ht.get(key);
-
- if (!(originalFiler instanceof InterceptingJavaFileManager)) {
- final Messager messager = processingEnv.getMessager();
- DiagnosticsReceiver receiver = new MessagerDiagnosticsReceiver(messager);
-
- JavaFileManager newFiler = new InterceptingJavaFileManager(originalFiler, receiver);
- ht.put(key, newFiler);
- Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager");
- filerFileManagerField.setAccessible(true);
- filerFileManagerField.set(processingEnv.getFiler(), newFiler);
- }
+ return writeFile(data);
} catch (Exception e) {
- throw Lombok.sneakyThrow(e);
+ return "Report:\n\n" + data;
}
}
- private void forceMultipleRoundsInNetBeansEditor() {
- try {
- Field f = JavacProcessingEnvironment.class.getDeclaredField("isBackgroundCompilation");
- f.setAccessible(true);
- f.set(processingEnv, true);
- } catch (NoSuchFieldException e) {
- // only NetBeans has it
- } catch (Throwable t) {
- throw Lombok.sneakyThrow(t);
- }
+ private String writeFile(String data) throws IOException {
+ File file = File.createTempFile("lombok-processor-report-", ".txt");
+ OutputStreamWriter writer = new OutputStreamWriter(new FileOutputStream(file));
+ writer.write(data);
+ writer.close();
+ return "Report written to '" + file.getCanonicalPath() + "'\n";
}
-
- private void disablePartialReparseInNetBeansEditor(Context context) {
- try {
- Class<?> cancelServiceClass = Class.forName("com.sun.tools.javac.util.CancelService");
- Method cancelServiceInstace = cancelServiceClass.getDeclaredMethod("instance", Context.class);
- Object cancelService = cancelServiceInstace.invoke(null, context);
- if (cancelService == null) return;
- Field parserField = cancelService.getClass().getDeclaredField("parser");
- parserField.setAccessible(true);
- Object parser = parserField.get(cancelService);
- Field supportsReparseField = parser.getClass().getDeclaredField("supportsReparse");
- supportsReparseField.setAccessible(true);
- supportsReparseField.set(parser, false);
- } catch (ClassNotFoundException e) {
- // only NetBeans has it
- } catch (NoSuchFieldException e) {
- // only NetBeans has it
- } catch (Throwable t) {
- throw Lombok.sneakyThrow(t);
- }
+
+ private String collectData(ProcessingEnvironment procEnv) {
+ StringBuilder message = new StringBuilder();
+ message.append("Problem report for usages of 'lombok.javac.apt.Processor'\n\n");
+ listOptions(message, procEnv);
+ findServices(message, procEnv.getFiler());
+ addStacktrace(message);
+ listProperties(message);
+ return message.toString();
}
- private static ClassLoader wrapClassLoader(final ClassLoader parent) {
- return new ClassLoader() {
-
- public Class<?> loadClass(String name) throws ClassNotFoundException {
- return parent.loadClass(name);
- }
-
- public String toString() {
- return parent.toString();
- }
-
- public URL getResource(String name) {
- return parent.getResource(name);
- }
-
- public Enumeration<URL> getResources(String name) throws IOException {
- return parent.getResources(name);
- }
-
- public InputStream getResourceAsStream(String name) {
- return parent.getResourceAsStream(name);
- }
-
- public void setDefaultAssertionStatus(boolean enabled) {
- parent.setDefaultAssertionStatus(enabled);
- }
-
- public void setPackageAssertionStatus(String packageName, boolean enabled) {
- parent.setPackageAssertionStatus(packageName, enabled);
- }
-
- public void setClassAssertionStatus(String className, boolean enabled) {
- parent.setClassAssertionStatus(className, enabled);
+ private void listOptions(StringBuilder message, ProcessingEnvironment procEnv) {
+ try {
+ JavacProcessingEnvironment environment = (JavacProcessingEnvironment) procEnv;
+ Options instance = Options.instance(environment.getContext());
+ Field field = Options.class.getDeclaredField("values");
+ field.setAccessible(true);
+ @SuppressWarnings("unchecked") Map<String, String> values = (Map<String, String>) field.get(instance);
+ if (values.isEmpty()) {
+ message.append("Options: empty\n\n");
+ return;
}
-
- public void clearAssertionStatus() {
- parent.clearAssertionStatus();
+ message.append("Compiler Options:\n");
+ for (Map.Entry<String, String> value : values.entrySet()) {
+ message.append("- ");
+ string(message, value.getKey());
+ message.append(" = ");
+ string(message, value.getValue());
+ message.append("\n");
}
- };
- }
-
- private void stopJavacProcessingEnvironmentFromClosingOurClassloader() {
- try {
- Field f = JavacProcessingEnvironment.class.getDeclaredField("processorClassLoader");
- f.setAccessible(true);
- ClassLoader unwrapped = (ClassLoader) f.get(processingEnv);
- if (unwrapped == null) return;
- ClassLoader wrapped = wrapClassLoader(unwrapped);
- f.set(processingEnv, wrapped);
- } catch (NoSuchFieldException e) {
- // Some versions of javac have this (and call close on it), some don't. I guess this one doesn't have it.
- } catch (Throwable t) {
- throw Lombok.sneakyThrow(t);
- }
- }
-
- private final IdentityHashMap<JCCompilationUnit, Long> roots = new IdentityHashMap<JCCompilationUnit, Long>();
- private long[] priorityLevels;
- private Set<Long> priorityLevelsRequiringResolutionReset;
-
- /** {@inheritDoc} */
- @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
- if (lombokDisabled) return false;
- if (roundEnv.processingOver()) return false;
-
- // We have: A sorted set of all priority levels: 'priorityLevels'
-
- // Step 1: Take all CUs which aren't already in the map. Give them the first priority level.
-
- for (Element element : roundEnv.getRootElements()) {
- JCCompilationUnit unit = toUnit(element);
- if (unit == null) continue;
- if (roots.containsKey(unit)) continue;
- roots.put(unit, priorityLevels[0]);
+ message.append("\n");
+ } catch (Exception e) {
+ message.append("No options available\n\n");
}
- while (true) {
- // Step 2: For all CUs (in the map, not the roundEnv!), run them across all handlers at their current prio level.
-
- for (long prio : priorityLevels) {
- List<JCCompilationUnit> cusForThisRound = new ArrayList<JCCompilationUnit>();
- for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
- Long prioOfCu = entry.getValue();
- if (prioOfCu == null || prioOfCu != prio) continue;
- cusForThisRound.add(entry.getKey());
- }
- transformer.transform(prio, processingEnv.getContext(), cusForThisRound);
+ }
+
+ private void findServices(StringBuilder message, Filer filer) {
+ try {
+ Field filerFileManagerField = JavacFiler.class.getDeclaredField("fileManager");
+ filerFileManagerField.setAccessible(true);
+ JavaFileManager jfm = (JavaFileManager) filerFileManagerField.get(filer);
+ ClassLoader processorClassLoader = jfm.hasLocation(ANNOTATION_PROCESSOR_PATH) ? jfm.getClassLoader(ANNOTATION_PROCESSOR_PATH) : jfm.getClassLoader(CLASS_PATH);
+ Enumeration<URL> resources = processorClassLoader.getResources("META-INF/services/javax.annotation.processing.Processor");
+ if (!resources.hasMoreElements()) {
+ message.append("No processors discovered\n\n");
+ return;
}
-
- // Step 3: Push up all CUs to the next level. Set level to null if there is no next level.
-
- Set<Long> newLevels = new HashSet<Long>();
- for (int i = priorityLevels.length - 1; i >= 0; i--) {
- Long curLevel = priorityLevels[i];
- Long nextLevel = (i == priorityLevels.length - 1) ? null : priorityLevels[i + 1];
- List<JCCompilationUnit> cusToAdvance = new ArrayList<JCCompilationUnit>();
- for (Map.Entry<JCCompilationUnit, Long> entry : roots.entrySet()) {
- if (curLevel.equals(entry.getValue())) {
- cusToAdvance.add(entry.getKey());
- newLevels.add(nextLevel);
+ message.append("Discovered processors:\n");
+ while (resources.hasMoreElements()) {
+ URL processorUrl = resources.nextElement();
+ message.append("- '").append(processorUrl).append("'");
+ InputStream content = (InputStream) processorUrl.getContent();
+ if (content != null) try {
+ InputStreamReader reader = new InputStreamReader(content, "UTF-8");
+ StringWriter sw = new StringWriter();
+ char[] buffer = new char[8192];
+ int read = 0;
+ while ((read = reader.read(buffer))!= -1) {
+ sw.write(buffer, 0, read);
}
- }
- for (JCCompilationUnit unit : cusToAdvance) {
- roots.put(unit, nextLevel);
+ String wholeFile = sw.toString();
+ if (wholeFile.contains("lombok.javac.apt.Processor")) {
+ message.append(" <= problem\n");
+ } else {
+ message.append(" (ok)\n");
+ }
+ message.append(" ").append(wholeFile.replace("\n", "\n ")).append("\n");
+ } finally {
+ content.close();
}
}
- newLevels.remove(null);
-
- // Step 4: If ALL values are null, quit. Else, either do another loop right now or force a resolution reset by forcing a new round in the annotation processor.
-
- if (newLevels.isEmpty()) return false;
- newLevels.retainAll(priorityLevelsRequiringResolutionReset);
- if (newLevels.isEmpty()) {
- // None of the new levels need resolution, so just keep going.
- continue;
- } else {
- // Force a new round to reset resolution. The next round will cause this method (process) to be called again.
- forceNewRound((JavacFiler) processingEnv.getFiler());
- return false;
- }
+ } catch (Exception e) {
+ message.append("Filer information unavailable\n");
}
+ message.append("\n");
}
-
- private int dummyCount = 0;
- private void forceNewRound(JavacFiler filer) {
- if (!filer.newFiles()) {
- try {
- JavaFileObject dummy = filer.createSourceFile("lombok.dummy.ForceNewRound" + (dummyCount++));
- Writer w = dummy.openWriter();
- w.close();
- } catch (Exception e) {
- e.printStackTrace();
- processingEnv.getMessager().printMessage(Kind.WARNING,
- "Can't force a new processing round. Lombok won't work.");
+
+ private void addStacktrace(StringBuilder message) {
+ StackTraceElement[] stackTraceElements = Thread.currentThread().getStackTrace();
+ if (stackTraceElements != null) {
+ message.append("Called from\n");
+ for (int i = 1; i < stackTraceElements.length; i++) {
+ StackTraceElement element = stackTraceElements[i];
+ if (!element.getClassName().equals("lombok.javac.apt.Processor")) message.append("- ").append(element).append("\n");
}
+ } else {
+ message.append("No stacktrace available\n");
}
+ message.append("\n");
+ }
+
+ private void listProperties(StringBuilder message) {
+ Properties properties = System.getProperties();
+ ArrayList<String> propertyNames = new ArrayList<String>(properties.stringPropertyNames());
+ Collections.sort(propertyNames);
+ message.append("Properties: \n");
+ for (String propertyName : propertyNames) {
+ if (propertyName.startsWith("user.")) continue;
+ message.append("- ").append(propertyName).append(" = ");
+ string(message, System.getProperty(propertyName));
+ message.append("\n");
+ }
+ message.append("\n");
}
- private JCCompilationUnit toUnit(Element element) {
- TreePath path = trees == null ? null : trees.getPath(element);
- if (path == null) return null;
-
- return (JCCompilationUnit) path.getCompilationUnit();
+ private static void string(StringBuilder sb, String s) {
+ if (s == null) {
+ sb.append("null");
+ return;
+ }
+ sb.append("\"");
+ for (int i = 0; i < s.length(); i++) sb.append(escape(s.charAt(i)));
+ sb.append("\"");
}
+ private static String escape(char ch) {
+ switch (ch) {
+ case '\b': return "\\b";
+ case '\f': return "\\f";
+ case '\n': return "\\n";
+ case '\r': return "\\r";
+ case '\t': return "\\t";
+ case '\'': return "\\'";
+ case '\"': return "\\\"";
+ case '\\': return "\\\\";
+ default:
+ if (ch < 32) return String.format("\\%03o", (int) ch);
+ return String.valueOf(ch);
+ }
+ }
+
/**
* We just return the latest version of whatever JDK we run on. Stupid? Yeah, but it's either that or warnings on all versions but 1.
*/
@Override public SourceVersion getSupportedSourceVersion() {
return SourceVersion.values()[SourceVersion.values().length - 1];
}
+
+ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ return false;
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilder.java b/src/core/lombok/javac/handlers/HandleBuilder.java
index 1885b8b4..86ac00e6 100644
--- a/src/core/lombok/javac/handlers/HandleBuilder.java
+++ b/src/core/lombok/javac/handlers/HandleBuilder.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
@@ -22,18 +22,22 @@
package lombok.javac.handlers;
import java.util.ArrayList;
-import java.util.Collections;
+
+import javax.lang.model.element.Modifier;
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.JCArrayTypeTree;
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.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.tree.JCTree.JCIf;
+import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
@@ -46,16 +50,22 @@ import com.sun.tools.javac.util.ListBuffer;
import com.sun.tools.javac.util.Name;
import lombok.AccessLevel;
+import lombok.Builder;
+import lombok.Builder.ObtainVia;
import lombok.ConfigurationKeys;
+import lombok.Singular;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
import lombok.core.HandlerPriority;
-import lombok.experimental.Builder;
+import lombok.core.handlers.HandlerUtil;
import lombok.experimental.NonFinal;
+import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
import lombok.javac.handlers.HandleConstructor.SkipIfConstructorExists;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import static lombok.javac.Javac.*;
@@ -64,13 +74,41 @@ import static lombok.javac.JavacTreeMaker.TypeTag.*;
@ProviderFor(JavacAnnotationHandler.class)
@HandlerPriority(-1024) //-2^10; to ensure we've picked up @FieldDefault's changes (-2048) but @Value hasn't removed itself yet (-512), so that we can error on presence of it on the builder classes.
public class HandleBuilder extends JavacAnnotationHandler<Builder> {
- @Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
- handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.BUILDER_FLAG_USAGE, "@Builder");
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
+ private static final boolean toBoolean(Object expr, boolean defaultValue) {
+ if (expr == null) return defaultValue;
+ if (expr instanceof JCLiteral) return ((Integer) ((JCLiteral) expr).value) != 0;
+ return ((Boolean) expr).booleanValue();
+ }
+
+ private static class BuilderFieldData {
+ JCExpression type;
+ Name rawName;
+ Name name;
+ Name nameOfDefaultProvider;
+ Name nameOfSetFlag;
+ SingularData singularData;
+ ObtainVia obtainVia;
+ JavacNode obtainViaNode;
+ JavacNode originalFieldNode;
+ java.util.List<JavacNode> createdFields = new ArrayList<JavacNode>();
+ }
+
+ @Override public void handle(AnnotationValues<Builder> annotation, JCAnnotation ast, JavacNode annotationNode) {
Builder builderInstance = annotation.getInstance();
+
+ // These exist just to support the 'old' lombok.experimental.Builder, which had these properties. lombok.Builder no longer has them.
+ boolean fluent = toBoolean(annotation.getActualExpression("fluent"), true);
+ boolean chain = toBoolean(annotation.getActualExpression("chain"), true);
+
String builderMethodName = builderInstance.builderMethodName();
String buildMethodName = builderInstance.buildMethodName();
String builderClassName = builderInstance.builderClassName();
+ String toBuilderMethodName = "toBuilder";
+ boolean toBuilder = builderInstance.toBuilder();
+ java.util.List<Name> typeArgsForToBuilder = null;
if (builderMethodName == null) builderMethodName = "builder";
if (buildMethodName == null) buildMethodName = "build";
@@ -82,73 +120,99 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (!checkName("builderClassName", builderClassName, annotationNode)) return;
}
- deleteAnnotationIfNeccessary(annotationNode, Builder.class);
- deleteImportFromCompilationUnit(annotationNode, "lombok.experimental.Builder");
+ deleteAnnotationIfNeccessary(annotationNode, Builder.class, "lombok.experimental.Builder");
JavacNode parent = annotationNode.up();
- java.util.List<JCExpression> typesOfParameters = new ArrayList<JCExpression>();
- java.util.List<Name> namesOfParameters = new ArrayList<Name>();
+ java.util.List<BuilderFieldData> builderFields = new ArrayList<BuilderFieldData>();
JCExpression returnType;
List<JCTypeParameter> typeParams = List.nil();
List<JCExpression> thrownExceptions = List.nil();
- Name nameOfStaticBuilderMethod;
+ Name nameOfBuilderMethod;
JavacNode tdParent;
- JCMethodDecl fillParametersFrom = parent.get() instanceof JCMethodDecl ? ((JCMethodDecl) parent.get()) : null;
+ JavacNode fillParametersFrom = parent.get() instanceof JCMethodDecl ? parent : null;
+ boolean addCleaning = false;
+ boolean isStatic = true;
if (parent.get() instanceof JCClassDecl) {
tdParent = parent;
JCClassDecl td = (JCClassDecl) tdParent.get();
ListBuffer<JavacNode> allFields = new ListBuffer<JavacNode>();
- @SuppressWarnings("deprecation")
- boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation(lombok.experimental.Value.class, parent));
- for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent)) {
+ boolean valuePresent = (hasAnnotation(lombok.Value.class, parent) || hasAnnotation("lombok.experimental.Value", parent));
+ for (JavacNode fieldNode : HandleConstructor.findAllFields(tdParent, true)) {
JCVariableDecl fd = (JCVariableDecl) fieldNode.get();
- // final fields with an initializer cannot be written to, so they can't be 'builderized'. Unfortunately presence of @Value makes
- // non-final fields final, but @Value's handler hasn't done this yet, so we have to do this math ourselves.
- // Value will only skip making a field final if it has an explicit @NonFinal annotation, so we check for that.
- if (fd.init != null && valuePresent && !hasAnnotation(NonFinal.class, fieldNode)) continue;
- namesOfParameters.add(removePrefixFromField(fieldNode));
- typesOfParameters.add(fd.vartype);
+ JavacNode isDefault = findAnnotation(Builder.Default.class, fieldNode, true);
+ boolean isFinal = (fd.mods.flags & Flags.FINAL) != 0 || (valuePresent && !hasAnnotation(NonFinal.class, fieldNode));
+ BuilderFieldData bfd = new BuilderFieldData();
+ bfd.rawName = fd.name;
+ bfd.name = removePrefixFromField(fieldNode);
+ bfd.type = fd.vartype;
+ bfd.singularData = getSingularData(fieldNode);
+ bfd.originalFieldNode = fieldNode;
+
+ if (bfd.singularData != null && isDefault != null) {
+ isDefault.addError("@Builder.Default and @Singular cannot be mixed.");
+ isDefault = null;
+ }
+
+ if (fd.init == null && isDefault != null) {
+ isDefault.addWarning("@Builder.Default requires an initializing expression (' = something;').");
+ isDefault = null;
+ }
+
+ if (fd.init != null && isDefault == null) {
+ if (isFinal) continue;
+ fieldNode.addWarning("@Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.");
+ }
+
+ if (isDefault != null) {
+ bfd.nameOfDefaultProvider = parent.toName("$default$" + bfd.name);
+ bfd.nameOfSetFlag = parent.toName(bfd.name + "$set");
+ JCMethodDecl md = generateDefaultProvider(bfd.nameOfDefaultProvider, fieldNode, td.typarams);
+ recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
+ if (md != null) injectMethod(tdParent, md);
+ }
+ addObtainVia(bfd, fieldNode);
+ builderFields.add(bfd);
allFields.append(fieldNode);
}
-
- new HandleConstructor().generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), null, SkipIfConstructorExists.I_AM_BUILDER, null, annotationNode);
+ handleConstructor.generateConstructor(tdParent, AccessLevel.PACKAGE, List.<JCAnnotation>nil(), allFields.toList(), false, null, SkipIfConstructorExists.I_AM_BUILDER, annotationNode);
returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams);
typeParams = td.typarams;
thrownExceptions = List.nil();
- nameOfStaticBuilderMethod = null;
+ nameOfBuilderMethod = null;
if (builderClassName.isEmpty()) builderClassName = td.name.toString() + "Builder";
} else if (fillParametersFrom != null && fillParametersFrom.getName().toString().equals("<init>")) {
- if (!fillParametersFrom.typarams.isEmpty()) {
+ JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
+ if (!jmd.typarams.isEmpty()) {
annotationNode.addError("@Builder is not supported on constructors with constructor type parameters.");
return;
}
+
tdParent = parent.up();
JCClassDecl td = (JCClassDecl) tdParent.get();
returnType = namePlusTypeParamsToTypeReference(tdParent.getTreeMaker(), td.name, td.typarams);
typeParams = td.typarams;
- thrownExceptions = fillParametersFrom.thrown;
- nameOfStaticBuilderMethod = null;
+ thrownExceptions = jmd.thrown;
+ nameOfBuilderMethod = null;
if (builderClassName.isEmpty()) builderClassName = td.name.toString() + "Builder";
} else if (fillParametersFrom != null) {
tdParent = parent.up();
JCClassDecl td = (JCClassDecl) tdParent.get();
- if ((fillParametersFrom.mods.flags & Flags.STATIC) == 0) {
- annotationNode.addError("@Builder is only supported on types, constructors, and static methods.");
- return;
+ JCMethodDecl jmd = (JCMethodDecl) fillParametersFrom.get();
+ isStatic = (jmd.mods.flags & Flags.STATIC) != 0;
+ JCExpression fullReturnType = jmd.restype;
+ returnType = fullReturnType;
+ typeParams = jmd.typarams;
+ thrownExceptions = jmd.thrown;
+ nameOfBuilderMethod = jmd.name;
+ if (returnType instanceof JCTypeApply) {
+ returnType = cloneType(tdParent.getTreeMaker(), returnType, ast, annotationNode.getContext());
}
- returnType = fillParametersFrom.restype;
- typeParams = fillParametersFrom.typarams;
- thrownExceptions = fillParametersFrom.thrown;
- nameOfStaticBuilderMethod = fillParametersFrom.name;
if (builderClassName.isEmpty()) {
- if (returnType instanceof JCTypeApply) {
- returnType = ((JCTypeApply) returnType).clazz;
- }
if (returnType instanceof JCFieldAccess) {
builderClassName = ((JCFieldAccess) returnType).name.toString() + "Builder";
} else if (returnType instanceof JCIdent) {
@@ -166,96 +230,375 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
if (Character.isLowerCase(builderClassName.charAt(0))) {
builderClassName = Character.toTitleCase(builderClassName.charAt(0)) + builderClassName.substring(1);
}
-
- } else {
+ } else if (returnType instanceof JCTypeApply) {
+ JCExpression clazz = ((JCTypeApply) returnType).clazz;
+ if (clazz instanceof JCFieldAccess) {
+ builderClassName = ((JCFieldAccess) clazz).name + "Builder";
+ } else if (clazz instanceof JCIdent) {
+ builderClassName = ((JCIdent) clazz).name + "Builder";
+ }
+ }
+
+ if (builderClassName.isEmpty()) {
// This shouldn't happen.
System.err.println("Lombok bug ID#20140614-1651: javac HandleBuilder: return type to name conversion failed: " + returnType.getClass());
builderClassName = td.name.toString() + "Builder";
}
}
+ if (toBuilder) {
+ final String TO_BUILDER_NOT_SUPPORTED = "@Builder(toBuilder=true) is only supported if you return your own type.";
+ if (returnType instanceof JCArrayTypeTree) {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ Name simpleName;
+ String pkg;
+ List<JCExpression> tpOnRet = List.nil();
+
+ if (fullReturnType instanceof JCTypeApply) {
+ tpOnRet = ((JCTypeApply) fullReturnType).arguments;
+ }
+
+ JCExpression namingType = returnType;
+ if (returnType instanceof JCTypeApply) namingType = ((JCTypeApply) returnType).clazz;
+
+ if (namingType instanceof JCIdent) {
+ simpleName = ((JCIdent) namingType).name;
+ pkg = null;
+ } else if (namingType instanceof JCFieldAccess) {
+ JCFieldAccess jcfa = (JCFieldAccess) namingType;
+ simpleName = jcfa.name;
+ pkg = unpack(jcfa.selected);
+ if (pkg.startsWith("ERR:")) {
+ String err = pkg.substring(4, pkg.indexOf("__ERR__"));
+ annotationNode.addError(err);
+ return;
+ }
+ } else {
+ annotationNode.addError("Expected a (parameterized) type here instead of a " + namingType.getClass().getName());
+ return;
+ }
+
+ if (pkg != null && !parent.getPackageDeclaration().equals(pkg)) {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ if (!tdParent.getName().contentEquals(simpleName)) {
+ annotationNode.addError(TO_BUILDER_NOT_SUPPORTED);
+ return;
+ }
+
+ List<JCTypeParameter> tpOnMethod = jmd.typarams;
+ List<JCTypeParameter> tpOnType = ((JCClassDecl) tdParent.get()).typarams;
+ typeArgsForToBuilder = new ArrayList<Name>();
+
+ for (JCTypeParameter tp : tpOnMethod) {
+ int pos = -1;
+ int idx = -1;
+ for (JCExpression tOnRet : tpOnRet) {
+ idx++;
+ if (!(tOnRet instanceof JCIdent)) continue;
+ if (((JCIdent) tOnRet).name != tp.name) continue;
+ pos = idx;
+ }
+
+ if (pos == -1 || tpOnType.size() <= pos) {
+ annotationNode.addError("@Builder(toBuilder=true) requires that each type parameter on the static method is part of the typeargs of the return value. Type parameter " + tp.name + " is not part of the return type.");
+ return;
+ }
+ typeArgsForToBuilder.add(tpOnType.get(pos).name);
+ }
+ }
} else {
- annotationNode.addError("@Builder is only supported on types, constructors, and static methods.");
+ annotationNode.addError("@Builder is only supported on types, constructors, and methods.");
return;
}
if (fillParametersFrom != null) {
- for (JCVariableDecl param : fillParametersFrom.params) {
- namesOfParameters.add(param.name);
- typesOfParameters.add(param.vartype);
+ for (JavacNode param : fillParametersFrom.down()) {
+ if (param.getKind() != Kind.ARGUMENT) continue;
+ BuilderFieldData bfd = new BuilderFieldData();
+ JCVariableDecl raw = (JCVariableDecl) param.get();
+ bfd.name = raw.name;
+ bfd.rawName = raw.name;
+ bfd.type = raw.vartype;
+ bfd.singularData = getSingularData(param);
+ bfd.originalFieldNode = param;
+ addObtainVia(bfd, param);
+ builderFields.add(bfd);
}
}
JavacNode builderType = findInnerClass(tdParent, builderClassName);
if (builderType == null) {
- builderType = makeBuilderClass(tdParent, builderClassName, typeParams, ast);
+ builderType = makeBuilderClass(isStatic, annotationNode, tdParent, builderClassName, typeParams, ast);
} else {
+ JCClassDecl builderTypeDeclaration = (JCClassDecl) builderType.get();
+ if (isStatic && !builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
+ annotationNode.addError("Existing Builder must be a static inner class.");
+ return;
+ } else if (!isStatic && builderTypeDeclaration.getModifiers().getFlags().contains(Modifier.STATIC)) {
+ annotationNode.addError("Existing Builder must be a non-static inner class.");
+ return;
+ }
sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(builderType, annotationNode);
+ /* generate errors for @Singular BFDs that have one already defined node. */ {
+ for (BuilderFieldData bfd : builderFields) {
+ SingularData sd = bfd.singularData;
+ if (sd == null) continue;
+ JavacSingularizer singularizer = sd.getSingularizer();
+ if (singularizer == null) continue;
+ if (singularizer.checkForAlreadyExistingNodesAndGenerateError(builderType, sd)) {
+ bfd.singularData = null;
+ }
+ }
+ }
}
- java.util.List<JavacNode> fieldNodes = addFieldsToBuilder(builderType, namesOfParameters, typesOfParameters, ast);
- java.util.List<JCMethodDecl> newMethods = new ArrayList<JCMethodDecl>();
- for (JavacNode fieldNode : fieldNodes) {
- JCMethodDecl newMethod = makeSetterMethodForBuilder(builderType, fieldNode, annotationNode, builderInstance.fluent(), builderInstance.chain());
- if (newMethod != null) newMethods.add(newMethod);
+
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ if (bfd.singularData.getSingularizer().requiresCleaning()) {
+ addCleaning = true;
+ break;
+ }
+ }
+ if (bfd.obtainVia != null) {
+ if (bfd.obtainVia.field().isEmpty() == bfd.obtainVia.method().isEmpty()) {
+ bfd.obtainViaNode.addError("The syntax is either @ObtainVia(field = \"fieldName\") or @ObtainVia(method = \"methodName\").");
+ return;
+ }
+ if (bfd.obtainVia.method().isEmpty() && bfd.obtainVia.isStatic()) {
+ bfd.obtainViaNode.addError("@ObtainVia(isStatic = true) is not valid unless 'method' has been set.");
+ return;
+ }
+ }
+ }
+
+ generateBuilderFields(builderType, builderFields, ast);
+ if (addCleaning) {
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ JCVariableDecl uncleanField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName("$lombokUnclean"), maker.TypeIdent(CTC_BOOLEAN), null);
+ injectFieldAndMarkGenerated(builderType, uncleanField);
}
if (constructorExists(builderType) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), null, annotationNode);
+ JCMethodDecl cd = HandleConstructor.createConstructor(AccessLevel.PACKAGE, List.<JCAnnotation>nil(), builderType, List.<JavacNode>nil(), false, annotationNode);
if (cd != null) injectMethod(builderType, cd);
}
- for (JCMethodDecl newMethod : newMethods) injectMethod(builderType, newMethod);
+ for (BuilderFieldData bfd : builderFields) {
+ makeSetterMethodsForBuilder(builderType, bfd, annotationNode, fluent, chain);
+ }
if (methodExists(buildMethodName, builderType, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuildMethod(buildMethodName, nameOfStaticBuilderMethod, returnType, namesOfParameters, builderType, thrownExceptions);
+ JCMethodDecl md = generateBuildMethod(tdParent, isStatic, buildMethodName, nameOfBuilderMethod, returnType, builderFields, builderType, thrownExceptions, ast, addCleaning);
if (md != null) injectMethod(builderType, md);
}
if (methodExists("toString", builderType, 0) == MemberExistsResult.NOT_EXISTS) {
+ java.util.List<JavacNode> fieldNodes = new ArrayList<JavacNode>();
+ for (BuilderFieldData bfd : builderFields) {
+ fieldNodes.addAll(bfd.createdFields);
+ }
JCMethodDecl md = HandleToString.createToString(builderType, fieldNodes, true, false, FieldAccess.ALWAYS_FIELD, ast);
if (md != null) injectMethod(builderType, md);
}
+ if (addCleaning) injectMethod(builderType, generateCleanMethod(builderFields, builderType, ast));
+
if (methodExists(builderMethodName, tdParent, -1) == MemberExistsResult.NOT_EXISTS) {
- JCMethodDecl md = generateBuilderMethod(builderMethodName, builderClassName, tdParent, typeParams);
+ JCMethodDecl md = generateBuilderMethod(isStatic, builderMethodName, builderClassName, annotationNode, tdParent, typeParams);
+ recursiveSetGeneratedBy(md, ast, annotationNode.getContext());
if (md != null) injectMethod(tdParent, md);
}
+
+ if (toBuilder) {
+ switch (methodExists(toBuilderMethodName, tdParent, 0)) {
+ case EXISTS_BY_USER:
+ annotationNode.addWarning("Not generating toBuilder() as it already exists.");
+ return;
+ case NOT_EXISTS:
+ List<JCTypeParameter> tps = typeParams;
+ if (typeArgsForToBuilder != null) {
+ ListBuffer<JCTypeParameter> lb = new ListBuffer<JCTypeParameter>();
+ JavacTreeMaker maker = tdParent.getTreeMaker();
+ for (Name n : typeArgsForToBuilder) {
+ lb.append(maker.TypeParameter(n, List.<JCExpression>nil()));
+ }
+ tps = lb.toList();
+ }
+ JCMethodDecl md = generateToBuilderMethod(toBuilderMethodName, builderClassName, tdParent, tps, builderFields, fluent, ast);
+ if (md != null) injectMethod(tdParent, md);
+ }
+ }
+
+ recursiveSetGeneratedBy(builderType.get(), ast, annotationNode.getContext());
+ }
+
+ private static String unpack(JCExpression expr) {
+ StringBuilder sb = new StringBuilder();
+ unpack(sb, expr);
+ return sb.toString();
+ }
+
+ private static void unpack(StringBuilder sb, JCExpression expr) {
+ if (expr instanceof JCIdent) {
+ sb.append(((JCIdent) expr).name.toString());
+ return;
+ }
+
+ if (expr instanceof JCFieldAccess) {
+ JCFieldAccess jcfa = (JCFieldAccess) expr;
+ unpack(sb, jcfa.selected);
+ sb.append(".").append(jcfa.name.toString());
+ return;
+ }
+
+ if (expr instanceof JCTypeApply) {
+ sb.setLength(0);
+ sb.append("ERR:");
+ sb.append("@Builder(toBuilder=true) is not supported if returning a type with generics applied to an intermediate.");
+ sb.append("__ERR__");
+ return;
+ }
+
+ sb.setLength(0);
+ sb.append("ERR:");
+ sb.append("Expected a type of some sort, not a " + expr.getClass().getName());
+ sb.append("__ERR__");
}
- public JCMethodDecl generateBuildMethod(String name, Name staticName, JCExpression returnType, java.util.List<Name> fieldNames, JavacNode type, List<JCExpression> thrownExceptions) {
+ private JCMethodDecl generateToBuilderMethod(String toBuilderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams, java.util.List<BuilderFieldData> builderFields, boolean fluent, JCAnnotation ast) {
+ // return new ThingieBuilder<A, B>().setA(this.a).setB(this.b);
+ JavacTreeMaker maker = type.getTreeMaker();
+
+ ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
+ for (JCTypeParameter typeParam : typeParams) {
+ typeArgs.append(maker.Ident(typeParam.name));
+ }
+
+ JCExpression call = maker.NewClass(null, List.<JCExpression>nil(), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCExpression>nil(), null);
+ JCExpression invoke = call;
+ for (BuilderFieldData bfd : builderFields) {
+ Name setterName = fluent ? bfd.name : type.toName(HandlerUtil.buildAccessorName("set", bfd.name.toString()));
+ JCExpression arg;
+ if (bfd.obtainVia == null || !bfd.obtainVia.field().isEmpty()) {
+ arg = maker.Select(maker.Ident(type.toName("this")), bfd.obtainVia == null ? bfd.rawName : type.toName(bfd.obtainVia.field()));
+ } else {
+ if (bfd.obtainVia.isStatic()) {
+ JCExpression c = maker.Select(maker.Ident(type.toName(type.getName())), type.toName(bfd.obtainVia.method()));
+ arg = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>of(maker.Ident(type.toName("this"))));
+ } else {
+ JCExpression c = maker.Select(maker.Ident(type.toName("this")), type.toName(bfd.obtainVia.method()));
+ arg = maker.Apply(List.<JCExpression>nil(), c, List.<JCExpression>nil());
+ }
+ }
+ invoke = maker.Apply(List.<JCExpression>nil(), maker.Select(invoke, setterName), List.of(arg));
+ }
+ JCStatement statement = maker.Return(invoke);
+
+ JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
+ return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(toBuilderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ }
+
+ private JCMethodDecl generateCleanMethod(java.util.List<BuilderFieldData> builderFields, JavacNode type, JCTree source) {
+ JavacTreeMaker maker = type.getTreeMaker();
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ bfd.singularData.getSingularizer().appendCleaningCode(bfd.singularData, type, source, statements);
+ }
+ }
+
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 0))));
+ JCBlock body = maker.Block(0, statements.toList());
+ return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName("$lombokClean"), maker.Type(Javac.createVoidType(type.getSymbolTable(), CTC_VOID)), List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ /*
+ * if (shouldReturnThis) {
+ methodType = cloneSelfType(field);
+ }
+
+ if (methodType == null) {
+ //WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6.
+ methodType = treeMaker.Type(Javac.createVoidType(treeMaker, CTC_VOID));
+ shouldReturnThis = false;
+ }
+
+ */
+ }
+
+ private JCMethodDecl generateBuildMethod(JavacNode tdParent, boolean isStatic, String buildName, Name builderName, JCExpression returnType, java.util.List<BuilderFieldData> builderFields, JavacNode type, List<JCExpression> thrownExceptions, JCTree source, boolean addCleaning) {
JavacTreeMaker maker = type.getTreeMaker();
JCExpression call;
- JCStatement statement;
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+
+ if (addCleaning) {
+ JCExpression notClean = maker.Unary(CTC_NOT, maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")));
+ JCStatement invokeClean = maker.Exec(maker.Apply(List.<JCExpression>nil(), maker.Ident(type.toName("$lombokClean")), List.<JCExpression>nil()));
+ JCIf ifUnclean = maker.If(notClean, invokeClean, null);
+ statements.append(ifUnclean);
+ }
+
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ bfd.singularData.getSingularizer().appendBuildCode(bfd.singularData, type, source, statements, bfd.name);
+ }
+ }
ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
- for (Name n : fieldNames) {
- args.append(maker.Ident(n));
+ for (BuilderFieldData bfd : builderFields) {
+ if (bfd.nameOfSetFlag != null) {
+ statements.append(maker.VarDef(maker.Modifiers(0L), bfd.name, cloneType(maker, bfd.type, source, tdParent.getContext()), maker.Select(maker.Ident(type.toName("this")), bfd.name)));
+ statements.append(maker.If(maker.Unary(CTC_NOT, maker.Ident(bfd.nameOfSetFlag)), maker.Exec(maker.Assign(maker.Ident(bfd.name),maker.Apply(typeParameterNames(maker, ((JCClassDecl) tdParent.get()).typarams), maker.Select(maker.Ident(((JCClassDecl) tdParent.get()).name), bfd.nameOfDefaultProvider), List.<JCExpression>nil()))), null));
+ }
+ args.append(maker.Ident(bfd.name));
}
- if (staticName == null) {
+ if (addCleaning) {
+ statements.append(maker.Exec(maker.Assign(maker.Select(maker.Ident(type.toName("this")), type.toName("$lombokUnclean")), maker.Literal(CTC_BOOLEAN, 1))));
+ }
+
+ if (builderName == null) {
call = maker.NewClass(null, List.<JCExpression>nil(), returnType, args.toList(), null);
- statement = maker.Return(call);
+ statements.append(maker.Return(call));
} else {
ListBuffer<JCExpression> typeParams = new ListBuffer<JCExpression>();
for (JCTypeParameter tp : ((JCClassDecl) type.get()).typarams) {
typeParams.append(maker.Ident(tp.name));
}
-
- JCExpression fn = maker.Select(maker.Ident(((JCClassDecl) type.up().get()).name), staticName);
+ JCExpression callee = maker.Ident(((JCClassDecl) type.up().get()).name);
+ if (!isStatic) callee = maker.Select(callee, type.up().toName("this"));
+ JCExpression fn = maker.Select(callee, builderName);
call = maker.Apply(typeParams.toList(), fn, args.toList());
if (returnType instanceof JCPrimitiveTypeTree && CTC_VOID.equals(typeTag(returnType))) {
- statement = maker.Exec(call);
+ statements.append(maker.Exec(call));
} else {
- statement = maker.Return(call);
+ statements.append(maker.Return(call));
}
}
- JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
+ JCBlock body = maker.Block(0, statements.toList());
- return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(name), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
+ return maker.MethodDef(maker.Modifiers(Flags.PUBLIC), type.toName(buildName), returnType, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), thrownExceptions, body, null);
}
- public JCMethodDecl generateBuilderMethod(String builderMethodName, String builderClassName, JavacNode type, List<JCTypeParameter> typeParams) {
+ public JCMethodDecl generateDefaultProvider(Name methodName, JavacNode fieldNode, List<JCTypeParameter> params) {
+ JavacTreeMaker maker = fieldNode.getTreeMaker();
+ JCVariableDecl field = (JCVariableDecl) fieldNode.get();
+
+ JCStatement statement = maker.Return(field.init);
+ field.init = null;
+
+ JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
+ int modifiers = Flags.PRIVATE | Flags.STATIC;
+ return maker.MethodDef(maker.Modifiers(modifiers), methodName, cloneType(maker, field.vartype, field, fieldNode.getContext()), copyTypeParams(fieldNode, params), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ }
+
+ public JCMethodDecl generateBuilderMethod(boolean isStatic, String builderMethodName, String builderClassName, JavacNode source, JavacNode type, List<JCTypeParameter> typeParams) {
JavacTreeMaker maker = type.getTreeMaker();
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
@@ -267,53 +610,71 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
JCStatement statement = maker.Return(call);
JCBlock body = maker.Block(0, List.<JCStatement>of(statement));
- return maker.MethodDef(maker.Modifiers(Flags.STATIC | Flags.PUBLIC), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), copyTypeParams(maker, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
+ int modifiers = Flags.PUBLIC;
+ if (isStatic) modifiers |= Flags.STATIC;
+ return maker.MethodDef(maker.Modifiers(modifiers), type.toName(builderMethodName), namePlusTypeParamsToTypeReference(maker, type.toName(builderClassName), typeParams), copyTypeParams(source, typeParams), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null);
}
- public java.util.List<JavacNode> addFieldsToBuilder(JavacNode builderType, java.util.List<Name> namesOfParameters, java.util.List<JCExpression> typesOfParameters, JCTree source) {
- int len = namesOfParameters.size();
+ public void generateBuilderFields(JavacNode builderType, java.util.List<BuilderFieldData> builderFields, JCTree source) {
+ int len = builderFields.size();
java.util.List<JavacNode> existing = new ArrayList<JavacNode>();
for (JavacNode child : builderType.down()) {
if (child.getKind() == Kind.FIELD) existing.add(child);
}
- java.util.List<JavacNode>out = new ArrayList<JavacNode>();
-
- top:
for (int i = len - 1; i >= 0; i--) {
- Name name = namesOfParameters.get(i);
- for (JavacNode exists : existing) {
- Name n = ((JCVariableDecl) exists.get()).name;
- if (n.equals(name)) {
- out.add(exists);
- continue top;
+ BuilderFieldData bfd = builderFields.get(i);
+ if (bfd.singularData != null && bfd.singularData.getSingularizer() != null) {
+ bfd.createdFields.addAll(bfd.singularData.getSingularizer().generateFields(bfd.singularData, builderType, source));
+ } else {
+ JavacNode field = null, setFlag = null;
+ for (JavacNode exists : existing) {
+ Name n = ((JCVariableDecl) exists.get()).name;
+ if (n.equals(bfd.name)) field = exists;
+ if (n.equals(bfd.nameOfSetFlag)) setFlag = exists;
+ }
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ if (field == null) {
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.name, cloneType(maker, bfd.type, source, builderType.getContext()), null);
+ field = injectFieldAndMarkGenerated(builderType, newField);
}
+ if (setFlag == null && bfd.nameOfSetFlag != null) {
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
+ JCVariableDecl newField = maker.VarDef(mods, bfd.nameOfSetFlag, maker.TypeIdent(CTC_BOOLEAN), null);
+ injectFieldAndMarkGenerated(builderType, newField);
+ }
+ bfd.createdFields.add(field);
}
- JavacTreeMaker maker = builderType.getTreeMaker();
- JCModifiers mods = maker.Modifiers(Flags.PRIVATE);
- JCVariableDecl newField = maker.VarDef(mods, name, cloneType(maker, typesOfParameters.get(i), source, builderType.getContext()), null);
- out.add(injectField(builderType, newField));
}
-
- Collections.reverse(out);
- return out;
}
+ public void makeSetterMethodsForBuilder(JavacNode builderType, BuilderFieldData fieldNode, JavacNode source, boolean fluent, boolean chain) {
+ boolean deprecate = isFieldDeprecated(fieldNode.originalFieldNode);
+ if (fieldNode.singularData == null || fieldNode.singularData.getSingularizer() == null) {
+ makeSimpleSetterMethodForBuilder(builderType, deprecate, fieldNode.createdFields.get(0), fieldNode.nameOfSetFlag, source, fluent, chain);
+ } else {
+ fieldNode.singularData.getSingularizer().generateMethods(fieldNode.singularData, deprecate, builderType, source.get(), fluent, chain);
+ }
+ }
- public JCMethodDecl makeSetterMethodForBuilder(JavacNode builderType, JavacNode fieldNode, JavacNode source, boolean fluent, boolean chain) {
+ private void makeSimpleSetterMethodForBuilder(JavacNode builderType, boolean deprecate, JavacNode fieldNode, Name nameOfSetFlag, JavacNode source, boolean fluent, boolean chain) {
Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
for (JavacNode child : builderType.down()) {
if (child.getKind() != Kind.METHOD) continue;
- Name existingName = ((JCMethodDecl) child.get()).name;
- if (existingName.equals(fieldName)) return null;
+ JCMethodDecl methodDecl = (JCMethodDecl) child.get();
+ Name existingName = methodDecl.name;
+ if (existingName.equals(fieldName) && !isTolerate(fieldNode, methodDecl)) return;
}
- boolean isBoolean = isBoolean(fieldNode);
- String setterName = fluent ? fieldNode.getName() : toSetterName(builderType.getAst(), null, fieldNode.getName(), isBoolean);
+ String setterName = fluent ? fieldNode.getName() : HandlerUtil.buildAccessorName("set", fieldNode.getName());
+
+ JavacTreeMaker maker = fieldNode.getTreeMaker();
- JavacTreeMaker maker = builderType.getTreeMaker();
- return HandleSetter.createSetter(Flags.PUBLIC, fieldNode, maker, setterName, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
+ JCMethodDecl newMethod = HandleSetter.createSetter(Flags.PUBLIC, deprecate, fieldNode, maker, setterName, nameOfSetFlag, chain, source, List.<JCAnnotation>nil(), List.<JCAnnotation>nil());
+
+ injectMethod(builderType, newMethod);
}
public JavacNode findInnerClass(JavacNode parent, String name) {
@@ -325,10 +686,77 @@ public class HandleBuilder extends JavacAnnotationHandler<Builder> {
return null;
}
- public JavacNode makeBuilderClass(JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast) {
+ public JavacNode makeBuilderClass(boolean isStatic, JavacNode source, JavacNode tdParent, String builderClassName, List<JCTypeParameter> typeParams, JCAnnotation ast) {
JavacTreeMaker maker = tdParent.getTreeMaker();
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC | Flags.STATIC);
- JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(maker, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil());
+ int modifiers = Flags.PUBLIC;
+ if (isStatic) modifiers |= Flags.STATIC;
+ JCModifiers mods = maker.Modifiers(modifiers);
+ JCClassDecl builder = maker.ClassDef(mods, tdParent.toName(builderClassName), copyTypeParams(source, typeParams), null, List.<JCExpression>nil(), List.<JCTree>nil());
return injectType(tdParent, builder);
}
+
+ private void addObtainVia(BuilderFieldData bfd, JavacNode node) {
+ for (JavacNode child : node.down()) {
+ if (!annotationTypeMatches(ObtainVia.class, child)) continue;
+ AnnotationValues<ObtainVia> ann = createAnnotation(ObtainVia.class, child);
+ bfd.obtainVia = ann.getInstance();
+ bfd.obtainViaNode = child;
+ deleteAnnotationIfNeccessary(child, ObtainVia.class);
+ return;
+ }
+ }
+
+ /**
+ * Returns the explicitly requested singular annotation on this node (field
+ * or parameter), or null if there's no {@code @Singular} annotation on it.
+ *
+ * @param node The node (field or method param) to inspect for its name and potential {@code @Singular} annotation.
+ */
+ private SingularData getSingularData(JavacNode node) {
+ for (JavacNode child : node.down()) {
+ if (!annotationTypeMatches(Singular.class, child)) continue;
+ Name pluralName = node.getKind() == Kind.FIELD ? removePrefixFromField(node) : ((JCVariableDecl) node.get()).name;
+ AnnotationValues<Singular> ann = createAnnotation(Singular.class, child);
+ deleteAnnotationIfNeccessary(child, Singular.class);
+ String explicitSingular = ann.getInstance().value();
+ if (explicitSingular.isEmpty()) {
+ if (Boolean.FALSE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_AUTO))) {
+ node.addError("The singular must be specified explicitly (e.g. @Singular(\"task\")) because auto singularization is disabled.");
+ explicitSingular = pluralName.toString();
+ } else {
+ explicitSingular = autoSingularize(pluralName.toString());
+ if (explicitSingular == null) {
+ node.addError("Can't singularize this name; please specify the singular explicitly (i.e. @Singular(\"sheep\"))");
+ explicitSingular = pluralName.toString();
+ }
+ }
+ }
+ Name singularName = node.toName(explicitSingular);
+
+ JCExpression type = null;
+ if (node.get() instanceof JCVariableDecl) {
+ type = ((JCVariableDecl) node.get()).vartype;
+ }
+
+ String name = null;
+ List<JCExpression> typeArgs = List.nil();
+ if (type instanceof JCTypeApply) {
+ typeArgs = ((JCTypeApply) type).arguments;
+ type = ((JCTypeApply) type).clazz;
+ }
+
+ name = type.toString();
+
+ String targetFqn = JavacSingularsRecipes.get().toQualified(name);
+ JavacSingularizer singularizer = JavacSingularsRecipes.get().getSingularizer(targetFqn);
+ if (singularizer == null) {
+ node.addError("Lombok does not know how to create the singular-form builder methods for type '" + name + "'; they won't be generated.");
+ return null;
+ }
+
+ return new SingularData(child, singularName, pluralName, typeArgs, targetFqn, singularizer);
+ }
+
+ return null;
+ }
}
diff --git a/src/core/lombok/javac/handlers/HandleBuilderDefault.java b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
new file mode 100644
index 00000000..4c4ba0e8
--- /dev/null
+++ b/src/core/lombok/javac/handlers/HandleBuilderDefault.java
@@ -0,0 +1,49 @@
+/*
+ * Copyright (C) 2017-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
+ * 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.javac.handlers;
+
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+
+import lombok.Builder;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+
+@ProviderFor(JavacAnnotationHandler.class)
+@HandlerPriority(-1025) //HandleBuilder's level, minus one.
+public class HandleBuilderDefault extends JavacAnnotationHandler<Builder.Default> {
+ @Override public void handle(AnnotationValues<Builder.Default> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ JavacNode annotatedField = annotationNode.up();
+ if (annotatedField.getKind() != Kind.FIELD) return;
+ JavacNode classWithAnnotatedField = annotatedField.up();
+ if (!hasAnnotation(Builder.class, classWithAnnotatedField) && !hasAnnotation("lombok.experimental.Builder", classWithAnnotatedField)) {
+ annotationNode.addWarning("@Builder.Default requires @Builder on the class for it to mean anything.");
+ deleteAnnotationIfNeccessary(annotationNode, Builder.Default.class);
+ }
+ }
+}
diff --git a/src/core/lombok/javac/handlers/HandleConstructor.java b/src/core/lombok/javac/handlers/HandleConstructor.java
index 6043d1cb..dca25ee7 100644
--- a/src/core/lombok/javac/handlers/HandleConstructor.java
+++ b/src/core/lombok/javac/handlers/HandleConstructor.java
@@ -23,15 +23,18 @@ package lombok.javac.handlers;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
+import static lombok.javac.Javac.*;
+
import lombok.AccessLevel;
import lombok.AllArgsConstructor;
+import lombok.Builder;
import lombok.ConfigurationKeys;
import lombok.NoArgsConstructor;
import lombok.RequiredArgsConstructor;
import lombok.core.AnnotationValues;
import lombok.core.AST.Kind;
import lombok.delombok.LombokOptionsFactory;
-import lombok.experimental.Builder;
+import lombok.javac.Javac;
import lombok.javac.JavacAnnotationHandler;
import lombok.javac.JavacNode;
import lombok.javac.JavacTreeMaker;
@@ -39,15 +42,17 @@ import lombok.javac.JavacTreeMaker;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
-import com.sun.tools.javac.tree.JCTree.JCAssign;
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.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
import com.sun.tools.javac.tree.JCTree.JCReturn;
import com.sun.tools.javac.tree.JCTree.JCStatement;
import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
@@ -59,6 +64,8 @@ import com.sun.tools.javac.util.Name;
public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleNoArgsConstructor extends JavacAnnotationHandler<NoArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<NoArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.NO_ARGS_CONSTRUCTOR_FLAG_USAGE, "@NoArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -66,18 +73,21 @@ public class HandleConstructor {
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, NoArgsConstructor.class.getSimpleName())) return;
- List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor=", annotationNode);
+ List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@NoArgsConstructor(onConstructor", annotationNode);
NoArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- List<JavacNode> fields = List.nil();
- new HandleConstructor().generateConstructor(typeNode, level, onConstructor, fields, staticName, SkipIfConstructorExists.NO, null, annotationNode);
+ boolean force = ann.force();
+ List<JavacNode> fields = force ? findFinalFields(typeNode) : List.<JavacNode>nil();
+ handleConstructor.generateConstructor(typeNode, level, onConstructor, fields, force, staticName, SkipIfConstructorExists.NO, annotationNode);
}
}
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleRequiredArgsConstructor extends JavacAnnotationHandler<RequiredArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<RequiredArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.REQUIRED_ARGS_CONSTRUCTOR_FLAG_USAGE, "@RequiredArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -85,23 +95,28 @@ public class HandleConstructor {
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, RequiredArgsConstructor.class.getSimpleName())) return;
- List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor=", annotationNode);
+ List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@RequiredArgsConstructor(onConstructor", annotationNode);
RequiredArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- Boolean suppressConstructorProperties = null;
if (annotation.isExplicit("suppressConstructorProperties")) {
- @SuppressWarnings("deprecation")
- boolean suppress = ann.suppressConstructorProperties();
- suppressConstructorProperties = suppress;
+ annotationNode.addError("This deprecated feature is no longer supported. Remove it; you can create a lombok.config file with 'lombok.anyConstructor.suppressConstructorProperties = true'.");
}
- new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode);
+ handleConstructor.generateConstructor(typeNode, level, onConstructor, findRequiredFields(typeNode), false, staticName, SkipIfConstructorExists.NO, annotationNode);
}
}
public static List<JavacNode> findRequiredFields(JavacNode typeNode) {
+ return findFields(typeNode, true);
+ }
+
+ public static List<JavacNode> findFinalFields(JavacNode typeNode) {
+ return findFields(typeNode, false);
+ }
+
+ public static List<JavacNode> findFields(JavacNode typeNode, boolean nullMarked) {
ListBuffer<JavacNode> fields = new ListBuffer<JavacNode>();
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
@@ -112,7 +127,7 @@ public class HandleConstructor {
//Skip static fields.
if ((fieldFlags & Flags.STATIC) != 0) continue;
boolean isFinal = (fieldFlags & Flags.FINAL) != 0;
- boolean isNonNull = !findAnnotations(child, NON_NULL_PATTERN).isEmpty();
+ boolean isNonNull = nullMarked && !findAnnotations(child, NON_NULL_PATTERN).isEmpty();
if ((isFinal || isNonNull) && fieldDecl.init == null) fields.append(child);
}
return fields.toList();
@@ -120,6 +135,8 @@ public class HandleConstructor {
@ProviderFor(JavacAnnotationHandler.class)
public static class HandleAllArgsConstructor extends JavacAnnotationHandler<AllArgsConstructor> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+
@Override public void handle(AnnotationValues<AllArgsConstructor> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.ALL_ARGS_CONSTRUCTOR_FLAG_USAGE, "@AllArgsConstructor", ConfigurationKeys.ANY_CONSTRUCTOR_FLAG_USAGE, "any @xArgsConstructor");
@@ -127,22 +144,23 @@ public class HandleConstructor {
deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
JavacNode typeNode = annotationNode.up();
if (!checkLegality(typeNode, annotationNode, AllArgsConstructor.class.getSimpleName())) return;
- List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor=", annotationNode);
+ List<JCAnnotation> onConstructor = unboxAndRemoveAnnotationParameter(ast, "onConstructor", "@AllArgsConstructor(onConstructor", annotationNode);
AllArgsConstructor ann = annotation.getInstance();
AccessLevel level = ann.access();
if (level == AccessLevel.NONE) return;
String staticName = ann.staticName();
- Boolean suppressConstructorProperties = null;
if (annotation.isExplicit("suppressConstructorProperties")) {
- @SuppressWarnings("deprecation")
- boolean suppress = ann.suppressConstructorProperties();
- suppressConstructorProperties = suppress;
+ annotationNode.addError("This deprecated feature is no longer supported. Remove it; you can create a lombok.config file with 'lombok.anyConstructor.suppressConstructorProperties = true'.");
}
- new HandleConstructor().generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), staticName, SkipIfConstructorExists.NO, suppressConstructorProperties, annotationNode);
+ handleConstructor.generateConstructor(typeNode, level, onConstructor, findAllFields(typeNode), false, staticName, SkipIfConstructorExists.NO, annotationNode);
}
}
public static List<JavacNode> findAllFields(JavacNode typeNode) {
+ return findAllFields(typeNode, false);
+ }
+
+ public static List<JavacNode> findAllFields(JavacNode typeNode, boolean evenFinalInitialized) {
ListBuffer<JavacNode> fields = new ListBuffer<JavacNode>();
for (JavacNode child : typeNode.down()) {
if (child.getKind() != Kind.FIELD) continue;
@@ -154,7 +172,7 @@ public class HandleConstructor {
if ((fieldFlags & Flags.STATIC) != 0) continue;
//Skip initialized final fields
boolean isFinal = (fieldFlags & Flags.FINAL) != 0;
- if (!isFinal || fieldDecl.init == null) fields.append(child);
+ if (evenFinalInitialized || !isFinal || fieldDecl.init == null) fields.append(child);
}
return fields.toList();
}
@@ -174,7 +192,7 @@ public class HandleConstructor {
}
public void generateRequiredArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
- generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), staticName, skipIfConstructorExists, null, source);
+ generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findRequiredFields(typeNode), false, staticName, skipIfConstructorExists, source);
}
public enum SkipIfConstructorExists {
@@ -182,10 +200,10 @@ public class HandleConstructor {
}
public void generateAllArgsConstructor(JavacNode typeNode, AccessLevel level, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
- generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findAllFields(typeNode), staticName, skipIfConstructorExists, null, source);
+ generateConstructor(typeNode, level, List.<JCAnnotation>nil(), findAllFields(typeNode), false, staticName, skipIfConstructorExists, source);
}
- public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, String staticName, SkipIfConstructorExists skipIfConstructorExists, Boolean suppressConstructorProperties, JavacNode source) {
+ public void generateConstructor(JavacNode typeNode, AccessLevel level, List<JCAnnotation> onConstructor, List<JavacNode> fields, boolean allToDefault, String staticName, SkipIfConstructorExists skipIfConstructorExists, JavacNode source) {
boolean staticConstrRequired = staticName != null && !staticName.equals("");
if (skipIfConstructorExists != SkipIfConstructorExists.NO && constructorExists(typeNode) != MemberExistsResult.NOT_EXISTS) return;
@@ -193,8 +211,8 @@ public class HandleConstructor {
for (JavacNode child : typeNode.down()) {
if (child.getKind() == Kind.ANNOTATION) {
boolean skipGeneration = annotationTypeMatches(NoArgsConstructor.class, child) ||
- annotationTypeMatches(AllArgsConstructor.class, child) ||
- annotationTypeMatches(RequiredArgsConstructor.class, child);
+ annotationTypeMatches(AllArgsConstructor.class, child) ||
+ annotationTypeMatches(RequiredArgsConstructor.class, child);
if (!skipGeneration && skipIfConstructorExists == SkipIfConstructorExists.YES) {
skipGeneration = annotationTypeMatches(Builder.class, child);
@@ -214,11 +232,23 @@ public class HandleConstructor {
}
}
- JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, suppressConstructorProperties, source);
- injectMethod(typeNode, constr);
+ JCMethodDecl constr = createConstructor(staticConstrRequired ? AccessLevel.PRIVATE : level, onConstructor, typeNode, fields, allToDefault, source);
+ ListBuffer<Type> argTypes = new ListBuffer<Type>();
+ for (JavacNode fieldNode : fields) {
+ Type mirror = getMirrorForFieldType(fieldNode);
+ if (mirror == null) {
+ argTypes = null;
+ break;
+ }
+ argTypes.append(mirror);
+ }
+ List<Type> argTypes_ = argTypes == null ? null : argTypes.toList();
+ injectMethod(typeNode, constr, argTypes_, Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
if (staticConstrRequired) {
- JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, fields, source.get());
- injectMethod(typeNode, staticConstr);
+ ClassSymbol sym = ((JCClassDecl) typeNode.get()).sym;
+ Type returnType = sym == null ? null : sym.type;
+ JCMethodDecl staticConstr = createStaticConstructor(staticName, level, typeNode, allToDefault ? List.<JavacNode>nil() : fields, source.get());
+ injectMethod(typeNode, staticConstr, argTypes_, returnType);
}
}
@@ -236,18 +266,20 @@ public class HandleConstructor {
mods.annotations = mods.annotations.append(annotation);
}
- public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, Boolean suppressConstructorProperties, JavacNode source) {
+ @SuppressWarnings("deprecation") public static JCMethodDecl createConstructor(AccessLevel level, List<JCAnnotation> onConstructor, JavacNode typeNode, List<JavacNode> fields, boolean allToDefault, JavacNode source) {
JavacTreeMaker maker = typeNode.getTreeMaker();
boolean isEnum = (((JCClassDecl) typeNode.get()).mods.flags & Flags.ENUM) != 0;
if (isEnum) level = AccessLevel.PRIVATE;
- if (suppressConstructorProperties == null) {
- if (fields.isEmpty()) {
- suppressConstructorProperties = false;
- } else {
- suppressConstructorProperties = Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
- }
+ boolean addConstructorProperties;
+
+ if (fields.isEmpty()) {
+ addConstructorProperties = false;
+ } else {
+ Boolean v = typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_ADD_CONSTRUCTOR_PROPERTIES);
+ addConstructorProperties = v != null ? v.booleanValue() :
+ Boolean.FALSE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.ANY_CONSTRUCTOR_SUPPRESS_CONSTRUCTOR_PROPERTIES));
}
ListBuffer<JCStatement> nullChecks = new ListBuffer<JCStatement>();
@@ -259,29 +291,55 @@ public class HandleConstructor {
Name fieldName = removePrefixFromField(fieldNode);
Name rawName = field.name;
List<JCAnnotation> nonNulls = findAnnotations(fieldNode, NON_NULL_PATTERN);
- List<JCAnnotation> nullables = findAnnotations(fieldNode, NULLABLE_PATTERN);
- long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
- JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null);
- params.append(param);
+ if (!allToDefault) {
+ List<JCAnnotation> nullables = findAnnotations(fieldNode, NULLABLE_PATTERN);
+ long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, typeNode.getContext());
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, nonNulls.appendList(nullables)), fieldName, field.vartype, null);
+ params.append(param);
+ if (!nonNulls.isEmpty()) {
+ JCStatement nullCheck = generateNullCheck(maker, fieldNode, param, source);
+ if (nullCheck != null) nullChecks.append(nullCheck);
+ }
+ }
JCFieldAccess thisX = maker.Select(maker.Ident(fieldNode.toName("this")), rawName);
- JCAssign assign = maker.Assign(thisX, maker.Ident(fieldName));
+ JCExpression assign = maker.Assign(thisX, allToDefault ? getDefaultExpr(maker, field.vartype) : maker.Ident(fieldName));
assigns.append(maker.Exec(assign));
-
- if (!nonNulls.isEmpty()) {
- JCStatement nullCheck = generateNullCheck(maker, fieldNode, source);
- if (nullCheck != null) nullChecks.append(nullCheck);
- }
}
JCModifiers mods = maker.Modifiers(toJavacModifier(level), List.<JCAnnotation>nil());
- if (!suppressConstructorProperties && level != AccessLevel.PRIVATE && level != AccessLevel.PACKAGE && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
+ if (!allToDefault && addConstructorProperties && !isLocalType(typeNode) && LombokOptionsFactory.getDelombokOptions(typeNode.getContext()).getFormatPreferences().generateConstructorProperties()) {
addConstructorProperties(mods, typeNode, fields);
}
if (onConstructor != null) mods.annotations = mods.annotations.appendList(copyAnnotations(onConstructor));
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("<init>"),
- null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
- maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext());
+ null, List.<JCTypeParameter>nil(), params.toList(), List.<JCExpression>nil(),
+ maker.Block(0L, nullChecks.appendList(assigns).toList()), null), source.get(), typeNode.getContext());
+ }
+
+ private static JCExpression getDefaultExpr(JavacTreeMaker maker, JCExpression type) {
+ if (type instanceof JCPrimitiveTypeTree) {
+ switch (((JCPrimitiveTypeTree) type).getPrimitiveTypeKind()) {
+ case BOOLEAN:
+ return maker.Literal(CTC_BOOLEAN, 0);
+ case CHAR:
+ return maker.Literal(CTC_CHAR, 0);
+ default:
+ case BYTE:
+ case SHORT:
+ case INT:
+ return maker.Literal(CTC_INT, 0);
+ case LONG:
+ return maker.Literal(CTC_LONG, 0L);
+ case FLOAT:
+ return maker.Literal(CTC_FLOAT, 0F);
+ case DOUBLE:
+ return maker.Literal(CTC_DOUBLE, 0D);
+ }
+ }
+
+ return maker.Literal(CTC_BOT, null);
+
}
public static boolean isLocalType(JavacNode type) {
diff --git a/src/core/lombok/javac/handlers/HandleData.java b/src/core/lombok/javac/handlers/HandleData.java
index 9ecf8754..15f1fd83 100644
--- a/src/core/lombok/javac/handlers/HandleData.java
+++ b/src/core/lombok/javac/handlers/HandleData.java
@@ -40,6 +40,12 @@ import com.sun.tools.javac.tree.JCTree.JCAnnotation;
*/
@ProviderFor(JavacAnnotationHandler.class)
public class HandleData extends JavacAnnotationHandler<Data> {
+ private HandleConstructor handleConstructor = new HandleConstructor();
+ private HandleGetter handleGetter = new HandleGetter();
+ private HandleSetter handleSetter = new HandleSetter();
+ private HandleEqualsAndHashCode handleEqualsAndHashCode = new HandleEqualsAndHashCode();
+ private HandleToString handleToString = new HandleToString();
+
@Override public void handle(AnnotationValues<Data> annotation, JCAnnotation ast, JavacNode annotationNode) {
handleFlagUsage(annotationNode, ConfigurationKeys.DATA_FLAG_USAGE, "@Data");
@@ -54,11 +60,10 @@ public class HandleData extends JavacAnnotationHandler<Data> {
String staticConstructorName = annotation.getInstance().staticConstructor();
- // TODO move this to the end OR move it to the top in eclipse.
- new HandleConstructor().generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
- new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleSetter().generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
- new HandleToString().generateToStringForType(typeNode, annotationNode);
+ handleConstructor.generateRequiredArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleSetter.generateSetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
+ handleToString.generateToStringForType(typeNode, annotationNode);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleDelegate.java b/src/core/lombok/javac/handlers/HandleDelegate.java
index fc3c81f3..49bef769 100644
--- a/src/core/lombok/javac/handlers/HandleDelegate.java
+++ b/src/core/lombok/javac/handlers/HandleDelegate.java
@@ -299,7 +299,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
annotations = com.sun.tools.javac.util.List.nil();
}
- JCModifiers mods = maker.Modifiers(Flags.PUBLIC, annotations);
+ JCModifiers mods = maker.Modifiers(PUBLIC, annotations);
JCExpression returnType = JavacResolution.typeToJCTree((Type) sig.type.getReturnType(), annotation.getAst(), true);
boolean useReturn = sig.type.getReturnType().getKind() != TypeKind.VOID;
ListBuffer<JCVariableDecl> params = sig.type.getParameterTypes().isEmpty() ? null : new ListBuffer<JCVariableDecl>();
@@ -312,7 +312,7 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
for (TypeMirror param : sig.type.getTypeVariables()) {
Name name = ((TypeVar) param).tsym.name;
- ListBuffer<JCExpression> bounds = types.getBounds((TypeVar) param).isEmpty() ? null : new ListBuffer<JCExpression>();
+ ListBuffer<JCExpression> bounds = new ListBuffer<JCExpression>();
for (Type type : types.getBounds((TypeVar) param)) {
bounds.append(JavacResolution.typeToJCTree(type, annotation.getAst(), true));
}
@@ -326,11 +326,15 @@ public class HandleDelegate extends JavacAnnotationHandler<Delegate> {
}
int idx = 0;
+ String[] paramNames = sig.getParameterNames();
+ boolean varargs = sig.elem.isVarArgs();
for (TypeMirror param : sig.type.getParameterTypes()) {
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, annotation.getContext());
JCModifiers paramMods = maker.Modifiers(flags);
- String[] paramNames = sig.getParameterNames();
Name name = annotation.toName(paramNames[idx++]);
+ if (varargs && idx == paramNames.length) {
+ paramMods.flags |= VARARGS;
+ }
params.append(maker.VarDef(paramMods, name, JavacResolution.typeToJCTree((Type) param, annotation.getAst(), true), null));
args.append(maker.Ident(name));
}
diff --git a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
index 1a6f4a8f..d8bfd154 100644
--- a/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
+++ b/src/core/lombok/javac/handlers/HandleEqualsAndHashCode.java
@@ -32,6 +32,7 @@ import java.util.Collections;
import lombok.ConfigurationKeys;
import lombok.EqualsAndHashCode;
import lombok.core.AST.Kind;
+import lombok.core.configuration.CallSuperType;
import lombok.core.AnnotationValues;
import lombok.core.handlers.HandlerUtil;
import lombok.javac.Javac;
@@ -94,7 +95,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
List<String> excludes = List.from(ann.exclude());
List<String> includes = List.from(ann.of());
JavacNode typeNode = annotationNode.up();
- List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam=", annotationNode);
+ List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@EqualsAndHashCode(onParam", annotationNode);
checkForBogusFieldNames(typeNode, annotation);
Boolean callSuper = ann.callSuper();
@@ -120,14 +121,18 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
return;
}
- generateMethods(typeNode, source, null, null, null, false, FieldAccess.GETTER, List.<JCAnnotation>nil());
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateMethods(typeNode, source, null, null, null, false, access, List.<JCAnnotation>nil());
}
public void generateMethods(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
- Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<JCAnnotation> onParam) {
+ Boolean callSuper, boolean whineIfExists, FieldAccess fieldAccess, List<JCAnnotation> onParam) {
+
boolean notAClass = true;
if (typeNode.get() instanceof JCClassDecl) {
- long flags = ((JCClassDecl)typeNode.get()).mods.flags;
+ long flags = ((JCClassDecl) typeNode.get()).mods.flags;
notAClass = (flags & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
}
@@ -140,7 +145,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
boolean implicitCallSuper = callSuper == null;
if (callSuper == null) {
try {
- callSuper = ((Boolean)EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
+ callSuper = ((Boolean) EqualsAndHashCode.class.getMethod("callSuper").getDefaultValue()).booleanValue();
} catch (Exception ignore) {
throw new InternalError("Lombok bug - this cannot happen - can't find callSuper field in EqualsAndHashCode annotation.");
}
@@ -157,8 +162,23 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
return;
}
- if (!isDirectDescendantOfObject && !callSuper && implicitCallSuper) {
- source.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
+ if (implicitCallSuper && !isDirectDescendantOfObject) {
+ CallSuperType cst = typeNode.getAst().readConfiguration(ConfigurationKeys.EQUALS_AND_HASH_CODE_CALL_SUPER);
+ if (cst == null) cst = CallSuperType.WARN;
+
+ switch (cst) {
+ default:
+ case WARN:
+ source.addWarning("Generating equals/hashCode implementation but without a call to superclass, even though this class does not extend java.lang.Object. If this is intentional, add '@EqualsAndHashCode(callSuper=false)' to your type.");
+ callSuper = false;
+ break;
+ case SKIP:
+ callSuper = false;
+ break;
+ case CALL:
+ callSuper = true;
+ break;
+ }
}
ListBuffer<JavacNode> nodesForEquality = new ListBuffer<JavacNode>();
@@ -184,7 +204,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
}
- boolean isFinal = (((JCClassDecl)typeNode.get()).mods.flags & Flags.FINAL) != 0;
+ boolean isFinal = (((JCClassDecl) typeNode.get()).mods.flags & Flags.FINAL) != 0;
boolean needsCanEqual = !isFinal || !isDirectDescendantOfObject;
MemberExistsResult equalsExists = methodExists("equals", typeNode, 1);
MemberExistsResult hashCodeExists = methodExists("hashCode", typeNode, 0);
@@ -202,8 +222,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
// The user code couldn't possibly (barring really weird subclassing shenanigans) be in a shippable state anyway; the implementations of these 2 methods are
// all inter-related and should be written by the same entity.
String msg = String.format("Not generating %s: One of equals or hashCode exists. " +
- "You should either write both of these or none of these (in the latter case, lombok generates them).",
- equalsExists == MemberExistsResult.NOT_EXISTS ? "equals" : "hashCode");
+ "You should either write both of these or none of these (in the latter case, lombok generates them).",
+ equalsExists == MemberExistsResult.NOT_EXISTS ? "equals" : "hashCode");
source.addWarning(msg);
}
return;
@@ -213,6 +233,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
JCMethodDecl equalsMethod = createEquals(typeNode, nodesForEquality.toList(), callSuper, fieldAccess, needsCanEqual, source.get(), onParam);
+
injectMethod(typeNode, equalsMethod);
if (needsCanEqual && canEqualExists == MemberExistsResult.NOT_EXISTS) {
@@ -237,20 +258,23 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
long finalFlag = JavacHandlerUtil.addFinalIfNeeded(0L, typeNode.getContext());
/* final int PRIME = X; */ {
- if (!fields.isEmpty() || callSuper) {
+ if (!fields.isEmpty()) {
statements.append(maker.VarDef(maker.Modifiers(finalFlag), primeName, maker.TypeIdent(CTC_INT), maker.Literal(HandlerUtil.primeForHashcode())));
}
}
- /* int result = 1; */ {
- statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), maker.Literal(1)));
- }
-
- if (callSuper) {
- JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
- maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")),
- List.<JCExpression>nil());
- statements.append(createResultCalculation(typeNode, callToSuper));
+ /* int result = ... */ {
+ final JCExpression init;
+ if (callSuper) {
+ /* ... super.hashCode(); */
+ init = maker.Apply(List.<JCExpression>nil(),
+ maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("hashCode")),
+ List.<JCExpression>nil());
+ } else {
+ /* ... 1; */
+ init = maker.Literal(1);
+ }
+ statements.append(maker.VarDef(maker.Modifiers(0), resultName, maker.TypeIdent(CTC_INT), init));
}
Name dollar = typeNode.toName("$");
@@ -258,14 +282,14 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JCExpression fType = getFieldType(fieldNode, fieldAccess);
JCExpression fieldAccessor = createFieldAccessor(maker, fieldNode, fieldAccess);
if (fType instanceof JCPrimitiveTypeTree) {
- switch (((JCPrimitiveTypeTree)fType).getPrimitiveTypeKind()) {
+ switch (((JCPrimitiveTypeTree) fType).getPrimitiveTypeKind()) {
case BOOLEAN:
/* this.fieldName ? X : Y */
- statements.append(createResultCalculation(typeNode, maker.Conditional(fieldAccessor,
- maker.Literal(HandlerUtil.primeForTrue()), maker.Literal(HandlerUtil.primeForFalse()))));
+ statements.append(createResultCalculation(typeNode, maker.Parens(maker.Conditional(fieldAccessor,
+ maker.Literal(HandlerUtil.primeForTrue()), maker.Literal(HandlerUtil.primeForFalse())))));
break;
case LONG: {
- Name dollarFieldName = dollar.append(((JCVariableDecl)fieldNode.get()).name);
+ Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), fieldAccessor));
statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
}
@@ -273,17 +297,17 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
case FLOAT:
/* Float.floatToIntBits(this.fieldName) */
statements.append(createResultCalculation(typeNode, maker.Apply(
- List.<JCExpression>nil(),
- genJavaLangTypeRef(typeNode, "Float", "floatToIntBits"),
- List.of(fieldAccessor))));
+ List.<JCExpression>nil(),
+ genJavaLangTypeRef(typeNode, "Float", "floatToIntBits"),
+ List.of(fieldAccessor))));
break;
case DOUBLE: {
/* longToIntForHashCode(Double.doubleToLongBits(this.fieldName)) */
- Name dollarFieldName = dollar.append(((JCVariableDecl)fieldNode.get()).name);
+ Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
JCExpression init = maker.Apply(
- List.<JCExpression>nil(),
- genJavaLangTypeRef(typeNode, "Double", "doubleToLongBits"),
- List.of(fieldAccessor));
+ List.<JCExpression>nil(),
+ genJavaLangTypeRef(typeNode, "Double", "doubleToLongBits"),
+ List.of(fieldAccessor));
statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, maker.TypeIdent(CTC_LONG), init));
statements.append(createResultCalculation(typeNode, longToIntForHashCode(maker, maker.Ident(dollarFieldName), maker.Ident(dollarFieldName))));
}
@@ -299,23 +323,23 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
} else if (fType instanceof JCArrayTypeTree) {
/* java.util.Arrays.deepHashCode(this.fieldName) //use just hashCode() for primitive arrays. */
- boolean multiDim = ((JCArrayTypeTree)fType).elemtype instanceof JCArrayTypeTree;
- boolean primitiveArray = ((JCArrayTypeTree)fType).elemtype instanceof JCPrimitiveTypeTree;
+ boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree;
+ boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree;
boolean useDeepHC = multiDim || !primitiveArray;
JCExpression hcMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepHC ? "deepHashCode" : "hashCode");
statements.append(createResultCalculation(typeNode, maker.Apply(List.<JCExpression>nil(), hcMethod, List.of(fieldAccessor))));
} else /* objects */ {
/* final java.lang.Object $fieldName = this.fieldName; */
- /* $fieldName == null ? 0 : $fieldName.hashCode() */
+ /* ($fieldName == null ? NULL_PRIME : $fieldName.hashCode()) */
- Name dollarFieldName = dollar.append(((JCVariableDecl)fieldNode.get()).name);
+ Name dollarFieldName = dollar.append(((JCVariableDecl) fieldNode.get()).name);
statements.append(maker.VarDef(maker.Modifiers(finalFlag), dollarFieldName, genJavaLangTypeRef(typeNode, "Object"), fieldAccessor));
JCExpression hcCall = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(dollarFieldName), typeNode.toName("hashCode")),
- List.<JCExpression>nil());
+ List.<JCExpression>nil());
JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(dollarFieldName), maker.Literal(CTC_BOT, null));
- statements.append(createResultCalculation(typeNode, maker.Conditional(thisEqualsNull, maker.Literal(0), hcCall)));
+ statements.append(createResultCalculation(typeNode, maker.Parens(maker.Conditional(thisEqualsNull, maker.Literal(HandlerUtil.primeForNull()), hcCall))));
}
}
@@ -325,11 +349,11 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JCBlock body = maker.Block(0, statements.toList());
return recursiveSetGeneratedBy(maker.MethodDef(mods, typeNode.toName("hashCode"), returnType,
- List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source, typeNode.getContext());
+ List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), body, null), source, typeNode.getContext());
}
public JCExpressionStatement createResultCalculation(JavacNode typeNode, JCExpression expr) {
- /* result = result * PRIME + (expr); */
+ /* result = result * PRIME + expr; */
JavacTreeMaker maker = typeNode.getTreeMaker();
Name resultName = typeNode.toName(RESULT_NAME);
JCExpression mult = maker.Binary(CTC_MUL, maker.Ident(resultName), maker.Ident(typeNode.toName(PRIME_NAME)));
@@ -339,35 +363,56 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
/** The 2 references must be clones of each other. */
public JCExpression longToIntForHashCode(JavacTreeMaker maker, JCExpression ref1, JCExpression ref2) {
- /* (int)(ref >>> 32 ^ ref) */
+ /* (int) (ref >>> 32 ^ ref) */
JCExpression shift = maker.Binary(CTC_UNSIGNED_SHIFT_RIGHT, ref1, maker.Literal(32));
JCExpression xorBits = maker.Binary(CTC_BITXOR, shift, ref2);
- return maker.TypeCast(maker.TypeIdent(CTC_INT), xorBits);
+ return maker.TypeCast(maker.TypeIdent(CTC_INT), maker.Parens(xorBits));
}
- public JCExpression createTypeReference(JavacNode type) {
+ public JCExpression createTypeReference(JavacNode type, boolean addWildcards) {
java.util.List<String> list = new ArrayList<String>();
+ java.util.List<Integer> genericsCount = addWildcards ? new ArrayList<Integer>() : null;
+
list.add(type.getName());
+ if (addWildcards) genericsCount.add(((JCClassDecl) type.get()).typarams.size());
+ boolean staticContext = (((JCClassDecl) type.get()).getModifiers().flags & Flags.STATIC) != 0;
JavacNode tNode = type.up();
+
while (tNode != null && tNode.getKind() == Kind.TYPE) {
list.add(tNode.getName());
+ if (addWildcards) genericsCount.add(staticContext ? 0 : ((JCClassDecl) tNode.get()).typarams.size());
+ if (!staticContext) staticContext = (((JCClassDecl) tNode.get()).getModifiers().flags & Flags.STATIC) != 0;
tNode = tNode.up();
}
Collections.reverse(list);
+ if (addWildcards) Collections.reverse(genericsCount);
JavacTreeMaker maker = type.getTreeMaker();
+
JCExpression chain = maker.Ident(type.toName(list.get(0)));
+ if (addWildcards) chain = wildcardify(maker, chain, genericsCount.get(0));
for (int i = 1; i < list.size(); i++) {
chain = maker.Select(chain, type.toName(list.get(i)));
+ if (addWildcards) chain = wildcardify(maker, chain, genericsCount.get(i));
}
return chain;
}
+ private JCExpression wildcardify(JavacTreeMaker maker, JCExpression expr, int count) {
+ if (count == 0) return expr;
+
+ ListBuffer<JCExpression> wildcards = new ListBuffer<JCExpression>();
+ for (int i = 0 ; i < count ; i++) {
+ wildcards.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
+ }
+
+ return maker.TypeApply(expr, wildcards.toList());
+ }
+
public JCMethodDecl createEquals(JavacNode typeNode, List<JavacNode> fields, boolean callSuper, FieldAccess fieldAccess, boolean needsCanEqual, JCTree source, List<JCAnnotation> onParam) {
JavacTreeMaker maker = typeNode.getTreeMaker();
- JCClassDecl type = (JCClassDecl) typeNode.get();
Name oName = typeNode.toName("o");
Name otherName = typeNode.toName("other");
@@ -385,35 +430,21 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
/* if (o == this) return true; */ {
statements.append(maker.If(maker.Binary(CTC_EQUAL, maker.Ident(oName),
- maker.Ident(thisName)), returnBool(maker, true), null));
+ maker.Ident(thisName)), returnBool(maker, true), null));
}
- /* if (!(o instanceof Outer.Inner.MyType) return false; */ {
+ /* if (!(o instanceof Outer.Inner.MyType)) return false; */ {
- JCUnary notInstanceOf = maker.Unary(CTC_NOT, maker.TypeTest(maker.Ident(oName), createTypeReference(typeNode)));
+ JCUnary notInstanceOf = maker.Unary(CTC_NOT, maker.Parens(maker.TypeTest(maker.Ident(oName), createTypeReference(typeNode, false))));
statements.append(maker.If(notInstanceOf, returnBool(maker, false), null));
}
- /* MyType<?> other = (MyType<?>) o; */ {
+ /* Outer.Inner.MyType<?> other = (Outer.Inner.MyType<?>) o; */ {
if (!fields.isEmpty() || needsCanEqual) {
- final JCExpression selfType1, selfType2;
- ListBuffer<JCExpression> wildcards1 = new ListBuffer<JCExpression>();
- ListBuffer<JCExpression> wildcards2 = new ListBuffer<JCExpression>();
- for (int i = 0 ; i < type.typarams.length() ; i++) {
- wildcards1.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
- wildcards2.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
- }
-
- if (type.typarams.isEmpty()) {
- selfType1 = maker.Ident(type.name);
- selfType2 = maker.Ident(type.name);
- } else {
- selfType1 = maker.TypeApply(maker.Ident(type.name), wildcards1.toList());
- selfType2 = maker.TypeApply(maker.Ident(type.name), wildcards2.toList());
- }
+ final JCExpression selfType1 = createTypeReference(typeNode, true), selfType2 = createTypeReference(typeNode, true);
statements.append(
- maker.VarDef(maker.Modifiers(finalFlag), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName))));
+ maker.VarDef(maker.Modifiers(finalFlag), otherName, selfType1, maker.TypeCast(selfType2, maker.Ident(oName))));
}
}
@@ -423,8 +454,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JCExpression thisRef = maker.Ident(thisName);
JCExpression castThisRef = maker.TypeCast(genJavaLangTypeRef(typeNode, "Object"), thisRef);
JCExpression equalityCheck = maker.Apply(exprNil,
- maker.Select(maker.Ident(otherName), typeNode.toName("canEqual")),
- List.of(castThisRef));
+ maker.Select(maker.Ident(otherName), typeNode.toName("canEqual")),
+ List.of(castThisRef));
statements.append(maker.If(maker.Unary(CTC_NOT, equalityCheck), returnBool(maker, false), null));
}
}
@@ -432,8 +463,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
/* if (!super.equals(o)) return false; */
if (callSuper) {
JCMethodInvocation callToSuper = maker.Apply(List.<JCExpression>nil(),
- maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")),
- List.<JCExpression>of(maker.Ident(oName)));
+ maker.Select(maker.Ident(typeNode.toName("super")), typeNode.toName("equals")),
+ List.<JCExpression>of(maker.Ident(oName)));
JCUnary superNotEqual = maker.Unary(CTC_NOT, callToSuper);
statements.append(maker.If(superNotEqual, returnBool(maker, false), null));
}
@@ -462,19 +493,19 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
} else if (fType instanceof JCArrayTypeTree) {
/* if (!java.util.Arrays.deepEquals(this.fieldName, other.fieldName)) return false; //use equals for primitive arrays. */
- boolean multiDim = ((JCArrayTypeTree)fType).elemtype instanceof JCArrayTypeTree;
- boolean primitiveArray = ((JCArrayTypeTree)fType).elemtype instanceof JCPrimitiveTypeTree;
+ boolean multiDim = ((JCArrayTypeTree) fType).elemtype instanceof JCArrayTypeTree;
+ boolean primitiveArray = ((JCArrayTypeTree) fType).elemtype instanceof JCPrimitiveTypeTree;
boolean useDeepEquals = multiDim || !primitiveArray;
JCExpression eqMethod = chainDots(typeNode, "java", "util", "Arrays", useDeepEquals ? "deepEquals" : "equals");
List<JCExpression> args = List.of(thisFieldAccessor, otherFieldAccessor);
statements.append(maker.If(maker.Unary(CTC_NOT,
- maker.Apply(List.<JCExpression>nil(), eqMethod, args)), returnBool(maker, false), null));
+ maker.Apply(List.<JCExpression>nil(), eqMethod, args)), returnBool(maker, false), null));
} else /* objects */ {
/* final java.lang.Object this$fieldName = this.fieldName; */
/* final java.lang.Object other$fieldName = other.fieldName; */
- /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false;; */
- Name fieldName = ((JCVariableDecl)fieldNode.get()).name;
+ /* if (this$fieldName == null ? other$fieldName != null : !this$fieldName.equals(other$fieldName)) return false; */
+ Name fieldName = ((JCVariableDecl) fieldNode.get()).name;
Name thisDollarFieldName = thisDollar.append(fieldName);
Name otherDollarFieldName = otherDollar.append(fieldName);
@@ -484,8 +515,8 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
JCExpression thisEqualsNull = maker.Binary(CTC_EQUAL, maker.Ident(thisDollarFieldName), maker.Literal(CTC_BOT, null));
JCExpression otherNotEqualsNull = maker.Binary(CTC_NOT_EQUAL, maker.Ident(otherDollarFieldName), maker.Literal(CTC_BOT, null));
JCExpression thisEqualsThat = maker.Apply(List.<JCExpression>nil(),
- maker.Select(maker.Ident(thisDollarFieldName), typeNode.toName("equals")),
- List.<JCExpression>of(maker.Ident(otherDollarFieldName)));
+ maker.Select(maker.Ident(thisDollarFieldName), typeNode.toName("equals")),
+ List.<JCExpression>of(maker.Ident(otherDollarFieldName)));
JCExpression fieldsAreNotEqual = maker.Conditional(thisEqualsNull, otherNotEqualsNull, maker.Unary(CTC_NOT, thisEqualsThat));
statements.append(maker.If(fieldsAreNotEqual, returnBool(maker, false), null));
}
@@ -500,7 +531,7 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
}
public JCMethodDecl createCanEqual(JavacNode typeNode, JCTree source, List<JCAnnotation> onParam) {
- /* public boolean canEqual(final java.lang.Object other) {
+ /* protected boolean canEqual(final java.lang.Object other) {
* return other instanceof Outer.Inner.MyType;
* }
*/
@@ -515,18 +546,19 @@ public class HandleEqualsAndHashCode extends JavacAnnotationHandler<EqualsAndHas
List<JCVariableDecl> params = List.of(maker.VarDef(maker.Modifiers(flags, onParam), otherName, objectType, null));
JCBlock body = maker.Block(0, List.<JCStatement>of(
- maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode)))));
+ maker.Return(maker.TypeTest(maker.Ident(otherName), createTypeReference(typeNode, false)))));
return recursiveSetGeneratedBy(maker.MethodDef(mods, canEqualName, returnType, List.<JCTypeParameter>nil(), params, List.<JCExpression>nil(), body, null), source, typeNode.getContext());
}
public JCStatement generateCompareFloatOrDouble(JCExpression thisDotField, JCExpression otherDotField,
- JavacTreeMaker maker, JavacNode node, boolean isDouble) {
+ JavacTreeMaker maker, JavacNode node, boolean isDouble) {
+
/* if (Float.compare(fieldName, other.fieldName) != 0) return false; */
JCExpression clazz = genJavaLangTypeRef(node, isDouble ? "Double" : "Float");
List<JCExpression> args = List.of(thisDotField, otherDotField);
JCBinary compareCallEquals0 = maker.Binary(CTC_NOT_EQUAL, maker.Apply(
- List.<JCExpression>nil(), maker.Select(clazz, node.toName("compare")), args), maker.Literal(0));
+ List.<JCExpression>nil(), maker.Select(clazz, node.toName("compare")), args), maker.Literal(0));
return maker.If(compareCallEquals0, returnBool(maker, false), null);
}
diff --git a/src/core/lombok/javac/handlers/HandleFieldDefaults.java b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
index 335ab1fe..52f6c39c 100644
--- a/src/core/lombok/javac/handlers/HandleFieldDefaults.java
+++ b/src/core/lombok/javac/handlers/HandleFieldDefaults.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2012-2016 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
@@ -31,23 +31,24 @@ import lombok.core.HandlerPriority;
import lombok.experimental.FieldDefaults;
import lombok.experimental.NonFinal;
import lombok.experimental.PackagePrivate;
-import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacASTAdapter;
+import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacNode;
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.JCClassDecl;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
-import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
/**
* Handles the {@code lombok.FieldDefaults} annotation for eclipse.
*/
-@ProviderFor(JavacAnnotationHandler.class)
+@ProviderFor(JavacASTVisitor.class)
@HandlerPriority(-2048) //-2^11; to ensure @Value picks up on messing with the fields' 'final' state, run earlier.
-public class HandleFieldDefaults extends JavacAnnotationHandler<FieldDefaults> {
+public class HandleFieldDefaults extends JavacASTAdapter {
public boolean generateFieldDefaultsForType(JavacNode typeNode, JavacNode errorNode, AccessLevel level, boolean makeFinal, boolean checkForTypeLevelFieldDefaults) {
if (checkForTypeLevelFieldDefaults) {
if (hasAnnotation(FieldDefaults.class, typeNode)) {
@@ -72,56 +73,82 @@ public class HandleFieldDefaults extends JavacAnnotationHandler<FieldDefaults> {
//Skip fields that start with $
if (fieldDecl.name.toString().startsWith("$")) continue;
- setFieldDefaultsForField(field, errorNode.get(), level, makeFinal);
+ setFieldDefaultsForField(field, level, makeFinal);
}
return true;
}
- public void setFieldDefaultsForField(JavacNode fieldNode, DiagnosticPosition pos, AccessLevel level, boolean makeFinal) {
+ public void setFieldDefaultsForField(JavacNode fieldNode, AccessLevel level, boolean makeFinal) {
JCVariableDecl field = (JCVariableDecl) fieldNode.get();
if (level != null && level != AccessLevel.NONE) {
if ((field.mods.flags & (Flags.PUBLIC | Flags.PRIVATE | Flags.PROTECTED)) == 0) {
if (!hasAnnotationAndDeleteIfNeccessary(PackagePrivate.class, fieldNode)) {
- field.mods.flags |= toJavacModifier(level);
+ if ((field.mods.flags & Flags.STATIC) == 0) {
+ field.mods.flags |= toJavacModifier(level);
+ }
}
}
}
if (makeFinal && (field.mods.flags & Flags.FINAL) == 0) {
if (!hasAnnotationAndDeleteIfNeccessary(NonFinal.class, fieldNode)) {
- field.mods.flags |= Flags.FINAL;
+ if ((field.mods.flags & Flags.STATIC) == 0) {
+ field.mods.flags |= Flags.FINAL;
+ }
}
}
fieldNode.rebuild();
}
- @Override public void handle(AnnotationValues<FieldDefaults> annotation, JCAnnotation ast, JavacNode annotationNode) {
- handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.FIELD_DEFAULTS_FLAG_USAGE, "@FieldDefaults");
-
- deleteAnnotationIfNeccessary(annotationNode, FieldDefaults.class);
- deleteImportFromCompilationUnit(annotationNode, "lombok.AccessLevel");
- JavacNode node = annotationNode.up();
- FieldDefaults instance = annotation.getInstance();
- AccessLevel level = instance.level();
- boolean makeFinal = instance.makeFinal();
+ @Override public void visitType(JavacNode typeNode, JCClassDecl type) {
+ AnnotationValues<FieldDefaults> fieldDefaults = null;
+ JavacNode source = typeNode;
- if (level == AccessLevel.NONE && !makeFinal) {
- annotationNode.addError("This does nothing; provide either level or makeFinal or both.");
- return;
+ boolean levelIsExplicit = false;
+ boolean makeFinalIsExplicit = false;
+ FieldDefaults fd = null;
+ for (JavacNode jn : typeNode.down()) {
+ if (jn.getKind() != Kind.ANNOTATION) continue;
+ JCAnnotation ann = (JCAnnotation) jn.get();
+ JCTree typeTree = ann.annotationType;
+ if (typeTree == null) continue;
+ String typeTreeToString = typeTree.toString();
+ if (!typeTreeToString.equals("FieldDefaults") && !typeTreeToString.equals("lombok.experimental.FieldDefaults")) continue;
+ if (!typeMatches(FieldDefaults.class, jn, typeTree)) continue;
+
+ source = jn;
+ fieldDefaults = createAnnotation(FieldDefaults.class, jn);
+ levelIsExplicit = fieldDefaults.isExplicit("level");
+ makeFinalIsExplicit = fieldDefaults.isExplicit("makeFinal");
+
+ handleExperimentalFlagUsage(jn, ConfigurationKeys.FIELD_DEFAULTS_FLAG_USAGE, "@FieldDefaults");
+
+ fd = fieldDefaults.getInstance();
+ if (!levelIsExplicit && !makeFinalIsExplicit) {
+ jn.addError("This does nothing; provide either level or makeFinal or both.");
+ }
+
+ if (levelIsExplicit && fd.level() == AccessLevel.NONE) {
+ jn.addError("AccessLevel.NONE doesn't mean anything here. Pick another value.");
+ levelIsExplicit = false;
+ }
+
+ deleteAnnotationIfNeccessary(jn, FieldDefaults.class);
+ deleteImportFromCompilationUnit(jn, "lombok.AccessLevel");
+ break;
}
- if (level == AccessLevel.PACKAGE) {
- annotationNode.addError("Setting 'level' to PACKAGE does nothing. To force fields as package private, use the @PackagePrivate annotation on the field.");
- }
+ if (fd == null && (type.mods.flags & (Flags.INTERFACE | Flags.ANNOTATION)) != 0) return;
- if (!makeFinal && annotation.isExplicit("makeFinal")) {
- annotationNode.addError("Setting 'makeFinal' to false does nothing. To force fields to be non-final, use the @NonFinal annotation on the field.");
- }
+ boolean defaultToPrivate = levelIsExplicit ? false : Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.FIELD_DEFAULTS_PRIVATE_EVERYWHERE));
+ boolean defaultToFinal = makeFinalIsExplicit ? false : Boolean.TRUE.equals(typeNode.getAst().readConfiguration(ConfigurationKeys.FIELD_DEFAULTS_FINAL_EVERYWHERE));
- if (node == null) return;
+ if (!defaultToPrivate && !defaultToFinal && fieldDefaults == null) return;
+ AccessLevel fdAccessLevel = (fieldDefaults != null && levelIsExplicit) ? fd.level() : defaultToPrivate ? AccessLevel.PRIVATE : null;
+ boolean fdToFinal = (fieldDefaults != null && makeFinalIsExplicit) ? fd.makeFinal() : defaultToFinal;
- generateFieldDefaultsForType(node, annotationNode, level, makeFinal, false);
+ generateFieldDefaultsForType(typeNode, source, fdAccessLevel, fdToFinal, false);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleGetter.java b/src/core/lombok/javac/handlers/HandleGetter.java
index a330dbc1..0540465d 100644
--- a/src/core/lombok/javac/handlers/HandleGetter.java
+++ b/src/core/lombok/javac/handlers/HandleGetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -46,6 +46,7 @@ import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBinary;
@@ -94,7 +95,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
}
}
- public boolean fieldQualifiesForGetterGeneration(JavacNode field) {
+ public static boolean fieldQualifiesForGetterGeneration(JavacNode field) {
if (field.getKind() != Kind.FIELD) return false;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
//Skip fields that start with $
@@ -146,7 +147,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
if (node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod=", annotationNode);
+ List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Getter(onMethod", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -182,6 +183,10 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
source.addError("'lazy' requires the field to be private and final.");
return;
}
+ if ((fieldDecl.mods.flags & Flags.TRANSIENT) != 0) {
+ source.addError("'lazy' is not supported on transient fields.");
+ return;
+ }
if (fieldDecl.init == null) {
source.addError("'lazy' requires field initialization.");
return;
@@ -215,7 +220,7 @@ public class HandleGetter extends JavacAnnotationHandler<Getter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
- injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod));
+ injectMethod(fieldNode.up(), createGetter(access, fieldNode, fieldNode.getTreeMaker(), source.get(), lazy, onMethod), List.<Type>nil(), getMirrorForFieldType(fieldNode));
}
public JCMethodDecl createGetter(long access, JavacNode field, JavacTreeMaker treeMaker, JCTree source, boolean lazy, List<JCAnnotation> onMethod) {
diff --git a/src/core/lombok/javac/handlers/HandleHelper.java b/src/core/lombok/javac/handlers/HandleHelper.java
new file mode 100644
index 00000000..09ace4d6
--- /dev/null
+++ b/src/core/lombok/javac/handlers/HandleHelper.java
@@ -0,0 +1,151 @@
+/*
+ * Copyright (C) 2015-2016 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.javac.handlers;
+
+import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.sun.source.tree.MethodInvocationTree;
+import com.sun.source.tree.TreeVisitor;
+import com.sun.source.util.TreeScanner;
+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.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+import lombok.ConfigurationKeys;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.experimental.Helper;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+
+@ProviderFor(JavacAnnotationHandler.class)
+public class HandleHelper extends JavacAnnotationHandler<Helper> {
+ private List<JCStatement> getStatementsFromJcNode(JCTree tree) {
+ if (tree instanceof JCBlock) return ((JCBlock) tree).stats;
+ if (tree instanceof JCCase) return ((JCCase) tree).stats;
+ return null;
+ }
+
+ private void setStatementsOfJcNode(JCTree tree, List<JCStatement> statements) {
+ if (tree instanceof JCBlock) ((JCBlock) tree).stats = statements;
+ else if (tree instanceof JCCase) ((JCCase) tree).stats = statements;
+ else throw new IllegalArgumentException("Can't set statements on node type: " + tree.getClass());
+ }
+
+ @Override public void handle(AnnotationValues<Helper> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.HELPER_FLAG_USAGE, "@Helper");
+
+ deleteAnnotationIfNeccessary(annotationNode, Helper.class);
+ JavacNode annotatedType = annotationNode.up();
+ JavacNode containingBlock = annotatedType == null ? null : annotatedType.directUp();
+ List<JCStatement> origStatements = getStatementsFromJcNode(containingBlock == null ? null : containingBlock.get());
+
+ if (annotatedType == null || annotatedType.getKind() != Kind.TYPE || origStatements == null) {
+ annotationNode.addError("@Helper is legal only on method-local classes.");
+ return;
+ }
+
+ JCClassDecl annotatedType_ = (JCClassDecl) annotatedType.get();
+ Iterator<JCStatement> it = origStatements.iterator();
+ while (it.hasNext()) {
+ if (it.next() == annotatedType_) {
+ break;
+ }
+ }
+
+ java.util.List<String> knownMethodNames = new ArrayList<String>();
+
+ for (JavacNode ch : annotatedType.down()) {
+ if (ch.getKind() != Kind.METHOD) continue;
+ String n = ch.getName();
+ if (n == null || n.isEmpty() || n.charAt(0) == '<') continue;
+ knownMethodNames.add(n);
+ }
+
+ Collections.sort(knownMethodNames);
+ final String[] knownMethodNames_ = knownMethodNames.toArray(new String[knownMethodNames.size()]);
+
+ final Name helperName = annotationNode.toName("$" + annotatedType_.name);
+ final boolean[] helperUsed = new boolean[1];
+ final JavacTreeMaker maker = annotationNode.getTreeMaker();
+
+ TreeVisitor<Void, Void> visitor = new TreeScanner<Void, Void>() {
+ @Override public Void visitMethodInvocation(MethodInvocationTree node, Void p) {
+ JCMethodInvocation jcmi = (JCMethodInvocation) node;
+ apply(jcmi);
+ return super.visitMethodInvocation(node, p);
+ }
+
+ private void apply(JCMethodInvocation jcmi) {
+ if (!(jcmi.meth instanceof JCIdent)) return;
+ JCIdent jci = (JCIdent) jcmi.meth;
+ if (Arrays.binarySearch(knownMethodNames_, jci.name.toString()) < 0) return;
+ jcmi.meth = maker.Select(maker.Ident(helperName), jci.name);
+ helperUsed[0] = true;
+ }
+ };
+
+ while (it.hasNext()) {
+ JCStatement stat = it.next();
+ stat.accept(visitor, null);
+ }
+
+ if (!helperUsed[0]) {
+ annotationNode.addWarning("No methods of this helper class are ever used.");
+ return;
+ }
+
+ ListBuffer<JCStatement> newStatements = new ListBuffer<JCStatement>();
+
+ boolean mark = false;
+ for (JCStatement stat : origStatements) {
+ newStatements.append(stat);
+ if (mark || stat != annotatedType_) continue;
+ mark = true;
+ JCExpression init = maker.NewClass(null, List.<JCExpression>nil(), maker.Ident(annotatedType_.name), List.<JCExpression>nil(), null);
+ JCExpression varType = maker.Ident(annotatedType_.name);
+ JCVariableDecl decl = maker.VarDef(maker.Modifiers(Flags.FINAL), helperName, varType, init);
+ newStatements.append(decl);
+ }
+ setStatementsOfJcNode(containingBlock.get(), newStatements.toList());
+ }
+}
diff --git a/src/core/lombok/javac/handlers/HandleLog.java b/src/core/lombok/javac/handlers/HandleLog.java
index ee7268f7..d0d709e3 100644
--- a/src/core/lombok/javac/handlers/HandleLog.java
+++ b/src/core/lombok/javac/handlers/HandleLog.java
@@ -105,7 +105,7 @@ public class HandleLog {
maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (useStatic ? Flags.STATIC : 0)),
typeNode.toName(logFieldName), loggerType, factoryMethodCall), source, typeNode.getContext());
- injectFieldSuppressWarnings(typeNode, fieldDecl);
+ injectFieldAndMarkGenerated(typeNode, fieldDecl);
return true;
}
@@ -175,6 +175,17 @@ public class HandleLog {
}
}
+ /**
+ * Handles the {@link lombok.extern.jbosslog.JBossLog} annotation for javac.
+ */
+ @ProviderFor(JavacAnnotationHandler.class)
+ public static class HandleJBossLog extends JavacAnnotationHandler<lombok.extern.jbosslog.JBossLog> {
+ @Override public void handle(AnnotationValues<lombok.extern.jbosslog.JBossLog> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleFlagUsage(annotationNode, ConfigurationKeys.LOG_JBOSSLOG_FLAG_USAGE, "@JBossLog", ConfigurationKeys.LOG_ANY_FLAG_USAGE, "any @Log");
+ processAnnotation(LoggingFramework.JBOSSLOG, annotation, annotationNode, annotation.getInstance().topic());
+ }
+ }
+
enum LoggingFramework {
// private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog(TargetType.class);
COMMONS(lombok.extern.apachecommons.CommonsLog.class, "org.apache.commons.logging.Log", "org.apache.commons.logging.LogFactory.getLog"),
@@ -200,6 +211,8 @@ public class HandleLog {
// private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger(TargetType.class);
XSLF4J(lombok.extern.slf4j.XSlf4j.class, "org.slf4j.ext.XLogger", "org.slf4j.ext.XLoggerFactory.getXLogger"),
+ // private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(TargetType.class);
+ JBOSSLOG(lombok.extern.jbosslog.JBossLog.class, "org.jboss.logging.Logger", "org.jboss.logging.Logger.getLogger")
;
private final Class<? extends Annotation> annotationClass;
diff --git a/src/core/lombok/javac/handlers/HandleNonNull.java b/src/core/lombok/javac/handlers/HandleNonNull.java
index cd8e3402..81aa1525 100644
--- a/src/core/lombok/javac/handlers/HandleNonNull.java
+++ b/src/core/lombok/javac/handlers/HandleNonNull.java
@@ -85,7 +85,7 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
}
if (declaration.body == null) {
- annotationNode.addWarning("@NonNull is meaningless on a parameter of an abstract method.");
+ // This used to be a warning, but as @NonNull also has a documentary purpose, better to not warn about this. Since 1.16.7
return;
}
@@ -141,6 +141,7 @@ public class HandleNonNull extends JavacAnnotationHandler<NonNull> {
List<JCStatement> newList = tail.prepend(nullCheck);
for (JCStatement stat : head) newList = newList.prepend(stat);
declaration.body.stats = newList;
+ annotationNode.getAst().setChanged();
}
public boolean isNullCheck(JCStatement stat) {
diff --git a/src/core/lombok/javac/handlers/HandlePrintAST.java b/src/core/lombok/javac/handlers/HandlePrintAST.java
index 9a52b9d9..0826d1d1 100644
--- a/src/core/lombok/javac/handlers/HandlePrintAST.java
+++ b/src/core/lombok/javac/handlers/HandlePrintAST.java
@@ -59,7 +59,7 @@ public class HandlePrintAST extends JavacAnnotationHandler<PrintAST> {
try {
stream.close();
} catch (Exception e) {
- Lombok.sneakyThrow(e);
+ throw Lombok.sneakyThrow(e);
}
}
}
diff --git a/src/core/lombok/javac/handlers/HandleSetter.java b/src/core/lombok/javac/handlers/HandleSetter.java
index 3c4329b2..1453aa27 100644
--- a/src/core/lombok/javac/handlers/HandleSetter.java
+++ b/src/core/lombok/javac/handlers/HandleSetter.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -41,6 +41,8 @@ import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCAssign;
import com.sun.tools.javac.tree.JCTree.JCBlock;
@@ -127,8 +129,8 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
if (level == AccessLevel.NONE || node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode);
- List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode);
+ List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod", annotationNode);
+ List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -154,7 +156,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
return;
}
- JCVariableDecl fieldDecl = (JCVariableDecl)fieldNode.get();
+ JCVariableDecl fieldDecl = (JCVariableDecl) fieldNode.get();
String methodName = toSetterName(fieldNode);
if (methodName == null) {
@@ -188,16 +190,26 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
long access = toJavacModifier(level) | (fieldDecl.mods.flags & Flags.STATIC);
JCMethodDecl createdSetter = createSetter(access, fieldNode, fieldNode.getTreeMaker(), sourceNode, onMethod, onParam);
- injectMethod(fieldNode.up(), createdSetter);
+ Type fieldType = getMirrorForFieldType(fieldNode);
+ Type returnType;
+
+ if (shouldReturnThis(fieldNode)) {
+ ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
+ returnType = sym == null ? null : sym.type;
+ } else {
+ returnType = Javac.createVoidType(fieldNode.getSymbolTable(), CTC_VOID);
+ }
+
+ injectMethod(fieldNode.up(), createdSetter, fieldType == null ? null : List.of(fieldType), returnType);
}
public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
String setterName = toSetterName(field);
boolean returnThis = shouldReturnThis(field);
- return createSetter(access, field, treeMaker, setterName, returnThis, source, onMethod, onParam);
+ return createSetter(access, false, field, treeMaker, setterName, null, returnThis, source, onMethod, onParam);
}
- public static JCMethodDecl createSetter(long access, JavacNode field, JavacTreeMaker treeMaker, String setterName, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ public static JCMethodDecl createSetter(long access, boolean deprecate, JavacNode field, JavacTreeMaker treeMaker, String setterName, Name booleanFieldToSet, boolean shouldReturnThis, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
if (setterName == null) return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
@@ -223,6 +235,11 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
statements.append(treeMaker.Exec(assign));
}
+ if (booleanFieldToSet != null) {
+ JCAssign setBool = treeMaker.Assign(treeMaker.Ident(booleanFieldToSet), treeMaker.Literal(CTC_BOOLEAN, 1));
+ statements.append(treeMaker.Exec(setBool));
+ }
+
JCExpression methodType = null;
if (shouldReturnThis) {
methodType = cloneSelfType(field);
@@ -230,7 +247,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
if (methodType == null) {
//WARNING: Do not use field.getSymbolTable().voidType - that field has gone through non-backwards compatible API changes within javac1.6.
- methodType = treeMaker.Type(Javac.createVoidType(treeMaker, CTC_VOID));
+ methodType = treeMaker.Type(Javac.createVoidType(field.getSymbolTable(), CTC_VOID));
shouldReturnThis = false;
}
@@ -246,7 +263,7 @@ public class HandleSetter extends JavacAnnotationHandler<Setter> {
JCExpression annotationMethodDefaultValue = null;
List<JCAnnotation> annsOnMethod = copyAnnotations(onMethod);
- if (isFieldDeprecated(field)) {
+ if (isFieldDeprecated(field) || deprecate) {
annsOnMethod = annsOnMethod.prepend(treeMaker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
diff --git a/src/core/lombok/javac/handlers/HandleSynchronized.java b/src/core/lombok/javac/handlers/HandleSynchronized.java
index fb6678e6..20e85d7e 100644
--- a/src/core/lombok/javac/handlers/HandleSynchronized.java
+++ b/src/core/lombok/javac/handlers/HandleSynchronized.java
@@ -99,7 +99,7 @@ public class HandleSynchronized extends JavacAnnotationHandler<Synchronized> {
JCVariableDecl fieldDecl = recursiveSetGeneratedBy(maker.VarDef(
maker.Modifiers(Flags.PRIVATE | Flags.FINAL | (isStatic ? Flags.STATIC : 0)),
methodNode.toName(lockName), objectType, newObjectArray), ast, context);
- injectFieldSuppressWarnings(methodNode.up(), fieldDecl);
+ injectFieldAndMarkGenerated(methodNode.up(), fieldDecl);
}
if (method.body == null) return;
diff --git a/src/core/lombok/javac/handlers/HandleToString.java b/src/core/lombok/javac/handlers/HandleToString.java
index 743e7b26..897d5f2c 100644
--- a/src/core/lombok/javac/handlers/HandleToString.java
+++ b/src/core/lombok/javac/handlers/HandleToString.java
@@ -117,7 +117,11 @@ public class HandleToString extends JavacAnnotationHandler<ToString> {
Boolean configuration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_INCLUDE_FIELD_NAMES);
includeFieldNames = configuration != null ? configuration : ((Boolean)ToString.class.getMethod("includeFieldNames").getDefaultValue()).booleanValue();
} catch (Exception ignore) {}
- generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, FieldAccess.GETTER);
+
+ Boolean doNotUseGettersConfiguration = typeNode.getAst().readConfiguration(ConfigurationKeys.TO_STRING_DO_NOT_USE_GETTERS);
+ FieldAccess access = doNotUseGettersConfiguration == null || !doNotUseGettersConfiguration ? FieldAccess.GETTER : FieldAccess.PREFER_FIELD;
+
+ generateToString(typeNode, errorNode, null, null, includeFieldNames, null, false, access);
}
public void generateToString(JavacNode typeNode, JavacNode source, List<String> excludes, List<String> includes,
diff --git a/src/core/lombok/javac/handlers/HandleUtilityClass.java b/src/core/lombok/javac/handlers/HandleUtilityClass.java
new file mode 100644
index 00000000..ee8081d6
--- /dev/null
+++ b/src/core/lombok/javac/handlers/HandleUtilityClass.java
@@ -0,0 +1,161 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers;
+
+import static lombok.core.handlers.HandlerUtil.handleExperimentalFlagUsage;
+import static lombok.javac.Javac.CTC_VOID;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Type;
+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.List;
+import com.sun.tools.javac.util.Name;
+
+import lombok.ConfigurationKeys;
+import lombok.core.AST.Kind;
+import lombok.core.AnnotationValues;
+import lombok.core.HandlerPriority;
+import lombok.experimental.UtilityClass;
+import lombok.javac.Javac;
+import lombok.javac.JavacAnnotationHandler;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+
+/**
+ * Handles the {@code @UtilityClass} annotation for javac.
+ */
+@HandlerPriority(-4096) //-2^12; to ensure @FieldDefaults picks up on the 'static' we set here.
+@ProviderFor(JavacAnnotationHandler.class)
+public class HandleUtilityClass extends JavacAnnotationHandler<UtilityClass> {
+ @Override public void handle(AnnotationValues<UtilityClass> annotation, JCAnnotation ast, JavacNode annotationNode) {
+ handleExperimentalFlagUsage(annotationNode, ConfigurationKeys.UTILITY_CLASS_FLAG_USAGE, "@UtilityClass");
+
+ deleteAnnotationIfNeccessary(annotationNode, UtilityClass.class);
+
+ JavacNode typeNode = annotationNode.up();
+ if (!checkLegality(typeNode, annotationNode)) return;
+ changeModifiersAndGenerateConstructor(annotationNode.up(), annotationNode);
+ }
+
+ private static boolean checkLegality(JavacNode typeNode, JavacNode errorNode) {
+ JCClassDecl typeDecl = null;
+ if (typeNode.get() instanceof JCClassDecl) typeDecl = (JCClassDecl) typeNode.get();
+ long modifiers = typeDecl == null ? 0 : typeDecl.mods.flags;
+ boolean notAClass = (modifiers & (Flags.INTERFACE | Flags.ANNOTATION | Flags.ENUM)) != 0;
+
+ if (typeDecl == null || notAClass) {
+ errorNode.addError("@UtilityClass is only supported on a class (can't be an interface, enum, or annotation).");
+ return false;
+ }
+
+ // It might be an inner class. This is okay, but only if it is / can be a static inner class. Thus, all of its parents have to be static inner classes until the top-level.
+ JavacNode typeWalk = typeNode;
+ while (true) {
+ typeWalk = typeWalk.up();
+ switch (typeWalk.getKind()) {
+ case TYPE:
+ JCClassDecl typeDef = (JCClassDecl) typeWalk.get();
+ if ((typeDef.mods.flags & (Flags.STATIC | Flags.ANNOTATION | Flags.ENUM | Flags.INTERFACE)) != 0) continue;
+ if (typeWalk.up().getKind() == Kind.COMPILATION_UNIT) return true;
+ errorNode.addError("@UtilityClass automatically makes the class static, however, this class cannot be made static.");
+ return false;
+ case COMPILATION_UNIT:
+ return true;
+ default:
+ errorNode.addError("@UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class.");
+ return false;
+ }
+ }
+ }
+
+ private void changeModifiersAndGenerateConstructor(JavacNode typeNode, JavacNode errorNode) {
+ JCClassDecl classDecl = (JCClassDecl) typeNode.get();
+
+ boolean makeConstructor = true;
+
+ classDecl.mods.flags |= Flags.FINAL;
+
+ boolean markStatic = true;
+
+ if (typeNode.up().getKind() == Kind.COMPILATION_UNIT) markStatic = false;
+ if (markStatic && typeNode.up().getKind() == Kind.TYPE) {
+ JCClassDecl typeDecl = (JCClassDecl) typeNode.up().get();
+ if ((typeDecl.mods.flags & Flags.INTERFACE) != 0) markStatic = false;
+ }
+
+ if (markStatic) classDecl.mods.flags |= Flags.STATIC;
+
+ for (JavacNode element : typeNode.down()) {
+ if (element.getKind() == Kind.FIELD) {
+ JCVariableDecl fieldDecl = (JCVariableDecl) element.get();
+ fieldDecl.mods.flags |= Flags.STATIC;
+ } else if (element.getKind() == Kind.METHOD) {
+ JCMethodDecl methodDecl = (JCMethodDecl) element.get();
+ if (methodDecl.name.contentEquals("<init>")) {
+ if (getGeneratedBy(methodDecl) == null && (methodDecl.mods.flags & Flags.GENERATEDCONSTR) == 0) {
+ element.addError("@UtilityClasses cannot have declared constructors.");
+ makeConstructor = false;
+ continue;
+ }
+ }
+
+ methodDecl.mods.flags |= Flags.STATIC;
+ } else if (element.getKind() == Kind.TYPE) {
+ JCClassDecl innerClassDecl = (JCClassDecl) element.get();
+ innerClassDecl.mods.flags |= Flags.STATIC;
+ }
+ }
+
+ if (makeConstructor) createPrivateDefaultConstructor(typeNode);
+ }
+
+ private void createPrivateDefaultConstructor(JavacNode typeNode) {
+ JavacTreeMaker maker = typeNode.getTreeMaker();
+ JCModifiers mods = maker.Modifiers(Flags.PRIVATE, List.<JCAnnotation>nil());
+
+ Name name = typeNode.toName("<init>");
+ JCBlock block = maker.Block(0L, createThrowStatement(typeNode, maker));
+ JCMethodDecl methodDef = maker.MethodDef(mods, name, null, List.<JCTypeParameter>nil(), List.<JCVariableDecl>nil(), List.<JCExpression>nil(), block, null);
+ JCMethodDecl constructor = recursiveSetGeneratedBy(methodDef, typeNode.get(), typeNode.getContext());
+ JavacHandlerUtil.injectMethod(typeNode, constructor, List.<Type>nil(), Javac.createVoidType(typeNode.getSymbolTable(), CTC_VOID));
+ }
+
+ private List<JCStatement> createThrowStatement(JavacNode typeNode, JavacTreeMaker maker) {
+ JCExpression exceptionType = genJavaLangTypeRef(typeNode, "UnsupportedOperationException");
+ List<JCExpression> jceBlank = List.nil();
+ JCExpression message = maker.Literal("This is a utility class and cannot be instantiated");
+ JCExpression exceptionInstance = maker.NewClass(null, jceBlank, exceptionType, List.of(message), null);
+ JCStatement throwStatement = maker.Throw(exceptionInstance);
+ return List.of(throwStatement);
+ }
+}
diff --git a/src/core/lombok/javac/handlers/HandleVal.java b/src/core/lombok/javac/handlers/HandleVal.java
index 0230e1b0..14130bc4 100644
--- a/src/core/lombok/javac/handlers/HandleVal.java
+++ b/src/core/lombok/javac/handlers/HandleVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2014 The Project Lombok Authors.
+ * Copyright (C) 2010-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,11 +21,12 @@
*/
package lombok.javac.handlers;
-import static lombok.core.handlers.HandlerUtil.*;
+import static lombok.core.handlers.HandlerUtil.handleFlagUsage;
import static lombok.javac.handlers.JavacHandlerUtil.*;
import lombok.ConfigurationKeys;
import lombok.val;
import lombok.core.HandlerPriority;
+import lombok.var;
import lombok.javac.JavacASTAdapter;
import lombok.javac.JavacASTVisitor;
import lombok.javac.JavacNode;
@@ -35,12 +36,14 @@ import lombok.javac.ResolutionResetNeeded;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
import com.sun.tools.javac.tree.JCTree.JCExpression;
import com.sun.tools.javac.tree.JCTree.JCForLoop;
+import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCNewArray;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.util.List;
@@ -49,21 +52,36 @@ import com.sun.tools.javac.util.List;
@HandlerPriority(65536) // 2^16; resolution needs to work, so if the RHS expression is i.e. a call to a generated getter, we have to run after that getter has been generated.
@ResolutionResetNeeded
public class HandleVal extends JavacASTAdapter {
- @Override public void visitLocal(JavacNode localNode, JCVariableDecl local) {
- if (local.vartype == null || (!local.vartype.toString().equals("val") && !local.vartype.toString().equals("lombok.val"))) return;
-
- JCTree source = local.vartype;
+
+ private static boolean eq(String typeTreeToString, String key) {
+ return typeTreeToString.equals(key) || typeTreeToString.equals("lombok." + key) || typeTreeToString.equals("lombok.experimental." + key);
+ }
+
+ @SuppressWarnings("deprecation") @Override
+ public void visitLocal(JavacNode localNode, JCVariableDecl local) {
+ JCTree typeTree = local.vartype;
+ if (typeTree == null) return;
+ String typeTreeToString = typeTree.toString();
- if (!typeMatches(val.class, localNode, local.vartype)) return;
+ if (!(eq(typeTreeToString, "val") || eq(typeTreeToString, "var"))) return;
+ boolean isVal = typeMatches(val.class, localNode, typeTree);
+ boolean isVar = typeMatches(var.class, localNode, typeTree);
+ if (!(isVal || isVar)) return;
- handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
+ if (isVal) handleFlagUsage(localNode, ConfigurationKeys.VAL_FLAG_USAGE, "val");
+ if (isVar) handleFlagUsage(localNode, ConfigurationKeys.VAR_FLAG_USAGE, "var");
JCTree parentRaw = localNode.directUp().get();
- if (parentRaw instanceof JCForLoop) {
+ if (isVal && parentRaw instanceof JCForLoop) {
localNode.addError("'val' is not allowed in old-style for loops");
return;
}
+ if (parentRaw instanceof JCForLoop && ((JCForLoop) parentRaw).getInitializer().size() > 1) {
+ localNode.addError("'var' is not allowed in old-style for loops if there is more than 1 initializer");
+ return;
+ }
+
JCExpression rhsOfEnhancedForLoop = null;
if (local.init == null) {
if (parentRaw instanceof JCEnhancedForLoop) {
@@ -72,22 +90,27 @@ public class HandleVal extends JavacASTAdapter {
}
}
+ final String annotation = typeTreeToString;
if (rhsOfEnhancedForLoop == null && local.init == null) {
- localNode.addError("'val' on a local variable requires an initializer expression");
+ localNode.addError("'" + annotation + "' on a local variable requires an initializer expression");
return;
}
if (local.init instanceof JCNewArray && ((JCNewArray)local.init).elemtype == null) {
- localNode.addError("'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
+ localNode.addError("'" + annotation + "' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })");
return;
}
- if (localNode.shouldDeleteLombokAnnotations()) JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, "lombok.val");
+ if (localNode.shouldDeleteLombokAnnotations()) {
+ JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, val.class.getName());
+ JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, lombok.experimental.var.class.getName());
+ JavacHandlerUtil.deleteImportFromCompilationUnit(localNode, var.class.getName());
+ }
- local.mods.flags |= Flags.FINAL;
+ if (isVal) local.mods.flags |= Flags.FINAL;
if (!localNode.shouldDeleteLombokAnnotations()) {
- JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), source, localNode.getContext());
+ JCAnnotation valAnnotation = recursiveSetGeneratedBy(localNode.getTreeMaker().Annotation(local.vartype, List.<JCExpression>nil()), typeTree, localNode.getContext());
local.mods.annotations = local.mods.annotations == null ? List.of(valAnnotation) : local.mods.annotations.append(valAnnotation);
}
@@ -101,15 +124,28 @@ public class HandleVal extends JavacASTAdapter {
try {
if (rhsOfEnhancedForLoop == null) {
if (local.init.type == null) {
+ if (isVar && local.init instanceof JCLiteral && ((JCLiteral) local.init).value == null) {
+ localNode.addError("variable initializer is 'null'");
+ }
JavacResolution resolver = new JavacResolution(localNode.getContext());
try {
type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
} catch (RuntimeException e) {
- System.err.println("Exception while resolving: " + localNode);
+ System.err.println("Exception while resolving: " + localNode + "(" + localNode.getFileName() + ")");
throw e;
}
} else {
type = local.init.type;
+ if (type.isErroneous()) {
+ try {
+ JavacResolution resolver = new JavacResolution(localNode.getContext());
+ local.type = Symtab.instance(localNode.getContext()).unknownType;
+ type = ((JCExpression) resolver.resolveMethodMember(localNode).get(local.init)).type;
+ } catch (RuntimeException e) {
+ System.err.println("Exception while resolving: " + localNode + "(" + localNode.getFileName() + ")");
+ throw e;
+ }
+ }
}
} else {
if (rhsOfEnhancedForLoop.type == null) {
@@ -138,14 +174,14 @@ public class HandleVal extends JavacASTAdapter {
}
localNode.getAst().setChanged();
} catch (JavacResolution.TypeNotConvertibleException e) {
- localNode.addError("Cannot use 'val' here because initializer expression does not have a representable type: " + e.getMessage());
+ localNode.addError("Cannot use '" + annotation + "' here because initializer expression does not have a representable type: " + e.getMessage());
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
}
} catch (RuntimeException e) {
local.vartype = JavacResolution.createJavaLangObject(localNode.getAst());
throw e;
} finally {
- recursiveSetGeneratedBy(local.vartype, source, localNode.getContext());
+ recursiveSetGeneratedBy(local.vartype, typeTree, localNode.getContext());
}
}
}
diff --git a/src/core/lombok/javac/handlers/HandleValue.java b/src/core/lombok/javac/handlers/HandleValue.java
index 90f6a98d..d1af4168 100644
--- a/src/core/lombok/javac/handlers/HandleValue.java
+++ b/src/core/lombok/javac/handlers/HandleValue.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2012-2014 The Project Lombok Authors.
+ * Copyright (C) 2012-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
@@ -24,8 +24,6 @@ package lombok.javac.handlers;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.handlers.JavacHandlerUtil.*;
-import java.lang.annotation.Annotation;
-
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.core.AnnotationValues;
@@ -49,13 +47,16 @@ import com.sun.tools.javac.tree.JCTree.JCModifiers;
@ProviderFor(JavacAnnotationHandler.class)
@HandlerPriority(-512) //-2^9; to ensure @EqualsAndHashCode and such pick up on this handler making the class final and messing with the fields' access levels, run earlier.
public class HandleValue extends JavacAnnotationHandler<Value> {
+ private HandleFieldDefaults handleFieldDefaults = new HandleFieldDefaults();
+ private HandleConstructor handleConstructor = new HandleConstructor();
+ private HandleGetter handleGetter = new HandleGetter();
+ private HandleEqualsAndHashCode handleEqualsAndHashCode = new HandleEqualsAndHashCode();
+ private HandleToString handleToString = new HandleToString();
+
@Override public void handle(AnnotationValues<Value> annotation, JCAnnotation ast, JavacNode annotationNode) {
- @SuppressWarnings("deprecation")
- Class<? extends Annotation> oldExperimentalValue = lombok.experimental.Value.class;
-
handleFlagUsage(annotationNode, ConfigurationKeys.VALUE_FLAG_USAGE, "@Value");
- deleteAnnotationIfNeccessary(annotationNode, Value.class, oldExperimentalValue);
+ deleteAnnotationIfNeccessary(annotationNode, Value.class, "lombok.experimental.Value");
JavacNode typeNode = annotationNode.up();
boolean notAClass = !isClass(typeNode);
@@ -73,12 +74,10 @@ public class HandleValue extends JavacAnnotationHandler<Value> {
typeNode.rebuild();
}
}
- new HandleFieldDefaults().generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
-
- // TODO move this to the end OR move it to the top in eclipse.
- new HandleConstructor().generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
- new HandleGetter().generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
- new HandleEqualsAndHashCode().generateEqualsAndHashCodeForType(typeNode, annotationNode);
- new HandleToString().generateToStringForType(typeNode, annotationNode);
+ handleFieldDefaults.generateFieldDefaultsForType(typeNode, annotationNode, AccessLevel.PRIVATE, true, true);
+ handleConstructor.generateAllArgsConstructor(typeNode, AccessLevel.PUBLIC, staticConstructorName, SkipIfConstructorExists.YES, annotationNode);
+ handleGetter.generateGetterForType(typeNode, annotationNode, AccessLevel.PUBLIC, true);
+ handleEqualsAndHashCode.generateEqualsAndHashCodeForType(typeNode, annotationNode);
+ handleToString.generateToStringForType(typeNode, annotationNode);
}
}
diff --git a/src/core/lombok/javac/handlers/HandleWither.java b/src/core/lombok/javac/handlers/HandleWither.java
index 8a7b49b2..987a3d34 100644
--- a/src/core/lombok/javac/handlers/HandleWither.java
+++ b/src/core/lombok/javac/handlers/HandleWither.java
@@ -41,6 +41,8 @@ import lombok.javac.handlers.JavacHandlerUtil.FieldAccess;
import org.mangosdk.spi.ProviderFor;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
import com.sun.tools.javac.tree.JCTree.JCAnnotation;
import com.sun.tools.javac.tree.JCTree.JCBlock;
import com.sun.tools.javac.tree.JCTree.JCClassDecl;
@@ -129,8 +131,8 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
if (level == AccessLevel.NONE || node == null) return;
- List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Setter(onMethod=", annotationNode);
- List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Setter(onParam=", annotationNode);
+ List<JCAnnotation> onMethod = unboxAndRemoveAnnotationParameter(ast, "onMethod", "@Wither(onMethod", annotationNode);
+ List<JCAnnotation> onParam = unboxAndRemoveAnnotationParameter(ast, "onParam", "@Wither(onParam", annotationNode);
switch (node.getKind()) {
case FIELD:
@@ -150,7 +152,10 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
}
}
- public void createWitherForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean whineIfExists, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ public void createWitherForField(AccessLevel level, JavacNode fieldNode, JavacNode source, boolean strictMode, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ JavacNode typeNode = fieldNode.up();
+ boolean makeAbstract = typeNode != null && typeNode.getKind() == Kind.TYPE && (((JCClassDecl) typeNode.get()).mods.flags & Flags.ABSTRACT) != 0;
+
if (fieldNode.getKind() != Kind.FIELD) {
fieldNode.addError("@Wither is only supported on a class or a field.");
return;
@@ -165,17 +170,23 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
}
if ((fieldDecl.mods.flags & Flags.STATIC) != 0) {
- fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for static fields.");
+ if (strictMode) {
+ fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for static fields.");
+ }
return;
}
if ((fieldDecl.mods.flags & Flags.FINAL) != 0 && fieldDecl.init != null) {
- fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for final, initialized fields.");
+ if (strictMode) {
+ fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for final, initialized fields.");
+ }
return;
}
if (fieldDecl.name.toString().startsWith("$")) {
- fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for fields starting with $.");
+ if (strictMode) {
+ fieldNode.addWarning("Not generating wither for this field: Withers cannot be generated for fields starting with $.");
+ }
return;
}
@@ -184,7 +195,7 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
case EXISTS_BY_LOMBOK:
return;
case EXISTS_BY_USER:
- if (whineIfExists) {
+ if (strictMode) {
String altNameExpl = "";
if (!altName.equals(methodName)) altNameExpl = String.format(" (%s)", altName);
fieldNode.addWarning(
@@ -199,63 +210,71 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
long access = toJavacModifier(level);
- JCMethodDecl createdWither = createWither(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, onParam);
- injectMethod(fieldNode.up(), createdWither);
+ JCMethodDecl createdWither = createWither(access, fieldNode, fieldNode.getTreeMaker(), source, onMethod, onParam, makeAbstract);
+ ClassSymbol sym = ((JCClassDecl) fieldNode.up().get()).sym;
+ Type returnType = sym == null ? null : sym.type;
+
+ injectMethod(typeNode, createdWither, List.<Type>of(getMirrorForFieldType(fieldNode)), returnType);
}
- public JCMethodDecl createWither(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam) {
+ public JCMethodDecl createWither(long access, JavacNode field, JavacTreeMaker maker, JavacNode source, List<JCAnnotation> onMethod, List<JCAnnotation> onParam, boolean makeAbstract) {
String witherName = toWitherName(field);
if (witherName == null) return null;
JCVariableDecl fieldDecl = (JCVariableDecl) field.get();
- ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
List<JCAnnotation> nonNulls = findAnnotations(field, NON_NULL_PATTERN);
List<JCAnnotation> nullables = findAnnotations(field, NULLABLE_PATTERN);
Name methodName = field.toName(witherName);
- List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables);
+ JCExpression returnType = cloneSelfType(field);
+
+ JCBlock methodBody = null;
long flags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, field.getContext());
- JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
+ List<JCAnnotation> annsOnParam = copyAnnotations(onParam).appendList(nonNulls).appendList(nullables);
- JCExpression selfType = cloneSelfType(field);
- if (selfType == null) return null;
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(flags, annsOnParam), fieldDecl.name, fieldDecl.vartype, null);
- ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
- for (JavacNode child : field.up().down()) {
- if (child.getKind() != Kind.FIELD) continue;
- JCVariableDecl childDecl = (JCVariableDecl) child.get();
- // Skip fields that start with $
- if (childDecl.name.toString().startsWith("$")) continue;
- long fieldFlags = childDecl.mods.flags;
- // Skip static fields.
- if ((fieldFlags & Flags.STATIC) != 0) continue;
- // Skip initialized final fields.
- if (((fieldFlags & Flags.FINAL) != 0) && childDecl.init != null) continue;
- if (child.get() == field.get()) {
- args.append(maker.Ident(fieldDecl.name));
+ if (!makeAbstract) {
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+
+ JCExpression selfType = cloneSelfType(field);
+ if (selfType == null) return null;
+
+ ListBuffer<JCExpression> args = new ListBuffer<JCExpression>();
+ for (JavacNode child : field.up().down()) {
+ if (child.getKind() != Kind.FIELD) continue;
+ JCVariableDecl childDecl = (JCVariableDecl) child.get();
+ // Skip fields that start with $
+ if (childDecl.name.toString().startsWith("$")) continue;
+ long fieldFlags = childDecl.mods.flags;
+ // Skip static fields.
+ if ((fieldFlags & Flags.STATIC) != 0) continue;
+ // Skip initialized final fields.
+ if (((fieldFlags & Flags.FINAL) != 0) && childDecl.init != null) continue;
+ if (child.get() == field.get()) {
+ args.append(maker.Ident(fieldDecl.name));
+ } else {
+ args.append(createFieldAccessor(maker, child, FieldAccess.ALWAYS_FIELD));
+ }
+ }
+
+ JCNewClass newClass = maker.NewClass(null, List.<JCExpression>nil(), selfType, args.toList(), null);
+ JCExpression identityCheck = maker.Binary(CTC_EQUAL, createFieldAccessor(maker, field, FieldAccess.ALWAYS_FIELD), maker.Ident(fieldDecl.name));
+ JCConditional conditional = maker.Conditional(identityCheck, maker.Ident(field.toName("this")), newClass);
+ JCReturn returnStatement = maker.Return(conditional);
+
+ if (nonNulls.isEmpty()) {
+ statements.append(returnStatement);
} else {
- args.append(createFieldAccessor(maker, child, FieldAccess.ALWAYS_FIELD));
+ JCStatement nullCheck = generateNullCheck(maker, field, source);
+ if (nullCheck != null) statements.append(nullCheck);
+ statements.append(returnStatement);
}
+
+ methodBody = maker.Block(0, statements.toList());
}
-
- JCNewClass newClass = maker.NewClass(null, List.<JCExpression>nil(), selfType, args.toList(), null);
- JCExpression identityCheck = maker.Binary(CTC_EQUAL, createFieldAccessor(maker, field, FieldAccess.ALWAYS_FIELD), maker.Ident(fieldDecl.name));
- JCConditional conditional = maker.Conditional(identityCheck, maker.Ident(field.toName("this")), newClass);
- JCReturn returnStatement = maker.Return(conditional);
-
- if (nonNulls.isEmpty()) {
- statements.append(returnStatement);
- } else {
- JCStatement nullCheck = generateNullCheck(maker, field, source);
- if (nullCheck != null) statements.append(nullCheck);
- statements.append(returnStatement);
- }
-
- JCExpression returnType = cloneSelfType(field);
-
- JCBlock methodBody = maker.Block(0, statements.toList());
List<JCTypeParameter> methodGenericParams = List.nil();
List<JCVariableDecl> parameters = List.of(param);
List<JCExpression> throwsClauses = List.nil();
@@ -266,6 +285,7 @@ public class HandleWither extends JavacAnnotationHandler<Wither> {
if (isFieldDeprecated(field)) {
annsOnMethod = annsOnMethod.prepend(maker.Annotation(genJavaLangTypeRef(field, "Deprecated"), List.<JCExpression>nil()));
}
+ if (makeAbstract) access = access | Flags.ABSTRACT;
JCMethodDecl decl = recursiveSetGeneratedBy(maker.MethodDef(maker.Modifiers(access, annsOnMethod), methodName, returnType,
methodGenericParams, parameters, throwsClauses, methodBody, annotationMethodDefaultValue), source.get(), field.getContext());
copyJavadoc(field, decl, CopyJavadoc.WITHER);
diff --git a/src/core/lombok/javac/handlers/JavacHandlerUtil.java b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
index 6413e8ef..65d09a9a 100644
--- a/src/core/lombok/javac/handlers/JavacHandlerUtil.java
+++ b/src/core/lombok/javac/handlers/JavacHandlerUtil.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 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
@@ -21,11 +21,13 @@
*/
package lombok.javac.handlers;
+import static com.sun.tools.javac.code.Flags.GENERATEDCONSTR;
import static lombok.core.handlers.HandlerUtil.*;
import static lombok.javac.Javac.*;
import static lombok.javac.JavacAugments.JCTree_generatedNode;
import java.lang.annotation.Annotation;
+import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.ArrayList;
@@ -35,12 +37,15 @@ import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import javax.lang.model.element.Element;
+
import lombok.AccessLevel;
import lombok.ConfigurationKeys;
import lombok.Data;
import lombok.Getter;
import lombok.core.AST.Kind;
import lombok.core.AnnotationValues;
+import lombok.core.LombokImmutableList;
import lombok.core.AnnotationValues.AnnotationValue;
import lombok.core.TypeResolver;
import lombok.core.configuration.NullCheckExceptionType;
@@ -54,6 +59,14 @@ import lombok.javac.JavacTreeMaker;
import com.sun.tools.javac.code.BoundKind;
import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Scope;
+import com.sun.tools.javac.code.Symbol;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.code.Type;
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.MethodSymbol;
+import com.sun.tools.javac.code.Symbol.VarSymbol;
+import com.sun.tools.javac.code.Type.MethodType;
import com.sun.tools.javac.parser.Tokens.Comment;
import com.sun.tools.javac.tree.DocCommentTable;
import com.sun.tools.javac.tree.JCTree;
@@ -68,7 +81,6 @@ import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
import com.sun.tools.javac.tree.JCTree.JCIdent;
import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.JCTree.JCLiteral;
import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
import com.sun.tools.javac.tree.JCTree.JCModifiers;
@@ -80,6 +92,7 @@ import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.JCTree.JCWildcard;
import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
+import com.sun.tools.javac.tree.TreeMaker;
import com.sun.tools.javac.tree.TreeScanner;
import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
@@ -149,6 +162,10 @@ public class JavacHandlerUtil {
return node;
}
+ public static boolean hasAnnotation(String type, JavacNode node) {
+ return hasAnnotation(type, node, false);
+ }
+
public static boolean hasAnnotation(Class<? extends Annotation> type, JavacNode node) {
return hasAnnotation(type, node, false);
}
@@ -178,6 +195,48 @@ public class JavacHandlerUtil {
}
}
+ private static boolean hasAnnotation(String type, JavacNode node, boolean delete) {
+ if (node == null) return false;
+ if (type == null) return false;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (JavacNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) {
+ if (delete) deleteAnnotationIfNeccessary(child, type);
+ return true;
+ }
+ }
+ // intentional fallthrough
+ default:
+ return false;
+ }
+ }
+
+ static JavacNode findAnnotation(Class<? extends Annotation> type, JavacNode node, boolean delete) {
+ if (node == null) return null;
+ if (type == null) return null;
+ switch (node.getKind()) {
+ case ARGUMENT:
+ case FIELD:
+ case LOCAL:
+ case TYPE:
+ case METHOD:
+ for (JavacNode child : node.down()) {
+ if (annotationTypeMatches(type, child)) {
+ if (delete) deleteAnnotationIfNeccessary(child, type);
+ return child;
+ }
+ }
+ // intentional fallthrough
+ default:
+ return null;
+ }
+ }
+
/**
* Checks if the Annotation AST Node provided is likely to be an instance of the provided annotation type.
*
@@ -190,6 +249,17 @@ public class JavacHandlerUtil {
}
/**
+ * Checks if the Annotation AST Node provided is likely to be an instance of the provided annotation type.
+ *
+ * @param type An actual annotation type, such as {@code lombok.Getter.class}.
+ * @param node A Lombok AST node representing an annotation in source code.
+ */
+ public static boolean annotationTypeMatches(String type, JavacNode node) {
+ if (node.getKind() != Kind.ANNOTATION) return false;
+ return typeMatches(type, node, ((JCAnnotation)node.get()).annotationType);
+ }
+
+ /**
* Checks if the given TypeReference node is likely to be a reference to the provided class.
*
* @param type An actual type. This method checks if {@code typeNode} is likely to be a reference to this type.
@@ -197,10 +267,21 @@ public class JavacHandlerUtil {
* @param typeNode A type reference to check.
*/
public static boolean typeMatches(Class<?> type, JavacNode node, JCTree typeNode) {
+ return typeMatches(type.getName(), node, typeNode);
+ }
+
+ /**
+ * Checks if the given TypeReference node is likely to be a reference to the provided class.
+ *
+ * @param type An actual type. This method checks if {@code typeNode} is likely to be a reference to this type.
+ * @param node A Lombok AST node. Any node in the appropriate compilation unit will do (used to get access to import statements).
+ * @param typeNode A type reference to check.
+ */
+ public static boolean typeMatches(String type, JavacNode node, JCTree typeNode) {
String typeName = typeNode.toString();
TypeResolver resolver = new TypeResolver(node.getImportList());
- return resolver.typeMatches(node, type.getName(), typeName);
+ return resolver.typeMatches(node, type, typeName);
}
/**
@@ -209,6 +290,7 @@ public class JavacHandlerUtil {
* @return {@code true} if a field is marked deprecated, either by {@code @Deprecated} or in javadoc, otherwise {@code false}
*/
public static boolean isFieldDeprecated(JavacNode field) {
+ if (!(field.get() instanceof JCVariableDecl)) return false;
JCVariableDecl fieldNode = (JCVariableDecl) field.get();
if ((fieldNode.mods.flags & Flags.DEPRECATED) != 0) {
return true;
@@ -242,51 +324,45 @@ public class JavacHandlerUtil {
Map<String, AnnotationValue> values = new HashMap<String, AnnotationValue>();
JCAnnotation anno = (JCAnnotation) node.get();
List<JCExpression> arguments = anno.getArguments();
- for (Method m : type.getDeclaredMethods()) {
- if (!Modifier.isPublic(m.getModifiers())) continue;
- String name = m.getName();
+
+ for (JCExpression arg : arguments) {
+ String mName;
+ JCExpression rhs;
java.util.List<String> raws = new ArrayList<String>();
java.util.List<Object> guesses = new ArrayList<Object>();
java.util.List<Object> expressions = new ArrayList<Object>();
final java.util.List<DiagnosticPosition> positions = new ArrayList<DiagnosticPosition>();
- boolean isExplicit = false;
- for (JCExpression arg : arguments) {
- String mName;
- JCExpression rhs;
-
- if (arg instanceof JCAssign) {
- JCAssign assign = (JCAssign) arg;
- mName = assign.lhs.toString();
- rhs = assign.rhs;
- } else {
- rhs = arg;
- mName = "value";
- }
-
- if (!mName.equals(name)) continue;
- isExplicit = true;
- if (rhs instanceof JCNewArray) {
- List<JCExpression> elems = ((JCNewArray)rhs).elems;
- for (JCExpression inner : elems) {
- raws.add(inner.toString());
- expressions.add(inner);
- guesses.add(calculateGuess(inner));
- positions.add(inner.pos());
- }
- } else {
- raws.add(rhs.toString());
- expressions.add(rhs);
- guesses.add(calculateGuess(rhs));
- positions.add(rhs.pos());
+ if (arg instanceof JCAssign) {
+ JCAssign assign = (JCAssign) arg;
+ mName = assign.lhs.toString();
+ rhs = assign.rhs;
+ } else {
+ rhs = arg;
+ mName = "value";
+ }
+
+ if (rhs instanceof JCNewArray) {
+ List<JCExpression> elems = ((JCNewArray)rhs).elems;
+ for (JCExpression inner : elems) {
+ raws.add(inner.toString());
+ expressions.add(inner);
+ guesses.add(calculateGuess(inner));
+ positions.add(inner.pos());
}
+ } else {
+ raws.add(rhs.toString());
+ expressions.add(rhs);
+ guesses.add(calculateGuess(rhs));
+ positions.add(rhs.pos());
}
- values.put(name, new AnnotationValue(node, raws, expressions, guesses, isExplicit) {
+ values.put(mName, new AnnotationValue(node, raws, expressions, guesses, true) {
@Override public void setError(String message, int valueIdx) {
if (valueIdx < 0) node.addError(message);
else node.addError(message, positions.get(valueIdx));
}
+
@Override public void setWarning(String message, int valueIdx) {
if (valueIdx < 0) node.addWarning(message);
else node.addWarning(message, positions.get(valueIdx));
@@ -294,6 +370,21 @@ public class JavacHandlerUtil {
});
}
+ for (Method m : type.getDeclaredMethods()) {
+ if (!Modifier.isPublic(m.getModifiers())) continue;
+ String name = m.getName();
+ if (!values.containsKey(name)) {
+ values.put(name, new AnnotationValue(node, new ArrayList<String>(), new ArrayList<Object>(), new ArrayList<Object>(), false) {
+ @Override public void setError(String message, int valueIdx) {
+ node.addError(message);
+ }
+ @Override public void setWarning(String message, int valueIdx) {
+ node.addWarning(message);
+ }
+ });
+ }
+ }
+
return new AnnotationValues<A>(type, values, node);
}
@@ -302,8 +393,7 @@ public class JavacHandlerUtil {
* then removes any import statement that imports this exact annotation (not star imports).
* Only does this if the DeleteLombokAnnotations class is in the context.
*/
- @SuppressWarnings("unchecked")
- public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? extends Annotation> annotationType) {
+ public static void deleteAnnotationIfNeccessary(JavacNode annotation, String annotationType) {
deleteAnnotationIfNeccessary0(annotation, annotationType);
}
@@ -312,12 +402,29 @@ public class JavacHandlerUtil {
* then removes any import statement that imports this exact annotation (not star imports).
* Only does this if the DeleteLombokAnnotations class is in the context.
*/
- @SuppressWarnings("unchecked")
+ public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? extends Annotation> annotationType) {
+ deleteAnnotationIfNeccessary0(annotation, annotationType.getName());
+ }
+
+ /**
+ * Removes the annotation from javac's AST (it remains in lombok's AST),
+ * then removes any import statement that imports this exact annotation (not star imports).
+ * Only does this if the DeleteLombokAnnotations class is in the context.
+ */
public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? extends Annotation> annotationType1, Class<? extends Annotation> annotationType2) {
- deleteAnnotationIfNeccessary0(annotation, annotationType1, annotationType2);
+ deleteAnnotationIfNeccessary0(annotation, annotationType1.getName(), annotationType2.getName());
}
- private static void deleteAnnotationIfNeccessary0(JavacNode annotation, Class<? extends Annotation>... annotationTypes) {
+ /**
+ * Removes the annotation from javac's AST (it remains in lombok's AST),
+ * then removes any import statement that imports this exact annotation (not star imports).
+ * Only does this if the DeleteLombokAnnotations class is in the context.
+ */
+ public static void deleteAnnotationIfNeccessary(JavacNode annotation, Class<? extends Annotation> annotationType1, String annotationType2) {
+ deleteAnnotationIfNeccessary0(annotation, annotationType1.getName(), annotationType2);
+ }
+
+ private static void deleteAnnotationIfNeccessary0(JavacNode annotation, String... annotationTypes) {
if (inNetbeansEditor(annotation)) return;
if (!annotation.shouldDeleteLombokAnnotations()) return;
JavacNode parentNode = annotation.directUp();
@@ -346,8 +453,8 @@ public class JavacHandlerUtil {
}
parentNode.getAst().setChanged();
- for (Class<?> annotationType : annotationTypes) {
- deleteImportFromCompilationUnit(annotation, annotationType.getName());
+ for (String annotationType : annotationTypes) {
+ deleteImportFromCompilationUnit(annotation, annotationType);
}
}
@@ -445,9 +552,9 @@ public class JavacHandlerUtil {
return HandlerUtil.shouldReturnThis0(accessors, field.getAst());
}
- public static JCExpression cloneSelfType(JavacNode field) {
- JavacNode typeNode = field;
- JavacTreeMaker maker = field.getTreeMaker();
+ public static JCExpression cloneSelfType(JavacNode childOfType) {
+ JavacNode typeNode = childOfType;
+ JavacTreeMaker maker = childOfType.getTreeMaker();
while (typeNode != null && typeNode.getKind() != Kind.TYPE) typeNode = typeNode.up();
if (typeNode != null && typeNode.get() instanceof JCClassDecl) {
JCClassDecl type = (JCClassDecl) typeNode.get();
@@ -591,10 +698,7 @@ public class JavacHandlerUtil {
if (params < minArgs || params > maxArgs) continue;
}
- List<JCAnnotation> annotations = md.getModifiers().getAnnotations();
- if (annotations != null) for (JCAnnotation anno : annotations) {
- if (typeMatches(Tolerate.class, node, anno.getAnnotationType())) continue top;
- }
+ if (isTolerate(node, md)) continue top;
return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
@@ -605,6 +709,14 @@ public class JavacHandlerUtil {
return MemberExistsResult.NOT_EXISTS;
}
+ public static boolean isTolerate(JavacNode node, JCTree.JCMethodDecl md) {
+ List<JCAnnotation> annotations = md.getModifiers().getAnnotations();
+ if (annotations != null) for (JCTree.JCAnnotation anno : annotations) {
+ if (typeMatches(Tolerate.class, node, anno.getAnnotationType())) return true;
+ }
+ return false;
+ }
+
/**
* Checks if there is a (non-default) constructor. In case of multiple constructors (overloading), only
* the first constructor decides if EXISTS_BY_USER or EXISTS_BY_LOMBOK is returned.
@@ -615,15 +727,12 @@ public class JavacHandlerUtil {
node = upToTypeNode(node);
if (node != null && node.get() instanceof JCClassDecl) {
- top: for (JCTree def : ((JCClassDecl)node.get()).defs) {
+ for (JCTree def : ((JCClassDecl)node.get()).defs) {
if (def instanceof JCMethodDecl) {
JCMethodDecl md = (JCMethodDecl) def;
if (md.name.contentEquals("<init>")) {
if ((md.mods.flags & Flags.GENERATEDCONSTR) != 0) continue;
- List<JCAnnotation> annotations = md.getModifiers().getAnnotations();
- if (annotations != null) for (JCAnnotation anno : annotations) {
- if (typeMatches(Tolerate.class, node, anno.getAnnotationType())) continue top;
- }
+ if (isTolerate(node, md)) continue;
return getGeneratedBy(def) == null ? MemberExistsResult.EXISTS_BY_USER : MemberExistsResult.EXISTS_BY_LOMBOK;
}
}
@@ -709,7 +818,7 @@ public class JavacHandlerUtil {
// Check if the class has a @Getter annotation.
- if (!hasGetterAnnotation && new HandleGetter().fieldQualifiesForGetterGeneration(field)) {
+ if (!hasGetterAnnotation && HandleGetter.fieldQualifiesForGetterGeneration(field)) {
//Check if the class has @Getter or @Data annotation.
JavacNode containingType = field.up();
@@ -803,13 +912,19 @@ public class JavacHandlerUtil {
return call;
}
+ public static Type getMirrorForFieldType(JavacNode fieldNode) {
+ Element fieldElement = fieldNode.getElement();
+ if (fieldElement instanceof VarSymbol) return ((VarSymbol) fieldElement).type;
+ return null;
+ }
+
/**
* Adds the given new field declaration to the provided type AST Node.
* The field carries the &#64;{@link SuppressWarnings}("all") annotation.
* Also takes care of updating the JavacAST.
*/
- public static void injectFieldSuppressWarnings(JavacNode typeNode, JCVariableDecl field) {
- injectField(typeNode, field, true);
+ public static JavacNode injectFieldAndMarkGenerated(JavacNode typeNode, JCVariableDecl field) {
+ return injectField(typeNode, field, true);
}
/**
@@ -821,21 +936,28 @@ public class JavacHandlerUtil {
return injectField(typeNode, field, false);
}
- private static JavacNode injectField(JavacNode typeNode, JCVariableDecl field, boolean addSuppressWarnings) {
+ private static JavacNode injectField(JavacNode typeNode, JCVariableDecl field, boolean addGenerated) {
JCClassDecl type = (JCClassDecl) typeNode.get();
- if (addSuppressWarnings) addSuppressWarningsAll(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext());
+ if (addGenerated) {
+ addSuppressWarningsAll(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext());
+ addGenerated(field.mods, typeNode, field.pos, getGeneratedBy(field), typeNode.getContext());
+ }
List<JCTree> insertAfter = null;
List<JCTree> insertBefore = type.defs;
- while (insertBefore.tail != null) {
+ while (true) {
+ boolean skip = false;
if (insertBefore.head instanceof JCVariableDecl) {
JCVariableDecl f = (JCVariableDecl) insertBefore.head;
- if (isEnumConstant(f) || isGenerated(f)) {
- insertAfter = insertBefore;
- insertBefore = insertBefore.tail;
- continue;
- }
+ if (isEnumConstant(f) || isGenerated(f)) skip = true;
+ } else if (insertBefore.head instanceof JCMethodDecl) {
+ if ((((JCMethodDecl) insertBefore.head).mods.flags & GENERATEDCONSTR) != 0) skip = true;
+ }
+ if (skip) {
+ insertAfter = insertBefore;
+ insertBefore = insertBefore.tail;
+ continue;
}
break;
}
@@ -854,13 +976,56 @@ public class JavacHandlerUtil {
return (field.mods.flags & Flags.ENUM) != 0;
}
+ // jdk9 support, types have changed, names stay the same
+ static class ClassSymbolMembersField {
+ private static final Field membersField;
+ private static final Method removeMethod;
+ private static final Method enterMethod;
+
+ static {
+ Field f = null;
+ Method r = null;
+ Method e = null;
+ try {
+ f = ClassSymbol.class.getField("members_field");
+ r = f.getType().getMethod("remove", Symbol.class);
+ e = f.getType().getMethod("enter", Symbol.class);
+ } catch (Exception ex) {}
+ membersField = f;
+ removeMethod = r;
+ enterMethod = e;
+ }
+
+ static void remove(ClassSymbol from, Symbol toRemove) {
+ if (from == null) return;
+ try {
+ Scope scope = (Scope) membersField.get(from);
+ if (scope == null) return;
+ removeMethod.invoke(scope, toRemove);
+ } catch (Exception e) {}
+ }
+
+ static void enter(ClassSymbol from, Symbol toEnter) {
+ if (from == null) return;
+ try {
+ Scope scope = (Scope) membersField.get(from);
+ if (scope == null) return;
+ enterMethod.invoke(scope, toEnter);
+ } catch (Exception e) {}
+ }
+ }
+
+ public static void injectMethod(JavacNode typeNode, JCMethodDecl method) {
+ injectMethod(typeNode, method, null, null);
+ }
+
/**
* Adds the given new method declaration to the provided type AST Node.
* Can also inject constructors.
*
* Also takes care of updating the JavacAST.
*/
- public static void injectMethod(JavacNode typeNode, JCMethodDecl method) {
+ public static void injectMethod(JavacNode typeNode, JCMethodDecl method, List<Type> paramTypes, Type returnType) {
JCClassDecl type = (JCClassDecl) typeNode.get();
if (method.getName().contentEquals("<init>")) {
@@ -868,13 +1033,11 @@ public class JavacHandlerUtil {
int idx = 0;
for (JCTree def : type.defs) {
if (def instanceof JCMethodDecl) {
- if ((((JCMethodDecl)def).mods.flags & Flags.GENERATEDCONSTR) != 0) {
+ if ((((JCMethodDecl) def).mods.flags & Flags.GENERATEDCONSTR) != 0) {
JavacNode tossMe = typeNode.getNodeFor(def);
if (tossMe != null) tossMe.up().removeChild(tossMe);
type.defs = addAllButOne(type.defs, idx);
- if (type.sym != null && type.sym.members_field != null) {
- type.sym.members_field.remove(((JCMethodDecl)def).sym);
- }
+ ClassSymbolMembersField.remove(type.sym, ((JCMethodDecl)def).sym);
break;
}
}
@@ -883,11 +1046,21 @@ public class JavacHandlerUtil {
}
addSuppressWarningsAll(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
+ addGenerated(method.mods, typeNode, method.pos, getGeneratedBy(method), typeNode.getContext());
type.defs = type.defs.append(method);
+ fixMethodMirror(typeNode.getContext(), typeNode.getElement(), method.getModifiers().flags, method.getName(), paramTypes, returnType);
+
typeNode.add(method, Kind.METHOD);
}
+ private static void fixMethodMirror(Context context, Element typeMirror, long access, Name methodName, List<Type> paramTypes, Type returnType) {
+ if (typeMirror == null || paramTypes == null || returnType == null) return;
+ ClassSymbol cs = (ClassSymbol) typeMirror;
+ MethodSymbol methodSymbol = new MethodSymbol(access, methodName, new MethodType(paramTypes, returnType, List.<Type>nil(), Symtab.instance(context).methodClass), cs);
+ ClassSymbolMembersField.enter(cs, methodSymbol);
+ }
+
/**
* Adds an inner type (class, interface, enum) to the given type. Cannot inject top-level types.
*
@@ -898,6 +1071,7 @@ public class JavacHandlerUtil {
public static JavacNode injectType(JavacNode typeNode, final JCClassDecl type) {
JCClassDecl typeDecl = (JCClassDecl) typeNode.get();
addSuppressWarningsAll(type.mods, typeNode, type.pos, getGeneratedBy(type), typeNode.getContext());
+ addGenerated(type.mods, typeNode, type.pos, getGeneratedBy(type), typeNode.getContext());
typeDecl.defs = typeDecl.defs.append(type);
return typeNode.add(type, Kind.TYPE);
}
@@ -938,20 +1112,59 @@ public class JavacHandlerUtil {
public static void addSuppressWarningsAll(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) {
if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateSuppressWarnings()) return;
+ addAnnotation(mods, node, pos, source, context, "java.lang.SuppressWarnings", node.getTreeMaker().Literal("all"));
+
+ if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_FINDBUGS_SUPPRESSWARNINGS_ANNOTATIONS))) {
+ JavacTreeMaker maker = node.getTreeMaker();
+ JCExpression arg = maker.Assign(maker.Ident(node.toName("justification")), maker.Literal("generated code"));
+ addAnnotation(mods, node, pos, source, context, "edu.umd.cs.findbugs.annotations.SuppressFBWarnings", arg);
+ }
+ }
+
+ public static void addGenerated(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context) {
+ if (!LombokOptionsFactory.getDelombokOptions(context).getFormatPreferences().generateGenerated()) return;
+
+ if (HandlerUtil.shouldAddGenerated(node)) {
+ addAnnotation(mods, node, pos, source, context, "javax.annotation.Generated", node.getTreeMaker().Literal("lombok"));
+ }
+ if (Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.ADD_LOMBOK_GENERATED_ANNOTATIONS))) {
+ addAnnotation(mods, node, pos, source, context, "lombok.Generated", null);
+ }
+ }
+
+ private static void addAnnotation(JCModifiers mods, JavacNode node, int pos, JCTree source, Context context, String annotationTypeFqn, JCExpression arg) {
+ boolean isJavaLangBased;
+ String simpleName; {
+ int idx = annotationTypeFqn.lastIndexOf('.');
+ simpleName = idx == -1 ? annotationTypeFqn : annotationTypeFqn.substring(idx + 1);
+
+ isJavaLangBased = idx == 9 && annotationTypeFqn.regionMatches(0, "java.lang.", 0, 10);
+ }
+
for (JCAnnotation ann : mods.annotations) {
JCTree annType = ann.getAnnotationType();
- Name lastPart = null;
- if (annType instanceof JCIdent) lastPart = ((JCIdent) annType).name;
- else if (annType instanceof JCFieldAccess) lastPart = ((JCFieldAccess) annType).name;
+ if (annType instanceof JCIdent) {
+ Name lastPart = ((JCIdent) annType).name;
+ if (lastPart.contentEquals(simpleName)) return;
+ }
- if (lastPart != null && lastPart.contentEquals("SuppressWarnings")) return;
+ if (annType instanceof JCFieldAccess) {
+ if (annType.toString().equals(annotationTypeFqn)) return;
+ }
}
+
JavacTreeMaker maker = node.getTreeMaker();
- JCExpression suppressWarningsType = genJavaLangTypeRef(node, "SuppressWarnings");
- JCLiteral allLiteral = maker.Literal("all");
- suppressWarningsType.pos = pos;
- allLiteral.pos = pos;
- JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(suppressWarningsType, List.<JCExpression>of(allLiteral)), source, context);
+ JCExpression annType = isJavaLangBased ? genJavaLangTypeRef(node, simpleName) : chainDotsString(node, annotationTypeFqn);
+ annType.pos = pos;
+ if (arg != null) {
+ arg.pos = pos;
+ if (arg instanceof JCAssign) {
+ ((JCAssign) arg).lhs.pos = pos;
+ ((JCAssign) arg).rhs.pos = pos;
+ }
+ }
+ List<JCExpression> argList = arg != null ? List.of(arg) : List.<JCExpression>nil();
+ JCAnnotation annotation = recursiveSetGeneratedBy(maker.Annotation(annType, argList), source, context);
annotation.pos = pos;
mods.annotations = mods.annotations.append(annotation);
}
@@ -985,6 +1198,17 @@ public class JavacHandlerUtil {
return chainDots(node, -1, null, null, elems);
}
+ public static JCExpression chainDots(JavacNode node, LombokImmutableList<String> elems) {
+ assert elems != null;
+
+ JavacTreeMaker maker = node.getTreeMaker();
+ JCExpression e = null;
+ for (String elem : elems) {
+ if (e == null) e = maker.Ident(node.toName(elem));
+ else e = maker.Select(e, node.toName(elem));
+ }
+ return e;
+ }
/**
* In javac, dotted access of any kind, from {@code java.lang.String} to {@code var.methodName}
* is represented by a fold-left of {@code Select} nodes with the leftmost string represented by
@@ -1013,7 +1237,6 @@ public class JavacHandlerUtil {
return e;
}
-
/**
* In javac, dotted access of any kind, from {@code java.lang.String} to {@code var.methodName}
@@ -1051,16 +1274,25 @@ public class JavacHandlerUtil {
}
/**
- * Generates a new statement that checks if the given variable is null, and if so, throws a specified exception with the
+ * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the
* variable name as message.
- *
- * @param exName The name of the exception to throw; normally {@code java.lang.NullPointerException}.
*/
public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JavacNode source) {
+ return generateNullCheck(maker, variable, (JCVariableDecl)variable.get(), source);
+ }
+
+ /**
+ * Generates a new statement that checks if the given variable is null, and if so, throws a configured exception with the
+ * variable name as message.
+ *
+ * This is a special case method reserved for use when the provided declaration differs from the
+ * variable's declaration, i.e. in a constructor or setter where the local parameter is named the same but with the prefix
+ * stripped as a result of @Accessors.prefix.
+ */
+ public static JCStatement generateNullCheck(JavacTreeMaker maker, JavacNode variable, JCVariableDecl varDecl, JavacNode source) {
NullCheckExceptionType exceptionType = source.getAst().readConfiguration(ConfigurationKeys.NON_NULL_EXCEPTION_TYPE);
if (exceptionType == null) exceptionType = NullCheckExceptionType.NULL_POINTER_EXCEPTION;
- JCVariableDecl varDecl = (JCVariableDecl) variable.get();
if (isPrimitive(varDecl.vartype)) return null;
Name fieldName = varDecl.name;
JCExpression exType = genTypeRef(variable, exceptionType.getExceptionType());
@@ -1102,19 +1334,9 @@ public class JavacHandlerUtil {
ListBuffer<JCExpression> params = new ListBuffer<JCExpression>();
ListBuffer<JCAnnotation> result = new ListBuffer<JCAnnotation>();
- try {
- for (JCExpression arg : ast.args) {
- String argName = "value";
- if (arg instanceof JCAssign) {
- JCAssign as = (JCAssign) arg;
- argName = as.lhs.toString();
- }
- if (!argName.equals(parameterName)) continue;
- }
- } catch (Exception ignore) {}
-
outer:
for (JCExpression param : ast.args) {
+ boolean allowRaw;
String nameOfParam = "value";
JCExpression valueOfParam = null;
if (param instanceof JCAssign) {
@@ -1126,6 +1348,15 @@ public class JavacHandlerUtil {
valueOfParam = assign.rhs;
}
+ /* strip trailing underscores */ {
+ int lastIdx;
+ for (lastIdx = nameOfParam.length() ; lastIdx > 0; lastIdx--) {
+ if (nameOfParam.charAt(lastIdx - 1) != '_') break;
+ }
+ allowRaw = lastIdx < nameOfParam.length();
+ nameOfParam = nameOfParam.substring(0, lastIdx);
+ }
+
if (!parameterName.equals(nameOfParam)) {
params.append(param);
continue outer;
@@ -1138,75 +1369,109 @@ public class JavacHandlerUtil {
String dummyAnnotationName = ((JCAnnotation) valueOfParam).annotationType.toString();
dummyAnnotationName = dummyAnnotationName.replace("_", "").replace("$", "").replace("x", "").replace("X", "");
if (dummyAnnotationName.length() > 0) {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
- }
- for (JCExpression expr : ((JCAnnotation) valueOfParam).args) {
- if (expr instanceof JCAssign && ((JCAssign) expr).lhs instanceof JCIdent) {
- JCIdent id = (JCIdent) ((JCAssign) expr).lhs;
- if ("value".equals(id.name.toString())) {
- expr = ((JCAssign) expr).rhs;
- } else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
- }
+ if (allowRaw) {
+ result.append((JCAnnotation) valueOfParam);
+ } else {
+ addError(errorName, annotationNode);
+ continue outer;
}
-
- if (expr instanceof JCAnnotation) {
- result.append((JCAnnotation) expr);
- } else if (expr instanceof JCNewArray) {
- for (JCExpression expr2 : ((JCNewArray) expr).elems) {
- if (expr2 instanceof JCAnnotation) {
- result.append((JCAnnotation) expr2);
+ } else {
+ for (JCExpression expr : ((JCAnnotation) valueOfParam).args) {
+ if (expr instanceof JCAssign && ((JCAssign) expr).lhs instanceof JCIdent) {
+ JCIdent id = (JCIdent) ((JCAssign) expr).lhs;
+ if ("value".equals(id.name.toString())) {
+ expr = ((JCAssign) expr).rhs;
} else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
+ addError(errorName, annotationNode);
}
}
- } else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
- continue outer;
+
+ if (expr instanceof JCAnnotation) {
+ result.append((JCAnnotation) expr);
+ } else if (expr instanceof JCNewArray) {
+ for (JCExpression expr2 : ((JCNewArray) expr).elems) {
+ if (expr2 instanceof JCAnnotation) {
+ result.append((JCAnnotation) expr2);
+ } else {
+ addError(errorName, annotationNode);
+ continue outer;
+ }
+ }
+ } else {
+ addError(errorName, annotationNode);
+ continue outer;
+ }
}
}
- } else {
- if (valueOfParam instanceof JCNewArray && ((JCNewArray) valueOfParam).elems.isEmpty()) {
- // Then we just remove it and move on (it's onMethod={} for example).
+ } else if (valueOfParam instanceof JCNewArray) {
+ JCNewArray arr = (JCNewArray) valueOfParam;
+ if (arr.elems.isEmpty()) {
+ // Just remove it, this is always fine.
+ } else if (allowRaw) {
+ for (JCExpression jce : arr.elems) {
+ if (jce instanceof JCAnnotation) result.append((JCAnnotation) jce);
+ else addError(errorName, annotationNode);
+ }
} else {
- annotationNode.addError("The correct format is " + errorName + "@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ addError(errorName, annotationNode);
}
+ } else {
+ addError(errorName, annotationNode);
}
}
ast.args = params.toList();
return result.toList();
}
- public static List<JCTypeParameter> copyTypeParams(JavacTreeMaker maker, List<JCTypeParameter> params) {
+ private static void addError(String errorName, JavacNode node) {
+ if (node.getLatestJavaSpecSupported() < 8) {
+ node.addError("The correct format up to JDK7 is " + errorName + "=@__({@SomeAnnotation, @SomeOtherAnnotation}))");
+ } else {
+ node.addError("The correct format for JDK8+ is " + errorName + "_={@SomeAnnotation, @SomeOtherAnnotation})");
+ }
+ }
+
+ public static List<JCTypeParameter> copyTypeParams(JavacNode source, List<JCTypeParameter> params) {
if (params == null || params.isEmpty()) return params;
ListBuffer<JCTypeParameter> out = new ListBuffer<JCTypeParameter>();
- for (JCTypeParameter tp : params) out.append(maker.TypeParameter(tp.name, tp.bounds));
+ JavacTreeMaker maker = source.getTreeMaker();
+ Context context = source.getContext();
+ for (JCTypeParameter tp : params) {
+ List<JCExpression> bounds = tp.bounds;
+ if (bounds != null && !bounds.isEmpty()) {
+ ListBuffer<JCExpression> boundsCopy = new ListBuffer<JCExpression>();
+ for (JCExpression expr : tp.bounds) {
+ boundsCopy.append(cloneType(maker, expr, source.get(), context));
+ }
+ bounds = boundsCopy.toList();
+ }
+ out.append(maker.TypeParameter(tp.name, bounds));
+ }
return out.toList();
}
public static JCExpression namePlusTypeParamsToTypeReference(JavacTreeMaker maker, Name typeName, List<JCTypeParameter> params) {
+ if (params.isEmpty()) {
+ return maker.Ident(typeName);
+ }
+ return maker.TypeApply(maker.Ident(typeName), typeParameterNames(maker, params));
+ }
+
+ public static List<JCExpression> typeParameterNames(JavacTreeMaker maker, List<JCTypeParameter> params) {
ListBuffer<JCExpression> typeArgs = new ListBuffer<JCExpression>();
-
- if (!params.isEmpty()) {
- for (JCTypeParameter param : params) {
- typeArgs.append(maker.Ident(param.name));
- }
-
- return maker.TypeApply(maker.Ident(typeName), typeArgs.toList());
+ for (JCTypeParameter param : params) {
+ typeArgs.append(maker.Ident(param.name));
}
-
- return maker.Ident(typeName);
+ return typeArgs.toList();
}
public static void sanityCheckForMethodGeneratingAnnotationsOnBuilderClass(JavacNode typeNode, JavacNode errorNode) {
List<String> disallowed = List.nil();
for (JavacNode child : typeNode.down()) {
- for (Class<? extends java.lang.annotation.Annotation> annType : INVALID_ON_BUILDERS) {
+ for (String annType : INVALID_ON_BUILDERS) {
if (annotationTypeMatches(annType, child)) {
- disallowed = disallowed.append(annType.getSimpleName());
+ int lastIndex = annType.lastIndexOf('.');
+ disallowed = disallowed.append(lastIndex == -1 ? annType : annType.substring(lastIndex + 1));
}
}
}
@@ -1429,6 +1694,18 @@ public class JavacHandlerUtil {
} catch (Exception ignore) {}
}
+ private static final Pattern FIND_RETURN = Pattern.compile("^\\s*\\**\\s*@returns?\\s+.*$", Pattern.MULTILINE | Pattern.CASE_INSENSITIVE);
+ static String addReturnsThisIfNeeded(String in) {
+ if (FIND_RETURN.matcher(in).find()) return in;
+
+ return addJavadocLine(in, "@return this");
+ }
+
+ static String addJavadocLine(String in, String line) {
+ if (in.endsWith("\n")) return in + line + "\n";
+ return in + "\n" + line;
+ }
+
private static class CopyJavadoc_8 {
static void copyJavadoc(JavacNode from, JCTree to, CopyJavadoc copyMode, Object dc) {
DocCommentTable dct = (DocCommentTable) dc;
@@ -1436,6 +1713,9 @@ public class JavacHandlerUtil {
if (javadoc != null) {
String[] filtered = copyMode.split(javadoc.getText());
+ if (copyMode == CopyJavadoc.SETTER && shouldReturnThis(from)) {
+ filtered[0] = addReturnsThisIfNeeded(filtered[0]);
+ }
dct.putComment(to, createJavadocComment(filtered[0], from));
dct.putComment(from.get(), createJavadocComment(filtered[1], from));
}
@@ -1469,6 +1749,9 @@ public class JavacHandlerUtil {
if (javadoc != null) {
String[] filtered = copyMode.split(javadoc);
+ if (copyMode == CopyJavadoc.SETTER && shouldReturnThis(from)) {
+ filtered[0] = addReturnsThisIfNeeded(filtered[0]);
+ }
docComments.put(to, filtered[0]);
docComments.put(from.get(), filtered[1]);
}
diff --git a/src/core/lombok/javac/handlers/JavacSingularsRecipes.java b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
new file mode 100644
index 00000000..6a76e1dd
--- /dev/null
+++ b/src/core/lombok/javac/handlers/JavacSingularsRecipes.java
@@ -0,0 +1,310 @@
+/*
+ * Copyright (C) 2015-2017 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.javac.handlers;
+
+import static lombok.javac.Javac.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import lombok.core.LombokImmutableList;
+import lombok.core.SpiLoadUtil;
+import lombok.core.TypeLibrary;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+
+import com.sun.source.tree.Tree.Kind;
+import com.sun.tools.javac.code.BoundKind;
+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.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.JCVariableDecl;
+import com.sun.tools.javac.tree.JCTree.JCWildcard;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+public class JavacSingularsRecipes {
+ private static final JavacSingularsRecipes INSTANCE = new JavacSingularsRecipes();
+ private final Map<String, JavacSingularizer> singularizers = new HashMap<String, JavacSingularizer>();
+ private final TypeLibrary singularizableTypes = new TypeLibrary();
+
+ private JavacSingularsRecipes() {
+ try {
+ loadAll(singularizableTypes, singularizers);
+ singularizableTypes.lock();
+ } catch (IOException e) {
+ System.err.println("Lombok's @Singularizable feature is broken due to misconfigured SPI files: " + e);
+ }
+ }
+
+ private static void loadAll(TypeLibrary library, Map<String, JavacSingularizer> map) throws IOException {
+ for (JavacSingularizer handler : SpiLoadUtil.findServices(JavacSingularizer.class, JavacSingularizer.class.getClassLoader())) {
+ for (String type : handler.getSupportedTypes()) {
+ JavacSingularizer existingSingularizer = map.get(type);
+ if (existingSingularizer != null) {
+ JavacSingularizer toKeep = existingSingularizer.getClass().getName().compareTo(handler.getClass().getName()) > 0 ? handler : existingSingularizer;
+ System.err.println("Multiple singularizers found for type " + type + "; the alphabetically first class is used: " + toKeep.getClass().getName());
+ map.put(type, toKeep);
+ } else {
+ map.put(type, handler);
+ library.addType(type);
+ }
+ }
+ }
+ }
+
+ public static JavacSingularsRecipes get() {
+ return INSTANCE;
+ }
+
+ public String toQualified(String typeReference) {
+ return singularizableTypes.toQualified(typeReference);
+ }
+
+ public JavacSingularizer getSingularizer(String fqn) {
+ return singularizers.get(fqn);
+ }
+
+ public static final class SingularData {
+ private final JavacNode annotation;
+ private final Name singularName;
+ private final Name pluralName;
+ private final List<JCExpression> typeArgs;
+ private final String targetFqn;
+ private final JavacSingularizer singularizer;
+
+ public SingularData(JavacNode annotation, Name singularName, Name pluralName, List<JCExpression> typeArgs, String targetFqn, JavacSingularizer singularizer) {
+ this.annotation = annotation;
+ this.singularName = singularName;
+ this.pluralName = pluralName;
+ this.typeArgs = typeArgs;
+ this.targetFqn = targetFqn;
+ this.singularizer = singularizer;
+ }
+
+ public JavacNode getAnnotation() {
+ return annotation;
+ }
+
+ public Name getSingularName() {
+ return singularName;
+ }
+
+ public Name getPluralName() {
+ return pluralName;
+ }
+
+ public List<JCExpression> getTypeArgs() {
+ return typeArgs;
+ }
+
+ public String getTargetFqn() {
+ return targetFqn;
+ }
+
+ public JavacSingularizer getSingularizer() {
+ return singularizer;
+ }
+
+ public String getTargetSimpleType() {
+ int idx = targetFqn.lastIndexOf(".");
+ return idx == -1 ? targetFqn : targetFqn.substring(idx + 1);
+ }
+ }
+
+ public static abstract class JavacSingularizer {
+ public abstract LombokImmutableList<String> getSupportedTypes();
+
+ protected JCModifiers makeMods(JavacTreeMaker maker, JavacNode node, boolean deprecate) {
+ if (deprecate) return maker.Modifiers(Flags.PUBLIC, List.<JCAnnotation>of(maker.Annotation(genJavaLangTypeRef(node, "Deprecated"), List.<JCExpression>nil())));
+ return maker.Modifiers(Flags.PUBLIC);
+ }
+
+ /** Checks if any of the to-be-generated nodes (fields, methods) already exist. If so, errors on these (singulars don't support manually writing some of it, and returns true). */
+ public boolean checkForAlreadyExistingNodesAndGenerateError(JavacNode builderType, SingularData data) {
+ for (JavacNode child : builderType.down()) {
+ switch (child.getKind()) {
+ case FIELD: {
+ JCVariableDecl field = (JCVariableDecl) child.get();
+ Name name = field.name;
+ if (name == null) break;
+ if (getGeneratedBy(field) != null) continue;
+ for (Name fieldToBeGenerated : listFieldsToBeGenerated(data, builderType)) {
+ if (!fieldToBeGenerated.equals(name)) continue;
+ child.addError("Manually adding a field that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }
+ case METHOD: {
+ JCMethodDecl method = (JCMethodDecl) child.get();
+ Name name = method.name;
+ if (name == null) break;
+ if (getGeneratedBy(method) != null) continue;
+ for (Name methodToBeGenerated : listMethodsToBeGenerated(data, builderType)) {
+ if (!methodToBeGenerated.equals(name)) continue;
+ child.addError("Manually adding a method that @Singular @Builder would generate is not supported. If you want to manually manage the builder aspect for this field/parameter, don't use @Singular.");
+ return true;
+ }
+ break;
+ }}
+ }
+
+ return false;
+ }
+
+ public java.util.List<Name> listFieldsToBeGenerated(SingularData data, JavacNode builderType) {
+ return Collections.singletonList(data.pluralName);
+ }
+
+ public java.util.List<Name> listMethodsToBeGenerated(SingularData data, JavacNode builderType) {
+ Name p = data.pluralName;
+ Name s = data.singularName;
+ if (p.equals(s)) return Collections.singletonList(p);
+ return Arrays.asList(p, s);
+ }
+
+ public abstract java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source);
+ public abstract void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain);
+ public abstract void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName);
+
+ public boolean requiresCleaning() {
+ try {
+ return !getClass().getMethod("appendCleaningCode", SingularData.class, JavacNode.class, JCTree.class, ListBuffer.class).getDeclaringClass().equals(JavacSingularizer.class);
+ } catch (NoSuchMethodException e) {
+ return false;
+ }
+ }
+
+ public void appendCleaningCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements) {
+ }
+
+ // -- Utility methods --
+
+ /**
+ * Adds the requested number of type arguments to the provided type, copying each argument in {@code typeArgs}. If typeArgs is too long, the extra elements are ignored.
+ * If {@code typeArgs} is null or too short, {@code java.lang.Object} will be substituted for each missing type argument.
+ *
+ * @param count The number of type arguments requested.
+ * @param addExtends If {@code true}, all bounds are either '? extends X' or just '?'. If false, the reverse is applied, and '? extends Foo' is converted to Foo, '?' to Object, etc.
+ * @param node Some node in the same AST. Just used to obtain makers and contexts and such.
+ * @param type The type to add generics to.
+ * @param typeArgs the list of type args to clone.
+ * @param source The source annotation that is the root cause of this code generation.
+ */
+ protected JCExpression addTypeArgs(int count, boolean addExtends, JavacNode node, JCExpression type, List<JCExpression> typeArgs, JCTree source) {
+ JavacTreeMaker maker = node.getTreeMaker();
+ List<JCExpression> clonedAndFixedTypeArgs = createTypeArgs(count, addExtends, node, typeArgs, source);
+
+ return maker.TypeApply(type, clonedAndFixedTypeArgs);
+ }
+
+ protected List<JCExpression> createTypeArgs(int count, boolean addExtends, JavacNode node, List<JCExpression> typeArgs, JCTree source) {
+ JavacTreeMaker maker = node.getTreeMaker();
+ Context context = node.getContext();
+
+ if (count < 0) throw new IllegalArgumentException("count is negative");
+ if (count == 0) return List.nil();
+ ListBuffer<JCExpression> arguments = new ListBuffer<JCExpression>();
+
+ if (typeArgs != null) for (JCExpression orig : typeArgs) {
+ if (!addExtends) {
+ if (orig.getKind() == Kind.UNBOUNDED_WILDCARD || orig.getKind() == Kind.SUPER_WILDCARD) {
+ arguments.append(genJavaLangTypeRef(node, "Object"));
+ } else if (orig.getKind() == Kind.EXTENDS_WILDCARD) {
+ JCExpression inner;
+ try {
+ inner = (JCExpression) ((JCWildcard) orig).inner;
+ } catch (Exception e) {
+ inner = genJavaLangTypeRef(node, "Object");
+ }
+ arguments.append(cloneType(maker, inner, source, context));
+ } else {
+ arguments.append(cloneType(maker, orig, source, context));
+ }
+ } else {
+ if (orig.getKind() == Kind.UNBOUNDED_WILDCARD || orig.getKind() == Kind.SUPER_WILDCARD) {
+ arguments.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
+ } else if (orig.getKind() == Kind.EXTENDS_WILDCARD) {
+ arguments.append(cloneType(maker, orig, source, context));
+ } else {
+ arguments.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.EXTENDS), cloneType(maker, orig, source, context)));
+ }
+ }
+ if (--count == 0) break;
+ }
+
+ while (count-- > 0) {
+ if (addExtends) {
+ arguments.append(maker.Wildcard(maker.TypeBoundKind(BoundKind.UNBOUND), null));
+ } else {
+ arguments.append(genJavaLangTypeRef(node, "Object"));
+ }
+ }
+
+ return arguments.toList();
+ }
+
+ /** Generates 'this.<em>name</em>.size()' as an expression; if nullGuard is true, it's this.name == null ? 0 : this.name.size(). */
+ protected JCExpression getSize(JavacTreeMaker maker, JavacNode builderType, Name name, boolean nullGuard, boolean parens) {
+ Name thisName = builderType.toName("this");
+ JCExpression fn = maker.Select(maker.Select(maker.Ident(thisName), name), builderType.toName("size"));
+ JCExpression sizeInvoke = maker.Apply(List.<JCExpression>nil(), fn, List.<JCExpression>nil());
+ if (nullGuard) {
+ JCExpression isNull = maker.Binary(CTC_EQUAL, maker.Select(maker.Ident(thisName), name), maker.Literal(CTC_BOT, 0));
+ JCExpression out = maker.Conditional(isNull, maker.Literal(CTC_INT, 0), sizeInvoke);
+ if (parens) return maker.Parens(out);
+ return out;
+ }
+ return sizeInvoke;
+ }
+
+ protected JCExpression cloneParamType(int index, JavacTreeMaker maker, List<JCExpression> typeArgs, JavacNode builderType, JCTree source) {
+ if (typeArgs == null || typeArgs.size() <= index) {
+ return genJavaLangTypeRef(builderType, "Object");
+ } else {
+ JCExpression originalType = typeArgs.get(index);
+ if (originalType.getKind() == Kind.UNBOUNDED_WILDCARD || originalType.getKind() == Kind.SUPER_WILDCARD) {
+ return genJavaLangTypeRef(builderType, "Object");
+ } else if (originalType.getKind() == Kind.EXTENDS_WILDCARD) {
+ try {
+ return cloneType(maker, (JCExpression) ((JCWildcard) originalType).inner, source, builderType.getContext());
+ } catch (Exception e) {
+ return genJavaLangTypeRef(builderType, "Object");
+ }
+ } else {
+ return cloneType(maker, originalType, source, builderType.getContext());
+ }
+ }
+ }
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java
new file mode 100644
index 00000000..e0621cf7
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaMapSingularizer.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers.singulars;
+
+import lombok.core.LombokImmutableList;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+
+import org.mangosdk.spi.ProviderFor;
+
+@ProviderFor(JavacSingularizer.class)
+public class JavacGuavaMapSingularizer extends JavacGuavaSingularizer {
+ // TODO cgcc.ImmutableMultimap, cgcc.ImmutableListMultimap, cgcc.ImmutableSetMultimap
+ // TODO cgcc.ImmutableClassToInstanceMap
+ // TODO cgcc.ImmutableRangeMap
+
+ private static final LombokImmutableList<String> SUFFIXES =
+ LombokImmutableList.of("key", "value");
+ private static final LombokImmutableList<String> SUPPORTED_TYPES = LombokImmutableList.of(
+ "com.google.common.collect.ImmutableMap",
+ "com.google.common.collect.ImmutableBiMap",
+ "com.google.common.collect.ImmutableSortedMap"
+ );
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return SUPPORTED_TYPES;
+ }
+
+ @Override protected LombokImmutableList<String> getArgumentSuffixes() {
+ return SUFFIXES;
+ }
+
+ @Override protected String getAddMethodName() {
+ return "put";
+ }
+
+ @Override protected String getAddAllTypeName() {
+ return "java.util.Map";
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java
new file mode 100644
index 00000000..5c7fcab5
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSetListSingularizer.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+
+@ProviderFor(JavacSingularizer.class)
+public class JavacGuavaSetListSingularizer extends JavacGuavaSingularizer {
+ // TODO com.google.common.collect.ImmutableRangeSet
+ // TODO com.google.common.collect.ImmutableMultiset and com.google.common.collect.ImmutableSortedMultiset
+ private static final LombokImmutableList<String> SUFFIXES = LombokImmutableList.of("");
+ private static final LombokImmutableList<String> SUPPORTED_TYPES = LombokImmutableList.of(
+ "com.google.common.collect.ImmutableCollection",
+ "com.google.common.collect.ImmutableList",
+ "com.google.common.collect.ImmutableSet",
+ "com.google.common.collect.ImmutableSortedSet"
+ );
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return SUPPORTED_TYPES;
+ }
+
+ @Override protected LombokImmutableList<String> getArgumentSuffixes() {
+ return SUFFIXES;
+ }
+
+ @Override protected String getAddMethodName() {
+ return "add";
+ }
+
+ @Override protected String getAddAllTypeName() {
+ return "java.lang.Iterable";
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
new file mode 100644
index 00000000..0ab7da54
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaSingularizer.java
@@ -0,0 +1,222 @@
+/*
+ * Copyright (C) 2015-2017 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.javac.handlers.singulars;
+
+import static lombok.javac.Javac.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import java.util.Collections;
+
+import lombok.core.GuavaTypeMap;
+import lombok.core.LombokImmutableList;
+import lombok.core.handlers.HandlerUtil;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacHandlerUtil;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+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.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+abstract class JavacGuavaSingularizer extends JavacSingularizer {
+ protected String getSimpleTargetTypeName(SingularData data) {
+ return GuavaTypeMap.getGuavaTypeName(data.getTargetFqn());
+ }
+
+ protected String getBuilderMethodName(SingularData data) {
+ String simpleTypeName = getSimpleTargetTypeName(data);
+ if ("ImmutableSortedSet".equals(simpleTypeName) || "ImmutableSortedMap".equals(simpleTypeName)) return "naturalOrder";
+ return "builder";
+ }
+
+ @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ String simpleTypeName = getSimpleTargetTypeName(data);
+ JCExpression type = JavacHandlerUtil.chainDots(builderType, "com", "google", "common", "collect", simpleTypeName, "Builder");
+ type = addTypeArgs(getTypeArgumentsCount(), false, builderType, type, data.getTypeArgs(), source);
+
+ JCVariableDecl buildField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), data.getPluralName(), type, null);
+ return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
+ }
+
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ Symtab symbolTable = builderType.getSymbolTable();
+ JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
+ }
+
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ List<JCVariableDecl> params = List.nil();
+
+ JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
+ JCStatement clearField = maker.Exec(maker.Assign(thisDotField, maker.Literal(CTC_BOT, null)));
+ List<JCStatement> statements = returnStatement != null ? List.of(clearField, returnStatement) : List.of(clearField);
+
+ JCBlock body = maker.Block(0, statements);
+ Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
+ JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+
+ LombokImmutableList<String> suffixes = getArgumentSuffixes();
+ Name[] names = new Name[suffixes.size()];
+ for (int i = 0; i < suffixes.size(); i++) {
+ String s = suffixes.get(i);
+ Name n = data.getSingularName();
+ names[i] = s.isEmpty() ? n : builderType.toName(s);
+ }
+
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+ statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
+ JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName());
+ ListBuffer<JCExpression> invokeAddExprBuilder = new ListBuffer<JCExpression>();
+ for (int i = 0; i < suffixes.size(); i++) {
+ invokeAddExprBuilder.append(maker.Ident(names[i]));
+ }
+ List<JCExpression> invokeAddExpr = invokeAddExprBuilder.toList();
+ JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, invokeAddExpr);
+ statements.append(maker.Exec(invokeAdd));
+ if (returnStatement != null) statements.append(returnStatement);
+ JCBlock body = maker.Block(0, statements.toList());
+ Name methodName = data.getSingularName();
+ long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
+ if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName(), methodName.toString()));
+ ListBuffer<JCVariableDecl> params = new ListBuffer<JCVariableDecl>();
+ for (int i = 0; i < suffixes.size(); i++) {
+ JCExpression pt = cloneParamType(i, maker, data.getTypeArgs(), builderType, source);
+ JCVariableDecl p = maker.VarDef(maker.Modifiers(paramFlags), names[i], pt, null);
+ params.append(p);
+ }
+
+ JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params.toList(), thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ protected void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+ statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, source));
+ JCExpression thisDotFieldDotAddAll = chainDots(builderType, "this", data.getPluralName().toString(), getAddMethodName() + "All");
+ JCExpression invokeAddAll = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAddAll, List.<JCExpression>of(maker.Ident(data.getPluralName())));
+ statements.append(maker.Exec(invokeAddAll));
+ if (returnStatement != null) statements.append(returnStatement);
+ JCBlock body = maker.Block(0, statements.toList());
+ Name methodName = data.getPluralName();
+ long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
+ if (!fluent) methodName = builderType.toName(HandlerUtil.buildAccessorName(getAddMethodName() + "All", methodName.toString()));
+ JCExpression paramType;
+ String aaTypeName = getAddAllTypeName();
+ if (aaTypeName.startsWith("java.lang.") && aaTypeName.indexOf('.', 11) == -1) {
+ paramType = genJavaLangTypeRef(builderType, aaTypeName.substring(10));
+ } else {
+ paramType = chainDotsString(builderType, aaTypeName);
+ }
+ paramType = addTypeArgs(getTypeArgumentsCount(), true, builderType, paramType, data.getTypeArgs(), source);
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
+ JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, List.of(param), thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName) {
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ List<JCExpression> jceBlank = List.nil();
+
+ JCExpression varType = chainDotsString(builderType, data.getTargetFqn());
+ int agrumentsCount = getTypeArgumentsCount();
+ varType = addTypeArgs(agrumentsCount, false, builderType, varType, data.getTypeArgs(), source);
+
+ JCExpression empty; {
+ //ImmutableX.of()
+ JCExpression emptyMethod = chainDots(builderType, "com", "google", "common", "collect", getSimpleTargetTypeName(data), "of");
+ List<JCExpression> invokeTypeArgs = createTypeArgs(agrumentsCount, false, builderType, data.getTypeArgs(), source);
+ empty = maker.Apply(invokeTypeArgs, emptyMethod, jceBlank);
+ }
+
+ JCExpression invokeBuild; {
+ //this.pluralName.build();
+ invokeBuild = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName().toString(), "build"), jceBlank);
+ }
+
+ JCExpression isNull; {
+ //this.pluralName == null
+ isNull = maker.Binary(CTC_EQUAL, maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()), maker.Literal(CTC_BOT, null));
+ }
+
+ JCExpression init = maker.Conditional(isNull, empty, invokeBuild); // this.pluralName == null ? ImmutableX.of() : this.pluralName.build()
+
+ JCStatement jcs = maker.VarDef(maker.Modifiers(0), data.getPluralName(), varType, init);
+ statements.append(jcs);
+ }
+
+ protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ List<JCExpression> jceBlank = List.nil();
+
+ JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
+ JCExpression thisDotField2 = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
+ JCExpression cond = maker.Binary(CTC_EQUAL, thisDotField, maker.Literal(CTC_BOT, null));
+
+ JCExpression create = maker.Apply(jceBlank, chainDots(builderType, "com", "google", "common", "collect", getSimpleTargetTypeName(data), getBuilderMethodName(data)), jceBlank);
+ JCStatement thenPart = maker.Exec(maker.Assign(thisDotField2, create));
+
+ return maker.If(cond, thenPart, null);
+ }
+
+ protected abstract LombokImmutableList<String> getArgumentSuffixes();
+ protected abstract String getAddMethodName();
+ protected abstract String getAddAllTypeName();
+
+ protected int getTypeArgumentsCount() {
+ return getArgumentSuffixes().size();
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java
new file mode 100644
index 00000000..080266b8
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacGuavaTableSingularizer.java
@@ -0,0 +1,51 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+
+@ProviderFor(JavacSingularizer.class)
+public class JavacGuavaTableSingularizer extends JavacGuavaSingularizer {
+ private static final LombokImmutableList<String> SUFFIXES =
+ LombokImmutableList.of("rowKey", "columnKey", "value");
+ private static final LombokImmutableList<String> SUPPORTED_TYPES =
+ LombokImmutableList.of("com.google.common.collect.ImmutableTable");
+
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return SUPPORTED_TYPES;
+ }
+
+ @Override protected LombokImmutableList<String> getArgumentSuffixes() {
+ return SUFFIXES;
+ }
+
+ @Override protected String getAddMethodName() {
+ return "put";
+ }
+
+ @Override protected String getAddAllTypeName() {
+ return "com.google.common.collect.Table";
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
new file mode 100644
index 00000000..196ce45d
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSetSingularizer.java
@@ -0,0 +1,162 @@
+/*
+ * Copyright (C) 2015-2017 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.javac.handlers.singulars;
+
+import static lombok.javac.Javac.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import java.util.Collections;
+
+import lombok.core.handlers.HandlerUtil;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacHandlerUtil;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+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.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+abstract class JavacJavaUtilListSetSingularizer extends JavacJavaUtilSingularizer {
+ @Override public java.util.List<Name> listFieldsToBeGenerated(SingularData data, JavacNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaListSetSingularizer.listFieldsToBeGenerated(data, builderType);
+ }
+
+ return super.listFieldsToBeGenerated(data, builderType);
+ }
+
+ @Override public java.util.List<Name> listMethodsToBeGenerated(SingularData data, JavacNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaListSetSingularizer.listMethodsToBeGenerated(data, builderType);
+ }
+
+ return super.listMethodsToBeGenerated(data, builderType);
+ }
+
+ @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
+ if (useGuavaInstead(builderType)) {
+ return guavaListSetSingularizer.generateFields(data, builderType, source);
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ JCExpression type = JavacHandlerUtil.chainDots(builderType, "java", "util", "ArrayList");
+ type = addTypeArgs(1, false, builderType, type, data.getTypeArgs(), source);
+
+ JCVariableDecl buildField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), data.getPluralName(), type, null);
+ return Collections.singletonList(injectFieldAndMarkGenerated(builderType, buildField));
+ }
+
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ if (useGuavaInstead(builderType)) {
+ guavaListSetSingularizer.generateMethods(data, deprecate, builderType, source, fluent, chain);
+ return;
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ Symtab symbolTable = builderType.getSymbolTable();
+ Name thisName = builderType.toName("this");
+
+ JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ JCStatement returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ returnStatement = chain ? maker.Return(maker.Ident(thisName)) : null;
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
+ }
+
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ List<JCVariableDecl> params = List.nil();
+ List<JCExpression> jceBlank = List.nil();
+
+ JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName());
+ JCExpression thisDotFieldDotClear = maker.Select(maker.Select(maker.Ident(builderType.toName("this")), data.getPluralName()), builderType.toName("clear"));
+ JCStatement clearCall = maker.Exec(maker.Apply(jceBlank, thisDotFieldDotClear, jceBlank));
+ JCExpression cond = maker.Binary(CTC_NOT_EQUAL, thisDotField, maker.Literal(CTC_BOT, null));
+ JCStatement ifSetCallClear = maker.If(cond, clearCall, null);
+ List<JCStatement> statements = returnStatement != null ? List.of(ifSetCallClear, returnStatement) : List.of(ifSetCallClear);
+
+ JCBlock body = maker.Block(0, statements);
+ Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
+ JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+ statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
+ JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "add");
+ JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(data.getSingularName())));
+ statements.append(maker.Exec(invokeAdd));
+ if (returnStatement != null) statements.append(returnStatement);
+ JCBlock body = maker.Block(0, statements.toList());
+ Name name = data.getSingularName();
+ long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
+ if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("add", name.toString()));
+ JCExpression paramType = cloneParamType(0, maker, data.getTypeArgs(), builderType, source);
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getSingularName(), paramType, null);
+ JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(param), thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+ statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, false, source));
+ JCExpression thisDotFieldDotAdd = chainDots(builderType, "this", data.getPluralName().toString(), "addAll");
+ JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotFieldDotAdd, List.<JCExpression>of(maker.Ident(data.getPluralName())));
+ statements.append(maker.Exec(invokeAdd));
+ if (returnStatement != null) statements.append(returnStatement);
+ JCBlock body = maker.Block(0, statements.toList());
+ Name name = data.getPluralName();
+ long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
+ if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("addAll", name.toString()));
+ JCExpression paramType = chainDots(builderType, "java", "util", "Collection");
+ paramType = addTypeArgs(1, true, builderType, paramType, data.getTypeArgs(), source);
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
+ JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(param), thrown, body, null);
+ injectMethod(builderType, method);
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
new file mode 100644
index 00000000..3002a98f
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilListSingularizer.java
@@ -0,0 +1,120 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers.singulars;
+
+import static lombok.javac.Javac.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+@ProviderFor(JavacSingularizer.class)
+public class JavacJavaUtilListSingularizer extends JavacJavaUtilListSetSingularizer {
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of("java.util.List", "java.util.Collection", "java.lang.Iterable");
+ }
+
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName) {
+ if (useGuavaInstead(builderType)) {
+ guavaListSetSingularizer.appendBuildCode(data, builderType, source, statements, targetVariableName);
+ return;
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ List<JCExpression> jceBlank = List.nil();
+ ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
+
+ /* case 0: (empty); break; */ {
+ JCStatement assignStat; {
+ // pluralName = java.util.Collections.emptyList();
+ JCExpression invoke = maker.Apply(jceBlank, chainDots(builderType, "java", "util", "Collections", "emptyList"), jceBlank);
+ assignStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), invoke));
+ }
+ JCStatement breakStat = maker.Break(null);
+ JCCase emptyCase = maker.Case(maker.Literal(CTC_INT, 0), List.of(assignStat, breakStat));
+ cases.append(emptyCase);
+ }
+
+ /* case 1: (singletonList); break; */ {
+ JCStatement assignStat; {
+ // pluralName = java.util.Collections.singletonList(this.pluralName.get(0));
+ JCExpression zeroLiteral = maker.Literal(CTC_INT, 0);
+ JCExpression arg = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName().toString(), "get"), List.of(zeroLiteral));
+ List<JCExpression> args = List.of(arg);
+ JCExpression invoke = maker.Apply(jceBlank, chainDots(builderType, "java", "util", "Collections", "singletonList"), args);
+ assignStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), invoke));
+ }
+ JCStatement breakStat = maker.Break(null);
+ JCCase singletonCase = maker.Case(maker.Literal(CTC_INT, 1), List.of(assignStat, breakStat));
+ cases.append(singletonCase);
+ }
+
+ /* default: Create with right size, then addAll */ {
+ List<JCStatement> defStats = createListCopy(maker, data, builderType, source);
+ JCCase defaultCase = maker.Case(null, defStats);
+ cases.append(defaultCase);
+ }
+
+ JCStatement switchStat = maker.Switch(getSize(maker, builderType, data.getPluralName(), true, false), cases.toList());
+ JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
+ localShadowerType = addTypeArgs(1, false, builderType, localShadowerType, data.getTypeArgs(), source);
+ JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null);
+ statements.append(varDefStat);
+ statements.append(switchStat);
+ }
+
+ private List<JCStatement> createListCopy(JavacTreeMaker maker, SingularData data, JavacNode builderType, JCTree source) {
+ List<JCExpression> jceBlank = List.nil();
+ Name thisName = builderType.toName("this");
+
+ JCExpression argToUnmodifiable; {
+ // new java.util.ArrayList<Generics>(this.pluralName);
+ List<JCExpression> constructorArgs = List.nil();
+ JCExpression thisDotPluralName = maker.Select(maker.Ident(thisName), data.getPluralName());
+ constructorArgs = List.<JCExpression>of(thisDotPluralName);
+ JCExpression targetTypeExpr = chainDots(builderType, "java", "util", "ArrayList");
+ targetTypeExpr = addTypeArgs(1, false, builderType, targetTypeExpr, data.getTypeArgs(), source);
+ argToUnmodifiable = maker.NewClass(null, jceBlank, targetTypeExpr, constructorArgs, null);
+ }
+
+ JCStatement unmodifiableStat; {
+ // pluralname = Collections.unmodifiableInterfaceType(-newlist-);
+ JCExpression invoke = maker.Apply(jceBlank, chainDots(builderType, "java", "util", "Collections", "unmodifiableList"), List.of(argToUnmodifiable));
+ unmodifiableStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), invoke));
+ }
+
+ return List.of(unmodifiableStat);
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
new file mode 100644
index 00000000..fd699275
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilMapSingularizer.java
@@ -0,0 +1,229 @@
+/*
+ * Copyright (C) 2015-2017 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.javac.handlers.singulars;
+
+import static lombok.javac.Javac.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import java.util.Arrays;
+
+import lombok.core.LombokImmutableList;
+import lombok.core.handlers.HandlerUtil;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacHandlerUtil;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+
+import org.mangosdk.spi.ProviderFor;
+
+import com.sun.tools.javac.code.Flags;
+import com.sun.tools.javac.code.Symtab;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+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.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+@ProviderFor(JavacSingularizer.class)
+public class JavacJavaUtilMapSingularizer extends JavacJavaUtilSingularizer {
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of("java.util.Map", "java.util.SortedMap", "java.util.NavigableMap");
+ }
+
+ @Override public java.util.List<Name> listFieldsToBeGenerated(SingularData data, JavacNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaMapSingularizer.listFieldsToBeGenerated(data, builderType);
+ }
+
+ String p = data.getPluralName().toString();
+ return Arrays.asList(builderType.toName(p + "$key"), builderType.toName(p + "$value"));
+ }
+
+ @Override public java.util.List<Name> listMethodsToBeGenerated(SingularData data, JavacNode builderType) {
+ if (useGuavaInstead(builderType)) {
+ return guavaMapSingularizer.listMethodsToBeGenerated(data, builderType);
+ }
+
+ return super.listMethodsToBeGenerated(data, builderType);
+ }
+
+ @Override public java.util.List<JavacNode> generateFields(SingularData data, JavacNode builderType, JCTree source) {
+ if (useGuavaInstead(builderType)) {
+ return guavaMapSingularizer.generateFields(data, builderType, source);
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+
+ JCVariableDecl buildKeyField; {
+ JCExpression type = JavacHandlerUtil.chainDots(builderType, "java", "util", "ArrayList");
+ type = addTypeArgs(1, false, builderType, type, data.getTypeArgs(), source);
+ buildKeyField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName(data.getPluralName() + "$key"), type, null);
+ }
+
+ JCVariableDecl buildValueField; {
+ JCExpression type = JavacHandlerUtil.chainDots(builderType, "java", "util", "ArrayList");
+ List<JCExpression> tArgs = data.getTypeArgs();
+ if (tArgs != null && tArgs.size() > 1) tArgs = tArgs.tail;
+ else tArgs = List.nil();
+ type = addTypeArgs(1, false, builderType, type, tArgs, source);
+ buildValueField = maker.VarDef(maker.Modifiers(Flags.PRIVATE), builderType.toName(data.getPluralName() + "$value"), type, null);
+ }
+
+ JavacNode valueFieldNode = injectFieldAndMarkGenerated(builderType, buildValueField);
+ JavacNode keyFieldNode = injectFieldAndMarkGenerated(builderType, buildKeyField);
+
+ return Arrays.asList(keyFieldNode, valueFieldNode);
+ }
+
+ @Override public void generateMethods(SingularData data, boolean deprecate, JavacNode builderType, JCTree source, boolean fluent, boolean chain) {
+ if (useGuavaInstead(builderType)) {
+ guavaMapSingularizer.generateMethods(data, deprecate, builderType, source, fluent, chain);
+ return;
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+ Symtab symbolTable = builderType.getSymbolTable();
+
+ JCExpression returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ JCStatement returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ generateSingularMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ generatePluralMethod(deprecate, maker, returnType, returnStatement, data, builderType, source, fluent);
+
+ returnType = chain ? cloneSelfType(builderType) : maker.Type(createVoidType(symbolTable, CTC_VOID));
+ returnStatement = chain ? maker.Return(maker.Ident(builderType.toName("this"))) : null;
+ generateClearMethod(deprecate, maker, returnType, returnStatement, data, builderType, source);
+ }
+
+ private void generateClearMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source) {
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ List<JCVariableDecl> params = List.nil();
+ List<JCExpression> jceBlank = List.nil();
+
+ JCExpression thisDotKeyField = chainDots(builderType, "this", data.getPluralName() + "$key");
+ JCExpression thisDotKeyFieldDotClear = chainDots(builderType, "this", data.getPluralName() + "$key", "clear");
+ JCExpression thisDotValueFieldDotClear = chainDots(builderType, "this", data.getPluralName() + "$value", "clear");
+ JCStatement clearKeyCall = maker.Exec(maker.Apply(jceBlank, thisDotKeyFieldDotClear, jceBlank));
+ JCStatement clearValueCall = maker.Exec(maker.Apply(jceBlank, thisDotValueFieldDotClear, jceBlank));
+ JCExpression cond = maker.Binary(CTC_NOT_EQUAL, thisDotKeyField, maker.Literal(CTC_BOT, null));
+ JCBlock clearCalls = maker.Block(0, List.of(clearKeyCall, clearValueCall));
+ JCStatement ifSetCallClear = maker.If(cond, clearCalls, null);
+ List<JCStatement> statements = returnStatement != null ? List.of(ifSetCallClear, returnStatement) : List.of(ifSetCallClear);
+
+ JCBlock body = maker.Block(0, statements);
+ Name methodName = builderType.toName(HandlerUtil.buildAccessorName("clear", data.getPluralName().toString()));
+ JCMethodDecl method = maker.MethodDef(mods, methodName, returnType, typeParams, params, thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ private void generateSingularMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> thrown = List.nil();
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+ statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
+ Name keyName = builderType.toName(data.getSingularName().toString() + "Key");
+ Name valueName = builderType.toName(data.getSingularName().toString() + "Value");
+ /* this.pluralname$key.add(singularnameKey); */ {
+ JCExpression thisDotKeyFieldDotAdd = chainDots(builderType, "this", data.getPluralName() + "$key", "add");
+ JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotKeyFieldDotAdd, List.<JCExpression>of(maker.Ident(keyName)));
+ statements.append(maker.Exec(invokeAdd));
+ }
+ /* this.pluralname$value.add(singularnameValue); */ {
+ JCExpression thisDotValueFieldDotAdd = chainDots(builderType, "this", data.getPluralName() + "$value", "add");
+ JCExpression invokeAdd = maker.Apply(List.<JCExpression>nil(), thisDotValueFieldDotAdd, List.<JCExpression>of(maker.Ident(valueName)));
+ statements.append(maker.Exec(invokeAdd));
+ }
+ if (returnStatement != null) statements.append(returnStatement);
+ JCBlock body = maker.Block(0, statements.toList());
+ long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
+
+ Name name = data.getSingularName();
+ if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("put", name.toString()));
+ JCExpression paramTypeKey = cloneParamType(0, maker, data.getTypeArgs(), builderType, source);
+ JCExpression paramTypeValue = cloneParamType(1, maker, data.getTypeArgs(), builderType, source);
+ JCVariableDecl paramKey = maker.VarDef(maker.Modifiers(paramFlags), keyName, paramTypeKey, null);
+ JCVariableDecl paramValue = maker.VarDef(maker.Modifiers(paramFlags), valueName, paramTypeValue, null);
+ JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(paramKey, paramValue), thrown, body, null);
+ injectMethod(builderType, method);
+ }
+
+ private void generatePluralMethod(boolean deprecate, JavacTreeMaker maker, JCExpression returnType, JCStatement returnStatement, SingularData data, JavacNode builderType, JCTree source, boolean fluent) {
+ List<JCTypeParameter> typeParams = List.nil();
+ List<JCExpression> jceBlank = List.nil();
+ JCModifiers mods = makeMods(maker, builderType, deprecate);
+ ListBuffer<JCStatement> statements = new ListBuffer<JCStatement>();
+ statements.append(createConstructBuilderVarIfNeeded(maker, data, builderType, true, source));
+ long paramFlags = JavacHandlerUtil.addFinalIfNeeded(Flags.PARAMETER, builderType.getContext());
+ long baseFlags = JavacHandlerUtil.addFinalIfNeeded(0, builderType.getContext());
+ Name entryName = builderType.toName("$lombokEntry");
+
+ JCExpression forEachType = chainDots(builderType, "java", "util", "Map", "Entry");
+ forEachType = addTypeArgs(2, true, builderType, forEachType, data.getTypeArgs(), source);
+ JCExpression keyArg = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(entryName), builderType.toName("getKey")), List.<JCExpression>nil());
+ JCExpression valueArg = maker.Apply(List.<JCExpression>nil(), maker.Select(maker.Ident(entryName), builderType.toName("getValue")), List.<JCExpression>nil());
+ JCExpression addKey = maker.Apply(List.<JCExpression>nil(), chainDots(builderType, "this", data.getPluralName() + "$key", "add"), List.of(keyArg));
+ JCExpression addValue = maker.Apply(List.<JCExpression>nil(), chainDots(builderType, "this", data.getPluralName() + "$value", "add"), List.of(valueArg));
+ JCBlock forEachBody = maker.Block(0, List.<JCStatement>of(maker.Exec(addKey), maker.Exec(addValue)));
+ JCExpression entrySetInvocation = maker.Apply(jceBlank, maker.Select(maker.Ident(data.getPluralName()), builderType.toName("entrySet")), jceBlank);
+ JCStatement forEach = maker.ForeachLoop(maker.VarDef(maker.Modifiers(baseFlags), entryName, forEachType, null), entrySetInvocation, forEachBody);
+ statements.append(forEach);
+
+ if (returnStatement != null) statements.append(returnStatement);
+ JCBlock body = maker.Block(0, statements.toList());
+ Name name = data.getPluralName();
+ if (!fluent) name = builderType.toName(HandlerUtil.buildAccessorName("putAll", name.toString()));
+ JCExpression paramType = chainDots(builderType, "java", "util", "Map");
+ paramType = addTypeArgs(2, true, builderType, paramType, data.getTypeArgs(), source);
+ JCVariableDecl param = maker.VarDef(maker.Modifiers(paramFlags), data.getPluralName(), paramType, null);
+ JCMethodDecl method = maker.MethodDef(mods, name, returnType, typeParams, List.of(param), jceBlank, body, null);
+ injectMethod(builderType, method);
+ }
+
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName) {
+ if (useGuavaInstead(builderType)) {
+ guavaMapSingularizer.appendBuildCode(data, builderType, source, statements, targetVariableName);
+ return;
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+
+ if (data.getTargetFqn().equals("java.util.Map")) {
+ statements.appendList(createJavaUtilSetMapInitialCapacitySwitchStatements(maker, data, builderType, true, "emptyMap", "singletonMap", "LinkedHashMap", source));
+ } else {
+ statements.appendList(createJavaUtilSimpleCreationAndFillStatements(maker, data, builderType, true, true, false, true, "TreeMap", source));
+ }
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java
new file mode 100644
index 00000000..317233cb
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSetSingularizer.java
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers.singulars;
+
+import org.mangosdk.spi.ProviderFor;
+
+import lombok.core.LombokImmutableList;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+@ProviderFor(JavacSingularizer.class)
+public class JavacJavaUtilSetSingularizer extends JavacJavaUtilListSetSingularizer {
+ @Override public LombokImmutableList<String> getSupportedTypes() {
+ return LombokImmutableList.of("java.util.Set", "java.util.SortedSet", "java.util.NavigableSet");
+ }
+
+ @Override public void appendBuildCode(SingularData data, JavacNode builderType, JCTree source, ListBuffer<JCStatement> statements, Name targetVariableName) {
+ if (useGuavaInstead(builderType)) {
+ guavaListSetSingularizer.appendBuildCode(data, builderType, source, statements, targetVariableName);
+ return;
+ }
+
+ JavacTreeMaker maker = builderType.getTreeMaker();
+
+ if (data.getTargetFqn().equals("java.util.Set")) {
+ statements.appendList(createJavaUtilSetMapInitialCapacitySwitchStatements(maker, data, builderType, false, "emptySet", "singleton", "LinkedHashSet", source));
+ } else {
+ statements.appendList(createJavaUtilSimpleCreationAndFillStatements(maker, data, builderType, false, true, false, true, "TreeSet", source));
+ }
+ }
+}
diff --git a/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
new file mode 100644
index 00000000..0589ac34
--- /dev/null
+++ b/src/core/lombok/javac/handlers/singulars/JavacJavaUtilSingularizer.java
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 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.javac.handlers.singulars;
+
+import static lombok.javac.Javac.*;
+import static lombok.javac.handlers.JavacHandlerUtil.*;
+
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.ListBuffer;
+import com.sun.tools.javac.util.Name;
+
+import lombok.ConfigurationKeys;
+import lombok.javac.JavacNode;
+import lombok.javac.JavacTreeMaker;
+import lombok.javac.handlers.JavacSingularsRecipes.JavacSingularizer;
+import lombok.javac.handlers.JavacSingularsRecipes.SingularData;
+
+abstract class JavacJavaUtilSingularizer extends JavacSingularizer {
+ protected final JavacSingularizer guavaListSetSingularizer = new JavacGuavaSetListSingularizer();
+ protected final JavacSingularizer guavaMapSingularizer = new JavacGuavaMapSingularizer();
+
+ protected boolean useGuavaInstead(JavacNode node) {
+ return Boolean.TRUE.equals(node.getAst().readConfiguration(ConfigurationKeys.SINGULAR_USE_GUAVA));
+ }
+
+ protected List<JCStatement> createJavaUtilSetMapInitialCapacitySwitchStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, String emptyCollectionMethod, String singletonCollectionMethod, String targetType, JCTree source) {
+ List<JCExpression> jceBlank = List.nil();
+ ListBuffer<JCCase> cases = new ListBuffer<JCCase>();
+
+ if (emptyCollectionMethod != null) { // case 0: (empty); break;
+ JCStatement assignStat; {
+ // pluralName = java.util.Collections.emptyCollectionMethod();
+ JCExpression invoke = maker.Apply(jceBlank, chainDots(builderType, "java", "util", "Collections", emptyCollectionMethod), jceBlank);
+ assignStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), invoke));
+ }
+ JCStatement breakStat = maker.Break(null);
+ JCCase emptyCase = maker.Case(maker.Literal(CTC_INT, 0), List.of(assignStat, breakStat));
+ cases.append(emptyCase);
+ }
+
+ if (singletonCollectionMethod != null) { // case 1: (singleton); break;
+ JCStatement assignStat; {
+ // !mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName.get(0));
+ // mapMode: pluralName = java.util.Collections.singletonCollectionMethod(this.pluralName$key.get(0), this.pluralName$value.get(0));
+ JCExpression zeroLiteral = maker.Literal(CTC_INT, 0);
+ JCExpression arg = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + (mapMode ? "$key" : ""), "get"), List.of(zeroLiteral));
+ List<JCExpression> args;
+ if (mapMode) {
+ JCExpression zeroLiteralClone = maker.Literal(CTC_INT, 0);
+ JCExpression arg2 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + (mapMode ? "$value" : ""), "get"), List.of(zeroLiteralClone));
+ args = List.of(arg, arg2);
+ } else {
+ args = List.of(arg);
+ }
+ JCExpression invoke = maker.Apply(jceBlank, chainDots(builderType, "java", "util", "Collections", singletonCollectionMethod), args);
+ assignStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), invoke));
+ }
+ JCStatement breakStat = maker.Break(null);
+ JCCase singletonCase = maker.Case(maker.Literal(CTC_INT, 1), List.of(assignStat, breakStat));
+ cases.append(singletonCase);
+ }
+
+ { // default:
+ List<JCStatement> statements = createJavaUtilSimpleCreationAndFillStatements(maker, data, builderType, mapMode, false, true, emptyCollectionMethod == null, targetType, source);
+ JCCase defaultCase = maker.Case(null, statements);
+ cases.append(defaultCase);
+ }
+
+ JCStatement switchStat = maker.Switch(getSize(maker, builderType, mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName(), true, false), cases.toList());
+ JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
+ localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source);
+ JCStatement varDefStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, null);
+ return List.of(varDefStat, switchStat);
+ }
+
+ protected JCStatement createConstructBuilderVarIfNeeded(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, JCTree source) {
+ List<JCExpression> jceBlank = List.nil();
+
+ Name v1Name = mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName();
+ Name v2Name = mapMode ? builderType.toName(data.getPluralName() + "$value") : null;
+ JCExpression thisDotField = maker.Select(maker.Ident(builderType.toName("this")), v1Name);
+ JCExpression cond = maker.Binary(CTC_EQUAL, thisDotField, maker.Literal(CTC_BOT, null));
+ thisDotField = maker.Select(maker.Ident(builderType.toName("this")), v1Name);
+ JCExpression v1Type = chainDots(builderType, "java", "util", "ArrayList");
+ v1Type = addTypeArgs(1, false, builderType, v1Type, data.getTypeArgs(), source);
+ JCExpression constructArrayList = maker.NewClass(null, jceBlank, v1Type, jceBlank, null);
+ JCStatement initV1 = maker.Exec(maker.Assign(thisDotField, constructArrayList));
+ JCStatement thenPart;
+ if (mapMode) {
+ thisDotField = maker.Select(maker.Ident(builderType.toName("this")), v2Name);
+ JCExpression v2Type = chainDots(builderType, "java", "util", "ArrayList");
+ List<JCExpression> tArgs = data.getTypeArgs();
+ if (tArgs != null && tArgs.tail != null) tArgs = tArgs.tail;
+ else tArgs = List.nil();
+ v2Type = addTypeArgs(1, false, builderType, v2Type, tArgs, source);
+ constructArrayList = maker.NewClass(null, jceBlank, v2Type, jceBlank, null);
+ JCStatement initV2 = maker.Exec(maker.Assign(thisDotField, constructArrayList));
+ thenPart = maker.Block(0, List.of(initV1, initV2));
+ } else {
+ thenPart = initV1;
+ }
+ return maker.If(cond, thenPart, null);
+ }
+
+ protected List<JCStatement> createJavaUtilSimpleCreationAndFillStatements(JavacTreeMaker maker, SingularData data, JavacNode builderType, boolean mapMode, boolean defineVar, boolean addInitialCapacityArg, boolean nullGuard, String targetType, JCTree source) {
+ List<JCExpression> jceBlank = List.nil();
+ Name thisName = builderType.toName("this");
+
+ JCStatement createStat; {
+ // pluralName = new java.util.TargetType(initialCap);
+ List<JCExpression> constructorArgs = List.nil();
+ if (addInitialCapacityArg) {
+ Name varName = mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName();
+ // this.varName.size() < MAX_POWER_OF_2 ? 1 + this.varName.size() + (this.varName.size() - 3) / 3 : Integer.MAX_VALUE;
+ // lessThanCutOff = this.varName.size() < MAX_POWER_OF_2
+ JCExpression lessThanCutoff = maker.Binary(CTC_LESS_THAN, getSize(maker, builderType, varName, nullGuard, true), maker.Literal(CTC_INT, 0x40000000));
+ JCExpression integerMaxValue = genJavaLangTypeRef(builderType, "Integer", "MAX_VALUE");
+ JCExpression sizeFormulaLeft = maker.Binary(CTC_PLUS, maker.Literal(CTC_INT, 1), getSize(maker, builderType, varName, nullGuard, true));
+ JCExpression sizeFormulaRightLeft = maker.Parens(maker.Binary(CTC_MINUS, getSize(maker, builderType, varName, nullGuard, true), maker.Literal(CTC_INT, 3)));
+ JCExpression sizeFormulaRight = maker.Binary(CTC_DIV, sizeFormulaRightLeft, maker.Literal(CTC_INT, 3));
+ JCExpression sizeFormula = maker.Binary(CTC_PLUS, sizeFormulaLeft, sizeFormulaRight);
+ constructorArgs = List.<JCExpression>of(maker.Conditional(lessThanCutoff, sizeFormula, integerMaxValue));
+ }
+
+ JCExpression targetTypeExpr = chainDots(builderType, "java", "util", targetType);
+ targetTypeExpr = addTypeArgs(mapMode ? 2 : 1, false, builderType, targetTypeExpr, data.getTypeArgs(), source);
+ JCExpression constructorCall = maker.NewClass(null, jceBlank, targetTypeExpr, constructorArgs, null);
+ if (defineVar) {
+ JCExpression localShadowerType = chainDotsString(builderType, data.getTargetFqn());
+ localShadowerType = addTypeArgs(mapMode ? 2 : 1, false, builderType, localShadowerType, data.getTypeArgs(), source);
+ createStat = maker.VarDef(maker.Modifiers(0), data.getPluralName(), localShadowerType, constructorCall);
+ } else {
+ createStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), constructorCall));
+ }
+ }
+
+ JCStatement fillStat; {
+ if (mapMode) {
+ // for (int $i = 0; $i < this.pluralname$key.size(); i++) pluralname.put(this.pluralname$key.get($i), this.pluralname$value.get($i));
+ Name ivar = builderType.toName("$i");
+ Name keyVarName = builderType.toName(data.getPluralName() + "$key");
+ JCExpression pluralnameDotPut = maker.Select(maker.Ident(data.getPluralName()), builderType.toName("put"));
+ JCExpression arg1 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + "$key", "get"), List.<JCExpression>of(maker.Ident(ivar)));
+ JCExpression arg2 = maker.Apply(jceBlank, chainDots(builderType, "this", data.getPluralName() + "$value", "get"), List.<JCExpression>of(maker.Ident(ivar)));
+ // [jdk9] We add an unneccessary (V) cast here. Not doing so gives an error in javac (build 9-ea+156-jigsaw-nightly-h6072-20170212):
+ // error: method put in interface Map<K#2,V#2> cannot be applied to given types;
+ arg2 = maker.TypeCast(createTypeArgs(2, false, builderType, data.getTypeArgs(), source).get(1), arg2);
+ JCStatement putStatement = maker.Exec(maker.Apply(jceBlank, pluralnameDotPut, List.of(arg1, arg2)));
+ JCStatement forInit = maker.VarDef(maker.Modifiers(0), ivar, maker.TypeIdent(CTC_INT), maker.Literal(CTC_INT, 0));
+ JCExpression checkExpr = maker.Binary(CTC_LESS_THAN, maker.Ident(ivar), getSize(maker, builderType, keyVarName, nullGuard, true));
+ JCExpression incrementExpr = maker.Unary(CTC_POSTINC, maker.Ident(ivar));
+ fillStat = maker.ForLoop(List.of(forInit), checkExpr, List.of(maker.Exec(incrementExpr)), putStatement);
+ } else {
+ // pluralname.addAll(this.pluralname);
+ JCExpression thisDotPluralName = maker.Select(maker.Ident(thisName), data.getPluralName());
+ fillStat = maker.Exec(maker.Apply(jceBlank, maker.Select(maker.Ident(data.getPluralName()), builderType.toName("addAll")), List.of(thisDotPluralName)));
+ }
+ if (nullGuard) {
+ JCExpression thisDotField = maker.Select(maker.Ident(thisName), mapMode ? builderType.toName(data.getPluralName() + "$key") : data.getPluralName());
+ JCExpression nullCheck = maker.Binary(CTC_NOT_EQUAL, thisDotField, maker.Literal(CTC_BOT, null));
+ fillStat = maker.If(nullCheck, fillStat, null);
+ }
+ }
+ JCStatement unmodifiableStat; {
+ // pluralname = Collections.unmodifiableInterfaceType(pluralname);
+ JCExpression arg = maker.Ident(data.getPluralName());
+ JCExpression invoke = maker.Apply(jceBlank, chainDots(builderType, "java", "util", "Collections", "unmodifiable" + data.getTargetSimpleType()), List.of(arg));
+ unmodifiableStat = maker.Exec(maker.Assign(maker.Ident(data.getPluralName()), invoke));
+ }
+
+ return List.of(createStat, fillStat, unmodifiableStat);
+ }
+}
diff --git a/src/core/lombok/package-info.java b/src/core/lombok/package-info.java
index b5406a74..1c01dd0d 100644
--- a/src/core/lombok/package-info.java
+++ b/src/core/lombok/package-info.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -29,6 +29,6 @@
* <li>{@code lombok.experimental} – This package contains lombok features that are new or likely to change before committing to long-term support.
* </ul>
*
- * @see <a href="http://projectlombok.org/features/index.html">Lombok features</a>
+ * @see <a href="https://projectlombok.org/features/all">Lombok features</a>
*/
package lombok;
diff --git a/src/core/lombok/val.java b/src/core/lombok/val.java
index cd8652d6..a69d514c 100644
--- a/src/core/lombok/val.java
+++ b/src/core/lombok/val.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2013 The Project Lombok Authors.
+ * Copyright (C) 2010-2017 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
@@ -28,7 +28,7 @@ package lombok;
* <p>
* Note that this is an annotation type because {@code val x = 10;} will be desugared to {@code @val final int x = 10;}
* <p>
- * Complete documentation is found at <a href="http://projectlombok.org/features/val.html">the project lombok features page for &#64;val</a>.
+ * Complete documentation is found at <a href="https://projectlombok.org/features/val">the project lombok features page for &#64;val</a>.
*/
public @interface val {
}
diff --git a/src/core/lombok/var.java b/src/core/lombok/var.java
new file mode 100644
index 00000000..63a70213
--- /dev/null
+++ b/src/core/lombok/var.java
@@ -0,0 +1,35 @@
+/*
+ * Copyright (C) 2010-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
+ * 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;
+
+/**
+ * Use {@code var} as the type of any local variable declaration (even in a {@code for} statement), and the type will be inferred from the initializing expression
+ * (any further assignments to the variable are not involved in this type inference).
+ * <p>
+ * For example: {@code var x = 10.0;} will infer {@code double}, and {@code var y = new ArrayList<String>();} will infer {@code ArrayList<String>}.
+ * <p>
+ * Note that this is an annotation type because {@code var x = 10;} will be desugared to {@code @var int x = 10;}
+ * <p>
+ * Complete documentation is found at <a href="https://projectlombok.org/features/var">the project lombok features page for &#64;var</a>.
+ */
+public @interface var {
+}
diff --git a/src/core9/module-info.java b/src/core9/module-info.java
new file mode 100644
index 00000000..87f819e2
--- /dev/null
+++ b/src/core9/module-info.java
@@ -0,0 +1,38 @@
+/*
+ * Copyright (C) 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
+ * 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.
+ */
+module lombok {
+ requires java.compiler;
+ requires java.instrument;
+ requires jdk.unsupported;
+
+ exports lombok;
+ exports lombok.experimental;
+ exports lombok.extern.apachecommons;
+ exports lombok.extern.java;
+ exports lombok.extern.jbosslog;
+ exports lombok.extern.log4j;
+ exports lombok.extern.slf4j;
+
+ provides javax.annotation.processing.Processor with lombok.launch.AnnotationProcessorHider.AnnotationProcessor;
+ provides org.mapstruct.ap.spi.AstModifyingAnnotationProcessor with lombok.launch.AnnotationProcessorHider.AstModificationNotifier;
+}
+
diff --git a/src/delombok/lombok/delombok/Delombok.java b/src/delombok/lombok/delombok/Delombok.java
index f64e36a1..0d887cb9 100644
--- a/src/delombok/lombok/delombok/Delombok.java
+++ b/src/delombok/lombok/delombok/Delombok.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,12 +30,14 @@ import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintStream;
import java.io.Writer;
+import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URI;
import java.nio.charset.Charset;
import java.nio.charset.UnsupportedCharsetException;
import java.util.ArrayList;
+import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.IdentityHashMap;
@@ -43,15 +45,23 @@ import java.util.LinkedHashMap;
import java.util.List;
import java.util.ListIterator;
import java.util.Map;
+import java.util.Set;
+import java.util.regex.Pattern;
import javax.tools.DiagnosticListener;
+import javax.tools.JavaFileManager;
import javax.tools.JavaFileObject;
import lombok.Lombok;
import lombok.javac.CommentCatcher;
+import lombok.javac.Javac;
import lombok.javac.LombokOptions;
+import lombok.javac.apt.LombokProcessor;
+import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.comp.Todo;
+import com.sun.tools.javac.file.BaseFileManager;
+import com.sun.tools.javac.main.Arguments;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
import com.sun.tools.javac.util.Context;
@@ -204,7 +214,7 @@ public class Delombok {
System.out.println(indentAndWordbreak(e.getValue(), 4, 70));
}
System.out.println("Example: -f indent:4 -f emptyLines:indent");
- System.out.println("The '-f pretty' option is shorthand for '-f suppressWarnings:skip -f danceAroundIdeChecks:skip -f generateDelombokComment:skip -f javaLangAsFQN:skip'");
+ System.out.println("The '-f pretty' option is shorthand for '-f suppressWarnings:skip -f generated:skip -f danceAroundIdeChecks:skip -f generateDelombokComment:skip -f javaLangAsFQN:skip'");
System.exit(0);
return;
}
@@ -301,6 +311,7 @@ public class Delombok {
if (prettyEnabled) {
if (!formatPrefs.containsKey("suppresswarnings")) formatPrefs.put("suppresswarnings", "skip");
+ if (!formatPrefs.containsKey("generated")) formatPrefs.put("generated", "skip");
if (!formatPrefs.containsKey("dancearoundidechecks")) formatPrefs.put("dancearoundidechecks", "skip");
if (!formatPrefs.containsKey("generatedelombokcomment")) formatPrefs.put("generatedelombokcomment", "skip");
if (!formatPrefs.containsKey("javalangasfqn")) formatPrefs.put("javalangasfqn", "skip");
@@ -465,26 +476,83 @@ public class Delombok {
return out;
}
+ private static final Field MODULE_FIELD = getModuleField();
+ private static Field getModuleField() {
+ try {
+ return JCCompilationUnit.class.getField("modle");
+ } catch (NoSuchFieldException e) {
+ return null;
+ } catch (SecurityException e) {
+ return null;
+ }
+ }
+
public boolean delombok() throws IOException {
LombokOptions options = LombokOptionsFactory.getDelombokOptions(context);
options.deleteLombokAnnotations();
options.putJavacOption("ENCODING", charset.name());
- if (classpath != null) options.putJavacOption("CLASSPATH", classpath);
+ if (classpath != null) options.putJavacOption("CLASSPATH", unpackClasspath(classpath));
if (sourcepath != null) options.putJavacOption("SOURCEPATH", sourcepath);
- if (bootclasspath != null) options.putJavacOption("BOOTCLASSPATH", bootclasspath);
+ if (bootclasspath != null) options.putJavacOption("BOOTCLASSPATH", unpackClasspath(bootclasspath));
options.setFormatPreferences(new FormatPreferences(formatPrefs));
options.put("compilePolicy", "check");
+ if (Javac.getJavaCompilerVersion() >= 9) {
+ Arguments args = Arguments.instance(context);
+ List<String> argsList = new ArrayList<String>();
+ if (classpath != null) {
+ argsList.add("--class-path");
+ argsList.add(options.get("--class-path"));
+ }
+ if (sourcepath != null) {
+ argsList.add("--source-path");
+ argsList.add(options.get("--source-path"));
+ }
+ if (bootclasspath != null) {
+ argsList.add("--boot-class-path");
+ argsList.add(options.get("--boot-class-path"));
+ }
+ if (charset != null) {
+ argsList.add("-encoding");
+ argsList.add(charset.name());
+ }
+ String[] argv = argsList.toArray(new String[0]);
+ args.init("javac", argv);
+ }
+
CommentCatcher catcher = CommentCatcher.create(context);
JavaCompiler compiler = catcher.getCompiler();
List<JCCompilationUnit> roots = new ArrayList<JCCompilationUnit>();
Map<JCCompilationUnit, File> baseMap = new IdentityHashMap<JCCompilationUnit, File>();
- compiler.initProcessAnnotations(Collections.singleton(new lombok.javac.apt.Processor()));
+ Set<LombokProcessor> processors = Collections.singleton(new lombok.javac.apt.LombokProcessor());
+
+ if (Javac.getJavaCompilerVersion() >= 9) {
+ JavaFileManager jfm_ = context.get(JavaFileManager.class);
+ if (jfm_ instanceof BaseFileManager) {
+ Arguments args = Arguments.instance(context);
+ ((BaseFileManager) jfm_).setContext(context); // reinit with options
+ ((BaseFileManager) jfm_).handleOptions(args.getDeferredFileManagerOptions());
+ }
+ }
+
+ if (Javac.getJavaCompilerVersion() < 9) {
+ compiler.initProcessAnnotations(processors);
+ } else {
+ compiler.initProcessAnnotations(processors, Collections.<JavaFileObject>emptySet(), Collections.<String>emptySet());
+ }
+
+ Object unnamedModule = null;
+ if (Javac.getJavaCompilerVersion() >= 9) unnamedModule = Symtab.instance(context).unnamedModule;
for (File fileToParse : filesToParse) {
- @SuppressWarnings("deprecation") JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());
+ JCCompilationUnit unit = compiler.parse(fileToParse.getAbsolutePath());
+ if (Javac.getJavaCompilerVersion() >= 9) try {
+ MODULE_FIELD.set(unit, unnamedModule);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
baseMap.put(unit, fileToBase.get(fileToParse));
roots.add(unit);
}
@@ -497,9 +565,19 @@ public class Delombok {
catcher.setComments(unit, new DocCommentIntegrator().integrate(catcher.getComments(unit), unit));
}
+ if (Javac.getJavaCompilerVersion() >= 9) {
+ compiler.initModules(com.sun.tools.javac.util.List.from(roots.toArray(new JCCompilationUnit[0])));
+ }
com.sun.tools.javac.util.List<JCCompilationUnit> trees = compiler.enterTrees(toJavacList(roots));
- JavaCompiler delegate = compiler.processAnnotations(trees);
+ JavaCompiler delegate;
+ if (Javac.getJavaCompilerVersion() < 9) {
+ delegate = compiler.processAnnotations(trees, com.sun.tools.javac.util.List.<String>nil());
+ } else {
+ delegate = compiler;
+ Collection<String> c = com.sun.tools.javac.util.List.nil();
+ compiler.processAnnotations(trees, c);
+ }
Object care = callAttributeMethodOnJavaCompiler(delegate, delegate.todo);
@@ -507,9 +585,9 @@ public class Delombok {
FormatPreferences fps = new FormatPreferences(formatPrefs);
for (JCCompilationUnit unit : roots) {
DelombokResult result = new DelombokResult(catcher.getComments(unit), unit, force || options.isChanged(unit), fps);
- if (verbose) feedback.printf("File: %s [%s]\n", unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged");
+ if (verbose) feedback.printf("File: %s [%s%s]\n", unit.sourcefile.getName(), result.isChanged() ? "delomboked" : "unchanged", force && !options.isChanged(unit) ? " (forced)" : "");
Writer rawWriter;
- if (presetWriter != null) rawWriter = presetWriter;
+ if (presetWriter != null) rawWriter = createUnicodeEscapeWriter(presetWriter);
else if (output == null) rawWriter = createStandardOutWriter();
else rawWriter = createFileWriter(output, baseMap.get(unit), unit.sourcefile.toUri());
BufferedWriter writer = new BufferedWriter(rawWriter);
@@ -528,6 +606,29 @@ public class Delombok {
return true;
}
+ private String unpackClasspath(String cp) {
+ String[] parts = cp.split(Pattern.quote(File.pathSeparator));
+ StringBuilder out = new StringBuilder();
+ for (String p : parts) {
+ if (!p.endsWith("*")) {
+ if (out.length() > 0) out.append(File.pathSeparator);
+ out.append(p);
+ continue;
+ }
+ File f = new File(p.substring(0, p.length() - 2));
+ File[] files = f.listFiles();
+ if (files == null) continue;
+ for (File file : files) {
+ if (file.isFile()) {
+ if (out.length() > 0) out.append(File.pathSeparator);
+ out.append(p, 0, p.length() - 1);
+ out.append(file.getName());
+ }
+ }
+ }
+ return out.toString();
+ }
+
private static Method attributeMethod;
/** Method is needed because the call signature has changed between javac6 and javac7; no matter what we compile against, using delombok in the other means VerifyErrors. */
private static Object callAttributeMethodOnJavaCompiler(JavaCompiler compiler, Todo arg) {
@@ -605,6 +706,10 @@ public class Delombok {
return createUnicodeEscapeWriter(System.out);
}
+ private Writer createUnicodeEscapeWriter(Writer writer) {
+ return new UnicodeEscapeWriter(writer, charset);
+ }
+
private Writer createUnicodeEscapeWriter(OutputStream out) {
return new UnicodeEscapeWriter(new OutputStreamWriter(out, charset), charset);
}
diff --git a/src/delombok/lombok/delombok/DelombokApp.java b/src/delombok/lombok/delombok/DelombokApp.java
index 276bd7de..aa753fc8 100644
--- a/src/delombok/lombok/delombok/DelombokApp.java
+++ b/src/delombok/lombok/delombok/DelombokApp.java
@@ -88,7 +88,7 @@ public class DelombokApp extends LombokApp {
// Since we only read from it, not closing it should not be a problem.
@SuppressWarnings({"resource", "all"}) final JarFile toolsJarFile = new JarFile(toolsJar);
- ClassLoader loader = new ClassLoader() {
+ ClassLoader loader = new ClassLoader(DelombokApp.class.getClassLoader()) {
private Class<?> loadStreamAsClass(String name, boolean resolve, InputStream in) throws ClassNotFoundException {
try {
try {
@@ -107,16 +107,24 @@ public class DelombokApp extends LombokApp {
} finally {
in.close();
}
- } catch (IOException e2) {
+ } catch (Exception e2) {
throw new ClassNotFoundException(name, e2);
}
}
@Override protected synchronized Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
- String rawName = name.replace(".", "/") + ".class";
+ String rawName, altName; {
+ String binName = name.replace(".", "/");
+ rawName = binName + ".class";
+ altName = binName + ".SCL.lombok";
+ }
JarEntry entry = toolsJarFile.getJarEntry(rawName);
if (entry == null) {
- if (name.startsWith("lombok.")) return loadStreamAsClass(name, resolve, super.getResourceAsStream(rawName));
+ if (name.startsWith("lombok.")) {
+ InputStream res = getParent().getResourceAsStream(rawName);
+ if (res == null) res = getParent().getResourceAsStream(altName);
+ return loadStreamAsClass(name, resolve, res);
+ }
return super.loadClass(name, resolve);
}
diff --git a/src/delombok/lombok/delombok/DelombokResult.java b/src/delombok/lombok/delombok/DelombokResult.java
index 84aeb68b..8985b257 100644
--- a/src/delombok/lombok/delombok/DelombokResult.java
+++ b/src/delombok/lombok/delombok/DelombokResult.java
@@ -65,7 +65,8 @@ public class DelombokResult {
else comments_ = com.sun.tools.javac.util.List.from(comments.toArray(new CommentInfo[0]));
FormatPreferences preferences = new FormatPreferenceScanner().scan(formatPreferences, getContent());
- compilationUnit.accept(new PrettyCommentsPrinter(out, compilationUnit, comments_, preferences));
+ //compilationUnit.accept(new PrettyCommentsPrinter(out, compilationUnit, comments_, preferences));
+ compilationUnit.accept(new PrettyPrinter(out, compilationUnit, comments_, preferences));
}
private CharSequence getContent() throws IOException {
diff --git a/src/delombok/lombok/delombok/DocCommentIntegrator.java b/src/delombok/lombok/delombok/DocCommentIntegrator.java
index c66ff0ec..bab0abd8 100644
--- a/src/delombok/lombok/delombok/DocCommentIntegrator.java
+++ b/src/delombok/lombok/delombok/DocCommentIntegrator.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 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
@@ -29,6 +29,7 @@ import java.util.regex.Pattern;
import lombok.javac.CommentInfo;
import lombok.javac.Javac;
+import lombok.javac.PackageName;
import lombok.javac.handlers.JavacHandlerUtil;
import com.sun.tools.javac.parser.Tokens.Comment;
@@ -73,7 +74,7 @@ public class DocCommentIntegrator {
return out;
}
- private static final Pattern CONTENT_STRIPPER = Pattern.compile("^(?:\\s*\\*)?[ \\t]*(.*?)$", Pattern.MULTILINE);
+ private static final Pattern CONTENT_STRIPPER = Pattern.compile("^(?:\\s*\\*)?(.*?)$", Pattern.MULTILINE);
@SuppressWarnings("unchecked") private boolean attach(JCCompilationUnit top, final JCTree node, CommentInfo cmt) {
String docCommentContent = cmt.content;
if (docCommentContent.startsWith("/**")) docCommentContent = docCommentContent.substring(3);
@@ -120,7 +121,8 @@ public class DocCommentIntegrator {
}
private JCTree findJavadocableNodeOnOrAfter(JCCompilationUnit unit, int endPos) {
- if (unit.pid != null && endPos <= unit.pid.pos) return null;
+ JCTree pid = PackageName.getPackageNode(unit);
+ if (pid != null && endPos <= pid.pos) return null;
Iterator<JCTree> it = unit.defs.iterator();
while (it.hasNext()) {
diff --git a/src/delombok/lombok/delombok/FormatPreferences.java b/src/delombok/lombok/delombok/FormatPreferences.java
index 9bd668a5..3861685d 100644
--- a/src/delombok/lombok/delombok/FormatPreferences.java
+++ b/src/delombok/lombok/delombok/FormatPreferences.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2013-2015 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
@@ -33,6 +33,7 @@ public final class FormatPreferences {
private final boolean generateConstructorProperties;
private final boolean generateSuppressWarnings, danceAroundIdeChecks, generateDelombokComment, javaLangAsFqn;
final Map<String, String> rawMap;
+ private final boolean generateGenerated;
static final Map<String, String> KEYS;
@@ -42,7 +43,8 @@ public final class FormatPreferences {
keys.put("emptyLines", "Either 'indent' or 'blank'. indent means: Indent an empty line to the right level. Default: 'blank'");
keys.put("finalParams", "Either 'generate' or 'skip'. generate means: All lombok-generated methods set all parameters to final. Default: 'generate'");
keys.put("constructorProperties", "Either 'generate' or 'skip'. generate means: All lombok-generated constructors with 1 or more arguments get an @ConstructorProperties annotation. Default: 'generate'");
- keys.put("suppressWarnings", "Either 'generate' or 'skip'. generate means: All lombok-generated methods get a @SuppressWarnings annotation. Default: 'generate'");
+ keys.put("suppressWarnings", "Either 'generate' or 'skip'. generate means: All lombok-generated methods, types, and fields get a @SuppressWarnings annotation. Default: 'generate'");
+ keys.put("generated", "Either 'generate' or 'skip'. generate means: All lombok-generated methods, types, and fields get a @javax.annotation.Generated(\"lombok\") annotation. Default: 'generate'");
keys.put("danceAroundIdeChecks", "Either 'generate' or 'skip'. generate means: Lombok will intentionally obfuscate some generated code to avoid IDE warnings. Default: 'generate'");
keys.put("generateDelombokComment", "Either 'generate' or 'skip'. generate means: Any file modified by delombok will have a comment stating this at the top. Default: 'generate'");
keys.put("javaLangAsFQN", "Either 'generate' or 'skip'. generate means: Any generated reference to java.lang classes are prefixed with `java.lang.`. Default: 'generate'");
@@ -82,6 +84,7 @@ public final class FormatPreferences {
this.generateFinalParams = unrollBoolean(preferences, "finalParams", "generate", "skip", true);
this.generateConstructorProperties = unrollBoolean(preferences, "constructorProperties", "generate", "skip", true);
this.generateSuppressWarnings = unrollBoolean(preferences, "suppressWarnings", "generate", "skip", true);
+ this.generateGenerated = unrollBoolean(preferences, "generated", "generate", "skip", true);
this.danceAroundIdeChecks = unrollBoolean(preferences, "danceAroundIdeChecks", "generate", "skip", true);
this.generateDelombokComment = unrollBoolean(preferences, "generateDelombokComment", "generate", "skip", true);
this.javaLangAsFqn = unrollBoolean(preferences, "javaLangAsFQN", "generate", "skip", true);
@@ -112,6 +115,10 @@ public final class FormatPreferences {
return generateSuppressWarnings;
}
+ public boolean generateGenerated() {
+ return generateGenerated;
+ }
+
public boolean generateFinalParams() {
return generateFinalParams;
}
@@ -131,4 +138,8 @@ public final class FormatPreferences {
public boolean generateConstructorProperties() {
return generateConstructorProperties;
}
+
+ @Override public String toString() {
+ return rawMap.toString();
+ }
}
diff --git a/src/delombok/lombok/delombok/LombokOptionsFactory.java b/src/delombok/lombok/delombok/LombokOptionsFactory.java
index 47921931..62dc953a 100644
--- a/src/delombok/lombok/delombok/LombokOptionsFactory.java
+++ b/src/delombok/lombok/delombok/LombokOptionsFactory.java
@@ -24,6 +24,7 @@ package lombok.delombok;
import lombok.javac.Javac;
import lombok.javac.Javac6BasedLombokOptions;
import lombok.javac.Javac8BasedLombokOptions;
+import lombok.javac.Javac9BasedLombokOptions;
import lombok.javac.LombokOptions;
import com.sun.tools.javac.util.Context;
@@ -41,9 +42,15 @@ public class LombokOptionsFactory {
@Override LombokOptions createAndRegisterOptions(Context context) {
return Javac8BasedLombokOptions.replaceWithDelombokOptions(context);
}
+ },
+
+ JDK9 {
+ @Override LombokOptions createAndRegisterOptions(Context context) {
+ return Javac9BasedLombokOptions.replaceWithDelombokOptions(context);
+ }
};
- abstract LombokOptions createAndRegisterOptions(Context context);
+ abstract LombokOptions createAndRegisterOptions(Context context);
}
public static LombokOptions getDelombokOptions(Context context) {
@@ -53,8 +60,10 @@ public class LombokOptionsFactory {
LombokOptions options;
if (Javac.getJavaCompilerVersion() < 8) {
options = LombokOptionCompilerVersion.JDK7_AND_LOWER.createAndRegisterOptions(context);
- } else {
+ } else if (Javac.getJavaCompilerVersion() == 8) {
options = LombokOptionCompilerVersion.JDK8.createAndRegisterOptions(context);
+ } else {
+ options = LombokOptionCompilerVersion.JDK9.createAndRegisterOptions(context);
}
return options;
}
diff --git a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java b/src/delombok/lombok/delombok/PrettyCommentsPrinter.java
deleted file mode 100644
index 9dd7e40e..00000000
--- a/src/delombok/lombok/delombok/PrettyCommentsPrinter.java
+++ /dev/null
@@ -1,1680 +0,0 @@
-/*
- * Copyright 1999-2006 Sun Microsystems, Inc. All Rights Reserved.
- * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
- *
- * This code is free software; you can redistribute it and/or modify it
- * under the terms of the GNU General Public License version 2 only, as
- * published by the Free Software Foundation. Sun designates this
- * particular file as subject to the "Classpath" exception as provided
- * by Sun in the LICENSE file that accompanied this code.
- *
- * This code is distributed in the hope that it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
- * version 2 for more details (a copy is included in the LICENSE file that
- * accompanied this code).
- *
- * You should have received a copy of the GNU General Public License version
- * 2 along with this work; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
- *
- * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
- * 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.*;
-import static lombok.javac.Javac.*;
-import static lombok.javac.JavacTreeMaker.TreeTag.treeTag;
-import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
-
-import java.io.IOException;
-import java.io.Writer;
-import java.lang.reflect.Field;
-import java.util.HashMap;
-import java.util.Map;
-
-import lombok.javac.CommentInfo;
-import lombok.javac.CommentInfo.EndConnection;
-import lombok.javac.CommentInfo.StartConnection;
-import lombok.javac.JavacTreeMaker.TreeTag;
-import lombok.javac.JavacTreeMaker.TypeTag;
-
-import com.sun.source.tree.Tree;
-import com.sun.tools.javac.code.Flags;
-import com.sun.tools.javac.code.Symbol;
-import com.sun.tools.javac.tree.DocCommentTable;
-import com.sun.tools.javac.tree.JCTree;
-import com.sun.tools.javac.tree.JCTree.JCAnnotation;
-import com.sun.tools.javac.tree.JCTree.JCArrayAccess;
-import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
-import com.sun.tools.javac.tree.JCTree.JCAssert;
-import com.sun.tools.javac.tree.JCTree.JCAssign;
-import com.sun.tools.javac.tree.JCTree.JCAssignOp;
-import com.sun.tools.javac.tree.JCTree.JCBinary;
-import com.sun.tools.javac.tree.JCTree.JCBlock;
-import com.sun.tools.javac.tree.JCTree.JCBreak;
-import com.sun.tools.javac.tree.JCTree.JCCase;
-import com.sun.tools.javac.tree.JCTree.JCCatch;
-import com.sun.tools.javac.tree.JCTree.JCClassDecl;
-import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
-import com.sun.tools.javac.tree.JCTree.JCConditional;
-import com.sun.tools.javac.tree.JCTree.JCContinue;
-import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
-import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
-import com.sun.tools.javac.tree.JCTree.JCErroneous;
-import com.sun.tools.javac.tree.JCTree.JCExpression;
-import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
-import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
-import com.sun.tools.javac.tree.JCTree.JCForLoop;
-import com.sun.tools.javac.tree.JCTree.JCIdent;
-import com.sun.tools.javac.tree.JCTree.JCIf;
-import com.sun.tools.javac.tree.JCTree.JCImport;
-import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
-import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
-import com.sun.tools.javac.tree.JCTree.JCLiteral;
-import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
-import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
-import com.sun.tools.javac.tree.JCTree.JCModifiers;
-import com.sun.tools.javac.tree.JCTree.JCNewArray;
-import com.sun.tools.javac.tree.JCTree.JCNewClass;
-import com.sun.tools.javac.tree.JCTree.JCParens;
-import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
-import com.sun.tools.javac.tree.JCTree.JCReturn;
-import com.sun.tools.javac.tree.JCTree.JCSkip;
-import com.sun.tools.javac.tree.JCTree.JCStatement;
-import com.sun.tools.javac.tree.JCTree.JCSwitch;
-import com.sun.tools.javac.tree.JCTree.JCSynchronized;
-import com.sun.tools.javac.tree.JCTree.JCThrow;
-import com.sun.tools.javac.tree.JCTree.JCTry;
-import com.sun.tools.javac.tree.JCTree.JCTypeApply;
-import com.sun.tools.javac.tree.JCTree.JCTypeCast;
-import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
-import com.sun.tools.javac.tree.JCTree.JCUnary;
-import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
-import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
-import com.sun.tools.javac.tree.JCTree.JCWildcard;
-import com.sun.tools.javac.tree.JCTree.LetExpr;
-import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
-import com.sun.tools.javac.tree.TreeInfo;
-import com.sun.tools.javac.tree.TreeScanner;
-import com.sun.tools.javac.util.Convert;
-import com.sun.tools.javac.util.List;
-import com.sun.tools.javac.util.Name;
-import com.sun.tools.javac.util.Position;
-//import com.sun.tools.javac.code.TypeTags;
-
-/** Prints out a tree as an indented Java source program.
- *
- * <p><b>This is NOT part of any API supported by Sun Microsystems. If
- * you write code that depends on this, you do so at your own risk.
- * This code and its internal interfaces are subject to change or
- * deletion without notice.</b>
- */
-@SuppressWarnings("all") // Mainly sun code that has other warning settings
-public class PrettyCommentsPrinter extends JCTree.Visitor {
- private static final TreeTag PARENS = treeTag("PARENS");
- private static final TreeTag IMPORT = treeTag("IMPORT");
- private static final TreeTag VARDEF = treeTag("VARDEF");
- private static final TreeTag SELECT = treeTag("SELECT");
-
- private static final Map<TreeTag, String> OPERATORS;
-
- // StandardFlags | DEFAULT
- private static final long EXTENDED_STANDARD_FLAGS = 0x0fffL | 1L<<43;
-
- static {
- Map<TreeTag, String> map = new HashMap<TreeTag, String>();
-
- map.put(treeTag("POS"), "+");
- map.put(treeTag("NEG"), "-");
- map.put(treeTag("NOT"), "!");
- map.put(treeTag("COMPL"), "~");
- map.put(treeTag("PREINC"), "++");
- map.put(treeTag("PREDEC"), "--");
- map.put(treeTag("POSTINC"), "++");
- map.put(treeTag("POSTDEC"), "--");
- map.put(treeTag("NULLCHK"), "<*nullchk*>");
- map.put(treeTag("OR"), "||");
- map.put(treeTag("AND"), "&&");
- map.put(treeTag("EQ"), "==");
- map.put(treeTag("NE"), "!=");
- map.put(treeTag("LT"), "<");
- map.put(treeTag("GT"), ">");
- map.put(treeTag("LE"), "<=");
- map.put(treeTag("GE"), ">=");
- map.put(treeTag("BITOR"), "|");
- map.put(treeTag("BITXOR"), "^");
- map.put(treeTag("BITAND"), "&");
- map.put(treeTag("SL"), "<<");
- map.put(treeTag("SR"), ">>");
- map.put(treeTag("USR"), ">>>");
- map.put(treeTag("PLUS"), "+");
- map.put(treeTag("MINUS"), "-");
- map.put(treeTag("MUL"), "*");
- map.put(treeTag("DIV"), "/");
- map.put(treeTag("MOD"), "%");
-
- map.put(treeTag("BITOR_ASG"), "|=");
- map.put(treeTag("BITXOR_ASG"), "^=");
- map.put(treeTag("BITAND_ASG"), "&=");
- map.put(treeTag("SL_ASG"), "<<=");
- map.put(treeTag("SR_ASG"), ">>=");
- map.put(treeTag("USR_ASG"), ">>>=");
- map.put(treeTag("PLUS_ASG"), "+=");
- map.put(treeTag("MINUS_ASG"), "-=");
- map.put(treeTag("MUL_ASG"), "*=");
- map.put(treeTag("DIV_ASG"), "/=");
- map.put(treeTag("MOD_ASG"), "%=");
-
- OPERATORS = map;
- }
-
- private List<CommentInfo> comments;
- private final JCCompilationUnit cu;
- private boolean onNewLine = true;
- private boolean aligned = false;
- private boolean inParams = false;
-
- private boolean needsSpace = false;
- private boolean needsNewLine = false;
- private boolean needsAlign = false;
-
- // Flag for try-with-resources to make them not final and not print the last semicolon.
- // This flag is set just before printing the vardef and cleared when printing its modifiers.
- private boolean suppressFinalAndSemicolonsInTry = false;
-
- private final FormatPreferences formatPreferences;
-
- public PrettyCommentsPrinter(Writer out, JCCompilationUnit cu, List<CommentInfo> comments, FormatPreferences preferences) {
- this.out = out;
- this.comments = comments;
- this.cu = cu;
- this.formatPreferences = preferences;
- }
-
- private int endPos(JCTree tree) {
- return getEndPosition(tree, cu);
- }
-
- private void consumeComments(int until) throws IOException {
- consumeComments(until, null);
- }
-
- private void consumeComments(int until, JCTree tree) throws IOException {
- boolean prevNewLine = onNewLine;
- boolean found = false;
- CommentInfo head = comments.head;
- while (comments.nonEmpty() && head.pos < until) {
- printComment(head);
- comments = comments.tail;
- head = comments.head;
- }
- if (!onNewLine && prevNewLine) {
- println();
- }
- }
-
- private void consumeTrailingComments(int from) throws IOException {
- boolean prevNewLine = onNewLine;
- CommentInfo head = comments.head;
- boolean stop = false;
- while (comments.nonEmpty() && head.prevEndPos == from && !stop && !(head.start == StartConnection.ON_NEXT_LINE || head.start == StartConnection.START_OF_LINE)) {
- from = head.endPos;
- printComment(head);
- stop = (head.end == EndConnection.ON_NEXT_LINE);
- comments = comments.tail;
- head = comments.head;
- }
- if (!onNewLine && prevNewLine) {
- println();
- }
- }
-
- private void printComment(CommentInfo comment) throws IOException {
- prepareComment(comment.start);
- print(comment.content);
- switch (comment.end) {
- case ON_NEXT_LINE:
- if (!aligned) {
- needsNewLine = true;
- needsAlign = true;
- }
- break;
- case AFTER_COMMENT:
- needsSpace = true;
- break;
- case DIRECT_AFTER_COMMENT:
- // do nothing
- break;
- }
- }
-
- private void prepareComment(StartConnection start) throws IOException {
- switch (start) {
- case DIRECT_AFTER_PREVIOUS:
- needsSpace = false;
- break;
- case AFTER_PREVIOUS:
- needsSpace = true;
- break;
- case START_OF_LINE:
- needsNewLine = true;
- needsAlign = false;
- break;
- case ON_NEXT_LINE:
- if (!aligned) {
- needsNewLine = true;
- needsAlign = true;
- }
- break;
- }
- }
-
- /** The output stream on which trees are printed.
- */
- Writer out;
-
- /** The current left margin.
- */
- int lmargin = 0;
-
- /** The enclosing class name.
- */
- Name enclClassName;
-
- /** A hashtable mapping trees to their documentation comments
- * (can be null)
- */
- Map<JCTree, String> docComments = null;
- DocCommentTable docTable = null;
-
- String getJavadocFor(JCTree node) {
- if (docComments != null) return docComments.get(node);
- if (docTable != null) return docTable.getCommentText(node);
- return null;
- }
-
- /** Align code to be indented to left margin.
- */
- void align() throws IOException {
- onNewLine = false;
- aligned = true;
- needsAlign = false;
- for (int i = 0; i < lmargin; i++) out.write(formatPreferences.indent());
- }
-
- /** Increase left margin by indentation width.
- */
- void indent() {
- lmargin++;
- }
-
- /** Decrease left margin by indentation width.
- */
- void undent() {
- lmargin--;
- }
-
- /** Enter a new precedence level. Emit a `(' if new precedence level
- * is less than precedence level so far.
- * @param contextPrec The precedence level in force so far.
- * @param ownPrec The new precedence level.
- */
- void open(int contextPrec, int ownPrec) throws IOException {
- if (ownPrec < contextPrec) out.write("(");
- }
-
- /** Leave precedence level. Emit a `(' if inner precedence level
- * is less than precedence level we revert to.
- * @param contextPrec The precedence level we revert to.
- * @param ownPrec The inner precedence level.
- */
- void close(int contextPrec, int ownPrec) throws IOException {
- if (ownPrec < contextPrec) out.write(")");
- }
-
- /** Print string, replacing all non-ascii character with unicode escapes.
- */
- public void print(Object s) throws IOException {
- boolean align = needsAlign;
- if (needsNewLine && !onNewLine) {
- println();
- }
- if (align && !aligned) {
- align();
- }
- if (needsSpace && !onNewLine && !aligned) {
- out.write(' ');
- }
- needsSpace = false;
-
- out.write(Convert.escapeUnicode(s.toString()));
-
- onNewLine = false;
- aligned = false;
- }
-
- /** Print new line.
- */
- public void println() throws IOException {
- onNewLine = true;
- aligned = false;
- needsNewLine = false;
- out.write(lineSep);
- }
-
- String lineSep = System.getProperty("line.separator");
-
- /**************************************************************************
- * Traversal methods
- *************************************************************************/
-
- /** Exception to propagate IOException through visitXXX methods */
- private static class UncheckedIOException extends Error {
- static final long serialVersionUID = -4032692679158424751L;
- UncheckedIOException(IOException e) {
- super(e.getMessage(), e);
- }
- }
-
- /** Visitor argument: the current precedence level.
- */
- int prec;
-
- /** Visitor method: print expression tree.
- * @param prec The current precedence level.
- */
- public void printExpr(JCTree tree, int prec) throws IOException {
-
- int prevPrec = this.prec;
- try {
- this.prec = prec;
- if (tree == null) print("/*missing*/");
- else {
- consumeComments(tree.pos, tree);
- tree.accept(this);
- int endPos = endPos(tree);
- consumeTrailingComments(endPos);
- }
- } catch (UncheckedIOException ex) {
- IOException e = new IOException(ex.getMessage());
- e.initCause(ex);
- throw e;
- } finally {
- this.prec = prevPrec;
- }
- }
-
- /** Derived visitor method: print expression tree at minimum precedence level
- * for expression.
- */
- public void printExpr(JCTree tree) throws IOException {
- printExpr(tree, TreeInfo.noPrec);
- }
-
- /** Derived visitor method: print statement tree.
- */
- public void printStat(JCTree tree) throws IOException {
- if (isEmptyStat(tree)) {
- // printEmptyStat(); // -- starting in java 7, these get lost, so to be consistent, we never print them.
- } else {
- printExpr(tree, TreeInfo.notExpression);
- }
- }
-
- public void printEmptyStat() throws IOException {
- print(";");
- }
-
- public boolean isEmptyStat(JCTree tree) {
- if (!(tree instanceof JCBlock)) return false;
- JCBlock block = (JCBlock) tree;
- return (Position.NOPOS == block.pos) && block.stats.isEmpty();
- }
-
- /** Derived visitor method: print list of expression trees, separated by given string.
- * @param sep the separator string
- */
- public <T extends JCTree> void printExprs(List<T> trees, String sep) throws IOException {
- if (trees.nonEmpty()) {
- printExpr(trees.head);
- for (List<T> l = trees.tail; l.nonEmpty(); l = l.tail) {
- print(sep);
- printExpr(l.head);
- }
- }
- }
-
- /** Derived visitor method: print list of expression trees, separated by commas.
- */
- public <T extends JCTree> void printExprs(List<T> trees) throws IOException {
- printExprs(trees, ", ");
- }
-
- /** Derived visitor method: print list of statements, each on a separate line.
- */
- public void printStats(List<? extends JCTree> trees) throws IOException {
- for (List<? extends JCTree> l = trees; l.nonEmpty(); l = l.tail) {
- if (isSuppressed(l.head)) continue;
- if (!suppressAlignmentForEmptyLines(l.head)) align();
- printStat(l.head);
- println();
- }
- }
-
- private boolean suppressAlignmentForEmptyLines(JCTree tree) {
- return !formatPreferences.fillEmpties() && startsWithNewLine(tree);
- }
-
- private boolean startsWithNewLine(JCTree tree) {
- return tree instanceof JCMethodDecl || tree instanceof JCClassDecl;
- }
-
- private boolean isSuppressed(JCTree tree) {
- if (isEmptyStat(tree)) {
- return true;
- }
- if (tree instanceof JCExpressionStatement) {
- return isNoArgsSuperCall(((JCExpressionStatement)tree).expr);
- }
- return false;
- }
-
- /** Print a set of modifiers.
- */
- public void printFlags(long flags) throws IOException {
- if ((flags & SYNTHETIC) != 0) print("/*synthetic*/ ");
- if (suppressFinalAndSemicolonsInTry) {
- flags = flags & ~FINAL;
- suppressFinalAndSemicolonsInTry = false;
- }
- print(TreeInfo.flagNames(flags));
- if ((flags & EXTENDED_STANDARD_FLAGS) != 0) print(" ");
- if ((flags & ANNOTATION) != 0) print("@");
- }
-
- public void printAnnotations(List<JCAnnotation> trees) throws IOException {
- for (List<JCAnnotation> l = trees; l.nonEmpty(); l = l.tail) {
- printStat(l.head);
- if (inParams) {
- print(" ");
- }
- else {
- println();
- align();
- }
- }
- }
-
- /** Print documentation comment, if it exists
- * @param tree The tree for which a documentation comment should be printed.
- */
- public void printDocComment(JCTree tree) throws IOException {
- String dc = getJavadocFor(tree);
- if (dc == null) return;
- print("/**"); println();
- int pos = 0;
- int endpos = lineEndPos(dc, pos);
- boolean atStart = true;
- while (pos < dc.length()) {
- String line = dc.substring(pos, endpos);
- if (line.trim().isEmpty() && atStart) {
- atStart = false;
- continue;
- }
- atStart = false;
- align();
- print(" *");
- if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
- print(dc.substring(pos, endpos)); println();
- pos = endpos + 1;
- endpos = lineEndPos(dc, pos);
- }
- align(); print(" */"); println();
- align();
- }
-//where
- static int lineEndPos(String s, int start) {
- int pos = s.indexOf('\n', start);
- if (pos < 0) pos = s.length();
- return pos;
- }
-
- /** If type parameter list is non-empty, print it enclosed in "<...>" brackets.
- */
- public void printTypeParameters(List<JCTypeParameter> trees) throws IOException {
- if (trees.nonEmpty()) {
- print("<");
- printExprs(trees);
- print(">");
- }
- }
-
- /** Print a block.
- */
- public void printBlock(List<? extends JCTree> stats, JCTree container) throws IOException {
- print("{");
- println();
- indent();
- printStats(stats);
- consumeComments(endPos(container));
- undent();
- align();
- print("}");
- }
-
- /** Print a block.
- */
- public void printEnumBody(List<JCTree> stats) throws IOException {
- print("{");
- println();
- indent();
- boolean first = true;
- for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
- if (isEnumerator(l.head)) {
- if (!first) {
- print(",");
- println();
- }
- align();
- printStat(l.head);
- first = false;
- }
- }
- print(";");
- println();
- int x = 0;
- for (List<JCTree> l = stats; l.nonEmpty(); l = l.tail) {
- x++;
- if (!isEnumerator(l.head)) {
- if (!suppressAlignmentForEmptyLines(l.head)) align();
- printStat(l.head);
- println();
- }
- }
- undent();
- align();
- print("}");
- }
-
- public void printEnumMember(JCVariableDecl tree) throws IOException {
- printAnnotations(tree.mods.annotations);
- print(tree.name);
- if (tree.init instanceof JCNewClass) {
- JCNewClass constructor = (JCNewClass) tree.init;
- if (constructor.args != null && constructor.args.nonEmpty()) {
- print("(");
- printExprs(constructor.args);
- print(")");
- }
- if (constructor.def != null && constructor.def.defs != null) {
- print(" ");
- printBlock(constructor.def.defs, constructor.def);
- }
- }
- }
-
- /** Is the given tree an enumerator definition? */
- boolean isEnumerator(JCTree t) {
- return VARDEF.equals(treeTag(t)) && (((JCVariableDecl) t).mods.flags & ENUM) != 0;
- }
-
- /** Print unit consisting of package clause and import statements in toplevel,
- * followed by class definition. if class definition == null,
- * print all definitions in toplevel.
- * @param tree The toplevel tree
- * @param cdef The class definition, which is assumed to be part of the
- * toplevel tree.
- */
- public void printUnit(JCCompilationUnit tree, JCClassDecl cdef) throws IOException {
- Object dc = getDocComments(tree);
- loadDocCommentsTable(dc);
- printDocComment(tree);
- if (tree.pid != null) {
- consumeComments(tree.pos, tree);
- print("package ");
- printExpr(tree.pid);
- print(";");
- println();
- }
- boolean firstImport = true;
- for (List<JCTree> l = tree.defs;
- l.nonEmpty() && (cdef == null || IMPORT.equals(treeTag(l.head)));
- l = l.tail) {
- if (IMPORT.equals(treeTag(l.head))) {
- JCImport imp = (JCImport)l.head;
- Name name = TreeInfo.name(imp.qualid);
- if (name == name.table.fromChars(new char[] {'*'}, 0, 1) ||
- cdef == null ||
- isUsed(TreeInfo.symbol(imp.qualid), cdef)) {
- if (firstImport) {
- firstImport = false;
- println();
- }
- printStat(imp);
- }
- } else {
- printStat(l.head);
- }
- }
- if (cdef != null) {
- printStat(cdef);
- println();
- }
- }
- // where
- @SuppressWarnings("unchecked")
- private void loadDocCommentsTable(Object dc) {
- if (dc instanceof Map<?, ?>) this.docComments = (Map) dc;
- else if (dc instanceof DocCommentTable) this.docTable = (DocCommentTable) dc;
- }
-
- boolean isUsed(final Symbol t, JCTree cdef) {
- class UsedVisitor extends TreeScanner {
- public void scan(JCTree tree) {
- if (tree!=null && !result) tree.accept(this);
- }
- boolean result = false;
- public void visitIdent(JCIdent tree) {
- if (tree.sym == t) result = true;
- }
- }
- UsedVisitor v = new UsedVisitor();
- v.scan(cdef);
- return v.result;
- }
-
- /**************************************************************************
- * Visitor methods
- *************************************************************************/
-
- public void visitTopLevel(JCCompilationUnit tree) {
- try {
- printUnit(tree, null);
- consumeComments(Integer.MAX_VALUE);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitImport(JCImport tree) {
- try {
- print("import ");
- if (tree.staticImport) print("static ");
- printExpr(tree.qualid);
- print(";");
- println();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitClassDef(JCClassDecl tree) {
- try {
- consumeComments(tree.pos, tree);
- println(); align();
- printDocComment(tree);
- printAnnotations(tree.mods.annotations);
- printFlags(tree.mods.flags & ~INTERFACE);
- Name enclClassNamePrev = enclClassName;
- enclClassName = tree.name;
- if ((tree.mods.flags & INTERFACE) != 0) {
- print("interface " + tree.name);
- printTypeParameters(tree.typarams);
- if (tree.implementing.nonEmpty()) {
- print(" extends ");
- printExprs(tree.implementing);
- }
- } else {
- if ((tree.mods.flags & ENUM) != 0)
- print("enum " + tree.name);
- else
- print("class " + tree.name);
- printTypeParameters(tree.typarams);
- if (getExtendsClause(tree) != null) {
- print(" extends ");
- printExpr(getExtendsClause(tree));
- }
- if (tree.implementing.nonEmpty()) {
- print(" implements ");
- printExprs(tree.implementing);
- }
- }
- print(" ");
- // <Added for delombok by Reinier Zwitserloot>
- if ((tree.mods.flags & INTERFACE) != 0) {
- removeImplicitModifiersForInterfaceMembers(tree.defs);
- }
- // </Added for delombok by Reinier Zwitserloot>
- if ((tree.mods.flags & ENUM) != 0) {
- printEnumBody(tree.defs);
- } else {
- printBlock(tree.defs, tree);
- }
- enclClassName = enclClassNamePrev;
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- // Added for delombok by Reinier Zwitserloot
- private void removeImplicitModifiersForInterfaceMembers(List<JCTree> defs) {
- for (JCTree def :defs) {
- if (def instanceof JCVariableDecl) {
- ((JCVariableDecl) def).mods.flags &= ~(Flags.PUBLIC | Flags.STATIC | Flags.FINAL);
- }
- if (def instanceof JCMethodDecl) {
- ((JCMethodDecl) def).mods.flags &= ~(Flags.PUBLIC | Flags.ABSTRACT);
- }
- if (def instanceof JCClassDecl) {
- ((JCClassDecl) def).mods.flags &= ~(Flags.PUBLIC | Flags.STATIC);
- }
- }
- }
-
- public void visitMethodDef(JCMethodDecl tree) {
- try {
- boolean isConstructor = tree.name == tree.name.table.fromChars("<init>".toCharArray(), 0, 6);
- // when producing source output, omit anonymous constructors
- if (isConstructor && enclClassName == null) return;
- boolean isGeneratedConstructor = isConstructor && ((tree.mods.flags & Flags.GENERATEDCONSTR) != 0);
- if (isGeneratedConstructor) return;
- println(); align();
- printDocComment(tree);
- printExpr(tree.mods);
- printTypeParameters(tree.typarams);
- if (tree.typarams != null && tree.typarams.length() > 0) print(" ");
- if (tree.name == tree.name.table.fromChars("<init>".toCharArray(), 0, 6)) {
- print(enclClassName != null ? enclClassName : tree.name);
- } else {
- printExpr(tree.restype);
- print(" " + tree.name);
- }
- print("(");
- inParams = true;
- printExprs(tree.params);
- inParams = false;
- print(")");
- if (tree.thrown.nonEmpty()) {
- print(" throws ");
- printExprs(tree.thrown);
- }
- if (tree.defaultValue != null) {
- print(" default ");
- print(tree.defaultValue);
- }
- if (tree.body != null) {
- print(" ");
- printBlock(tree.body.stats, tree.body);
- } else {
- print(";");
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitVarDef(JCVariableDecl tree) {
- try {
- boolean suppressSemi = suppressFinalAndSemicolonsInTry;
- if (getJavadocFor(tree) != null) {
- println(); align();
- }
- printDocComment(tree);
- if ((tree.mods.flags & ENUM) != 0) {
- printEnumMember(tree);
- } else {
- printExpr(tree.mods);
- if ((tree.mods.flags & VARARGS) != 0) {
- printExpr(((JCArrayTypeTree) tree.vartype).elemtype);
- print("... " + tree.name);
- } else {
- printExpr(tree.vartype);
- print(" " + tree.name);
- }
- if (tree.init != null) {
- print(" = ");
- printExpr(tree.init);
- }
- if (prec == TreeInfo.notExpression && !suppressSemi) print(";");
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitSkip(JCSkip tree) {
- try {
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitBlock(JCBlock tree) {
- try {
- consumeComments(tree.pos);
- printFlags(tree.flags);
- printBlock(tree.stats, tree);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitDoLoop(JCDoWhileLoop tree) {
- try {
- print("do ");
- printStat(tree.body);
- align();
- print(" while ");
- if (PARENS.equals(treeTag(tree.cond))) {
- printExpr(tree.cond);
- } else {
- print("(");
- printExpr(tree.cond);
- print(")");
- }
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitWhileLoop(JCWhileLoop tree) {
- try {
- print("while ");
- if (PARENS.equals(treeTag(tree.cond))) {
- printExpr(tree.cond);
- } else {
- print("(");
- printExpr(tree.cond);
- print(")");
- }
- print(" ");
- printStat(tree.body);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitForLoop(JCForLoop tree) {
- try {
- print("for (");
- if (tree.init.nonEmpty()) {
- if (VARDEF.equals(treeTag(tree.init.head))) {
- printExpr(tree.init.head);
- for (List<JCStatement> l = tree.init.tail; l.nonEmpty(); l = l.tail) {
- JCVariableDecl vdef = (JCVariableDecl)l.head;
- print(", " + vdef.name + " = ");
- printExpr(vdef.init);
- }
- } else {
- printExprs(tree.init);
- }
- }
- print("; ");
- if (tree.cond != null) printExpr(tree.cond);
- print("; ");
- printExprs(tree.step);
- print(") ");
- printStat(tree.body);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitForeachLoop(JCEnhancedForLoop tree) {
- try {
- print("for (");
- printExpr(tree.var);
- print(" : ");
- printExpr(tree.expr);
- print(") ");
- printStat(tree.body);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitLabelled(JCLabeledStatement tree) {
- try {
- print(tree.label + ":");
- if (isEmptyStat(tree.body) || tree.body instanceof JCSkip) {
- print(" ;");
- } else if (tree.body instanceof JCBlock) {
- print(" ");
- printStat(tree.body);
- } else {
- println();
- align();
- printStat(tree.body);
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitSwitch(JCSwitch tree) {
- try {
- print("switch ");
- if (PARENS.equals(treeTag(tree.selector))) {
- printExpr(tree.selector);
- } else {
- print("(");
- printExpr(tree.selector);
- print(")");
- }
- print(" {");
- println();
- printStats(tree.cases);
- align();
- print("}");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitCase(JCCase tree) {
- try {
- if (tree.pat == null) {
- print("default");
- } else {
- print("case ");
- printExpr(tree.pat);
- }
- print(": ");
- println();
- indent();
- printStats(tree.stats);
- undent();
- align();
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitSynchronized(JCSynchronized tree) {
- try {
- print("synchronized ");
- if (PARENS.equals(treeTag(tree.lock))) {
- printExpr(tree.lock);
- } else {
- print("(");
- printExpr(tree.lock);
- print(")");
- }
- print(" ");
- printStat(tree.body);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- 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()) {
- print("(");
- int remaining = resources.size();
- if (remaining == 1) {
- JCTree var = (JCTree) resources.get(0);
- suppressFinalAndSemicolonsInTry = true;
- printStat(var);
- print(") ");
- } else {
- indent(); indent();
- for (Object var0 : resources) {
- println();
- align();
- JCTree var = (JCTree) var0;
- suppressFinalAndSemicolonsInTry = true;
- printStat(var);
- remaining--;
- if (remaining > 0) print(";");
- }
- print(") ");
- undent(); undent();
- }
- }
-
- printStat(tree.body);
- for (List<JCCatch> l = tree.catchers; l.nonEmpty(); l = l.tail) {
- printStat(l.head);
- }
- if (tree.finalizer != null) {
- print(" finally ");
- printStat(tree.finalizer);
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitCatch(JCCatch tree) {
- try {
- print(" catch (");
- printExpr(tree.param);
- print(") ");
- printStat(tree.body);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitConditional(JCConditional tree) {
- try {
- open(prec, TreeInfo.condPrec);
- printExpr(tree.cond, TreeInfo.condPrec);
- print(" ? ");
- printExpr(tree.truepart, TreeInfo.condPrec);
- print(" : ");
- printExpr(tree.falsepart, TreeInfo.condPrec);
- close(prec, TreeInfo.condPrec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitIf(JCIf tree) {
- try {
- print("if ");
- if (PARENS.equals(treeTag(tree.cond))) {
- printExpr(tree.cond);
- } else {
- print("(");
- printExpr(tree.cond);
- print(")");
- }
- print(" ");
- printStat(tree.thenpart);
- if (tree.elsepart != null) {
- print(" else ");
- printStat(tree.elsepart);
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private boolean isNoArgsSuperCall(JCExpression expr) {
- if (!(expr instanceof JCMethodInvocation)) return false;
- JCMethodInvocation tree = (JCMethodInvocation) expr;
- if (!tree.typeargs.isEmpty() || !tree.args.isEmpty()) return false;
- if (!(tree.meth instanceof JCIdent)) return false;
- return ((JCIdent) tree.meth).name.toString().equals("super");
- }
-
- public void visitExec(JCExpressionStatement tree) {
- if (isNoArgsSuperCall(tree.expr)) return;
- try {
- printExpr(tree.expr);
- if (prec == TreeInfo.notExpression) print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitBreak(JCBreak tree) {
- try {
- print("break");
- if (tree.label != null) print(" " + tree.label);
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitContinue(JCContinue tree) {
- try {
- print("continue");
- if (tree.label != null) print(" " + tree.label);
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitReturn(JCReturn tree) {
- try {
- print("return");
- if (tree.expr != null) {
- print(" ");
- printExpr(tree.expr);
- }
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitThrow(JCThrow tree) {
- try {
- print("throw ");
- printExpr(tree.expr);
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitAssert(JCAssert tree) {
- try {
- print("assert ");
- printExpr(tree.cond);
- if (tree.detail != null) {
- print(" : ");
- printExpr(tree.detail);
- }
- print(";");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitApply(JCMethodInvocation tree) {
- try {
- if (!tree.typeargs.isEmpty()) {
- if (SELECT.equals(treeTag(tree.meth))) {
- JCFieldAccess left = (JCFieldAccess)tree.meth;
- printExpr(left.selected);
- print(".<");
- printExprs(tree.typeargs);
- print(">" + left.name);
- } else {
- print("<");
- printExprs(tree.typeargs);
- print(">");
- printExpr(tree.meth);
- }
- } else {
- printExpr(tree.meth);
- }
- print("(");
- printExprs(tree.args);
- print(")");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitNewClass(JCNewClass tree) {
- try {
- if (tree.encl != null) {
- printExpr(tree.encl);
- print(".");
- }
- print("new ");
- if (!tree.typeargs.isEmpty()) {
- print("<");
- printExprs(tree.typeargs);
- print(">");
- }
- printExpr(tree.clazz);
- print("(");
- printExprs(tree.args);
- print(")");
- if (tree.def != null) {
- Name enclClassNamePrev = enclClassName;
- enclClassName =
- tree.def.name != null ? tree.def.name :
- tree.type != null && tree.type.tsym.name != tree.type.tsym.name.table.fromChars(new char[0], 0, 0) ? tree.type.tsym.name :
- null;
- if ((tree.def.mods.flags & Flags.ENUM) != 0) print("/*enum*/");
- printBlock(tree.def.defs, tree.def);
- enclClassName = enclClassNamePrev;
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitNewArray(JCNewArray tree) {
- try {
- if (tree.elemtype != null) {
- print("new ");
- JCTree elem = tree.elemtype;
- if (elem instanceof JCArrayTypeTree)
- printBaseElementType((JCArrayTypeTree) elem);
- else
- printExpr(elem);
- for (List<JCExpression> l = tree.dims; l.nonEmpty(); l = l.tail) {
- print("[");
- printExpr(l.head);
- print("]");
- }
- if (elem instanceof JCArrayTypeTree)
- printBrackets((JCArrayTypeTree) elem);
- }
- if (tree.elems != null) {
- if (tree.elemtype != null) print("[]");
- print("{");
- printExprs(tree.elems);
- print("}");
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitParens(JCParens tree) {
- try {
- print("(");
- printExpr(tree.expr);
- print(")");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitAssign(JCAssign tree) {
- try {
- open(prec, TreeInfo.assignPrec);
- printExpr(tree.lhs, TreeInfo.assignPrec + 1);
- print(" = ");
- printExpr(tree.rhs, TreeInfo.assignPrec);
- close(prec, TreeInfo.assignPrec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public String operatorName(TreeTag tag) {
- String result = OPERATORS.get(tag);
- if (result == null) throw new Error();
- return result;
- }
-
- public void visitAssignop(JCAssignOp tree) {
- try {
- open(prec, TreeInfo.assignopPrec);
- printExpr(tree.lhs, TreeInfo.assignopPrec + 1);
- String opname = operatorName(treeTag(tree));
- print(" " + opname + " ");
- printExpr(tree.rhs, TreeInfo.assignopPrec);
- close(prec, TreeInfo.assignopPrec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitUnary(JCUnary tree) {
- try {
- int ownprec = isOwnPrec(tree);
- String opname = operatorName(treeTag(tree));
- open(prec, ownprec);
- if (isPrefixUnary(tree)) {
- print(opname);
- printExpr(tree.arg, ownprec);
- } else {
- printExpr(tree.arg, ownprec);
- print(opname);
- }
- close(prec, ownprec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private int isOwnPrec(JCExpression tree) {
- return treeTag(tree).getOperatorPrecedenceLevel();
- }
-
- private boolean isPrefixUnary(JCUnary tree) {
- return treeTag(tree).isPrefixUnaryOp();
- }
-
- public void visitBinary(JCBinary tree) {
- try {
- int ownprec = isOwnPrec(tree);
- String opname = operatorName(treeTag(tree));
- open(prec, ownprec);
- printExpr(tree.lhs, ownprec);
- print(" " + opname + " ");
- printExpr(tree.rhs, ownprec + 1);
- close(prec, ownprec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitTypeCast(JCTypeCast tree) {
- try {
- open(prec, TreeInfo.prefixPrec);
- print("(");
- printExpr(tree.clazz);
- print(")");
- printExpr(tree.expr, TreeInfo.prefixPrec);
- close(prec, TreeInfo.prefixPrec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitTypeTest(JCInstanceOf tree) {
- try {
- open(prec, TreeInfo.ordPrec);
- printExpr(tree.expr, TreeInfo.ordPrec);
- print(" instanceof ");
- printExpr(tree.clazz, TreeInfo.ordPrec + 1);
- close(prec, TreeInfo.ordPrec);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitIndexed(JCArrayAccess tree) {
- try {
- printExpr(tree.indexed, TreeInfo.postfixPrec);
- print("[");
- printExpr(tree.index);
- print("]");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitSelect(JCFieldAccess tree) {
- try {
- printExpr(tree.selected, TreeInfo.postfixPrec);
- print("." + tree.name);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitIdent(JCIdent tree) {
- try {
- print(tree.name);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitLiteral(JCLiteral tree) {
- TypeTag typeTag = typeTag(tree);
- try {
- if (CTC_INT.equals(typeTag)) print(tree.value.toString());
- else if (CTC_LONG.equals(typeTag)) print(tree.value + "L");
- else if (CTC_FLOAT.equals(typeTag)) print(tree.value + "F");
- else if (CTC_DOUBLE.equals(typeTag)) print(tree.value.toString());
- else if (CTC_CHAR.equals(typeTag)) {
- print("\'" + Convert.quote(String.valueOf((char)((Number)tree.value).intValue())) + "\'");
- }
- else if (CTC_BOOLEAN.equals(typeTag)) print(((Number)tree.value).intValue() == 1 ? "true" : "false");
- else if (CTC_BOT.equals(typeTag)) print("null");
- else print("\"" + Convert.quote(tree.value.toString()) + "\"");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitTypeIdent(JCPrimitiveTypeTree tree) {
- TypeTag typetag = typeTag(tree);
- try {
- if (CTC_BYTE.equals(typetag)) print ("byte");
- else if (CTC_CHAR.equals(typetag)) print ("char");
- else if (CTC_SHORT.equals(typetag)) print ("short");
- else if (CTC_INT.equals(typetag)) print ("int");
- else if (CTC_LONG.equals(typetag)) print ("long");
- else if (CTC_FLOAT.equals(typetag)) print ("float");
- else if (CTC_DOUBLE.equals(typetag)) print ("double");
- else if (CTC_BOOLEAN.equals(typetag)) print ("boolean");
- else if (CTC_VOID.equals(typetag)) print ("void");
- else print("error");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitTypeArray(JCArrayTypeTree tree) {
- try {
- printBaseElementType(tree);
- printBrackets(tree);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- // Prints the inner element type of a nested array
- private void printBaseElementType(JCArrayTypeTree tree) throws IOException {
- JCTree elem = tree.elemtype;
- while (elem instanceof JCWildcard)
- elem = ((JCWildcard) elem).inner;
- if (elem instanceof JCArrayTypeTree)
- printBaseElementType((JCArrayTypeTree) elem);
- else
- printExpr(elem);
- }
-
- // prints the brackets of a nested array in reverse order
- private void printBrackets(JCArrayTypeTree tree) throws IOException {
- JCTree elem;
- while (true) {
- elem = tree.elemtype;
- print("[]");
- if (!(elem instanceof JCArrayTypeTree)) break;
- tree = (JCArrayTypeTree) elem;
- }
- }
-
- public void visitTypeApply(JCTypeApply tree) {
- try {
- printExpr(tree.clazz);
- print("<");
- printExprs(tree.arguments);
- print(">");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitTypeParameter(JCTypeParameter tree) {
- try {
- print(tree.name);
- if (tree.bounds.nonEmpty()) {
- print(" extends ");
- printExprs(tree.bounds, " & ");
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- @Override
- public void visitWildcard(JCWildcard tree) {
- try {
- Object kind = tree.getClass().getField("kind").get(tree);
- print(kind);
- if (kind != null && kind.getClass().getSimpleName().equals("TypeBoundKind")) {
- kind = kind.getClass().getField("kind").get(kind);
- }
-
- if (tree.getKind() != Tree.Kind.UNBOUNDED_WILDCARD)
- printExpr(tree.inner);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- } catch (NoSuchFieldException e) {
- throw new RuntimeException(e);
- } catch (IllegalAccessException e) {
- throw new RuntimeException(e);
- }
- }
-
- public void visitTypeBoundKind(TypeBoundKind tree) {
- try {
- print(String.valueOf(tree.kind));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitErroneous(JCErroneous tree) {
- try {
- print("(ERROR)");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitLetExpr(LetExpr tree) {
- try {
- print("(let " + tree.defs + " in " + tree.expr + ")");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitModifiers(JCModifiers mods) {
- try {
- printAnnotations(mods.annotations);
- printFlags(mods.flags);
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitAnnotation(JCAnnotation tree) {
- try {
- print("@");
- printExpr(tree.annotationType);
- if (tree.args.nonEmpty()) {
- print("(");
- if (tree.args.length() == 1 && tree.args.get(0) instanceof JCAssign) {
- JCExpression lhs = ((JCAssign)tree.args.get(0)).lhs;
- if (lhs instanceof JCIdent && ((JCIdent)lhs).name.toString().equals("value")) tree.args = List.of(((JCAssign)tree.args.get(0)).rhs);
- }
- printExprs(tree.args);
- print(")");
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- public void visitTree(JCTree tree) {
- try {
- String simpleName = tree.getClass().getSimpleName();
- if ("JCTypeUnion".equals(simpleName)) {
- printExprs(readExpressionList(tree, "alternatives"), " | ");
- return;
- } else if ("JCTypeIntersection".equals(simpleName)) {
- printExprs(readExpressionList(tree, "bounds"), " & ");
- return;
- } else if ("JCLambda".equals(simpleName)) {
- visitLambda0(tree);
- return;
- } else if ("JCMemberReference".equals(simpleName)) {
- visitReference0(tree);
- return;
- } else {
- print("(UNKNOWN[" + tree.getClass().getSimpleName() + "]: " + tree + ")");
- println();
- }
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private void visitLambda0(JCTree tree) {
- try {
- print("(");
- @SuppressWarnings("unchecked")
- List<JCVariableDecl> params = (List<JCVariableDecl>) readTreeList(tree, "params");
- boolean explicit = true;
- try {
- explicit = readObject(tree, "paramKind").toString().equals("EXPLICIT");
- } catch (Exception e) {}
- if (explicit) {
- printExprs(params);
- } else {
- String sep = "";
- for (JCVariableDecl param : params) {
- print(sep);
- print(param.name);
- sep = ", ";
- }
- }
- print(") -> ");
- printExpr(readTree(tree, "body"));
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
-
- public void visitReference0(JCTree tree) {
- try {
- printExpr(readTree(tree, "expr"));
- print("::");
- List<JCExpression> typeArgs = readExpressionList(tree, "typeargs");
- if (typeArgs != null) {
- print("<");
- printExprs(typeArgs);
- print(">");
- }
- ;
- print(readObject(tree, "mode").toString().equals("INVOKE") ? readObject(tree, "name") : "new");
- } catch (IOException e) {
- throw new UncheckedIOException(e);
- }
- }
-
- private JCTree readTree(JCTree tree, String fieldName) {
- try {
- return (JCTree) readObject0(tree, fieldName);
- } catch (Exception e) {
- return null;
- }
- }
-
- @SuppressWarnings("unchecked")
- private List<? extends JCTree> readTreeList(JCTree tree, String fieldName) throws IOException {
- try {
- return (List<? extends JCTree>) readObject0(tree, fieldName);
- } catch (Exception e) {
- return List.nil();
- }
- }
-
- @SuppressWarnings("unchecked")
- private List<JCExpression> readExpressionList(JCTree tree, String fieldName) throws IOException {
- try {
- return (List<JCExpression>) readObject0(tree, fieldName);
- } catch (Exception e) {
- return List.nil();
- }
- }
-
- private Object readObject(JCTree tree, String fieldName) {
- try {
- return readObject0(tree, fieldName);
- } catch (Exception e) {
- return null;
- }
- }
-
- @SuppressWarnings("unchecked")
- private Object readObject0(JCTree tree, String fieldName) throws Exception {
- try {
- return tree.getClass().getDeclaredField(fieldName).get(tree);
- } catch (Exception e) {
- print("ERROR_READING_FIELD");
- throw e;
- }
- }
-}
diff --git a/src/delombok/lombok/delombok/PrettyPrinter.java b/src/delombok/lombok/delombok/PrettyPrinter.java
new file mode 100644
index 00000000..4261a558
--- /dev/null
+++ b/src/delombok/lombok/delombok/PrettyPrinter.java
@@ -0,0 +1,1524 @@
+/*
+ * Copyright (C) 2016 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.delombok;
+
+import static com.sun.tools.javac.code.Flags.*;
+import static lombok.javac.Javac.*;
+import static lombok.javac.JavacTreeMaker.TreeTag.treeTag;
+import static lombok.javac.JavacTreeMaker.TypeTag.typeTag;
+
+import java.io.IOException;
+import java.io.Writer;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.HashMap;
+import java.util.Map;
+
+import com.sun.tools.javac.tree.DocCommentTable;
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCAnnotation;
+import com.sun.tools.javac.tree.JCTree.JCArrayAccess;
+import com.sun.tools.javac.tree.JCTree.JCArrayTypeTree;
+import com.sun.tools.javac.tree.JCTree.JCAssert;
+import com.sun.tools.javac.tree.JCTree.JCAssign;
+import com.sun.tools.javac.tree.JCTree.JCAssignOp;
+import com.sun.tools.javac.tree.JCTree.JCBinary;
+import com.sun.tools.javac.tree.JCTree.JCBlock;
+import com.sun.tools.javac.tree.JCTree.JCBreak;
+import com.sun.tools.javac.tree.JCTree.JCCase;
+import com.sun.tools.javac.tree.JCTree.JCCatch;
+import com.sun.tools.javac.tree.JCTree.JCClassDecl;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCConditional;
+import com.sun.tools.javac.tree.JCTree.JCContinue;
+import com.sun.tools.javac.tree.JCTree.JCDoWhileLoop;
+import com.sun.tools.javac.tree.JCTree.JCEnhancedForLoop;
+import com.sun.tools.javac.tree.JCTree.JCErroneous;
+import com.sun.tools.javac.tree.JCTree.JCExpression;
+import com.sun.tools.javac.tree.JCTree.JCExpressionStatement;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCForLoop;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+import com.sun.tools.javac.tree.JCTree.JCIf;
+import com.sun.tools.javac.tree.JCTree.JCImport;
+import com.sun.tools.javac.tree.JCTree.JCInstanceOf;
+import com.sun.tools.javac.tree.JCTree.JCLabeledStatement;
+import com.sun.tools.javac.tree.JCTree.JCLiteral;
+import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
+import com.sun.tools.javac.tree.JCTree.JCMethodInvocation;
+import com.sun.tools.javac.tree.JCTree.JCModifiers;
+import com.sun.tools.javac.tree.JCTree.JCNewArray;
+import com.sun.tools.javac.tree.JCTree.JCNewClass;
+import com.sun.tools.javac.tree.JCTree.JCParens;
+import com.sun.tools.javac.tree.JCTree.JCPrimitiveTypeTree;
+import com.sun.tools.javac.tree.JCTree.JCReturn;
+import com.sun.tools.javac.tree.JCTree.JCSkip;
+import com.sun.tools.javac.tree.JCTree.JCStatement;
+import com.sun.tools.javac.tree.JCTree.JCSwitch;
+import com.sun.tools.javac.tree.JCTree.JCSynchronized;
+import com.sun.tools.javac.tree.JCTree.JCThrow;
+import com.sun.tools.javac.tree.JCTree.JCTry;
+import com.sun.tools.javac.tree.JCTree.JCTypeApply;
+import com.sun.tools.javac.tree.JCTree.JCTypeCast;
+import com.sun.tools.javac.tree.JCTree.JCTypeParameter;
+import com.sun.tools.javac.tree.JCTree.JCUnary;
+import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
+import com.sun.tools.javac.tree.JCTree.JCWhileLoop;
+import com.sun.tools.javac.tree.JCTree.JCWildcard;
+import com.sun.tools.javac.tree.JCTree.TypeBoundKind;
+import com.sun.tools.javac.util.JCDiagnostic.DiagnosticPosition;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.util.Name;
+import com.sun.tools.javac.util.Position;
+
+import lombok.javac.CommentInfo;
+import lombok.javac.PackageName;
+import lombok.javac.CommentInfo.EndConnection;
+import lombok.javac.CommentInfo.StartConnection;
+import lombok.javac.JavacTreeMaker.TreeTag;
+import lombok.javac.JavacTreeMaker.TypeTag;
+
+public class PrettyPrinter extends JCTree.Visitor {
+ private static final String LINE_SEP = System.getProperty("line.separator");
+ private static final Map<TreeTag, String> OPERATORS;
+
+ static {
+ Map<TreeTag, String> map = new HashMap<TreeTag, String>();
+
+ map.put(treeTag("POS"), "+");
+ map.put(treeTag("NEG"), "-");
+ map.put(treeTag("NOT"), "!");
+ map.put(treeTag("COMPL"), "~");
+ map.put(treeTag("PREINC"), "++");
+ map.put(treeTag("PREDEC"), "--");
+ map.put(treeTag("POSTINC"), "++");
+ map.put(treeTag("POSTDEC"), "--");
+ map.put(treeTag("NULLCHK"), "<*nullchk*>");
+ map.put(treeTag("OR"), "||");
+ map.put(treeTag("AND"), "&&");
+ map.put(treeTag("EQ"), "==");
+ map.put(treeTag("NE"), "!=");
+ map.put(treeTag("LT"), "<");
+ map.put(treeTag("GT"), ">");
+ map.put(treeTag("LE"), "<=");
+ map.put(treeTag("GE"), ">=");
+ map.put(treeTag("BITOR"), "|");
+ map.put(treeTag("BITXOR"), "^");
+ map.put(treeTag("BITAND"), "&");
+ map.put(treeTag("SL"), "<<");
+ map.put(treeTag("SR"), ">>");
+ map.put(treeTag("USR"), ">>>");
+ map.put(treeTag("PLUS"), "+");
+ map.put(treeTag("MINUS"), "-");
+ map.put(treeTag("MUL"), "*");
+ map.put(treeTag("DIV"), "/");
+ map.put(treeTag("MOD"), "%");
+
+ map.put(treeTag("BITOR_ASG"), "|=");
+ map.put(treeTag("BITXOR_ASG"), "^=");
+ map.put(treeTag("BITAND_ASG"), "&=");
+ map.put(treeTag("SL_ASG"), "<<=");
+ map.put(treeTag("SR_ASG"), ">>=");
+ map.put(treeTag("USR_ASG"), ">>>=");
+ map.put(treeTag("PLUS_ASG"), "+=");
+ map.put(treeTag("MINUS_ASG"), "-=");
+ map.put(treeTag("MUL_ASG"), "*=");
+ map.put(treeTag("DIV_ASG"), "/=");
+ map.put(treeTag("MOD_ASG"), "%=");
+
+ OPERATORS = map;
+ }
+
+ private final Writer out;
+ private final JCCompilationUnit compilationUnit;
+ private List<CommentInfo> comments;
+ private final FormatPreferences formatPreferences;
+
+ private final Map<JCTree, String> docComments;
+ private final DocCommentTable docTable;
+ private int indent = 0;
+
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public PrettyPrinter(Writer out, JCCompilationUnit cu, List<CommentInfo> comments, FormatPreferences preferences) {
+ this.out = out;
+ this.comments = comments;
+ this.compilationUnit = cu;
+ this.formatPreferences = preferences;
+
+ /* load doc comments */ {
+ Object dc = getDocComments(compilationUnit);
+ if (dc instanceof Map<?, ?>) {
+ this.docComments = (Map) dc;
+ this.docTable = null;
+ } else if (dc instanceof DocCommentTable) {
+ this.docComments = null;
+ this.docTable = (DocCommentTable) dc;
+ } else {
+ this.docComments = null;
+ this.docTable = null;
+ }
+ }
+ }
+
+ private int endPos(JCTree tree) {
+ return getEndPosition(tree, compilationUnit);
+ }
+
+ private static int lineEndPos(String s, int start) {
+ int pos = s.indexOf('\n', start);
+ if (pos < 0) pos = s.length();
+ return pos;
+ }
+
+ private boolean needsAlign, needsNewLine, onNewLine = true, needsSpace, aligned;
+
+ public static final class UncheckedIOException extends RuntimeException {
+ UncheckedIOException(IOException source) {
+ super(toMsg(source));
+ setStackTrace(source.getStackTrace());
+ }
+
+ private static String toMsg(Throwable t) {
+ String msg = t.getMessage();
+ String n = t.getClass().getSimpleName();
+ if (msg == null || msg.isEmpty()) return n;
+ return n + ": " + msg;
+ }
+ }
+
+ private void align() {
+ if (!onNewLine) return;
+ try {
+ for (int i = 0; i < indent; i++) out.write(formatPreferences.indent());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ onNewLine = false;
+ aligned = true;
+ needsAlign = false;
+ }
+
+ private void print(JCTree tree) {
+ if (tree == null) {
+ print("/*missing*/");
+ return;
+ }
+
+ consumeComments(tree);
+ tree.accept(this);
+ consumeTrailingComments(endPos(tree));
+ }
+
+ private void print(List<? extends JCTree> trees, String infix) {
+ boolean first = true;
+ JCTree prev = null;
+ for (JCTree tree : trees) {
+ if (suppress(tree)) continue;
+ if (!first && infix != null && !infix.isEmpty()) {
+ if ("\n".equals(infix)) println(prev);
+ else print(infix);
+ }
+ first = false;
+ print(tree);
+ prev = tree;
+ }
+ }
+
+ private boolean suppress(JCTree tree) {
+ if (tree instanceof JCBlock) {
+ JCBlock block = (JCBlock) tree;
+ return (Position.NOPOS == block.pos) && block.stats.isEmpty();
+ }
+
+ if (tree instanceof JCExpressionStatement) {
+ JCExpression expr = ((JCExpressionStatement)tree).expr;
+ if (expr instanceof JCMethodInvocation) {
+ JCMethodInvocation inv = (JCMethodInvocation) expr;
+ if (!inv.typeargs.isEmpty() || !inv.args.isEmpty()) return false;
+ if (!(inv.meth instanceof JCIdent)) return false;
+ return ((JCIdent) inv.meth).name.toString().equals("super");
+ }
+ }
+
+ return false;
+ }
+
+ private void print(CharSequence s) {
+ boolean align = needsAlign;
+ if (needsNewLine && !onNewLine) println();
+ if (align && !aligned) align();
+ try {
+ if (needsSpace && !onNewLine && !aligned) out.write(' ');
+ out.write(s.toString());
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ needsSpace = false;
+ onNewLine = false;
+ aligned = false;
+ }
+
+
+ private void println() {
+ try {
+ out.write(LINE_SEP);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ onNewLine = true;
+ aligned = false;
+ needsNewLine = false;
+ }
+
+ private void println(JCTree completed) {
+ if (completed != null) {
+ int endPos = endPos(completed);
+ consumeTrailingComments(endPos);
+ }
+ try {
+ out.write(LINE_SEP);
+ } catch (IOException e) {
+ throw new UncheckedIOException(e);
+ }
+
+ onNewLine = true;
+ aligned = false;
+ needsNewLine = false;
+ }
+
+ private void println(CharSequence s) {
+ print(s);
+ println();
+ }
+
+ private void println(CharSequence s, JCTree completed) {
+ print(s);
+ println(completed);
+ }
+
+ private void aPrint(CharSequence s) {
+ align();
+ print(s);
+ }
+
+ private void aPrintln(CharSequence s) {
+ align();
+ print(s);
+ println();
+ }
+
+ private void aPrintln(CharSequence s, JCTree completed) {
+ align();
+ print(s);
+ println(completed);
+ }
+
+ private void consumeComments(int until) {
+ CommentInfo head = comments.head;
+ while (comments.nonEmpty() && head.pos < until) {
+ printComment(head);
+ comments = comments.tail;
+ head = comments.head;
+ }
+ }
+
+ private void consumeComments(JCTree tree) {
+ consumeComments(tree.pos);
+ }
+
+ private void consumeTrailingComments(int from) {
+ boolean prevNewLine = onNewLine;
+ CommentInfo head = comments.head;
+ boolean stop = false;
+
+ while (comments.nonEmpty() && head.prevEndPos == from && !stop && !(head.start == StartConnection.ON_NEXT_LINE || head.start == StartConnection.START_OF_LINE)) {
+ from = head.endPos;
+ printComment(head);
+ stop = (head.end == EndConnection.ON_NEXT_LINE);
+ comments = comments.tail;
+ head = comments.head;
+ }
+
+ if (!onNewLine && prevNewLine) {
+ println();
+ }
+ }
+
+ private String getJavadocFor(JCTree node) {
+ if (docComments != null) return docComments.get(node);
+ if (docTable != null) return docTable.getCommentText(node);
+ return null;
+ }
+
+ private int dims(JCExpression vartype) {
+ if (vartype instanceof JCArrayTypeTree) {
+ return 1 + dims(((JCArrayTypeTree) vartype).elemtype);
+ }
+
+ return 0;
+ }
+
+ private void printComment(CommentInfo comment) {
+ switch (comment.start) {
+ case DIRECT_AFTER_PREVIOUS:
+ needsSpace = false;
+ break;
+ case AFTER_PREVIOUS:
+ needsSpace = true;
+ break;
+ case START_OF_LINE:
+ needsNewLine = true;
+ needsAlign = false;
+ break;
+ case ON_NEXT_LINE:
+ if (!onNewLine) {
+ needsNewLine = true;
+ needsAlign = true;
+ } else if (!aligned) {
+ needsAlign = true;
+ }
+ break;
+ }
+
+ if (onNewLine && !aligned && comment.start != StartConnection.START_OF_LINE) needsAlign = true;
+
+ print(comment.content);
+
+ switch (comment.end) {
+ case ON_NEXT_LINE:
+ if (!aligned) {
+ needsNewLine = true;
+ needsAlign = true;
+ }
+ break;
+ case AFTER_COMMENT:
+ needsSpace = true;
+ break;
+ case DIRECT_AFTER_COMMENT:
+ // do nothing
+ break;
+ }
+ }
+
+ private void printDocComment(JCTree tree) {
+ String dc = getJavadocFor(tree);
+ if (dc == null) return;
+ aPrintln("/**");
+ int pos = 0;
+ int endpos = lineEndPos(dc, pos);
+ boolean atStart = true;
+ while (pos < dc.length()) {
+ String line = dc.substring(pos, endpos);
+ if (line.trim().isEmpty() && atStart) {
+ atStart = false;
+ continue;
+ }
+ atStart = false;
+ aPrint(" *");
+ if (pos < dc.length() && dc.charAt(pos) > ' ') print(" ");
+ println(dc.substring(pos, endpos));
+ pos = endpos + 1;
+ endpos = lineEndPos(dc, pos);
+ }
+ aPrintln(" */");
+ }
+
+ private Name __INIT__, __VALUE__;
+ private Name name_init(Name someName) {
+ if (__INIT__ == null) __INIT__ = someName.table.fromChars("<init>".toCharArray(), 0, 6);
+ return __INIT__;
+ }
+ private Name name_value(Name someName) {
+ if (__VALUE__ == null) __VALUE__ = someName.table.fromChars("value".toCharArray(), 0, 5);
+ return __VALUE__;
+ }
+
+ @Override public void visitTopLevel(JCCompilationUnit tree) {
+ printDocComment(tree);
+ JCTree n = PackageName.getPackageNode(tree);
+ if (n != null) {
+ consumeComments(tree);
+ aPrint("package ");
+ print(n);
+ println(";", n);
+ }
+
+ boolean first = true;
+
+ for (JCTree child : tree.defs) {
+ if (!(child instanceof JCImport)) continue;
+ if (first) println();
+ first = false;
+ print(child);
+ }
+
+ for (JCTree child : tree.defs) {
+ if (child instanceof JCImport) continue;
+ print(child);
+ }
+ consumeComments(Integer.MAX_VALUE);
+ }
+
+ @Override public void visitImport(JCImport tree) {
+ aPrint("import ");
+ if (tree.staticImport) print("static ");
+ print(tree.qualid);
+ println(";", tree);
+ }
+
+ private Name currentTypeName;
+ @Override public void visitClassDef(JCClassDecl tree) {
+ println();
+ printDocComment(tree);
+ align();
+ print(tree.mods);
+
+ boolean isInterface = (tree.mods.flags & INTERFACE) != 0;
+ boolean isAnnotationInterface = isInterface && (tree.mods.flags & ANNOTATION) != 0;
+ boolean isEnum = (tree.mods.flags & ENUM) != 0;
+
+ if (isAnnotationInterface) print("@interface ");
+ else if (isInterface) print("interface ");
+ else if (isEnum) print("enum ");
+ else print("class ");
+
+ print(tree.name);
+ Name prevTypeName = currentTypeName;
+ currentTypeName = tree.name;
+
+ if (tree.typarams.nonEmpty()) {
+ print("<");
+ print(tree.typarams, ", ");
+ print(">");
+ }
+ JCTree extendsClause = getExtendsClause(tree);
+ if (extendsClause != null) {
+ print(" extends ");
+ print(extendsClause);
+ }
+
+ if (tree.implementing.nonEmpty()) {
+ print(isInterface ? " extends " : " implements ");
+ print(tree.implementing, ", ");
+ }
+
+ println(" {");
+ indent++;
+ printClassMembers(tree.defs, isEnum, isInterface);
+ consumeComments(endPos(tree));
+ indent--;
+ aPrintln("}", tree);
+ currentTypeName = prevTypeName;
+ }
+
+ private void printClassMembers(List<JCTree> members, boolean isEnum, boolean isInterface) {
+ Class<?> prefType = null;
+ int typeOfPrevEnumMember = isEnum ? 3 : 0; // 1 = normal, 2 = with body, 3 = no enum field yet.
+ boolean prevWasEnumMember = isEnum;
+
+ for (JCTree member : members) {
+ if (typeOfPrevEnumMember == 3 && member instanceof JCMethodDecl && (((JCMethodDecl) member).mods.flags & GENERATEDCONSTR) != 0) continue;
+ boolean isEnumVar = isEnum && member instanceof JCVariableDecl && (((JCVariableDecl) member).mods.flags & ENUM) != 0;
+ if (!isEnumVar && prevWasEnumMember) {
+ prevWasEnumMember = false;
+ if (typeOfPrevEnumMember == 3) align();
+ println(";");
+ }
+
+ if (isEnumVar) {
+ if (prefType != null && prefType != JCVariableDecl.class) println();
+ switch (typeOfPrevEnumMember) {
+ case 1:
+ print(", ");
+ break;
+ case 2:
+ println(",");
+ align();
+ break;
+ }
+ print(member);
+ JCTree init = ((JCVariableDecl) member).init;
+ typeOfPrevEnumMember = init instanceof JCNewClass && ((JCNewClass) init).def != null ? 2 : 1;
+ } else if (member instanceof JCVariableDecl) {
+ if (prefType != null && prefType != JCVariableDecl.class) println();
+ if (isInterface) flagMod = -1L & ~(PUBLIC | STATIC | FINAL);
+ print(member);
+ } else if (member instanceof JCMethodDecl) {
+ if ((((JCMethodDecl) member).mods.flags & GENERATEDCONSTR) != 0) continue;
+ if (prefType != null) println();
+ if (isInterface) flagMod = -1L & ~(PUBLIC | ABSTRACT);
+ print(member);
+ } else if (member instanceof JCClassDecl) {
+ if (prefType != null) println();
+ if (isInterface) flagMod = -1L & ~(PUBLIC | STATIC);
+ print(member);
+ } else {
+ if (prefType != null) println();
+ print(member);
+ }
+
+ prefType = member.getClass();
+ }
+
+ if (prevWasEnumMember) {
+ prevWasEnumMember = false;
+ if (typeOfPrevEnumMember == 3) align();
+ println(";");
+ }
+ }
+
+ @Override public void visitTypeParameter(JCTypeParameter tree) {
+ List<JCExpression> annotations = readObject(tree, "annotations", List.<JCExpression>nil());
+ if (!annotations.isEmpty()) {
+ print(annotations, " ");
+ print(" ");
+ }
+ print(tree.name);
+ if (tree.bounds.nonEmpty()) {
+ print(" extends ");
+ print(tree.bounds, " & ");
+ }
+ consumeComments(tree);
+ }
+
+ @Override public void visitVarDef(JCVariableDecl tree) {
+ printDocComment(tree);
+ align();
+ if ((tree.mods.flags & ENUM) != 0) {
+ printEnumMember(tree);
+ return;
+ }
+ printAnnotations(tree.mods.annotations, true);
+ printModifierKeywords(tree.mods);
+ printVarDef0(tree);
+ println(";", tree);
+ }
+
+ private void printVarDefInline(JCVariableDecl tree) {
+ printAnnotations(tree.mods.annotations, false);
+ printModifierKeywords(tree.mods);
+ printVarDef0(tree);
+ }
+
+ private void printVarDef0(JCVariableDecl tree) {
+ boolean varargs = (tree.mods.flags & VARARGS) != 0;
+ if (varargs && tree.vartype instanceof JCArrayTypeTree) {
+ print(((JCArrayTypeTree) tree.vartype).elemtype);
+ print("...");
+ } else {
+ print(tree.vartype);
+ }
+ print(" ");
+ print(tree.name);
+ if (tree.init != null) {
+ print(" = ");
+ print(tree.init);
+ }
+ }
+
+ private void printEnumMember(JCVariableDecl tree) {
+ printAnnotations(tree.mods.annotations, true);
+ print(tree.name);
+ if (tree.init instanceof JCNewClass) {
+ JCNewClass constructor = (JCNewClass) tree.init;
+ if (constructor.args != null && constructor.args.nonEmpty()) {
+ print("(");
+ print(constructor.args, ", ");
+ print(")");
+ }
+
+ if (constructor.def != null && constructor.def.defs != null) {
+ println(" {");
+ indent++;
+ printClassMembers(constructor.def.defs, false, false);
+ consumeComments(endPos(tree));
+ indent--;
+ aPrint("}");
+ }
+ }
+ }
+
+ // TODO: Test postfix syntax for methods (?), for decls. Multiline vardefs, possibly with comments. enums with bodies. constructor-local generics, method-local generics, also do/while, finally, try-with-resources, lambdas, annotations in java8 places...
+ // TODO: Whatever is JCAnnotatedType? We handle it in the 7+ bucket in the old one...
+
+ @Override public void visitTypeApply(JCTypeApply tree) {
+ print(tree.clazz);
+ print("<");
+ print(tree.arguments, ", ");
+ print(">");
+ }
+
+ @Override public void visitWildcard(JCWildcard tree) {
+ switch (tree.getKind()) {
+ default:
+ case UNBOUNDED_WILDCARD:
+ print("?");
+ return;
+ case EXTENDS_WILDCARD:
+ print("? extends ");
+ print(tree.inner);
+ return;
+ case SUPER_WILDCARD:
+ print("? super ");
+ print(tree.inner);
+ return;
+ }
+ }
+
+ @Override public void visitLiteral(JCLiteral tree) {
+ TypeTag typeTag = typeTag(tree);
+ if (CTC_INT.equals(typeTag)) print("" + tree.value);
+ else if (CTC_LONG.equals(typeTag)) print(tree.value + "L");
+ else if (CTC_FLOAT.equals(typeTag)) print(tree.value + "F");
+ else if (CTC_DOUBLE.equals(typeTag)) print("" + tree.value);
+ else if (CTC_CHAR.equals(typeTag)) {
+ print("\'" + quoteChar((char)((Number)tree.value).intValue()) + "\'");
+ }
+ else if (CTC_BOOLEAN.equals(typeTag)) print(((Number)tree.value).intValue() == 1 ? "true" : "false");
+ else if (CTC_BOT.equals(typeTag)) print("null");
+ else print("\"" + quoteChars(tree.value.toString()) + "\"");
+ }
+
+ @Override public void visitMethodDef(JCMethodDecl tree) {
+ boolean isConstructor = tree.name == name_init(tree.name);
+ if (isConstructor && (tree.mods.flags & GENERATEDCONSTR) != 0) return;
+ printDocComment(tree);
+ align();
+ print(tree.mods);
+ if (tree.typarams != null && tree.typarams.nonEmpty()) {
+ print("<");
+ print(tree.typarams, ", ");
+ print("> ");
+ }
+
+ if (isConstructor) {
+ print(currentTypeName == null ? "<init>" : currentTypeName);
+ } else {
+ print(tree.restype);
+ print(" ");
+ print(tree.name);
+ }
+
+ print("(");
+ boolean first = true;
+ for (JCVariableDecl param : tree.params) {
+ if (!first) print(", ");
+ first = false;
+ printVarDefInline(param);
+ }
+ print(")");
+
+ if (tree.thrown.nonEmpty()) {
+ print(" throws ");
+ print(tree.thrown, ", ");
+ }
+
+ if (tree.defaultValue != null) {
+ print(" default ");
+ print(tree.defaultValue);
+ }
+
+ if (tree.body != null) {
+ print(" ");
+ print(tree.body);
+ } else println(";", tree);
+ }
+
+ @Override public void visitSkip(JCSkip that) {
+ if (onNewLine && !aligned) {
+ align();
+ }
+ println(";");
+ }
+
+ @Override public void visitAnnotation(JCAnnotation tree) {
+ print("@");
+ print(tree.annotationType);
+ if (tree.args.isEmpty()) return;
+ print("(");
+ boolean done = false;
+ if (tree.args.length() == 1 && tree.args.get(0) instanceof JCAssign) {
+ JCAssign arg1 = (JCAssign) tree.args.get(0);
+ JCIdent arg1Name = arg1.lhs instanceof JCIdent ? ((JCIdent) arg1.lhs) : null;
+ if (arg1Name != null && arg1Name.name == name_value(arg1Name.name)) {
+ print(arg1.rhs);
+ done = true;
+ }
+ }
+ if (!done) print(tree.args, ", ");
+ print(")");
+ }
+
+ @Override public void visitTypeArray(JCArrayTypeTree tree) {
+ JCTree elem = tree.elemtype;
+ while (elem instanceof JCWildcard) elem = ((JCWildcard) elem).inner;
+ print(elem);
+ print("[]");
+ }
+
+ @Override public void visitNewArray(JCNewArray tree) {
+ JCTree elem = tree.elemtype;
+ int dims = 0;
+ if (elem != null) {
+ print("new ");
+
+ while (elem instanceof JCArrayTypeTree) {
+ dims++;
+ elem = ((JCArrayTypeTree) elem).elemtype;
+ }
+ print(elem);
+
+ for (JCExpression expr : tree.dims) {
+ print("[");
+ print(expr);
+ print("]");
+ }
+ }
+
+ for (int i = 0; i < dims; i++) print("[]");
+
+ if (tree.elems != null) {
+ if (elem != null) print("[] ");
+ print("{");
+ print(tree.elems, ", ");
+ print("}");
+ }
+ }
+
+ @Override public void visitNewClass(JCNewClass tree) {
+ if (tree.encl != null) {
+ print(tree.encl);
+ print(".");
+ }
+ boolean moveFirstParameter = tree.args.nonEmpty() && tree.args.head instanceof JCUnary && tree.args.head.toString().startsWith("<*nullchk*>");
+ if (moveFirstParameter) {
+ print(((JCUnary) tree.args.head).arg);
+ print(".");
+ }
+
+ print("new ");
+ if (!tree.typeargs.isEmpty()) {
+ print("<");
+ print(tree.typeargs, ", ");
+ print(">");
+ }
+ print(tree.clazz);
+ print("(");
+ if (moveFirstParameter) {
+ print(tree.args.tail, ", ");
+ } else {
+ print(tree.args, ", ");
+ }
+ print(")");
+ if (tree.def != null) {
+ Name previousTypeName = currentTypeName;
+ currentTypeName = null;
+ println(" {");
+ indent++;
+ print(tree.def.defs, "");
+ indent--;
+ aPrint("}");
+ currentTypeName = previousTypeName;
+ }
+ }
+
+ @Override public void visitIndexed(JCArrayAccess tree) {
+ print(tree.indexed);
+ print("[");
+ print(tree.index);
+ print("]");
+ }
+
+ @Override public void visitTypeIdent(JCPrimitiveTypeTree tree) {
+ TypeTag typeTag = typeTag(tree);
+
+ if (CTC_BYTE.equals(typeTag)) print("byte");
+ else if (CTC_CHAR.equals(typeTag)) print("char");
+ else if (CTC_SHORT.equals(typeTag)) print("short");
+ else if (CTC_INT.equals(typeTag)) print("int");
+ else if (CTC_LONG.equals(typeTag)) print("long");
+ else if (CTC_FLOAT.equals(typeTag)) print("float");
+ else if (CTC_DOUBLE.equals(typeTag)) print("double");
+ else if (CTC_BOOLEAN.equals(typeTag)) print("boolean");
+ else if (CTC_VOID.equals(typeTag)) print("void");
+ else print("error");
+ }
+
+ @Override public void visitLabelled(JCLabeledStatement tree) {
+ aPrint(tree.label);
+ print(":");
+ if (tree.body instanceof JCSkip || suppress(tree)) {
+ println(" ;", tree);
+ } else if (tree.body instanceof JCBlock) {
+ print(" ");
+ print(tree.body);
+ } else {
+ println(tree);
+ print(tree.body);
+ }
+ }
+
+ private long flagMod = -1L;
+ private static final long DEFAULT = 1L<<43;
+
+ @Override public void visitModifiers(JCModifiers tree) {
+ printAnnotations(tree.annotations, true);
+ printModifierKeywords(tree);
+ }
+
+ private void printAnnotations(List<JCAnnotation> annotations, boolean newlines) {
+ for (JCAnnotation ann : annotations) {
+ print(ann);
+ if (newlines) {
+ println();
+ align();
+ } else print(" ");
+ }
+ }
+
+ private void printModifierKeywords(JCModifiers tree) {
+ long v = flagMod & tree.flags;
+ flagMod = -1L;
+
+ if ((v & SYNTHETIC) != 0) print("/* synthetic */ ");
+ if ((v & PUBLIC) != 0) print("public ");
+ if ((v & PRIVATE) != 0) print("private ");
+ if ((v & PROTECTED) != 0) print("protected ");
+ if ((v & STATIC) != 0) print("static ");
+ if ((v & FINAL) != 0) print("final ");
+ if ((v & SYNCHRONIZED) != 0) print("synchronized ");
+ if ((v & VOLATILE) != 0) print("volatile ");
+ if ((v & TRANSIENT) != 0) print("transient ");
+ if ((v & NATIVE) != 0) print("native ");
+ if ((v & ABSTRACT) != 0) print("abstract ");
+ if ((v & STRICTFP) != 0) print("strictfp ");
+ if ((v & DEFAULT) != 0 && (v & INTERFACE) == 0) print("default ");
+ }
+
+ @Override public void visitSelect(JCFieldAccess tree) {
+ print(tree.selected);
+ print(".");
+ print(tree.name);
+ }
+
+ @Override public void visitIdent(JCIdent tree) {
+ print(tree.name);
+ }
+
+ @Override public void visitApply(JCMethodInvocation tree) {
+ if (tree.typeargs.nonEmpty()) {
+ if (tree.meth instanceof JCFieldAccess) {
+ JCFieldAccess fa = (JCFieldAccess) tree.meth;
+ print(fa.selected);
+ print(".<");
+ print(tree.typeargs, ", ");
+ print(">");
+ print(fa.name);
+ } else {
+ print("<");
+ print(tree.typeargs, ", ");
+ print(">");
+ print(tree.meth);
+ }
+ } else {
+ print(tree.meth);
+ }
+
+ print("(");
+ print(tree.args, ", ");
+ print(")");
+ }
+
+ @Override public void visitAssert(JCAssert tree) {
+ aPrint("assert ");
+ print(tree.cond);
+ if (tree.detail != null) {
+ print(" : ");
+ print(tree.detail);
+ }
+ println(";", tree);
+ }
+
+ @Override public void visitAssign(JCAssign tree) {
+ print(tree.lhs);
+ print(" = ");
+ print(tree.rhs);
+ }
+
+ @Override public void visitAssignop(JCAssignOp tree) {
+ print(tree.lhs);
+ String opname = operator(treeTag(tree));
+ print(" " + opname + " ");
+ print(tree.rhs);
+ }
+
+ private static final int PREFIX = 14;
+
+ @Override public void visitUnary(JCUnary tree) {
+ String op = operator(treeTag(tree));
+ if (treeTag(tree).getOperatorPrecedenceLevel() == PREFIX) {
+ print(op);
+ print(tree.arg);
+ } else {
+ print(tree.arg);
+ print(op);
+ }
+ }
+
+ @Override public void visitBinary(JCBinary tree) {
+ String op = operator(treeTag(tree));
+ print(tree.lhs);
+ print(" ");
+ print(op);
+ print(" ");
+ print(tree.rhs);
+ }
+
+ @Override public void visitTypeTest(JCInstanceOf tree) {
+ print(tree.expr);
+ print(" instanceof ");
+ print(tree.clazz);
+ }
+
+ @Override public void visitTypeCast(JCTypeCast tree) {
+ print("(");
+ print(tree.clazz);
+ print(") ");
+ print(tree.expr);
+ }
+
+ @Override public void visitBlock(JCBlock tree) {
+ if (tree.pos == Position.NOPOS && tree.stats.isEmpty()) return;
+ if (onNewLine) align();
+ if ((tree.flags & STATIC) != 0) print("static ");
+ println("{");
+ indent++;
+ print(tree.stats, "");
+ consumeComments(endPos(tree));
+ indent--;
+ aPrintln("}", tree);
+ }
+
+ @Override public void visitBreak(JCBreak tree) {
+ aPrint("break");
+ if (tree.label != null) {
+ print(" ");
+ print(tree.label);
+ }
+ println(";", tree);
+ }
+
+ @Override public void visitContinue(JCContinue tree) {
+ aPrint("continue");
+ if (tree.label != null) {
+ print(" ");
+ print(tree.label);
+ }
+ println(";", tree);
+ }
+
+ @Override public void visitConditional(JCConditional tree) {
+ print(tree.cond);
+ print(" ? ");
+ print(tree.truepart);
+ print(" : ");
+ print(tree.falsepart);
+ }
+
+ @Override public void visitParens(JCParens tree) {
+ print("(");
+ print(tree.expr);
+ print(")");
+ }
+
+ @Override public void visitReturn(JCReturn tree) {
+ aPrint("return");
+ if (tree.expr != null) {
+ print(" ");
+ print(tree.expr);
+ }
+ println(";", tree);
+ }
+
+ @Override public void visitThrow(JCThrow tree) {
+ aPrint("throw ");
+ print(tree.expr);
+ println(";", tree);
+ }
+
+ @Override public void visitWhileLoop(JCWhileLoop tree) {
+ aPrint("while ");
+ if (tree.cond instanceof JCParens) {
+ print(tree.cond);
+ } else {
+ print("(");
+ print(tree.cond);
+ print(")");
+ }
+ print(" ");
+ print(tree.body);
+ // make sure to test while (true) ; and while(true){} and while(true) x = 5;
+ }
+
+ @Override public void visitForLoop(JCForLoop tree) {
+ aPrint("for (");
+ if (tree.init.nonEmpty()) {
+ // ForInit is either a StatementExpressionList or a LocalVariableDeclaration
+ if (tree.init.head instanceof JCVariableDecl) {
+ boolean first = true;
+ int dims = 0;
+ for (JCStatement i : tree.init) {
+ JCVariableDecl vd = (JCVariableDecl) i;
+ if (first) {
+ printVarDefInline(vd);
+ dims = dims(vd.vartype);
+ } else {
+ print(", ");
+ print(vd.name);
+ int dimDiff = dims(vd.vartype) - dims;
+ for (int j = 0; j < dimDiff; j++) print("[]");
+ if (vd.init != null) {
+ print(" = ");
+ print(vd.init);
+ }
+ }
+ first = false;
+ }
+ } else {
+ boolean first = true;
+ for (JCStatement exprStatement : tree.init) {
+ if (!first) print(", ");
+ first = false;
+ print(((JCExpressionStatement) exprStatement).expr);
+ }
+ }
+ }
+ print("; ");
+ if (tree.cond != null) print(tree.cond);
+ print("; ");
+ boolean first = true;
+ for (JCExpressionStatement exprStatement : tree.step) {
+ if (!first) print(", ");
+ first = false;
+ print(exprStatement.expr);
+ }
+ print(") ");
+ print(tree.body);
+ }
+
+ @Override public void visitForeachLoop(JCEnhancedForLoop tree) {
+ aPrint("for (");
+ printVarDefInline(tree.var);
+ print(" : ");
+ print(tree.expr);
+ print(") ");
+ print(tree.body);
+ }
+
+ @Override public void visitIf(JCIf tree) {
+ aPrint("if ");
+ if (tree.cond instanceof JCParens) {
+ print(tree.cond);
+ } else {
+ print("(");
+ print(tree.cond);
+ print(")");
+ }
+ print(" ");
+ if (tree.thenpart instanceof JCBlock) {
+ println("{");
+ indent++;
+ print(((JCBlock) tree.thenpart).stats, "");
+ indent--;
+ if (tree.elsepart == null) {
+ aPrintln("}", tree);
+ } else {
+ aPrint("}");
+ }
+ } else {
+ print(tree.thenpart);
+ }
+ if (tree.elsepart != null) {
+ aPrint(" else ");
+ print(tree.elsepart);
+ }
+ }
+
+ @Override public void visitExec(JCExpressionStatement tree) {
+ align();
+ print(tree.expr);
+ println(";", tree);
+ }
+
+ @Override public void visitDoLoop(JCDoWhileLoop tree) {
+ aPrint("do ");
+ if (tree.body instanceof JCBlock) {
+ println("{");
+ indent++;
+ print(((JCBlock) tree.body).stats, "");
+ indent--;
+ aPrint("}");
+
+ } else print(tree.body);
+ print(" while ");
+ if (tree.cond instanceof JCParens) {
+ print(tree.cond);
+ } else {
+ print("(");
+ print(tree.cond);
+ print(")");
+ }
+ println(";", tree);
+ }
+
+ @Override public void visitSynchronized(JCSynchronized tree) {
+ aPrint("synchronized ");
+ if (tree.lock instanceof JCParens) {
+ print(tree.lock);
+ } else {
+ print("(");
+ print(tree.lock);
+ print(")");
+ }
+ print(" ");
+ print(tree.body);
+ }
+
+ @Override public void visitCase(JCCase tree) {
+ if (tree.pat == null) {
+ aPrint("default");
+ } else {
+ aPrint("case ");
+ print(tree.pat);
+ }
+ println(": ");
+ indent++;
+ print(tree.stats, "");
+ indent--;
+ }
+
+ @Override public void visitCatch(JCCatch tree) {
+ print(" catch (");
+ print(tree.param);
+ print(") ");
+ print(tree.body);
+ }
+
+ @Override public void visitSwitch(JCSwitch tree) {
+ aPrint("switch ");
+ if (tree.selector instanceof JCParens) {
+ print(tree.selector);
+ } else {
+ print("(");
+ print(tree.selector);
+ print(")");
+ }
+ println(" {");
+ print(tree.cases, "\n");
+ aPrintln("}", tree);
+ }
+
+ @Override public void visitTry(JCTry tree) {
+ aPrint("try ");
+ List<?> resources = readObject(tree, "resources", List.nil());
+ int len = resources.length();
+ switch (len) {
+ case 0:
+ break;
+ case 1:
+ print("(");
+ JCVariableDecl decl = (JCVariableDecl) resources.get(0);
+ flagMod = -1L & ~FINAL;
+ printVarDefInline(decl);
+ print(") ");
+ break;
+ default:
+ println("(");
+ indent++;
+ int c = 0;
+ for (Object i : resources) {
+ align();
+ flagMod = -1L & ~FINAL;
+ printVarDefInline((JCVariableDecl) i);
+ if (++c == len) {
+ print(") ");
+ } else {
+ println(";", (JCTree) i);
+ }
+ }
+ indent--;
+ }
+ println("{");
+ indent++;
+ for (JCStatement stat : tree.body.stats) print(stat);
+ indent--;
+ aPrint("}");
+ for (JCCatch catchBlock : tree.catchers) {
+ printCatch(catchBlock);
+ }
+ if (tree.finalizer != null) {
+ println(" finally {");
+ indent++;
+ for (JCStatement stat : tree.finalizer.stats) print(stat);
+ indent--;
+ aPrint("}");
+ }
+ println(tree);
+ }
+
+ private void printCatch(JCCatch catchBlock) {
+ print(" catch (");
+ printVarDefInline(catchBlock.param); // ExprType1 | ExprType2 handled via JCTypeUnion.
+ println(") {");
+ indent++;
+ for (JCStatement stat : catchBlock.body.stats) print(stat);
+ indent--;
+ aPrint("}");
+ }
+
+ public void visitErroneous(JCErroneous tree) {
+ print("(ERROR)");
+ }
+
+ private static String operator(TreeTag tag) {
+ String op = OPERATORS.get(tag);
+ if (op == null) return "(?op?)";
+ return op;
+ }
+
+ private static String quoteChars(String s) {
+ StringBuilder sb = new StringBuilder();
+ for (int i = 0; i < s.length(); i++) sb.append(quoteChar(s.charAt(i)));
+ return sb.toString();
+ }
+
+ private static String quoteChar(char ch) {
+ switch (ch) {
+ case '\b': return "\\b";
+ case '\f': return "\\f";
+ case '\n': return "\\n";
+ case '\r': return "\\r";
+ case '\t': return "\\t";
+ case '\'': return "\\'";
+ case '\"': return "\\\"";
+ case '\\': return "\\\\";
+ default:
+ if (ch < 32) return String.format("\\%03o", (int) ch);
+ return String.valueOf(ch);
+ }
+ }
+
+ private static final Method getExtendsClause, getEndPosition, storeEnd;
+
+ static {
+ getExtendsClause = getMethod(JCClassDecl.class, "getExtendsClause", new Class<?>[0]);
+ getExtendsClause.setAccessible(true);
+
+ if (getJavaCompilerVersion() < 8) {
+ getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", java.util.Map.class);
+ storeEnd = getMethod(java.util.Map.class, "put", Object.class, Object.class);
+ } else {
+ getEndPosition = getMethod(DiagnosticPosition.class, "getEndPosition", "com.sun.tools.javac.tree.EndPosTable");
+ Method storeEndMethodTemp;
+ Class<?> endPosTable;
+ try {
+ endPosTable = Class.forName("com.sun.tools.javac.tree.EndPosTable");
+ } catch (ClassNotFoundException ex) {
+ throw sneakyThrow(ex);
+ }
+ try {
+ storeEndMethodTemp = endPosTable.getMethod("storeEnd", JCTree.class, int.class);
+ } catch (NoSuchMethodException e) {
+ try {
+ endPosTable = Class.forName("com.sun.tools.javac.parser.JavacParser$AbstractEndPosTable");
+ storeEndMethodTemp = endPosTable.getDeclaredMethod("storeEnd", JCTree.class, int.class);
+ } catch (NoSuchMethodException ex) {
+ throw sneakyThrow(ex);
+ } catch (ClassNotFoundException ex) {
+ throw sneakyThrow(ex);
+ }
+ }
+ storeEnd = storeEndMethodTemp;
+ }
+ getEndPosition.setAccessible(true);
+ storeEnd.setAccessible(true);
+ }
+
+ private static Method getMethod(Class<?> clazz, String name, Class<?>... paramTypes) {
+ try {
+ return clazz.getMethod(name, paramTypes);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ private static Method getMethod(Class<?> clazz, String name, String... paramTypes) {
+ try {
+ Class<?>[] c = new Class[paramTypes.length];
+ for (int i = 0; i < paramTypes.length; i++) c[i] = Class.forName(paramTypes[i]);
+ return clazz.getMethod(name, c);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
+ } catch (ClassNotFoundException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ public static JCTree getExtendsClause(JCClassDecl decl) {
+ try {
+ return (JCTree) getExtendsClause.invoke(decl);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw sneakyThrow(e.getCause());
+ }
+ }
+
+ static RuntimeException sneakyThrow(Throwable t) {
+ if (t == null) throw new NullPointerException("t");
+ PrettyPrinter.<RuntimeException>sneakyThrow0(t);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
+ throw (T)t;
+ }
+
+ private static final Map<Class<?>, Map<String, Field>> reflectionCache = new HashMap<Class<?>, Map<String, Field>>();
+
+ @SuppressWarnings("unchecked")
+ private <T> T readObject(JCTree tree, String fieldName, T defaultValue) {
+ Class<?> tClass = tree.getClass();
+ Map<String, Field> c = reflectionCache.get(tClass);
+ if (c == null) reflectionCache.put(tClass, c = new HashMap<String, Field>());
+ Field f = c.get(fieldName);
+ if (f == null) {
+ try {
+ f = tClass.getDeclaredField(fieldName);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ f.setAccessible(true);
+ c.put(fieldName, f);
+ }
+
+ try {
+ return (T) f.get(tree);
+ } catch (Exception e) {
+ return defaultValue;
+ }
+ }
+
+ public void visitTypeBoundKind(TypeBoundKind tree) {
+ print(String.valueOf(tree.kind));
+ }
+
+ @Override public void visitTree(JCTree tree) {
+ String simpleName = tree.getClass().getSimpleName();
+ if ("JCTypeUnion".equals(simpleName)) {
+ List<JCExpression> types = readObject(tree, "alternatives", List.<JCExpression>nil());
+ print(types, " | ");
+ } else if ("JCTypeIntersection".equals(simpleName)) {
+ print(readObject(tree, "bounds", List.<JCExpression>nil()), " & ");
+ } else if ("JCMemberReference".equals(simpleName)) {
+ printMemberReference0(tree);
+ } else if ("JCLambda".equals(simpleName)) {
+ printLambda0(tree);
+ } else if ("JCAnnotatedType".equals(simpleName)) {
+ printAnnotatedType0(tree);
+ } else if ("JCPackageDecl".equals(simpleName)) {
+ // Starting with JDK9, this is inside the import list, but we've already printed it. Just ignore it.
+ } else {
+ throw new AssertionError("Unhandled tree type: " + tree.getClass() + ": " + tree);
+ }
+ }
+
+ private void printMemberReference0(JCTree tree) {
+ print(readObject(tree, "expr", (JCExpression) null));
+ print("::");
+ List<JCExpression> typeArgs = readObject(tree, "typeargs", List.<JCExpression>nil());
+ if (typeArgs != null && !typeArgs.isEmpty()) {
+ print("<");
+ print(typeArgs, ", ");
+ print(">");
+ }
+ print(readObject(tree, "mode", new Object()).toString().equals("INVOKE") ? readObject(tree, "name", (Name) null) : "new");
+ }
+
+ private void printLambda0(JCTree tree) {
+ List<JCVariableDecl> params = readObject(tree, "params", List.<JCVariableDecl>nil());
+ boolean explicit = true;
+ int paramLength = params.size();
+ try {
+ explicit = readObject(tree, "paramKind", new Object()).toString().equals("EXPLICIT");
+ } catch (Exception e) {}
+ boolean useParens = paramLength != 1 || explicit;
+ if (useParens) print("(");
+ if (explicit) {
+ boolean first = true;
+ for (JCVariableDecl vd : params) {
+ if (!first) print(", ");
+ first = false;
+ printVarDefInline(vd);
+ }
+ } else {
+ String sep = "";
+ for (JCVariableDecl param : params) {
+ print(sep);
+ print(param.name);
+ sep = ", ";
+ }
+ }
+ if (useParens) print(")");
+ print(" -> ");
+ JCTree body = readObject(tree, "body", (JCTree) null);
+ if (body instanceof JCBlock) {
+ println("{");
+ indent++;
+ print(((JCBlock) body).stats, "");
+ indent--;
+ aPrint("}");
+ } else {
+ print(body);
+ }
+ }
+
+ private void printAnnotatedType0(JCTree tree) {
+ JCTree underlyingType = readObject(tree, "underlyingType", (JCTree) null);
+ if (underlyingType instanceof JCFieldAccess) {
+ print(((JCFieldAccess) underlyingType).selected);
+ print(".");
+ print(readObject(tree, "annotations", List.<JCExpression>nil()), " ");
+ print(" ");
+ print(((JCFieldAccess) underlyingType).name);
+ } else {
+ print(readObject(tree, "annotations", List.<JCExpression>nil()), " ");
+ print(" ");
+ print(underlyingType);
+ }
+ }
+}
diff --git a/src/delombok/lombok/delombok/UnicodeEscapeWriter.java b/src/delombok/lombok/delombok/UnicodeEscapeWriter.java
index 95b55078..9c2ef190 100644
--- a/src/delombok/lombok/delombok/UnicodeEscapeWriter.java
+++ b/src/delombok/lombok/delombok/UnicodeEscapeWriter.java
@@ -63,6 +63,6 @@ public class UnicodeEscapeWriter extends Writer {
}
protected void writeUnicodeEscape(char c) throws IOException {
- writer.write("\\u" + Integer.toHexString(c));
+ writer.write(String.format("\\u%04x", (int) c));
}
} \ No newline at end of file
diff --git a/src/delombok/lombok/delombok/ant/DelombokTask.java b/src/delombok/lombok/delombok/ant/DelombokTask.java
index d5c17fe7..06bbe3e0 100644
--- a/src/delombok/lombok/delombok/ant/DelombokTask.java
+++ b/src/delombok/lombok/delombok/ant/DelombokTask.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -22,142 +22,189 @@
package lombok.delombok.ant;
import java.io.File;
-import java.io.IOException;
-import java.nio.charset.UnsupportedCharsetException;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
import java.util.ArrayList;
-import java.util.Iterator;
import java.util.List;
-import lombok.delombok.Delombok;
-import lombok.delombok.Delombok.InvalidFormatOptionException;
+import lombok.Lombok;
import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
import org.apache.tools.ant.Task;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.Path;
import org.apache.tools.ant.types.Reference;
-import org.apache.tools.ant.types.resources.FileResource;
-public class DelombokTask extends Task {
- private File fromDir, toDir;
- private Path classpath;
- private Path sourcepath;
- private boolean verbose;
- private String encoding;
- private Path path;
- private List<Format> formatOptions = new ArrayList<Format>();
-
- public void setClasspath(Path classpath) {
- if (this.classpath == null) {
- this.classpath = classpath;
- } else {
- this.classpath.append(classpath);
+@SuppressWarnings("unused") // we use reflection to transfer fields.
+class Tasks {
+ public static class Format {
+ private String value;
+
+ @Override public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result + ((value == null) ? 0 : value.hashCode());
+ return result;
}
- }
-
- public Path createClasspath() {
- if (classpath == null) {
- classpath = new Path(getProject());
+
+ @Override public boolean equals(Object obj) {
+ if (this == obj) return true;
+ if (obj == null) return false;
+ if (getClass() != obj.getClass()) return false;
+ Format other = (Format) obj;
+ if (value == null) {
+ if (other.value != null) return false;
+ } else if (!value.equals(other.value)) return false;
+ return true;
}
- return classpath.createPath();
- }
-
- public void setClasspathRef(Reference r) {
- createClasspath().setRefid(r);
- }
-
- public void setSourcepath(Path sourcepath) {
- if (this.sourcepath == null) {
- this.sourcepath = sourcepath;
- } else {
- this.sourcepath.append(sourcepath);
+
+ @Override public String toString() {
+ return "FormatOption [value=" + value + "]";
}
- }
-
- public Path createSourcepath() {
- if (sourcepath == null) {
- sourcepath = new Path(getProject());
+
+ public String getValue() {
+ return value;
+ }
+
+ public void setValue(String value) {
+ this.value = value;
}
- return sourcepath.createPath();
- }
-
- public void setSourcepathRef(Reference r) {
- createSourcepath().setRefid(r);
- }
-
- public void setFrom(File dir) {
- this.fromDir = dir;
- }
-
- public void setTo(File dir) {
- this.toDir = dir;
- }
-
- public void setVerbose(boolean verbose) {
- this.verbose = verbose;
- }
-
- public void setEncoding(String encoding) {
- this.encoding = encoding;
- }
-
- public void addFileset(FileSet set) {
- if (path == null) path = new Path(getProject());
- path.add(set);
- }
-
- public void addFormat(Format format) {
- formatOptions.add(format);
}
- @Override
- public void execute() throws BuildException {
- if (fromDir == null && path == null) throw new BuildException("Either 'from' attribute, or nested <fileset> tags are required.");
- if (fromDir != null && path != null) throw new BuildException("You can't specify both 'from' attribute and nested filesets. You need one or the other.");
- if (toDir == null) throw new BuildException("The to attribute is required.");
-
- Delombok delombok = new Delombok();
- if (verbose) delombok.setVerbose(true);
- try {
- if (encoding != null) delombok.setCharset(encoding);
- } catch (UnsupportedCharsetException e) {
- throw new BuildException("Unknown charset: " + encoding, getLocation());
- }
-
- if (classpath != null) delombok.setClasspath(classpath.toString());
- if (sourcepath != null) delombok.setSourcepath(sourcepath.toString());
-
- try {
- List<String> fo = new ArrayList<String>();
- for (Format f : formatOptions) {
- String v = f.getValue();
- if (v == null) throw new BuildException("'value' property required for <format>");
- fo.add(v);
+ public static class Delombok extends Task {
+ private File fromDir, toDir;
+ private Path classpath;
+ private Path sourcepath;
+ private boolean verbose;
+ private String encoding;
+ private Path path;
+ private List<Format> formatOptions = new ArrayList<Format>();
+
+ public void setClasspath(Path classpath) {
+ if (this.classpath == null) {
+ this.classpath = classpath;
+ } else {
+ this.classpath.append(classpath);
+ }
+ }
+
+ public Path createClasspath() {
+ if (classpath == null) {
+ classpath = new Path(getProject());
}
- delombok.setFormatPreferences(Delombok.formatOptionsToMap(fo));
- } catch (InvalidFormatOptionException e) {
- throw new BuildException(e.getMessage() + " Run java -jar lombok.jar --format-help for detailed format help.");
- }
-
- delombok.setOutput(toDir);
- try {
- if (fromDir != null) delombok.addDirectory(fromDir);
- else {
- Iterator<?> it = path.iterator();
- while (it.hasNext()) {
- FileResource fileResource = (FileResource) it.next();
- File baseDir = fileResource.getBaseDir();
- if (baseDir == null) {
- File file = fileResource.getFile();
- delombok.addFile(file.getParentFile(), file.getName());
+ return classpath.createPath();
+ }
+
+ public void setClasspathRef(Reference r) {
+ createClasspath().setRefid(r);
+ }
+
+ public void setSourcepath(Path sourcepath) {
+ if (this.sourcepath == null) {
+ this.sourcepath = sourcepath;
+ } else {
+ this.sourcepath.append(sourcepath);
+ }
+ }
+
+ public Path createSourcepath() {
+ if (sourcepath == null) {
+ sourcepath = new Path(getProject());
+ }
+ return sourcepath.createPath();
+ }
+
+ public void setSourcepathRef(Reference r) {
+ createSourcepath().setRefid(r);
+ }
+
+ public void setFrom(File dir) {
+ this.fromDir = dir;
+ }
+
+ public void setTo(File dir) {
+ this.toDir = dir;
+ }
+
+ public void setVerbose(boolean verbose) {
+ this.verbose = verbose;
+ }
+
+ public void setEncoding(String encoding) {
+ this.encoding = encoding;
+ }
+
+ public void addFileset(FileSet set) {
+ if (path == null) path = new Path(getProject());
+ path.add(set);
+ }
+
+ public Format createFormat() {
+ return new Format();
+ }
+
+ public void addFormat(Format format) {
+ formatOptions.add(format);
+ }
+
+ private static ClassLoader shadowLoader;
+
+ public static Class<?> shadowLoadClass(String name) {
+ try {
+ if (shadowLoader == null) {
+ try {
+ Class.forName("lombok.core.LombokNode");
+ // If we get here, then lombok is already available.
+ shadowLoader = Delombok.class.getClassLoader();
+ } catch (ClassNotFoundException e) {
+ // If we get here, it isn't, and we should use the shadowloader.
+ Class<?> launcherMain = Class.forName("lombok.launch.Main");
+ Method m = launcherMain.getDeclaredMethod("createShadowClassLoader");
+ m.setAccessible(true);
+ shadowLoader = (ClassLoader) m.invoke(null);
+ }
+ }
+
+ return Class.forName(name, true, shadowLoader);
+ } catch (Exception e) {
+ throw Lombok.sneakyThrow(e);
+ }
+ }
+
+ @Override
+ public void execute() throws BuildException {
+ Location loc = getLocation();
+
+ try {
+ Object instance = shadowLoadClass("lombok.delombok.ant.DelombokTaskImpl").newInstance();
+ for(Field selfField : getClass().getDeclaredFields()) {
+ if (selfField.isSynthetic() || Modifier.isStatic(selfField.getModifiers())) continue;
+ Field otherField = instance.getClass().getDeclaredField(selfField.getName());
+ otherField.setAccessible(true);
+ selfField.setAccessible(true);
+ if (selfField.getName().equals("formatOptions")) {
+ List<String> rep = new ArrayList<String>();
+ for (Format f : formatOptions) {
+ if (f.getValue() == null) throw new BuildException("'value' property required for <format>");
+ rep.add(f.getValue());
+ }
+ otherField.set(instance, rep);
} else {
- delombok.addFile(baseDir, fileResource.getName());
+ otherField.set(instance, selfField.get(this));
}
}
+
+ Method m = instance.getClass().getMethod("execute", Location.class);
+ m.setAccessible(true);
+ m.invoke(instance, loc);
+ } catch (InvocationTargetException e) {
+ throw Lombok.sneakyThrow(e.getCause());
+ } catch (Exception e) {
+ throw Lombok.sneakyThrow(e);
}
- delombok.delombok();
- } catch (IOException e) {
- throw new BuildException("I/O problem during delombok", e, getLocation());
}
}
}
diff --git a/src/delombok/lombok/delombok/ant/DelombokTaskImpl.java b/src/delombok/lombok/delombok/ant/DelombokTaskImpl.java
new file mode 100644
index 00000000..470819cd
--- /dev/null
+++ b/src/delombok/lombok/delombok/ant/DelombokTaskImpl.java
@@ -0,0 +1,91 @@
+/*
+ * Copyright (C) 2009-2015 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.delombok.ant;
+
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.UnsupportedCharsetException;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+import lombok.delombok.Delombok;
+import lombok.delombok.Delombok.InvalidFormatOptionException;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.Location;
+import org.apache.tools.ant.types.Path;
+import org.apache.tools.ant.types.resources.FileResource;
+
+public class DelombokTaskImpl {
+ private File fromDir, toDir;
+ private Path classpath;
+ private Path sourcepath;
+ private boolean verbose;
+ private String encoding;
+ private Path path;
+ private List<String> formatOptions = new ArrayList<String>();
+
+ public void execute(Location location) throws BuildException {
+ if (fromDir == null && path == null) throw new BuildException("Either 'from' attribute, or nested <fileset> tags are required.");
+ if (fromDir != null && path != null) throw new BuildException("You can't specify both 'from' attribute and nested filesets. You need one or the other.");
+ if (toDir == null) throw new BuildException("The to attribute is required.");
+
+ Delombok delombok = new Delombok();
+ if (verbose) delombok.setVerbose(true);
+ try {
+ if (encoding != null) delombok.setCharset(encoding);
+ } catch (UnsupportedCharsetException e) {
+ throw new BuildException("Unknown charset: " + encoding, location);
+ }
+
+ if (classpath != null) delombok.setClasspath(classpath.toString());
+ if (sourcepath != null) delombok.setSourcepath(sourcepath.toString());
+
+ try {
+ delombok.setFormatPreferences(Delombok.formatOptionsToMap(formatOptions));
+ } catch (InvalidFormatOptionException e) {
+ throw new BuildException(e.getMessage() + " Run java -jar lombok.jar --format-help for detailed format help.");
+ }
+
+ delombok.setOutput(toDir);
+ try {
+ if (fromDir != null) delombok.addDirectory(fromDir);
+ else {
+ Iterator<?> it = path.iterator();
+ while (it.hasNext()) {
+ FileResource fileResource = (FileResource) it.next();
+ File baseDir = fileResource.getBaseDir();
+ if (baseDir == null) {
+ File file = fileResource.getFile();
+ delombok.addFile(file.getParentFile(), file.getName());
+ } else {
+ delombok.addFile(baseDir, fileResource.getName());
+ }
+ }
+ }
+ delombok.delombok();
+ } catch (IOException e) {
+ throw new BuildException("I/O problem during delombok", e, location);
+ }
+ }
+}
diff --git a/src/delombok/lombok/delombok/ant/Format.java b/src/delombok/lombok/delombok/ant/Format.java
deleted file mode 100644
index bb2b5e87..00000000
--- a/src/delombok/lombok/delombok/ant/Format.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package lombok.delombok.ant;
-
-public class Format {
- private String value;
-
- @Override public int hashCode() {
- final int prime = 31;
- int result = 1;
- result = prime * result + ((value == null) ? 0 : value.hashCode());
- return result;
- }
-
- @Override public boolean equals(Object obj) {
- if (this == obj) return true;
- if (obj == null) return false;
- if (getClass() != obj.getClass()) return false;
- Format other = (Format) obj;
- if (value == null) {
- if (other.value != null) return false;
- } else if (!value.equals(other.value)) return false;
- return true;
- }
-
- @Override public String toString() {
- return "FormatOption [value=" + value + "]";
- }
-
- public String getValue() {
- return value;
- }
-
- public void setValue(String value) {
- this.value = value;
- }
-}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java
new file mode 100644
index 00000000..aa01c13d
--- /dev/null
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcher.java
@@ -0,0 +1,72 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.agent;
+
+import lombok.patcher.ClassRootFinder;
+import lombok.patcher.Hook;
+import lombok.patcher.MethodTarget;
+import lombok.patcher.ScriptManager;
+import lombok.patcher.StackRequest;
+import lombok.patcher.scripts.ScriptBuilder;
+
+public class EclipseLoaderPatcher {
+ private static final String TRANSPLANTS_CLASS_NAME = "lombok.eclipse.agent.EclipseLoaderPatcherTransplants";
+
+ public static void patchEquinoxLoaders(ScriptManager sm, Class<?> launchingContext) {
+ sm.addScript(ScriptBuilder.exitEarly()
+ .target(new MethodTarget("org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader", "loadClass",
+ "java.lang.Class", "java.lang.String", "boolean"))
+ .target(new MethodTarget("org.eclipse.osgi.framework.adapter.core.AbstractClassLoader", "loadClass",
+ "java.lang.Class", "java.lang.String", "boolean"))
+ .target(new MethodTarget("org.eclipse.osgi.internal.loader.ModuleClassLoader", "loadClass",
+ "java.lang.Class", "java.lang.String", "boolean"))
+ .decisionMethod(new Hook(TRANSPLANTS_CLASS_NAME, "overrideLoadDecide", "boolean", "java.lang.ClassLoader", "java.lang.String", "boolean"))
+ .valueMethod(new Hook(TRANSPLANTS_CLASS_NAME, "overrideLoadResult", "java.lang.Class", "java.lang.ClassLoader", "java.lang.String", "boolean"))
+ .transplant()
+ .request(StackRequest.THIS, StackRequest.PARAM1, StackRequest.PARAM2).build());
+
+ sm.addScript(ScriptBuilder.addField().setPublic().setVolatile()
+ .fieldType("Ljava/lang/ClassLoader;")
+ .fieldName("lombok$shadowLoader")
+ .targetClass("org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader")
+ .targetClass("org.eclipse.osgi.framework.adapter.core.AbstractClassLoader")
+ .targetClass("org.eclipse.osgi.internal.loader.ModuleClassLoader")
+ .build());
+
+ sm.addScript(ScriptBuilder.addField().setPublic().setVolatile().setStatic()
+ .fieldType("Ljava/lang/Class;")
+ .fieldName("lombok$shadowLoaderClass")
+ .targetClass("org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader")
+ .targetClass("org.eclipse.osgi.framework.adapter.core.AbstractClassLoader")
+ .targetClass("org.eclipse.osgi.internal.loader.ModuleClassLoader")
+ .build());
+
+ sm.addScript(ScriptBuilder.addField().setPublic().setStatic().setFinal()
+ .fieldType("Ljava/lang/String;")
+ .fieldName("lombok$location")
+ .targetClass("org.eclipse.osgi.internal.baseadaptor.DefaultClassLoader")
+ .targetClass("org.eclipse.osgi.framework.adapter.core.AbstractClassLoader")
+ .targetClass("org.eclipse.osgi.internal.loader.ModuleClassLoader")
+ .value(ClassRootFinder.findClassRootOfClass(launchingContext))
+ .build());
+ }
+}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java
new file mode 100644
index 00000000..ea72f56a
--- /dev/null
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipseLoaderPatcherTransplants.java
@@ -0,0 +1,128 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.agent;
+
+import java.io.InputStream;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.jar.JarFile;
+import java.util.zip.ZipEntry;
+
+/**
+ * Contains all the code to be transplanted into eclipse.
+ *
+ * Do not use:
+ *
+ * * Annotations
+ * * Generics
+ * * Varargs
+ * * Auto (un)boxing
+ * * class literals
+ *
+ * The above because this code is compiled with -source 1.4, and is transplanted.
+ *
+ * NB: The suppress warnings will be stripped out before compilation.
+ */
+@SuppressWarnings("all")
+public class EclipseLoaderPatcherTransplants {
+ public static boolean overrideLoadDecide(ClassLoader original, String name, boolean resolve) {
+ return name.startsWith("lombok.");
+ }
+
+ public static Class overrideLoadResult(ClassLoader original, String name, boolean resolve) throws ClassNotFoundException {
+ try {
+ Field shadowLoaderField = original.getClass().getField("lombok$shadowLoader");
+ ClassLoader shadowLoader = (ClassLoader) shadowLoaderField.get(original);
+ if (shadowLoader == null) {
+ synchronized ("lombok$shadowLoader$globalLock".intern()) {
+ shadowLoader = (ClassLoader) shadowLoaderField.get(original);
+ if (shadowLoader == null) {
+ Class shadowClassLoaderClass = (Class) original.getClass().getField("lombok$shadowLoaderClass").get(null);
+ Class classLoaderClass = Class.forName("java.lang.ClassLoader");
+ String jarLoc = (String) original.getClass().getField("lombok$location").get(null);
+ if (shadowClassLoaderClass == null) {
+ JarFile jf = new JarFile(jarLoc);
+ InputStream in = null;
+ try {
+ ZipEntry entry = jf.getEntry("lombok/launch/ShadowClassLoader.class");
+ in = jf.getInputStream(entry);
+ byte[] bytes = new byte[65536];
+ int len = 0;
+ while (true) {
+ int r = in.read(bytes, len, bytes.length - len);
+ if (r == -1) break;
+ len += r;
+ if (len == bytes.length) throw new IllegalStateException("lombok.launch.ShadowClassLoader too large.");
+ }
+ in.close();
+ {
+ Class[] paramTypes = new Class[4];
+ paramTypes[0] = "".getClass();
+ paramTypes[1] = new byte[0].getClass();
+ paramTypes[2] = Integer.TYPE;
+ paramTypes[3] = paramTypes[2];
+ Method defineClassMethod = classLoaderClass.getDeclaredMethod("defineClass", paramTypes);
+ defineClassMethod.setAccessible(true);
+ shadowClassLoaderClass = (Class) defineClassMethod.invoke(original, new Object[] {"lombok.launch.ShadowClassLoader", bytes, new Integer(0), new Integer(len)});
+ original.getClass().getField("lombok$shadowLoaderClass").set(null, shadowClassLoaderClass);
+ }
+ } finally {
+ if (in != null) in.close();
+ jf.close();
+ }
+ }
+ Class[] paramTypes = new Class[5];
+ paramTypes[0] = classLoaderClass;
+ paramTypes[1] = "".getClass();
+ paramTypes[2] = paramTypes[1];
+ paramTypes[3] = Class.forName("java.util.List");
+ paramTypes[4] = paramTypes[3];
+ Constructor constructor = shadowClassLoaderClass.getDeclaredConstructor(paramTypes);
+ constructor.setAccessible(true);
+ shadowLoader = (ClassLoader) constructor.newInstance(new Object[] {original, "lombok", jarLoc, Arrays.asList(new Object[] {"lombok."}), Arrays.asList(new Object[] {"lombok.patcher.Symbols"})});
+ shadowLoaderField.set(original, shadowLoader);
+ }
+ }
+ }
+
+ if (resolve) {
+ Class[] paramTypes = new Class[2];
+ paramTypes[0] = "".getClass();
+ paramTypes[1] = Boolean.TYPE;
+ Method m = shadowLoader.getClass().getDeclaredMethod("loadClass", new Class[] {String.class, boolean.class});
+ m.setAccessible(true);
+ return (Class) m.invoke(shadowLoader, new Object[] {name, Boolean.TRUE});
+ } else {
+ return shadowLoader.loadClass(name);
+ }
+ } catch (Exception ex) {
+ Throwable t = ex;
+ if (t instanceof InvocationTargetException) t = t.getCause();
+ if (t instanceof RuntimeException) throw (RuntimeException) t;
+ if (t instanceof Error) throw (Error) t;
+ throw new RuntimeException(t);
+ }
+ }
+}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
index e14d1367..a6d745b6 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/EclipsePatcher.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -23,18 +23,22 @@ package lombok.eclipse.agent;
import static lombok.patcher.scripts.ScriptBuilder.*;
+import java.io.File;
import java.lang.instrument.Instrumentation;
+import java.net.URLClassLoader;
+import java.security.ProtectionDomain;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
-import lombok.core.Agent;
+import lombok.core.AgentLauncher;
+import lombok.patcher.Filter;
import lombok.patcher.Hook;
import lombok.patcher.MethodTarget;
import lombok.patcher.ScriptManager;
import lombok.patcher.StackRequest;
import lombok.patcher.TargetMatcher;
-import lombok.patcher.equinox.EquinoxClassLoader;
+import lombok.patcher.TransplantMapper;
import lombok.patcher.scripts.ScriptBuilder;
/**
@@ -44,13 +48,12 @@ import lombok.patcher.scripts.ScriptBuilder;
* classes in this package for more information about which classes are transformed and how they are
* transformed.
*/
-public class EclipsePatcher extends Agent {
+public class EclipsePatcher implements AgentLauncher.AgentLaunchable {
// At some point I'd like the agent to be capable of auto-detecting if its on eclipse or on ecj. This class is a sure sign we're not in ecj but in eclipse. -ReinierZ
@SuppressWarnings("unused")
private static final String ECLIPSE_SIGNATURE_CLASS = "org/eclipse/core/runtime/adaptor/EclipseStarter";
- @Override
- public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected) throws Exception {
+ @Override public void runAgent(String agentArgs, Instrumentation instrumentation, boolean injected, Class<?> launchingContext) throws Exception {
String[] args = agentArgs == null ? new String[0] : agentArgs.split(":");
boolean forceEcj = false;
boolean forceEclipse = false;
@@ -69,18 +72,31 @@ public class EclipsePatcher extends Agent {
else if (forceEclipse) ecj = false;
else ecj = injected;
- registerPatchScripts(instrumentation, injected, ecj);
+ registerPatchScripts(instrumentation, injected, ecj, launchingContext);
}
- private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, boolean ecjOnly) {
+ private static void registerPatchScripts(Instrumentation instrumentation, boolean reloadExistingClasses, boolean ecjOnly, Class<?> launchingContext) {
ScriptManager sm = new ScriptManager();
sm.registerTransformer(instrumentation);
- if (!ecjOnly) {
- EquinoxClassLoader.addPrefix("lombok.");
- EquinoxClassLoader.registerScripts(sm);
- }
+ sm.setFilter(new Filter() {
+ @Override public boolean shouldTransform(ClassLoader loader, String className, Class<?> classBeingDefined, ProtectionDomain protectionDomain, byte[] classfileBuffer) {
+ if (!(loader instanceof URLClassLoader)) return true;
+ ClassLoader parent = loader.getParent();
+ if (parent == null) return true;
+ return !parent.getClass().getName().startsWith("org.eclipse.jdt.apt.core.internal.AnnotationProcessorFactoryLoader");
+ }
+ });
+
+ final boolean forceBaseResourceNames = shouldForceBaseResourceNames();
+ sm.setTransplantMapper(new TransplantMapper() {
+ public String mapResourceName(int classFileFormatVersion, String resourceName) {
+ if (classFileFormatVersion < 50 || forceBaseResourceNames) return resourceName;
+ return "Class50/" + resourceName;
+ }
+ });
if (!ecjOnly) {
+ EclipseLoaderPatcher.patchEquinoxLoaders(sm, launchingContext);
patchCatchReparse(sm);
patchIdentifierEndReparse(sm);
patchRetrieveEllipsisStartPosition(sm);
@@ -90,7 +106,7 @@ public class EclipsePatcher extends Agent {
patchHideGeneratedNodes(sm);
patchPostCompileHookEclipse(sm);
patchFixSourceTypeConverter(sm);
- patchDisableLombokForCodeFormatterAndCleanup(sm);
+ patchDisableLombokForCodeCleanup(sm);
patchListRewriteHandleGeneratedMethods(sm);
patchSyntaxAndOccurrencesHighlighting(sm);
patchSortMembersOperation(sm);
@@ -105,16 +121,43 @@ public class EclipsePatcher extends Agent {
patchLombokizeAST(sm);
patchEcjTransformers(sm, ecjOnly);
patchExtensionMethod(sm, ecjOnly);
+ patchRenameField(sm);
if (reloadExistingClasses) sm.reloadClasses(instrumentation);
}
+ private static boolean shouldForceBaseResourceNames() {
+ String shadowOverride = System.getProperty("shadow.override.lombok", "");
+ if (shadowOverride == null || shadowOverride.length() == 0) return false;
+ for (String part : shadowOverride.split("\\s*" + (File.pathSeparatorChar == ';' ? ";" : ":") + "\\s*")) {
+ if (part.equalsIgnoreCase("lombok.jar")) return false;
+ }
+ return true;
+ }
+
+ private static void patchRenameField(ScriptManager sm) {
+ /* RefactoringSearchEngine.search will not return results when renaming field and Data Annotation is present. Return a fake Element to make checks pass */
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor", "checkAccessorDeclarations", "org.eclipse.ltk.core.refactoring.RefactoringStatus", "org.eclipse.core.runtime.IProgressMonitor", "org.eclipse.jdt.core.IMethod"))
+ .methodToWrap(new Hook("org.eclipse.jdt.internal.corext.refactoring.RefactoringSearchEngine", "search", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "org.eclipse.jdt.core.search.SearchPattern","org.eclipse.jdt.core.search.IJavaSearchScope","org.eclipse.core.runtime.IProgressMonitor","org.eclipse.ltk.core.refactoring.RefactoringStatus"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "createFakeSearchResult", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup[]", "java.lang.Object"))
+ .requestExtra(StackRequest.THIS)
+ .transplant().build());
+
+ /* Filter search results which are Generated and based on Fields, e.g. Generated getters/setters */
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameFieldProcessor", "addAccessorOccurrences", "void", "org.eclipse.core.runtime.IProgressMonitor", "org.eclipse.jdt.core.IMethod", "java.lang.String","java.lang.String","org.eclipse.ltk.core.refactoring.RefactoringStatus"))
+ .methodToWrap(new Hook("org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup", "getSearchResults", "org.eclipse.jdt.core.search.SearchMatch[]"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGenerated", "org.eclipse.jdt.core.search.SearchMatch[]", "org.eclipse.jdt.core.search.SearchMatch[]"))
+ .transplant().build());
+ }
+
private static void patchExtractInterface(ScriptManager sm) {
/* Fix sourceEnding for generated nodes to avoid null pointer */
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.SourceElementNotifier", "notifySourceElementRequestor", "void", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration", "org.eclipse.jdt.internal.compiler.ast.TypeDeclaration", "org.eclipse.jdt.internal.compiler.ast.ImportReference"))
.methodToWrap(new Hook("org.eclipse.jdt.internal.compiler.util.HashtableOfObjectToInt", "get", "int", "java.lang.Object"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getSourceEndFixed", "int", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getSourceEndFixed", "int", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.requestExtra(StackRequest.PARAM1)
.transplant().build());
@@ -127,7 +170,7 @@ public class EclipsePatcher extends Agent {
"org.eclipse.jdt.core.dom.MethodDeclaration"
))
.methodToWrap(new Hook("org.eclipse.jface.text.IDocument", "get", "java.lang.String", "int", "int"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationSource", "java.lang.String", "java.lang.String", "java.lang.Object", "org.eclipse.jdt.core.dom.MethodDeclaration"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getRealMethodDeclarationSource", "java.lang.String", "java.lang.String", "java.lang.Object", "org.eclipse.jdt.core.dom.MethodDeclaration"))
.requestExtra(StackRequest.THIS, StackRequest.PARAM4)
.transplant().build());
@@ -136,20 +179,20 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMemberDeclarations"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComments"))
.methodToReplace(new Hook("org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil", "getMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit"))
- .replacementMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getRealMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit"))
+ .replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getRealMethodDeclarationNode", "org.eclipse.jdt.core.dom.MethodDeclaration", "org.eclipse.jdt.core.IMethod", "org.eclipse.jdt.core.dom.CompilationUnit"))
.transplant().build());
/* Do not add @Override's for generated methods */
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ListRewrite", "insertFirst"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isListRewriteOnGeneratedNode", "boolean", "org.eclipse.jdt.core.dom.rewrite.ListRewrite"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isListRewriteOnGeneratedNode", "boolean", "org.eclipse.jdt.core.dom.rewrite.ListRewrite"))
.request(StackRequest.THIS)
.transplant().build());
/* Do not add comments for generated methods */
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.structure.ExtractInterfaceProcessor", "createMethodComment"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
.request(StackRequest.PARAM2)
.transplant().build());
}
@@ -162,7 +205,7 @@ public class EclipsePatcher extends Agent {
*/
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.core.internal.runtime.Product", "getProperty", "java.lang.String", "java.lang.String"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "addLombokNotesToEclipseAboutDialog", "java.lang.String", "java.lang.String", "java.lang.String"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "addLombokNotesToEclipseAboutDialog", "java.lang.String", "java.lang.String", "java.lang.String"))
.request(StackRequest.RETURN_VALUE, StackRequest.PARAM1)
.transplant().build());
}
@@ -175,19 +218,13 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.internal.ui.search.OccurrencesFinder", "addUsage"))
.target(new MethodTarget("org.eclipse.jdt.internal.ui.search.OccurrencesFinder", "addWrite"))
.target(new MethodTarget("org.eclipse.jdt.internal.ui.javaeditor.SemanticHighlightingReconciler$PositionCollector", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
- .valueMethod(new Hook("lombok.eclipse.agent.PatchFixes", "returnFalse", "boolean", "java.lang.Object"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
+ .valueMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "returnFalse", "boolean", "java.lang.Object"))
.request(StackRequest.PARAM1)
.build());
}
- private static void patchDisableLombokForCodeFormatterAndCleanup(ScriptManager sm) {
- sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
- .target(new MethodTarget("org.eclipse.jdt.internal.formatter.DefaultCodeFormatter", "formatCompilationUnit"))
- .callToWrap(new Hook("org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil", "parseCompilationUnit", "org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration", "char[]", "java.util.Map", "boolean"))
- .symbol("lombok.disable")
- .build());
-
+ private static void patchDisableLombokForCodeCleanup(ScriptManager sm) {
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.ControlStatementsFix$ControlStatementFinder", "visit", "boolean", "org.eclipse.jdt.core.dom.DoStatement"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.ControlStatementsFix$ControlStatementFinder", "visit", "boolean", "org.eclipse.jdt.core.dom.EnhancedForStatement"))
@@ -201,9 +238,9 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.CodeStyleFix$CodeStyleVisitor", "visit", "boolean", "org.eclipse.jdt.core.dom.QualifiedName"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.fix.CodeStyleFix$CodeStyleVisitor", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
// if a generated node has children we can just ignore them as well;
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
.request(StackRequest.PARAM1)
- .valueMethod(new Hook("lombok.eclipse.agent.PatchFixes", "returnFalse", "boolean", "java.lang.Object"))
+ .valueMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "returnFalse", "boolean", "java.lang.Object"))
.build());
}
@@ -211,7 +248,7 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer$ListRewriter", "rewriteList"))
.methodToReplace(new Hook("org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent", "getChildren", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent[]"))
- .replacementMethod(new Hook("lombok.eclipse.agent.PatchFixes", "listRewriteHandleGeneratedMethods", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent[]", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent"))
+ .replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "listRewriteHandleGeneratedMethods", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent[]", "org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent"))
.build());
}
@@ -223,37 +260,37 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.CompilationUnit"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.CompilationUnit", "types", "java.util.List"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.AnnotationTypeDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.AnnotationTypeDeclaration", "bodyDeclarations", "java.util.List"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.AnonymousClassDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.AnonymousClassDeclaration", "bodyDeclarations", "java.util.List"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.TypeDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.TypeDeclaration", "bodyDeclarations", "java.util.List"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.EnumDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.EnumDeclaration", "bodyDeclarations", "java.util.List"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.SortElementsOperation$2", "visit", "boolean", "org.eclipse.jdt.core.dom.EnumDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.EnumDeclaration", "enumConstants", "java.util.List"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedNodes", "java.util.List", "java.util.List"))
.transplant().build());
}
@@ -261,7 +298,7 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.core.dom.rewrite.ASTRewriteAnalyzer", "visit"))
.methodToReplace(new Hook("org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "getTokenEndOffset", "int", "int", "int"))
- .replacementMethod(new Hook("lombok.eclipse.agent.PatchFixes", "getTokenEndOffsetFixed", "int", "org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "int", "int", "java.lang.Object"))
+ .replacementMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "getTokenEndOffsetFixed", "int", "org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner", "int", "int", "java.lang.Object"))
.requestExtra(StackRequest.PARAM1)
.transplant()
.build());
@@ -273,7 +310,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.internal.core.builder.IncrementalImageBuilder", "writeClassFileContents"))
.target(new MethodTarget("org.eclipse.jdt.internal.core.builder.AbstractImageBuilder", "writeClassFileContents"))
.methodToWrap(new Hook("org.eclipse.jdt.internal.compiler.ClassFile", "getBytes", "byte[]"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "runPostCompiler", "byte[]", "byte[]", "java.lang.String"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "runPostCompiler", "byte[]", "byte[]", "java.lang.String"))
.requestExtra(StackRequest.PARAM3)
.build());
}
@@ -282,24 +319,22 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.tool.EclipseCompilerImpl", "outputClassFiles"))
.methodToWrap(new Hook("javax.tools.JavaFileObject", "openOutputStream", "java.io.OutputStream"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "runPostCompiler", "java.io.OutputStream", "java.io.OutputStream"))
- .transplant()
- .build());
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "runPostCompiler", "java.io.OutputStream", "java.io.OutputStream"))
+ .transplant().build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.compiler.util.Util", "writeToDisk"))
.methodToWrap(new Hook("java.io.BufferedOutputStream", "<init>", "void", "java.io.OutputStream", "int"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "runPostCompiler", "java.io.BufferedOutputStream", "java.io.BufferedOutputStream", "java.lang.String", "java.lang.String"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$LombokDeps", "runPostCompiler", "java.io.BufferedOutputStream", "java.io.BufferedOutputStream", "java.lang.String", "java.lang.String"))
.requestExtra(StackRequest.PARAM2, StackRequest.PARAM3)
- .transplant()
- .build());
+ .transplant().build());
}
private static void patchHideGeneratedNodes(ScriptManager sm) {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder", "findByNode"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.dom.LinkedNodeFinder", "findByBinding"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedSimpleNames", "org.eclipse.jdt.core.dom.SimpleName[]",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedSimpleNames", "org.eclipse.jdt.core.dom.SimpleName[]",
"org.eclipse.jdt.core.dom.SimpleName[]"))
.request(StackRequest.RETURN_VALUE).build());
@@ -308,33 +343,41 @@ public class EclipsePatcher extends Agent {
}
private static void patchFormatters(ScriptManager sm) {
+ // before Eclipse Mars
sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
- .target(new MethodTarget("org.eclipse.jdt.internal.ui.text.java.JavaFormattingStrategy", "format", "void"))
- .callToWrap(new Hook("org.eclipse.jdt.internal.corext.util.CodeFormatterUtil", "reformat", "org.eclipse.text.edits.TextEdit",
- "int", "java.lang.String", "int", "int", "int", "java.lang.String", "java.util.Map"))
- .symbol("lombok.disable").build());
+ .target(new MethodTarget("org.eclipse.jdt.internal.formatter.DefaultCodeFormatter", "formatCompilationUnit"))
+ .callToWrap(new Hook("org.eclipse.jdt.internal.core.util.CodeSnippetParsingUtil", "parseCompilationUnit", "org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration", "char[]", "java.util.Map", "boolean"))
+ .symbol("lombok.disable")
+ .build());
+
+ // Eclipse Mars and beyond
+ sm.addScript(ScriptBuilder.setSymbolDuringMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.internal.formatter.DefaultCodeFormatter", "parseSourceCode"))
+ .callToWrap(new Hook("org.eclipse.jdt.core.dom.ASTParser", "createAST", "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.core.runtime.IProgressMonitor"))
+ .symbol("lombok.disable")
+ .build());
}
private static void patchRefactorScripts(ScriptManager sm) {
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ASTRewrite", "replace"))
.target(new MethodTarget("org.eclipse.jdt.core.dom.rewrite.ASTRewrite", "remove"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "skipRewritingGeneratedNodes", "boolean",
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "skipRewritingGeneratedNodes", "boolean",
"org.eclipse.jdt.core.dom.ASTNode"))
.transplant().request(StackRequest.PARAM1).build());
sm.addScript(ScriptBuilder.wrapMethodCall()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameTypeProcessor", "addConstructorRenames"))
.methodToWrap(new Hook("org.eclipse.jdt.core.IType", "getMethods", "org.eclipse.jdt.core.IMethod[]"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "removeGeneratedMethods", "org.eclipse.jdt.core.IMethod[]",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "removeGeneratedMethods", "org.eclipse.jdt.core.IMethod[]",
"org.eclipse.jdt.core.IMethod[]"))
.transplant().build());
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.TempOccurrenceAnalyzer", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
.target(new MethodTarget("org.eclipse.jdt.internal.corext.refactoring.rename.RenameAnalyzeUtil$ProblemNodeFinder$NameNodeVisitor", "visit", "boolean", "org.eclipse.jdt.core.dom.SimpleName"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
- .valueMethod(new Hook("lombok.eclipse.agent.PatchFixes", "returnTrue", "boolean", "java.lang.Object"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "isGenerated", "boolean", "org.eclipse.jdt.core.dom.ASTNode"))
+ .valueMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "returnTrue", "boolean", "java.lang.Object"))
.request(StackRequest.PARAM1)
.transplant().build());
}
@@ -342,30 +385,54 @@ public class EclipsePatcher extends Agent {
private static void patchCatchReparse(ScriptManager sm) {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveStartingCatchPosition"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "fixRetrieveStartingCatchPosition", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveStartingCatchPosition", "int", "int", "int"))
.transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM1).build());
}
private static void patchIdentifierEndReparse(ScriptManager sm) {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveIdentifierEndPosition"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "fixRetrieveIdentifierEndPosition", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveIdentifierEndPosition", "int", "int", "int"))
.transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM2).build());
}
private static void patchRetrieveEllipsisStartPosition(ScriptManager sm) {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveEllipsisStartPosition"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "fixRetrieveEllipsisStartPosition", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveEllipsisStartPosition", "int", "int", "int"))
.transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM2).build());
}
private static void patchRetrieveRightBraceOrSemiColonPosition(ScriptManager sm) {
- sm.addScript(ScriptBuilder.wrapReturnValue()
- .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBraceOrSemiColonPosition"))
- .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBrace"))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "fixRetrieveRightBraceOrSemiColonPosition", "int", "int", "int"))
- .transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM2).build());
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBraceOrSemiColonPosition", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveRightBraceOrSemiColonPosition", "int", "int", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
+ .requestExtra(StackRequest.PARAM2)
+ .transplant()
+ .build());
+
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBrace", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveRightBraceOrSemiColonPosition", "int", "int", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
+ .requestExtra(StackRequest.PARAM2)
+ .transplant()
+ .build());
+
+ sm.addScript(ScriptBuilder.wrapMethodCall()
+ .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration"))
+ .methodToWrap(new Hook("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBrace", "int", "int", "int"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveRightBraceOrSemiColonPosition", "int", "int", "org.eclipse.jdt.internal.compiler.ast.FieldDeclaration"))
+ .requestExtra(StackRequest.PARAM1)
+ .transplant()
+ .build());
+
+// sm.addScript(ScriptBuilder.wrapReturnValue()
+// .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBraceOrSemiColonPosition"))
+// .target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "retrieveRightBrace"))
+// .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "fixRetrieveRightBraceOrSemiColonPosition", "int", "int", "int"))
+// .transplant().request(StackRequest.RETURN_VALUE, StackRequest.PARAM2).build());
}
private static void patchSetGeneratedFlag(ScriptManager sm) {
@@ -396,14 +463,14 @@ public class EclipsePatcher extends Agent {
return Collections.singleton("org.eclipse.jdt.core.dom.ASTConverter");
}
}).request(StackRequest.PARAM1, StackRequest.RETURN_VALUE)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlag", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.transplant().build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
.request(StackRequest.PARAM2, StackRequest.RETURN_VALUE)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlag", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.transplant().build());
@@ -421,7 +488,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convertToVariableDeclarationStatement", "org.eclipse.jdt.core.dom.VariableDeclarationStatement", "org.eclipse.jdt.internal.compiler.ast.LocalDeclaration"))
/* Targets above are only patched because the resulting dom nodes should be marked if generated. */
.request(StackRequest.PARAM1, StackRequest.RETURN_VALUE)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlag", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlag", "void",
"org.eclipse.jdt.core.dom.ASTNode", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.transplant().build());
@@ -443,7 +510,7 @@ public class EclipsePatcher extends Agent {
}
}).methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM1)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
@@ -451,7 +518,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "convert", "org.eclipse.jdt.core.dom.ASTNode", "boolean", "org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM2)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
@@ -460,7 +527,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM4)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
@@ -468,7 +535,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "int", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM4)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
@@ -476,7 +543,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.SimpleName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM3)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
@@ -484,7 +551,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget("org.eclipse.jdt.core.dom.ASTConverter", "setQualifiedNameNameAndSourceRanges", "org.eclipse.jdt.core.dom.QualifiedName", "char[][]", "long[]", "org.eclipse.jdt.internal.compiler.ast.ASTNode"))
.methodToWrap(new Hook("org.eclipse.jdt.core.dom.QualifiedName", "<init>", "void", "org.eclipse.jdt.core.dom.AST"))
.requestExtra(StackRequest.PARAM3)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "setIsGeneratedFlagForName", "void",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "setIsGeneratedFlagForName", "void",
"org.eclipse.jdt.core.dom.Name", "java.lang.Object"))
.transplant().build());
}
@@ -495,7 +562,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget(PARSER_SIG, "parse", "void",
"org.eclipse.jdt.internal.compiler.ast.MethodDeclaration",
"org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "checkBit24", "boolean", "java.lang.Object"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "checkBit24", "boolean", "java.lang.Object"))
.transplant()
.request(StackRequest.PARAM1).build());
@@ -503,7 +570,7 @@ public class EclipsePatcher extends Agent {
.target(new MethodTarget(PARSER_SIG, "parse", "void",
"org.eclipse.jdt.internal.compiler.ast.ConstructorDeclaration",
"org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration", "boolean"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "checkBit24", "boolean", "java.lang.Object"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "checkBit24", "boolean", "java.lang.Object"))
.transplant()
.request(StackRequest.PARAM1).build());
@@ -512,7 +579,7 @@ public class EclipsePatcher extends Agent {
"org.eclipse.jdt.internal.compiler.ast.Initializer",
"org.eclipse.jdt.internal.compiler.ast.TypeDeclaration",
"org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration"))
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchFixes", "checkBit24", "boolean", "java.lang.Object"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "checkBit24", "boolean", "java.lang.Object"))
.transplant()
.request(StackRequest.PARAM1).build());
}
@@ -528,12 +595,12 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "getMethodBodies", "void", CUD_SIG))
- .wrapMethod(new Hook("lombok.eclipse.TransformEclipseAST", "transform", "void", PARSER_SIG, CUD_SIG))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Transform", "transform", "void", PARSER_SIG, CUD_SIG))
.request(StackRequest.THIS, StackRequest.PARAM1).build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "endParse", CUD_SIG, "int"))
- .wrapMethod(new Hook("lombok.eclipse.TransformEclipseAST", "transform_swapped", "void", CUD_SIG, PARSER_SIG))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$Transform", "transform_swapped", "void", CUD_SIG, PARSER_SIG))
.request(StackRequest.THIS, StackRequest.RETURN_VALUE).build());
}
@@ -549,7 +616,7 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget(CLASSSCOPE_SIG, "buildFieldsAndMethods", "void"))
.request(StackRequest.THIS)
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchDelegatePortal", "handleDelegateForType", "boolean", "java.lang.Object"))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Delegate", "handleDelegateForType", "boolean", "java.lang.Object"))
.build());
}
@@ -579,24 +646,24 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "consumeExitVariableWithInitialization", "void"))
.request(StackRequest.THIS)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchValEclipsePortal", "copyInitializationOfLocalDeclaration", "void", "java.lang.Object"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "copyInitializationOfLocalDeclaration", "void", "java.lang.Object"))
.build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(PARSER_SIG, "consumeEnhancedForStatementHeader", "void"))
.request(StackRequest.THIS)
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchValEclipsePortal", "copyInitializationOfForEachIterable", "void", "java.lang.Object"))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "copyInitializationOfForEachIterable", "void", "java.lang.Object"))
.build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(ASTCONVERTER_SIG, "setModifiers", "void", VARIABLEDECLARATIONSTATEMENT_SIG, LOCALDECLARATION_SIG))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchValEclipsePortal", "addFinalAndValAnnotationToVariableDeclarationStatement",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "addFinalAndValAnnotationToVariableDeclarationStatement",
"void", "java.lang.Object", "java.lang.Object", "java.lang.Object"))
.request(StackRequest.THIS, StackRequest.PARAM1, StackRequest.PARAM2).build());
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(ASTCONVERTER_SIG, "setModifiers", "void", SINGLEVARIABLEDECLARATION_SIG, LOCALDECLARATION_SIG))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchValEclipsePortal", "addFinalAndValAnnotationToSingleVariableDeclaration",
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$ValPortal", "addFinalAndValAnnotationToSingleVariableDeclaration",
"void", "java.lang.Object", "java.lang.Object", "java.lang.Object"))
.request(StackRequest.THIS, StackRequest.PARAM1, StackRequest.PARAM2).build());
}
@@ -611,26 +678,26 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.request(StackRequest.THIS, StackRequest.PARAM1)
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchVal", "handleValForLocalDeclaration", "boolean", LOCALDECLARATION_SIG, BLOCKSCOPE_SIG))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Val", "handleValForLocalDeclaration", "boolean", LOCALDECLARATION_SIG, BLOCKSCOPE_SIG))
.build());
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget(LOCALDECLARATION_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG))
.requestExtra(StackRequest.THIS)
- .replacementMethod(new Hook("lombok.eclipse.agent.PatchVal", "skipResolveInitializerIfAlreadyCalled2", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG, LOCALDECLARATION_SIG))
+ .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Val", "skipResolveInitializerIfAlreadyCalled2", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG, LOCALDECLARATION_SIG))
.build());
sm.addScript(ScriptBuilder.replaceMethodCall()
.target(new MethodTarget(FOREACHSTATEMENT_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.methodToReplace(new Hook(EXPRESSION_SIG, "resolveType", TYPEBINDING_SIG, BLOCKSCOPE_SIG))
- .replacementMethod(new Hook("lombok.eclipse.agent.PatchVal", "skipResolveInitializerIfAlreadyCalled", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG))
+ .replacementMethod(new Hook("lombok.launch.PatchFixesHider$Val", "skipResolveInitializerIfAlreadyCalled", TYPEBINDING_SIG, EXPRESSION_SIG, BLOCKSCOPE_SIG))
.build());
sm.addScript(ScriptBuilder.exitEarly()
.target(new MethodTarget(FOREACHSTATEMENT_SIG, "resolve", "void", BLOCKSCOPE_SIG))
.request(StackRequest.THIS, StackRequest.PARAM1)
- .decisionMethod(new Hook("lombok.eclipse.agent.PatchVal", "handleValForForEach", "boolean", FOREACHSTATEMENT_SIG, BLOCKSCOPE_SIG))
+ .decisionMethod(new Hook("lombok.launch.PatchFixesHider$Val", "handleValForForEach", "boolean", FOREACHSTATEMENT_SIG, BLOCKSCOPE_SIG))
.build());
}
@@ -641,7 +708,7 @@ public class EclipsePatcher extends Agent {
sm.addScript(ScriptBuilder.wrapReturnValue()
.target(new MethodTarget(SOURCE_TYPE_CONVERTER_SIG, "convertAnnotations", ANNOTATION_SIG + "[]", I_ANNOTATABLE_SIG))
- .wrapMethod(new Hook("lombok.eclipse.agent.PatchFixes", "convertAnnotations", ANNOTATION_SIG + "[]", ANNOTATION_SIG + "[]", I_ANNOTATABLE_SIG))
+ .wrapMethod(new Hook("lombok.launch.PatchFixesHider$PatchFixes", "convertAnnotations", ANNOTATION_SIG + "[]", ANNOTATION_SIG + "[]", I_ANNOTATABLE_SIG))
.request(StackRequest.PARAM1, StackRequest.RETURN_VALUE).build());
}
@@ -659,10 +726,11 @@ public class EclipsePatcher extends Agent {
}
private static void patchExtensionMethod(ScriptManager sm, boolean ecj) {
- final String PATCH_EXTENSIONMETHOD = "lombok.eclipse.agent.PatchExtensionMethod";
+ final String PATCH_EXTENSIONMETHOD = "lombok.launch.PatchFixesHider$ExtensionMethod";
final String PATCH_EXTENSIONMETHOD_COMPLETIONPROPOSAL_PORTAL = "lombok.eclipse.agent.PatchExtensionMethodCompletionProposalPortal";
final String MESSAGE_SEND_SIG = "org.eclipse.jdt.internal.compiler.ast.MessageSend";
final String TYPE_BINDING_SIG = "org.eclipse.jdt.internal.compiler.lookup.TypeBinding";
+ final String SCOPE_SIG = "org.eclipse.jdt.internal.compiler.lookup.Scope";
final String BLOCK_SCOPE_SIG = "org.eclipse.jdt.internal.compiler.lookup.BlockScope";
final String TYPE_BINDINGS_SIG = "org.eclipse.jdt.internal.compiler.lookup.TypeBinding[]";
final String PROBLEM_REPORTER_SIG = "org.eclipse.jdt.internal.compiler.problem.ProblemReporter";
@@ -690,6 +758,13 @@ public class EclipsePatcher extends Agent {
.replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "invalidMethod", "void", PROBLEM_REPORTER_SIG, MESSAGE_SEND_SIG, METHOD_BINDING_SIG))
.build());
+ // Since eclipse mars; they added a param.
+ sm.addScript(replaceMethodCall()
+ .target(new MethodTarget(MESSAGE_SEND_SIG, "resolveType", TYPE_BINDING_SIG, BLOCK_SCOPE_SIG))
+ .methodToReplace(new Hook(PROBLEM_REPORTER_SIG, "invalidMethod", "void", MESSAGE_SEND_SIG, METHOD_BINDING_SIG, SCOPE_SIG))
+ .replacementMethod(new Hook(PATCH_EXTENSIONMETHOD, "invalidMethod", "void", PROBLEM_REPORTER_SIG, MESSAGE_SEND_SIG, METHOD_BINDING_SIG, SCOPE_SIG))
+ .build());
+
if (!ecj) {
sm.addScript(wrapReturnValue()
.target(new MethodTarget(COMPLETION_PROPOSAL_COLLECTOR_SIG, "getJavaCompletionProposals", I_JAVA_COMPLETION_PROPOSAL_SIG))
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
index b1f5a43a..02760e35 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchDelegate.java
@@ -699,7 +699,10 @@ public class PatchDelegate {
}
private static void addAllMethodBindings0(List<BindingTuple> list, TypeBinding binding, Set<String> banList, char[] fieldName, ASTNode responsible) throws DelegateRecursion {
- if (binding instanceof SourceTypeBinding) ((SourceTypeBinding) binding).scope.environment().globalOptions.storeAnnotations = true;
+ if (binding instanceof SourceTypeBinding) {
+ ClassScope scope = ((SourceTypeBinding) binding).scope;
+ if (scope != null) scope.environment().globalOptions.storeAnnotations = true;
+ }
if (binding == null) return;
TypeBinding inner;
@@ -721,42 +724,44 @@ public class PatchDelegate {
}
}
- if (binding instanceof ReferenceBinding) {
- ReferenceBinding rb = (ReferenceBinding) binding;
- MethodBinding[] availableMethods = rb.availableMethods();
- FieldBinding[] availableFields = rb.availableFields();
- failIfContainsAnnotation(binding, availableMethods);
- failIfContainsAnnotation(binding, availableFields);
-
- MethodBinding[] parameterizedSigs = availableMethods;
- MethodBinding[] baseSigs = parameterizedSigs;
- if (binding instanceof ParameterizedTypeBinding) {
- baseSigs = ((ParameterizedTypeBinding)binding).genericType().availableMethods();
- if (baseSigs.length != parameterizedSigs.length) {
- // The last known state of eclipse source says this can't happen, so we rely on it,
- // but if this invariant is broken, better to go with 'arg0' naming instead of crashing.
- baseSigs = parameterizedSigs;
- }
- }
- for (int i = 0; i < parameterizedSigs.length; i++) {
- MethodBinding mb = parameterizedSigs[i];
- String sig = printSig(mb);
- if (mb.isStatic()) continue;
- if (mb.isBridge()) continue;
- if (mb.isConstructor()) continue;
- if (mb.isDefaultAbstract()) continue;
- if (!mb.isPublic()) continue;
- if (mb.isSynthetic()) continue;
- if (!banList.add(sig)) continue; // If add returns false, it was already in there.
- BindingTuple pair = new BindingTuple(mb, baseSigs[i], fieldName, responsible);
- list.add(pair);
- }
- addAllMethodBindings0(list, rb.superclass(), banList, fieldName, responsible);
- ReferenceBinding[] interfaces = rb.superInterfaces();
- if (interfaces != null) {
- for (ReferenceBinding iface : interfaces) addAllMethodBindings0(list, iface, banList, fieldName, responsible);
+ if (!(binding instanceof ReferenceBinding)) {
+ return;
+ }
+
+ ReferenceBinding rb = (ReferenceBinding) binding;
+ MethodBinding[] availableMethods = rb.availableMethods();
+ FieldBinding[] availableFields = rb.availableFields();
+ failIfContainsAnnotation(binding, availableMethods);
+ failIfContainsAnnotation(binding, availableFields);
+
+ MethodBinding[] parameterizedSigs = availableMethods;
+ MethodBinding[] baseSigs = parameterizedSigs;
+ if (binding instanceof ParameterizedTypeBinding) {
+ baseSigs = ((ParameterizedTypeBinding)binding).genericType().availableMethods();
+ if (baseSigs.length != parameterizedSigs.length) {
+ // The last known state of eclipse source says this can't happen, so we rely on it,
+ // but if this invariant is broken, better to go with 'arg0' naming instead of crashing.
+ baseSigs = parameterizedSigs;
}
}
+ for (int i = 0; i < parameterizedSigs.length; i++) {
+ MethodBinding mb = parameterizedSigs[i];
+ String sig = printSig(mb);
+ if (mb.isStatic()) continue;
+ if (mb.isBridge()) continue;
+ if (mb.isConstructor()) continue;
+ if (mb.isDefaultAbstract()) continue;
+ if (!mb.isPublic()) continue;
+ if (mb.isSynthetic()) continue;
+ if (!banList.add(sig)) continue; // If add returns false, it was already in there.
+ BindingTuple pair = new BindingTuple(mb, baseSigs[i], fieldName, responsible);
+ list.add(pair);
+ }
+ addAllMethodBindings0(list, rb.superclass(), banList, fieldName, responsible);
+ ReferenceBinding[] interfaces = rb.superInterfaces();
+ if (interfaces != null) {
+ for (ReferenceBinding iface : interfaces) addAllMethodBindings0(list, iface, banList, fieldName, responsible);
+ }
}
private static final char[] STRING_LOMBOK = new char[] {'l', 'o', 'm', 'b', 'o', 'k'};
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java
index 8eec27fb..5d586dff 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethod.java
@@ -24,6 +24,8 @@ package lombok.eclipse.agent;
import static lombok.eclipse.handlers.EclipseHandlerUtil.createAnnotation;
import java.lang.ref.WeakReference;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@@ -56,6 +58,7 @@ import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ProblemMethodBinding;
import org.eclipse.jdt.internal.compiler.lookup.ReferenceBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
@@ -89,16 +92,47 @@ public class PatchExtensionMethod {
private final ProblemReporter problemReporter;
private final WeakReference<MessageSend> messageSendRef;
private final MethodBinding method;
+ private final Scope scope;
- PostponedInvalidMethodError(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method) {
+ private static final Method shortMethod = getMethod("invalidMethod", MessageSend.class, MethodBinding.class);
+ private static final Method longMethod = getMethod("invalidMethod", MessageSend.class, MethodBinding.class, Scope.class);
+
+ private static Method getMethod(String name, Class<?>... types) {
+ try {
+ Method m = ProblemReporter.class.getMethod(name, types);
+ m.setAccessible(true);
+ return m;
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ PostponedInvalidMethodError(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method, Scope scope) {
this.problemReporter = problemReporter;
this.messageSendRef = new WeakReference<MessageSend>(messageSend);
this.method = method;
+ this.scope = scope;
+ }
+
+ static void invoke(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method, Scope scope) {
+ if (messageSend != null) {
+ try {
+ if (shortMethod != null) shortMethod.invoke(problemReporter, messageSend, method);
+ else if (longMethod != null) longMethod.invoke(problemReporter, messageSend, method, scope);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ } catch (InvocationTargetException e) {
+ Throwable t = e.getCause();
+ if (t instanceof Error) throw (Error) t;
+ if (t instanceof RuntimeException) throw (RuntimeException) t;
+ throw new RuntimeException(t);
+ }
+ }
}
public void fire() {
MessageSend messageSend = messageSendRef.get();
- if (messageSend != null) problemReporter.invalidMethod(messageSend, method);
+ invoke(problemReporter, messageSend, method, scope);
}
}
@@ -185,7 +219,11 @@ public class PatchExtensionMethod {
}
public static void invalidMethod(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method) {
- MessageSend_postponedErrors.set(messageSend, new PostponedInvalidMethodError(problemReporter, messageSend, method));
+ MessageSend_postponedErrors.set(messageSend, new PostponedInvalidMethodError(problemReporter, messageSend, method, null));
+ }
+
+ public static void invalidMethod(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method, Scope scope) {
+ MessageSend_postponedErrors.set(messageSend, new PostponedInvalidMethodError(problemReporter, messageSend, method, scope));
}
public static TypeBinding resolveType(TypeBinding resolvedType, MessageSend methodCall, BlockScope scope) {
@@ -224,12 +262,16 @@ public class PatchExtensionMethod {
if (methodCall.arguments != null) arguments.addAll(Arrays.asList(methodCall.arguments));
List<TypeBinding> argumentTypes = new ArrayList<TypeBinding>();
for (Expression argument : arguments) {
- argumentTypes.add(argument.resolvedType);
+ if (argument.resolvedType != null) argumentTypes.add(argument.resolvedType);
+ // TODO: Instead of just skipping nulls entirely, there is probably a 'unresolved type' placeholder. THAT is what we ought to be adding here!
}
+ Expression[] originalArgs = methodCall.arguments;
+ methodCall.arguments = arguments.toArray(new Expression[0]);
MethodBinding fixedBinding = scope.getMethod(extensionMethod.declaringClass, methodCall.selector, argumentTypes.toArray(new TypeBinding[0]), methodCall);
if (fixedBinding instanceof ProblemMethodBinding) {
+ methodCall.arguments = originalArgs;
if (fixedBinding.declaringClass != null) {
- scope.problemReporter().invalidMethod(methodCall, fixedBinding);
+ PostponedInvalidMethodError.invoke(scope.problemReporter(), methodCall, fixedBinding, scope);
}
} else {
for (int i = 0, iend = arguments.size(); i < iend; i++) {
@@ -246,7 +288,6 @@ public class PatchExtensionMethod {
arg.implicitConversion = TypeIds.UNBOXING | (id + (id << 4)); // magic see TypeIds
}
}
- methodCall.arguments = arguments.toArray(new Expression[0]);
methodCall.receiver = createNameRef(extensionMethod.declaringClass, methodCall);
methodCall.actualReceiverType = extensionMethod.declaringClass;
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java
index 97ca5a7e..c11a49cd 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposal.java
@@ -60,8 +60,6 @@ import org.eclipse.jdt.ui.text.java.CompletionProposalCollector;
import org.eclipse.jdt.ui.text.java.IJavaCompletionProposal;
public class PatchExtensionMethodCompletionProposal {
-
-
public static IJavaCompletionProposal[] getJavaCompletionProposals(IJavaCompletionProposal[] javaCompletionProposals,
CompletionProposalCollector completionProposalCollector) {
@@ -178,7 +176,7 @@ public class PatchExtensionMethodCompletionProposal {
return !proposals.isEmpty() && Reflection.isComplete();
}
- private static int getReplacementOffset(IJavaCompletionProposal proposal) {
+ private static int getReplacementOffset(Object proposal) {
try {
return Reflection.replacementOffsetField.getInt(proposal);
} catch (Exception ignore) {
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposalPortal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposalPortal.java
index 6dca1901..19e1952e 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposalPortal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchExtensionMethodCompletionProposalPortal.java
@@ -33,7 +33,6 @@ public class PatchExtensionMethodCompletionProposalPortal {
private static final String COMPLETION_PROPOSAL_COLLECTOR = "org.eclipse.jdt.ui.text.java.CompletionProposalCollector";
private static final String I_JAVA_COMPLETION_PROPOSAL_ARRAY = "[Lorg.eclipse.jdt.ui.text.java.IJavaCompletionProposal;";
-
public static IJavaCompletionProposal[] getJavaCompletionProposals(Object[] javaCompletionProposals, Object completionProposalCollector) {
try {
return (IJavaCompletionProposal[]) ReflectionForUi.getJavaCompletionProposals.invoke(null, javaCompletionProposals, completionProposalCollector);
@@ -52,7 +51,7 @@ public class PatchExtensionMethodCompletionProposalPortal {
}
//ignore, we don't have access to the correct ECJ classes, so lombok can't possibly
//do anything useful here.
- return (IJavaCompletionProposal[])javaCompletionProposals;
+ return (IJavaCompletionProposal[]) javaCompletionProposals;
}
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
deleted file mode 100644
index d1c668a0..00000000
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchFixes.java
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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
- * in the Software without restriction, including without limitation the rights
- * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
- * copies of the Software, and to permit persons to whom the Software is
- * furnished to do so, subject to the following conditions:
- *
- * The above copyright notice and this permission notice shall be included in
- * all copies or substantial portions of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
- * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
- * THE SOFTWARE.
- */
-package lombok.eclipse.agent;
-
-import java.io.BufferedOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.lang.reflect.Field;
-import java.util.ArrayList;
-import java.util.List;
-import java.util.Stack;
-
-import lombok.core.DiagnosticsReceiver;
-import lombok.core.PostCompiler;
-import lombok.core.Version;
-import lombok.eclipse.EclipseAugments;
-
-import org.eclipse.core.runtime.CoreException;
-import org.eclipse.jdt.core.IAnnotatable;
-import org.eclipse.jdt.core.IAnnotation;
-import org.eclipse.jdt.core.IMethod;
-import org.eclipse.jdt.core.IType;
-import org.eclipse.jdt.core.JavaModelException;
-import org.eclipse.jdt.core.dom.MethodDeclaration;
-import org.eclipse.jdt.core.dom.SimpleName;
-import org.eclipse.jdt.internal.compiler.ast.Annotation;
-import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
-import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
-import org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner;
-import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
-
-public class PatchFixes {
- public static String addLombokNotesToEclipseAboutDialog(String origReturnValue, String key) {
- if ("aboutText".equals(key)) {
- return origReturnValue + "\n\nLombok " + Version.getFullVersion() + " is installed. http://projectlombok.org/";
- }
-
- return origReturnValue;
- }
-
- public static boolean isGenerated(org.eclipse.jdt.core.dom.ASTNode node) {
- boolean result = false;
- try {
- result = ((Boolean)node.getClass().getField("$isGenerated").get(node)).booleanValue();
- if (!result && node.getParent() != null && node.getParent() instanceof org.eclipse.jdt.core.dom.QualifiedName)
- result = isGenerated(node.getParent());
- } catch (Exception e) {
- // better to assume it isn't generated
- }
- return result;
- }
-
- public static boolean isListRewriteOnGeneratedNode(org.eclipse.jdt.core.dom.rewrite.ListRewrite rewrite) {
- return isGenerated(rewrite.getParent());
- }
-
- public static boolean returnFalse(java.lang.Object object) {
- return false;
- }
-
- public static boolean returnTrue(java.lang.Object object) {
- return true;
- }
-
- @java.lang.SuppressWarnings({"unchecked", "rawtypes"}) public static java.util.List removeGeneratedNodes(java.util.List list) {
- try {
- java.util.List realNodes = new java.util.ArrayList(list.size());
- for (java.lang.Object node : list) {
- if(!isGenerated(((org.eclipse.jdt.core.dom.ASTNode)node))) {
- realNodes.add(node);
- }
- }
- return realNodes;
- } catch (Exception e) {
- }
- return list;
- }
-
- public static java.lang.String getRealMethodDeclarationSource(java.lang.String original, Object processor, org.eclipse.jdt.core.dom.MethodDeclaration declaration) throws Exception {
- if (!isGenerated(declaration)) return original;
-
- List<org.eclipse.jdt.core.dom.Annotation> annotations = new ArrayList<org.eclipse.jdt.core.dom.Annotation>();
- for (Object modifier : declaration.modifiers()) {
- if (modifier instanceof org.eclipse.jdt.core.dom.Annotation) {
- org.eclipse.jdt.core.dom.Annotation annotation = (org.eclipse.jdt.core.dom.Annotation)modifier;
- String qualifiedAnnotationName = annotation.resolveTypeBinding().getQualifiedName();
- if (!"java.lang.Override".equals(qualifiedAnnotationName) && !"java.lang.SuppressWarnings".equals(qualifiedAnnotationName)) annotations.add(annotation);
- }
- }
-
- StringBuilder signature = new StringBuilder();
- addAnnotations(annotations, signature);
-
- if ((Boolean)processor.getClass().getDeclaredField("fPublic").get(processor)) signature.append("public ");
- if ((Boolean)processor.getClass().getDeclaredField("fAbstract").get(processor)) signature.append("abstract ");
-
- signature
- .append(declaration.getReturnType2().toString())
- .append(" ").append(declaration.getName().getFullyQualifiedName())
- .append("(");
-
- boolean first = true;
- for (Object parameter : declaration.parameters()) {
- if (!first) signature.append(", ");
- first = false;
- // We should also add the annotations of the parameters
- signature.append(parameter);
- }
-
- signature.append(");");
- return signature.toString();
- }
-
- // part of getRealMethodDeclarationSource(...)
- public static void addAnnotations(List<org.eclipse.jdt.core.dom.Annotation> annotations, StringBuilder signature) {
- /*
- * We SHOULD be able to handle the following cases:
- * @Override
- * @Override()
- * @SuppressWarnings("all")
- * @SuppressWarnings({"all", "unused"})
- * @SuppressWarnings(value = "all")
- * @SuppressWarnings(value = {"all", "unused"})
- * @EqualsAndHashCode(callSuper=true, of="id")
- *
- * Currently, we only seem to correctly support:
- * @Override
- * @Override() N.B. We lose the parentheses here, since there are no values. No big deal.
- * @SuppressWarnings("all")
- */
- for (org.eclipse.jdt.core.dom.Annotation annotation : annotations) {
- List<String> values = new ArrayList<String>();
- if (annotation.isSingleMemberAnnotation()) {
- org.eclipse.jdt.core.dom.SingleMemberAnnotation smAnn = (org.eclipse.jdt.core.dom.SingleMemberAnnotation) annotation;
- values.add(smAnn.getValue().toString());
- } else if (annotation.isNormalAnnotation()) {
- org.eclipse.jdt.core.dom.NormalAnnotation normalAnn = (org.eclipse.jdt.core.dom.NormalAnnotation) annotation;
- for (Object value : normalAnn.values()) values.add(value.toString());
- }
-
- signature.append("@").append(annotation.resolveTypeBinding().getQualifiedName());
- if (!values.isEmpty()) {
- signature.append("(");
- boolean first = true;
- for (String string : values) {
- if (!first) signature.append(", ");
- first = false;
- signature.append('"').append(string).append('"');
- }
- signature.append(")");
- }
- signature.append(" ");
- }
- }
-
- public static org.eclipse.jdt.core.dom.MethodDeclaration getRealMethodDeclarationNode(org.eclipse.jdt.core.IMethod sourceMethod, org.eclipse.jdt.core.dom.CompilationUnit cuUnit) throws JavaModelException {
- MethodDeclaration methodDeclarationNode = ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, cuUnit);
- if (isGenerated(methodDeclarationNode)) {
- IType declaringType = sourceMethod.getDeclaringType();
- Stack<IType> typeStack = new Stack<IType>();
- while (declaringType != null) {
- typeStack.push(declaringType);
- declaringType = declaringType.getDeclaringType();
- }
-
- IType rootType = typeStack.pop();
- org.eclipse.jdt.core.dom.AbstractTypeDeclaration typeDeclaration = findTypeDeclaration(rootType, cuUnit.types());
- while (!typeStack.isEmpty() && typeDeclaration != null) {
- typeDeclaration = findTypeDeclaration(typeStack.pop(), typeDeclaration.bodyDeclarations());
- }
-
- if (typeStack.isEmpty() && typeDeclaration != null) {
- String methodName = sourceMethod.getElementName();
- for (Object declaration : typeDeclaration.bodyDeclarations()) {
- if (declaration instanceof org.eclipse.jdt.core.dom.MethodDeclaration) {
- org.eclipse.jdt.core.dom.MethodDeclaration methodDeclaration = (org.eclipse.jdt.core.dom.MethodDeclaration) declaration;
- if (methodDeclaration.getName().toString().equals(methodName)) {
- return methodDeclaration;
- }
- }
- }
- }
- }
- return methodDeclarationNode;
- }
-
- // part of getRealMethodDeclarationNode
- public static org.eclipse.jdt.core.dom.AbstractTypeDeclaration findTypeDeclaration(IType searchType, List<?> nodes) {
- for (Object object : nodes) {
- if (object instanceof org.eclipse.jdt.core.dom.AbstractTypeDeclaration) {
- org.eclipse.jdt.core.dom.AbstractTypeDeclaration typeDeclaration = (org.eclipse.jdt.core.dom.AbstractTypeDeclaration) object;
- if (typeDeclaration.getName().toString().equals(searchType.getElementName()))
- return typeDeclaration;
- }
- }
- return null;
- }
-
- public static int getSourceEndFixed(int sourceEnd, org.eclipse.jdt.internal.compiler.ast.ASTNode node) throws Exception {
- if (sourceEnd == -1) {
- org.eclipse.jdt.internal.compiler.ast.ASTNode object = (org.eclipse.jdt.internal.compiler.ast.ASTNode)node.getClass().getField("$generatedBy").get(node);
- if (object != null) {
- return object.sourceEnd;
- }
- }
- return sourceEnd;
- }
-
- public static int fixRetrieveStartingCatchPosition(int original, int start) {
- return original == -1 ? start : original;
- }
-
- public static int fixRetrieveIdentifierEndPosition(int original, int end) {
- return original == -1 ? end : original;
- }
-
- public static int fixRetrieveEllipsisStartPosition(int original, int end) {
- return original == -1 ? end : original;
- }
-
- public static int fixRetrieveRightBraceOrSemiColonPosition(int original, int end) {
-// return original;
- return original == -1 ? end : original; // Need to fix: see issue 325.
- }
-
- public static final int ALREADY_PROCESSED_FLAG = 0x800000; //Bit 24
-
- public static boolean checkBit24(Object node) throws Exception {
- int bits = (Integer)(node.getClass().getField("bits").get(node));
- return (bits & ALREADY_PROCESSED_FLAG) != 0;
- }
-
- public static boolean skipRewritingGeneratedNodes(org.eclipse.jdt.core.dom.ASTNode node) throws Exception {
- return ((Boolean)node.getClass().getField("$isGenerated").get(node)).booleanValue();
- }
-
- public static void setIsGeneratedFlag(org.eclipse.jdt.core.dom.ASTNode domNode,
- org.eclipse.jdt.internal.compiler.ast.ASTNode internalNode) throws Exception {
- if (internalNode == null || domNode == null) return;
- boolean isGenerated = EclipseAugments.ASTNode_generatedBy.get(internalNode) != null;
- if (isGenerated) domNode.getClass().getField("$isGenerated").set(domNode, true);
- }
-
- public static void setIsGeneratedFlagForName(org.eclipse.jdt.core.dom.Name name, Object internalNode) throws Exception {
- if (internalNode instanceof org.eclipse.jdt.internal.compiler.ast.ASTNode) {
- if (EclipseAugments.ASTNode_generatedBy.get((org.eclipse.jdt.internal.compiler.ast.ASTNode) internalNode) != null) {
- name.getClass().getField("$isGenerated").set(name, true);
- }
- }
- }
-
- public static RewriteEvent[] listRewriteHandleGeneratedMethods(RewriteEvent parent) {
- RewriteEvent[] children = parent.getChildren();
- List<RewriteEvent> newChildren = new ArrayList<RewriteEvent>();
- List<RewriteEvent> modifiedChildren = new ArrayList<RewriteEvent>();
- for (int i=0; i<children.length; i++) {
- RewriteEvent child = children[i];
- boolean isGenerated = isGenerated( (org.eclipse.jdt.core.dom.ASTNode)child.getOriginalValue() );
- if (isGenerated) {
- if ((child.getChangeKind() == RewriteEvent.REPLACED || child.getChangeKind() == RewriteEvent.REMOVED)
- && child.getOriginalValue() instanceof org.eclipse.jdt.core.dom.MethodDeclaration
- && child.getNewValue() != null
- ) {
- modifiedChildren.add(new NodeRewriteEvent(null, child.getNewValue()));
- }
- } else {
- newChildren.add(child);
- }
- }
- // Since Eclipse doesn't honor the "insert at specified location" for already existing members,
- // we'll just add them last
- newChildren.addAll(modifiedChildren);
- return newChildren.toArray(new RewriteEvent[newChildren.size()]);
- }
-
- public static int getTokenEndOffsetFixed(TokenScanner scanner, int token, int startOffset, Object domNode) throws CoreException {
- boolean isGenerated = false;
- try {
- isGenerated = (Boolean) domNode.getClass().getField("$isGenerated").get(domNode);
- } catch (Exception e) {
- // If this fails, better to break some refactor scripts than to crash eclipse.
- }
- if (isGenerated) return -1;
- return scanner.getTokenEndOffset(token, startOffset);
- }
-
- public static IMethod[] removeGeneratedMethods(IMethod[] methods) throws Exception {
- List<IMethod> result = new ArrayList<IMethod>();
- for (IMethod m : methods) {
- if (m.getNameRange().getLength() > 0 && !m.getNameRange().equals(m.getSourceRange())) result.add(m);
- }
- return result.size() == methods.length ? methods : result.toArray(new IMethod[result.size()]);
- }
-
- public static SimpleName[] removeGeneratedSimpleNames(SimpleName[] in) throws Exception {
- Field f = SimpleName.class.getField("$isGenerated");
-
- int count = 0;
- for (int i = 0; i < in.length; i++) {
- if (in[i] == null || !((Boolean)f.get(in[i])).booleanValue()) count++;
- }
- if (count == in.length) return in;
- SimpleName[] newSimpleNames = new SimpleName[count];
- count = 0;
- for (int i = 0; i < in.length; i++) {
- if (in[i] == null || !((Boolean)f.get(in[i])).booleanValue()) newSimpleNames[count++] = in[i];
- }
- return newSimpleNames;
- }
-
- public static byte[] runPostCompiler(byte[] bytes, String fileName) {
- byte[] transformed = PostCompiler.applyTransformations(bytes, fileName, DiagnosticsReceiver.CONSOLE);
- return transformed == null ? bytes : transformed;
- }
-
- public static OutputStream runPostCompiler(OutputStream out) throws IOException {
- return PostCompiler.wrapOutputStream(out, "TEST", DiagnosticsReceiver.CONSOLE);
- }
-
- public static BufferedOutputStream runPostCompiler(BufferedOutputStream out, String path, String name) throws IOException {
- String fileName = path + "/" + name;
- return new BufferedOutputStream(PostCompiler.wrapOutputStream(out, fileName, DiagnosticsReceiver.CONSOLE));
- }
-
- public static Annotation[] convertAnnotations(Annotation[] out, IAnnotatable annotatable) {
- IAnnotation[] in;
-
- try {
- in = annotatable.getAnnotations();
- } catch (Exception e) {
- return out;
- }
-
- if (out == null) return null;
- int toWrite = 0;
-
- for (int idx = 0; idx < out.length; idx++) {
- String oName = new String(out[idx].type.getLastToken());
- boolean found = false;
- for (IAnnotation i : in) {
- String name = i.getElementName();
- int li = name.lastIndexOf('.');
- if (li > -1) name = name.substring(li + 1);
- if (name.equals(oName)) {
- found = true;
- break;
- }
- }
- if (!found) out[idx] = null;
- else toWrite++;
- }
-
- Annotation[] replace = out;
- if (toWrite < out.length) {
- replace = new Annotation[toWrite];
- int idx = 0;
- for (int i = 0; i < out.length; i++) {
- if (out[i] == null) continue;
- replace[idx++] = out[i];
- }
- }
-
- return replace;
- }
-}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java b/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java
new file mode 100644
index 00000000..52f63765
--- /dev/null
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchFixesShadowLoaded.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2015 The Project Lombok Authors.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+package lombok.eclipse.agent;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+import lombok.core.DiagnosticsReceiver;
+import lombok.core.PostCompiler;
+import lombok.core.Version;
+
+public class PatchFixesShadowLoaded {
+ public static String addLombokNotesToEclipseAboutDialog(String origReturnValue, String key) {
+ if ("aboutText".equals(key)) {
+ return origReturnValue + "\n\nLombok " + Version.getFullVersion() + " is installed. https://projectlombok.org/";
+ }
+ return origReturnValue;
+ }
+
+ public static byte[] runPostCompiler(byte[] bytes, String fileName) {
+ byte[] transformed = PostCompiler.applyTransformations(bytes, fileName, DiagnosticsReceiver.CONSOLE);
+ return transformed == null ? bytes : transformed;
+ }
+
+ public static OutputStream runPostCompiler(OutputStream out) throws IOException {
+ return PostCompiler.wrapOutputStream(out, "TEST", DiagnosticsReceiver.CONSOLE);
+ }
+
+ public static BufferedOutputStream runPostCompiler(BufferedOutputStream out, String path, String name) throws IOException {
+ String fileName = path + "/" + name;
+ return new BufferedOutputStream(PostCompiler.wrapOutputStream(out, fileName, DiagnosticsReceiver.CONSOLE));
+ }
+}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
index e734dceb..3da37869 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchVal.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-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,11 +21,6 @@
*/
package lombok.eclipse.agent;
-import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
-import static lombok.eclipse.Eclipse.*;
-
-import java.lang.reflect.Field;
-
import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.Expression;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
@@ -43,6 +38,11 @@ import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
import org.eclipse.jdt.internal.compiler.lookup.TypeConstants;
import org.eclipse.jdt.internal.compiler.lookup.TypeIds;
+import java.lang.reflect.Field;
+
+import static lombok.eclipse.Eclipse.poss;
+import static lombok.eclipse.handlers.EclipseHandlerUtil.makeType;
+
public class PatchVal {
// This is half of the work for 'val' support - the other half is in PatchValEclipse. This half is enough for ecj.
@@ -57,6 +57,9 @@ public class PatchVal {
return expr.resolveType(scope);
} catch (NullPointerException e) {
return null;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // This will occur internally due to for example 'val x = mth("X");', where mth takes 2 arguments.
+ return null;
}
}
@@ -66,6 +69,9 @@ public class PatchVal {
return expr.resolveType(scope);
} catch (NullPointerException e) {
return null;
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // This will occur internally due to for example 'val x = mth("X");', where mth takes 2 arguments.
+ return null;
}
}
@@ -78,31 +84,44 @@ public class PatchVal {
return true;
}
- public static boolean couldBeVal(TypeReference ref) {
+ public static boolean couldBe(String key, TypeReference ref) {
+ String[] keyParts = key.split("\\.");
if (ref instanceof SingleTypeReference) {
char[] token = ((SingleTypeReference)ref).token;
- return matches("val", token);
+ return matches(keyParts[keyParts.length - 1], token);
}
if (ref instanceof QualifiedTypeReference) {
char[][] tokens = ((QualifiedTypeReference)ref).tokens;
- if (tokens == null || tokens.length != 2) return false;
- return matches("lombok", tokens[0]) && matches("val", tokens[1]);
+ if (keyParts.length != tokens.length) return false;
+ for(int i = 0; i < tokens.length; ++i) {
+ String part = keyParts[i];
+ char[] token = tokens[i];
+ if (!matches(part, token)) return false;
+ }
+ return true;
}
return false;
}
-
- private static boolean isVal(TypeReference ref, BlockScope scope) {
- if (!couldBeVal(ref)) return false;
-
+
+ private static boolean is(TypeReference ref, BlockScope scope, String key) {
+ if (!couldBe(key, ref)) return false;
+
TypeBinding resolvedType = ref.resolvedType;
if (resolvedType == null) resolvedType = ref.resolveType(scope, false);
if (resolvedType == null) return false;
char[] pkg = resolvedType.qualifiedPackageName();
char[] nm = resolvedType.qualifiedSourceName();
- return matches("lombok", pkg) && matches("val", nm);
+ int pkgFullLength = pkg.length > 0 ? pkg.length + 1: 0;
+ char[] fullName = new char[pkgFullLength + nm.length];
+ if(pkg.length > 0) {
+ System.arraycopy(pkg, 0, fullName, 0, pkg.length);
+ fullName[pkg.length] = '.';
+ }
+ System.arraycopy(nm, 0, fullName, pkgFullLength, nm.length);
+ return matches(key, fullName);
}
public static final class Reflection {
@@ -126,9 +145,20 @@ public class PatchVal {
if (local == null || !LocalDeclaration.class.equals(local.getClass())) return false;
boolean decomponent = false;
- if (!isVal(local.type, scope)) return false;
+ boolean val = isVal(local, scope);
+ boolean var = isVar(local, scope);
+ if (!(val || var)) return false;
- if (new Throwable().getStackTrace()[2].getClassName().contains("ForStatement")) return false;
+ StackTraceElement[] st = new Throwable().getStackTrace();
+ for (int i = 0; i < st.length - 2 && i < 10; i++) {
+ if (st[i].getClassName().equals("lombok.launch.PatchFixesHider$Val")) {
+ boolean valInForStatement = val &&
+ st[i + 1].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.LocalDeclaration") &&
+ st[i + 2].getClassName().equals("org.eclipse.jdt.internal.compiler.ast.ForStatement");
+ if (valInForStatement) return false;
+ break;
+ }
+ }
Expression init = local.initialization;
if (init == null && Reflection.initCopyField != null) {
@@ -157,7 +187,7 @@ public class PatchVal {
TypeBinding resolved = null;
try {
- resolved = decomponent ? getForEachComponentType(init, scope) : init.resolveType(scope);
+ resolved = decomponent ? getForEachComponentType(init, scope) : resolveForExpression(init, scope);
} catch (NullPointerException e) {
// This definitely occurs if as part of resolving the initializer expression, a
// lambda expression in it must also be resolved (such as when lambdas are part of
@@ -174,23 +204,33 @@ public class PatchVal {
}
}
- local.modifiers |= ClassFileConstants.AccFinal;
+ if(val) local.modifiers |= ClassFileConstants.AccFinal;
local.annotations = addValAnnotation(local.annotations, local.type, scope);
local.type = replacement != null ? replacement : new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(local.type, 3));
return false;
}
+ private static boolean isVar(LocalDeclaration local, BlockScope scope) {
+ return is(local.type, scope, "lombok.experimental.var") || is(local.type, scope, "lombok.var");
+ }
+
+ private static boolean isVal(LocalDeclaration local, BlockScope scope) {
+ return is(local.type, scope, "lombok.val");
+ }
+
public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) {
if (forEach.elementVariable == null) return false;
- if (!isVal(forEach.elementVariable.type, scope)) return false;
+ boolean val = isVal(forEach.elementVariable, scope);
+ boolean var = isVar(forEach.elementVariable, scope);
+ if (!(val || var)) return false;
TypeBinding component = getForEachComponentType(forEach.collection, scope);
if (component == null) return false;
TypeReference replacement = makeType(component, forEach.elementVariable.type, false);
- forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
+ if (val) forEach.elementVariable.modifiers |= ClassFileConstants.AccFinal;
forEach.elementVariable.annotations = addValAnnotation(forEach.elementVariable.annotations, forEach.elementVariable.type, scope);
forEach.elementVariable.type = replacement != null ? replacement :
new QualifiedTypeReference(TypeConstants.JAVA_LANG_OBJECT, poss(forEach.elementVariable.type, 3));
@@ -215,7 +255,7 @@ public class PatchVal {
private static TypeBinding getForEachComponentType(Expression collection, BlockScope scope) {
if (collection != null) {
TypeBinding resolved = collection.resolvedType;
- if (resolved == null) resolved = collection.resolveType(scope);
+ if (resolved == null) resolved = resolveForExpression(collection, scope);
if (resolved == null) return null;
if (resolved.isArrayType()) {
resolved = ((ArrayBinding) resolved).elementsType();
@@ -243,4 +283,13 @@ public class PatchVal {
return null;
}
+
+ private static TypeBinding resolveForExpression(Expression collection, BlockScope scope) {
+ try {
+ return collection.resolveType(scope);
+ } catch (ArrayIndexOutOfBoundsException e) {
+ // Known cause of issues; for example: val e = mth("X"), where mth takes 2 arguments.
+ return null;
+ }
+ }
}
diff --git a/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java b/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java
index 7d5f36f4..46237dcf 100644
--- a/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java
+++ b/src/eclipseAgent/lombok/eclipse/agent/PatchValEclipse.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-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
@@ -47,6 +47,7 @@ import org.eclipse.jdt.internal.compiler.ast.Annotation;
import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
import org.eclipse.jdt.internal.compiler.ast.SingleTypeReference;
+import org.eclipse.jdt.internal.compiler.ast.TypeReference;
import org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants;
import org.eclipse.jdt.internal.compiler.parser.Parser;
@@ -65,7 +66,9 @@ public class PatchValEclipse {
ForeachStatement foreachDecl = (ForeachStatement) astStack[astPtr];
ASTNode init = foreachDecl.collection;
if (init == null) return;
- if (foreachDecl.elementVariable == null || !PatchVal.couldBeVal(foreachDecl.elementVariable.type)) return;
+ boolean val = couldBeVal(foreachDecl.elementVariable.type);
+ boolean var = couldBeVar(foreachDecl.elementVariable.type);
+ if (foreachDecl.elementVariable == null || !(val || var)) return;
try {
if (Reflection.iterableCopyField != null) Reflection.iterableCopyField.set(foreachDecl.elementVariable, init);
@@ -88,7 +91,9 @@ public class PatchValEclipse {
if (!(variableDecl instanceof LocalDeclaration)) return;
ASTNode init = variableDecl.initialization;
if (init == null) return;
- if (!PatchVal.couldBeVal(variableDecl.type)) return;
+ boolean val = couldBeVal(variableDecl.type);
+ boolean var = couldBeVar(variableDecl.type);
+ if (!(val || var)) return;
try {
if (Reflection.initCopyField != null) Reflection.initCopyField.set(variableDecl, init);
@@ -97,6 +102,10 @@ public class PatchValEclipse {
}
}
+ private static boolean couldBeVar(TypeReference type) {
+ return PatchVal.couldBe("lombok.experimental.var", type) || PatchVal.couldBe("lombok.var", type);
+ }
+
public static void addFinalAndValAnnotationToSingleVariableDeclaration(Object converter, SingleVariableDeclaration out, LocalDeclaration in) {
@SuppressWarnings("unchecked") List<IExtendedModifier> modifiers = out.modifiers();
addFinalAndValAnnotationToModifierList(converter, modifiers, out.getAST(), in);
@@ -115,7 +124,7 @@ public class PatchValEclipse {
Annotation valAnnotation = null;
for (Annotation ann : in.annotations) {
- if (PatchVal.couldBeVal(ann.type)) {
+ if (couldBeVal(ann.type)) {
found = true;
valAnnotation = ann;
break;
@@ -167,6 +176,10 @@ public class PatchValEclipse {
}
}
+ private static boolean couldBeVal(TypeReference type) {
+ return PatchVal.couldBe("lombok.val", type);
+ }
+
public static Modifier createModifier(AST ast, ModifierKeyword keyword, int start, int end) {
Modifier modifier = null;
try {
diff --git a/src/eclipseAgent/lombok/launch/PatchFixesHider.java b/src/eclipseAgent/lombok/launch/PatchFixesHider.java
new file mode 100644
index 00000000..b1d73352
--- /dev/null
+++ b/src/eclipseAgent/lombok/launch/PatchFixesHider.java
@@ -0,0 +1,671 @@
+/*
+ * Copyright (C) 2010-2015 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.launch;
+
+import java.io.BufferedOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Stack;
+
+import lombok.eclipse.EclipseAugments;
+
+import org.eclipse.core.runtime.CoreException;
+import org.eclipse.jdt.core.IAnnotatable;
+import org.eclipse.jdt.core.IAnnotation;
+import org.eclipse.jdt.core.IField;
+import org.eclipse.jdt.core.IMethod;
+import org.eclipse.jdt.core.IType;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.jdt.core.dom.MethodDeclaration;
+import org.eclipse.jdt.core.dom.SimpleName;
+import org.eclipse.jdt.core.search.SearchMatch;
+import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Annotation;
+import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.Expression;
+import org.eclipse.jdt.internal.compiler.ast.FieldDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.ForeachStatement;
+import org.eclipse.jdt.internal.compiler.ast.LocalDeclaration;
+import org.eclipse.jdt.internal.compiler.ast.MessageSend;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+import org.eclipse.jdt.internal.compiler.lookup.MethodBinding;
+import org.eclipse.jdt.internal.compiler.lookup.Scope;
+import org.eclipse.jdt.internal.compiler.lookup.TypeBinding;
+import org.eclipse.jdt.internal.compiler.parser.Parser;
+import org.eclipse.jdt.internal.compiler.problem.ProblemReporter;
+import org.eclipse.jdt.internal.core.SourceField;
+import org.eclipse.jdt.internal.core.dom.rewrite.NodeRewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.RewriteEvent;
+import org.eclipse.jdt.internal.core.dom.rewrite.TokenScanner;
+import org.eclipse.jdt.internal.corext.refactoring.SearchResultGroup;
+import org.eclipse.jdt.internal.corext.refactoring.structure.ASTNodeSearchUtil;
+
+/** These contain a mix of the following:
+ * <ul>
+ * <li> 'dependency free' method wrappers that cross the shadowloader barrier.
+ * <li> methods that directly patch, <em>but</em>, these should ALWAYS be transplanted.
+ * </ul>
+ *
+ * <strong>This class lives on the outside of the shadowloader barrier, and as a consequence, cannot access any other lombok code except other
+ * code in the {@code lombok.launch} package!</strong>.
+ * <p>
+ * This class is package private with lots of public inner static classes. This hides all of them from IDE autocomplete dialogs and such but at the JVM
+ * level the inner static class are just plain public, which is important, because calls to the contents of these inner static classes are injected into
+ * various eclipse classes verbatim, and if they weren't public, the verifier wouldn't accept it.
+ */
+final class PatchFixesHider {
+
+ /** These utility methods are only used 'internally', but because of transplant methods, the class (and its methods) still have to be public! */
+ public static final class Util {
+ private static ClassLoader shadowLoader;
+
+ public static Class<?> shadowLoadClass(String name) {
+ try {
+ if (shadowLoader == null) {
+ try {
+ Class.forName("lombok.core.LombokNode");
+ // If we get here, then lombok is already available.
+ shadowLoader = Util.class.getClassLoader();
+ } catch (ClassNotFoundException e) {
+ // If we get here, it isn't, and we should use the shadowloader.
+ shadowLoader = Main.createShadowClassLoader();
+ }
+ }
+
+ return Class.forName(name, true, shadowLoader);
+ } catch (ClassNotFoundException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ public static Method findMethod(Class<?> type, String name, Class<?>... parameterTypes) {
+ try {
+ return type.getDeclaredMethod(name, parameterTypes);
+ } catch (NoSuchMethodException e) {
+ throw sneakyThrow(e);
+ }
+ }
+
+ public static Object invokeMethod(Method method, Object... args) {
+ try {
+ return method.invoke(null, args);
+ } catch (IllegalAccessException e) {
+ throw sneakyThrow(e);
+ } catch (InvocationTargetException e) {
+ throw sneakyThrow(e.getCause());
+ }
+ }
+
+ private static RuntimeException sneakyThrow(Throwable t) {
+ if (t == null) throw new NullPointerException("t");
+ Util.<RuntimeException>sneakyThrow0(t);
+ return null;
+ }
+
+ @SuppressWarnings("unchecked")
+ private static <T extends Throwable> void sneakyThrow0(Throwable t) throws T {
+ throw (T)t;
+ }
+ }
+
+ /** Contains patch fixes that are dependent on lombok internals. */
+ public static final class LombokDeps {
+ public static final Method ADD_LOMBOK_NOTES;
+ public static final Method POST_COMPILER_BYTES_STRING;
+ public static final Method POST_COMPILER_OUTPUTSTREAM;
+ public static final Method POST_COMPILER_BUFFEREDOUTPUTSTREAM_STRING_STRING;
+
+ static {
+ Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.agent.PatchFixesShadowLoaded");
+ ADD_LOMBOK_NOTES = Util.findMethod(shadowed, "addLombokNotesToEclipseAboutDialog", String.class, String.class);
+ POST_COMPILER_BYTES_STRING = Util.findMethod(shadowed, "runPostCompiler", byte[].class, String.class);
+ POST_COMPILER_OUTPUTSTREAM = Util.findMethod(shadowed, "runPostCompiler", OutputStream.class);
+ POST_COMPILER_BUFFEREDOUTPUTSTREAM_STRING_STRING = Util.findMethod(shadowed, "runPostCompiler", BufferedOutputStream.class, String.class, String.class);
+ }
+
+ public static String addLombokNotesToEclipseAboutDialog(String origReturnValue, String key) {
+ return (String) Util.invokeMethod(LombokDeps.ADD_LOMBOK_NOTES, origReturnValue, key);
+ }
+
+ public static byte[] runPostCompiler(byte[] bytes, String fileName) {
+ return (byte[]) Util.invokeMethod(LombokDeps.POST_COMPILER_BYTES_STRING, bytes, fileName);
+ }
+
+ public static OutputStream runPostCompiler(OutputStream out) throws IOException {
+ return (OutputStream) Util.invokeMethod(LombokDeps.POST_COMPILER_OUTPUTSTREAM, out);
+ }
+
+ public static BufferedOutputStream runPostCompiler(BufferedOutputStream out, String path, String name) throws IOException {
+ return (BufferedOutputStream) Util.invokeMethod(LombokDeps.POST_COMPILER_BUFFEREDOUTPUTSTREAM_STRING_STRING, out, path, name);
+ }
+ }
+
+ public static final class Transform {
+ private static final Method TRANSFORM;
+ private static final Method TRANSFORM_SWAPPED;
+
+ static {
+ Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.TransformEclipseAST");
+ TRANSFORM = Util.findMethod(shadowed, "transform", Parser.class, CompilationUnitDeclaration.class);
+ TRANSFORM_SWAPPED = Util.findMethod(shadowed, "transform_swapped", CompilationUnitDeclaration.class, Parser.class);
+ }
+
+ public static void transform(Parser parser, CompilationUnitDeclaration ast) throws IOException {
+ Util.invokeMethod(TRANSFORM, parser, ast);
+ }
+
+ public static void transform_swapped(CompilationUnitDeclaration ast, Parser parser) throws IOException {
+ Util.invokeMethod(TRANSFORM_SWAPPED, ast, parser);
+ }
+ }
+
+ /** Contains patch code to support {@code @Delegate} */
+ public static final class Delegate {
+ private static final Method HANDLE_DELEGATE_FOR_TYPE;
+
+ static {
+ Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.agent.PatchDelegatePortal");
+ HANDLE_DELEGATE_FOR_TYPE = Util.findMethod(shadowed, "handleDelegateForType", Object.class);
+ }
+
+ public static boolean handleDelegateForType(Object classScope) {
+ return (Boolean) Util.invokeMethod(HANDLE_DELEGATE_FOR_TYPE, classScope);
+ }
+ }
+
+ /** Contains patch code to support {@code val} (eclipse specific) */
+ public static final class ValPortal {
+ private static final Method COPY_INITIALIZATION_OF_FOR_EACH_ITERABLE;
+ private static final Method COPY_INITIALIZATION_OF_LOCAL_DECLARATION;
+ private static final Method ADD_FINAL_AND_VAL_ANNOTATION_TO_VARIABLE_DECLARATION_STATEMENT;
+ private static final Method ADD_FINAL_AND_VAL_ANNOTATION_TO_SINGLE_VARIABLE_DECLARATION;
+
+ static {
+ Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.agent.PatchValEclipsePortal");
+ COPY_INITIALIZATION_OF_FOR_EACH_ITERABLE = Util.findMethod(shadowed, "copyInitializationOfForEachIterable", Object.class);
+ COPY_INITIALIZATION_OF_LOCAL_DECLARATION = Util.findMethod(shadowed, "copyInitializationOfLocalDeclaration", Object.class);
+ ADD_FINAL_AND_VAL_ANNOTATION_TO_VARIABLE_DECLARATION_STATEMENT = Util.findMethod(shadowed, "addFinalAndValAnnotationToVariableDeclarationStatement", Object.class, Object.class, Object.class);
+ ADD_FINAL_AND_VAL_ANNOTATION_TO_SINGLE_VARIABLE_DECLARATION = Util.findMethod(shadowed, "addFinalAndValAnnotationToSingleVariableDeclaration", Object.class, Object.class, Object.class);
+ }
+
+ public static void copyInitializationOfForEachIterable(Object parser) {
+ Util.invokeMethod(COPY_INITIALIZATION_OF_FOR_EACH_ITERABLE, parser);
+ }
+
+ public static void copyInitializationOfLocalDeclaration(Object parser) {
+ Util.invokeMethod(COPY_INITIALIZATION_OF_LOCAL_DECLARATION, parser);
+ }
+
+ public static void addFinalAndValAnnotationToVariableDeclarationStatement(Object converter, Object out, Object in) {
+ Util.invokeMethod(ADD_FINAL_AND_VAL_ANNOTATION_TO_VARIABLE_DECLARATION_STATEMENT, converter, out, in);
+ }
+
+ public static void addFinalAndValAnnotationToSingleVariableDeclaration(Object converter, Object out, Object in) {
+ Util.invokeMethod(ADD_FINAL_AND_VAL_ANNOTATION_TO_SINGLE_VARIABLE_DECLARATION, converter, out, in);
+ }
+ }
+
+ /** Contains patch code to support {@code val} (eclipse and ecj) */
+ public static final class Val {
+ private static final Method SKIP_RESOLVE_INITIALIZER_IF_ALREADY_CALLED;
+ private static final Method SKIP_RESOLVE_INITIALIZER_IF_ALREADY_CALLED2;
+ private static final Method HANDLE_VAL_FOR_LOCAL_DECLARATION;
+ private static final Method HANDLE_VAL_FOR_FOR_EACH;
+
+ static {
+ Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.agent.PatchVal");
+ SKIP_RESOLVE_INITIALIZER_IF_ALREADY_CALLED = Util.findMethod(shadowed, "skipResolveInitializerIfAlreadyCalled", Expression.class, BlockScope.class);
+ SKIP_RESOLVE_INITIALIZER_IF_ALREADY_CALLED2 = Util.findMethod(shadowed, "skipResolveInitializerIfAlreadyCalled2", Expression.class, BlockScope.class, LocalDeclaration.class);
+ HANDLE_VAL_FOR_LOCAL_DECLARATION = Util.findMethod(shadowed, "handleValForLocalDeclaration", LocalDeclaration.class, BlockScope.class);
+ HANDLE_VAL_FOR_FOR_EACH = Util.findMethod(shadowed, "handleValForForEach", ForeachStatement.class, BlockScope.class);
+ }
+
+ public static TypeBinding skipResolveInitializerIfAlreadyCalled(Expression expr, BlockScope scope) {
+ return (TypeBinding) Util.invokeMethod(SKIP_RESOLVE_INITIALIZER_IF_ALREADY_CALLED, expr, scope);
+ }
+
+ public static TypeBinding skipResolveInitializerIfAlreadyCalled2(Expression expr, BlockScope scope, LocalDeclaration decl) {
+ return (TypeBinding) Util.invokeMethod(SKIP_RESOLVE_INITIALIZER_IF_ALREADY_CALLED2, expr, scope, decl);
+ }
+
+ public static boolean handleValForLocalDeclaration(LocalDeclaration local, BlockScope scope) {
+ return (Boolean) Util.invokeMethod(HANDLE_VAL_FOR_LOCAL_DECLARATION, local, scope);
+ }
+
+ public static boolean handleValForForEach(ForeachStatement forEach, BlockScope scope) {
+ return (Boolean) Util.invokeMethod(HANDLE_VAL_FOR_FOR_EACH, forEach, scope);
+ }
+ }
+
+ /** Contains patch code to support {@code @ExtensionMethod} */
+ public static final class ExtensionMethod {
+ private static final Method RESOLVE_TYPE;
+ private static final Method ERROR_NO_METHOD_FOR;
+ private static final Method INVALID_METHOD, INVALID_METHOD2;
+
+ static {
+ Class<?> shadowed = Util.shadowLoadClass("lombok.eclipse.agent.PatchExtensionMethod");
+ RESOLVE_TYPE = Util.findMethod(shadowed, "resolveType", TypeBinding.class, MessageSend.class, BlockScope.class);
+ ERROR_NO_METHOD_FOR = Util.findMethod(shadowed, "errorNoMethodFor", ProblemReporter.class, MessageSend.class, TypeBinding.class, TypeBinding[].class);
+ INVALID_METHOD = Util.findMethod(shadowed, "invalidMethod", ProblemReporter.class, MessageSend.class, MethodBinding.class);
+ INVALID_METHOD2 = Util.findMethod(shadowed, "invalidMethod", ProblemReporter.class, MessageSend.class, MethodBinding.class, Scope.class);
+ }
+
+ public static TypeBinding resolveType(TypeBinding resolvedType, MessageSend methodCall, BlockScope scope) {
+ return (TypeBinding) Util.invokeMethod(RESOLVE_TYPE, resolvedType, methodCall, scope);
+ }
+
+ public static void errorNoMethodFor(ProblemReporter problemReporter, MessageSend messageSend, TypeBinding recType, TypeBinding[] params) {
+ Util.invokeMethod(ERROR_NO_METHOD_FOR, problemReporter, messageSend, recType, params);
+ }
+
+ public static void invalidMethod(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method) {
+ Util.invokeMethod(INVALID_METHOD, problemReporter, messageSend, method);
+ }
+
+ public static void invalidMethod(ProblemReporter problemReporter, MessageSend messageSend, MethodBinding method, Scope scope) {
+ Util.invokeMethod(INVALID_METHOD2, problemReporter, messageSend, method, scope);
+ }
+ }
+
+ /**
+ * Contains a mix of methods: ecj only, ecj+eclipse, and eclipse only. As a consequence, _EVERY_ method from here used for ecj MUST be
+ * transplanted, as ecj itself cannot load this class (signatures refer to things that don't exist in ecj-only mode).
+ * <p>
+ * Because of usage of transplant(), a bunch of these contain direct code and don't try to cross the shadowloader barrier.
+ */
+ public static final class PatchFixes {
+ public static boolean isGenerated(org.eclipse.jdt.core.dom.ASTNode node) {
+ boolean result = false;
+ try {
+ result = ((Boolean)node.getClass().getField("$isGenerated").get(node)).booleanValue();
+ if (!result && node.getParent() != null && node.getParent() instanceof org.eclipse.jdt.core.dom.QualifiedName) {
+ result = isGenerated(node.getParent());
+ }
+ } catch (Exception e) {
+ // better to assume it isn't generated
+ }
+ return result;
+ }
+
+ public static boolean isListRewriteOnGeneratedNode(org.eclipse.jdt.core.dom.rewrite.ListRewrite rewrite) {
+ return isGenerated(rewrite.getParent());
+ }
+
+ public static boolean returnFalse(java.lang.Object object) {
+ return false;
+ }
+
+ public static boolean returnTrue(java.lang.Object object) {
+ return true;
+ }
+
+ @java.lang.SuppressWarnings({"unchecked", "rawtypes"}) public static java.util.List removeGeneratedNodes(java.util.List list) {
+ try {
+ java.util.List realNodes = new java.util.ArrayList(list.size());
+ for (java.lang.Object node : list) {
+ if(!isGenerated(((org.eclipse.jdt.core.dom.ASTNode)node))) {
+ realNodes.add(node);
+ }
+ }
+ return realNodes;
+ } catch (Exception e) {
+ }
+ return list;
+ }
+
+ public static java.lang.String getRealMethodDeclarationSource(java.lang.String original, Object processor, org.eclipse.jdt.core.dom.MethodDeclaration declaration) throws Exception {
+ if (!isGenerated(declaration)) return original;
+
+ List<org.eclipse.jdt.core.dom.Annotation> annotations = new ArrayList<org.eclipse.jdt.core.dom.Annotation>();
+ for (Object modifier : declaration.modifiers()) {
+ if (modifier instanceof org.eclipse.jdt.core.dom.Annotation) {
+ org.eclipse.jdt.core.dom.Annotation annotation = (org.eclipse.jdt.core.dom.Annotation)modifier;
+ String qualifiedAnnotationName = annotation.resolveTypeBinding().getQualifiedName();
+ if (!"java.lang.Override".equals(qualifiedAnnotationName) && !"java.lang.SuppressWarnings".equals(qualifiedAnnotationName)) annotations.add(annotation);
+ }
+ }
+
+ StringBuilder signature = new StringBuilder();
+ addAnnotations(annotations, signature);
+
+ if ((Boolean)processor.getClass().getDeclaredField("fPublic").get(processor)) signature.append("public ");
+ if ((Boolean)processor.getClass().getDeclaredField("fAbstract").get(processor)) signature.append("abstract ");
+
+ signature
+ .append(declaration.getReturnType2().toString())
+ .append(" ").append(declaration.getName().getFullyQualifiedName())
+ .append("(");
+
+ boolean first = true;
+ for (Object parameter : declaration.parameters()) {
+ if (!first) signature.append(", ");
+ first = false;
+ // We should also add the annotations of the parameters
+ signature.append(parameter);
+ }
+
+ signature.append(");");
+ return signature.toString();
+ }
+
+ // part of getRealMethodDeclarationSource(...)
+ public static void addAnnotations(List<org.eclipse.jdt.core.dom.Annotation> annotations, StringBuilder signature) {
+ /*
+ * We SHOULD be able to handle the following cases:
+ * @Override
+ * @Override()
+ * @SuppressWarnings("all")
+ * @SuppressWarnings({"all", "unused"})
+ * @SuppressWarnings(value = "all")
+ * @SuppressWarnings(value = {"all", "unused"})
+ * @EqualsAndHashCode(callSuper=true, of="id")
+ *
+ * Currently, we only seem to correctly support:
+ * @Override
+ * @Override() N.B. We lose the parentheses here, since there are no values. No big deal.
+ * @SuppressWarnings("all")
+ */
+ for (org.eclipse.jdt.core.dom.Annotation annotation : annotations) {
+ List<String> values = new ArrayList<String>();
+ if (annotation.isSingleMemberAnnotation()) {
+ org.eclipse.jdt.core.dom.SingleMemberAnnotation smAnn = (org.eclipse.jdt.core.dom.SingleMemberAnnotation) annotation;
+ values.add(smAnn.getValue().toString());
+ } else if (annotation.isNormalAnnotation()) {
+ org.eclipse.jdt.core.dom.NormalAnnotation normalAnn = (org.eclipse.jdt.core.dom.NormalAnnotation) annotation;
+ for (Object value : normalAnn.values()) values.add(value.toString());
+ }
+
+ signature.append("@").append(annotation.resolveTypeBinding().getQualifiedName());
+ if (!values.isEmpty()) {
+ signature.append("(");
+ boolean first = true;
+ for (String string : values) {
+ if (!first) signature.append(", ");
+ first = false;
+ signature.append('"').append(string).append('"');
+ }
+ signature.append(")");
+ }
+ signature.append(" ");
+ }
+ }
+
+ public static org.eclipse.jdt.core.dom.MethodDeclaration getRealMethodDeclarationNode(org.eclipse.jdt.core.IMethod sourceMethod, org.eclipse.jdt.core.dom.CompilationUnit cuUnit) throws JavaModelException {
+ MethodDeclaration methodDeclarationNode = ASTNodeSearchUtil.getMethodDeclarationNode(sourceMethod, cuUnit);
+ if (isGenerated(methodDeclarationNode)) {
+ IType declaringType = sourceMethod.getDeclaringType();
+ Stack<IType> typeStack = new Stack<IType>();
+ while (declaringType != null) {
+ typeStack.push(declaringType);
+ declaringType = declaringType.getDeclaringType();
+ }
+
+ IType rootType = typeStack.pop();
+ org.eclipse.jdt.core.dom.AbstractTypeDeclaration typeDeclaration = findTypeDeclaration(rootType, cuUnit.types());
+ while (!typeStack.isEmpty() && typeDeclaration != null) {
+ typeDeclaration = findTypeDeclaration(typeStack.pop(), typeDeclaration.bodyDeclarations());
+ }
+
+ if (typeStack.isEmpty() && typeDeclaration != null) {
+ String methodName = sourceMethod.getElementName();
+ for (Object declaration : typeDeclaration.bodyDeclarations()) {
+ if (declaration instanceof org.eclipse.jdt.core.dom.MethodDeclaration) {
+ org.eclipse.jdt.core.dom.MethodDeclaration methodDeclaration = (org.eclipse.jdt.core.dom.MethodDeclaration) declaration;
+ if (methodDeclaration.getName().toString().equals(methodName)) {
+ return methodDeclaration;
+ }
+ }
+ }
+ }
+ }
+ return methodDeclarationNode;
+ }
+
+ // part of getRealMethodDeclarationNode
+ public static org.eclipse.jdt.core.dom.AbstractTypeDeclaration findTypeDeclaration(IType searchType, List<?> nodes) {
+ for (Object object : nodes) {
+ if (object instanceof org.eclipse.jdt.core.dom.AbstractTypeDeclaration) {
+ org.eclipse.jdt.core.dom.AbstractTypeDeclaration typeDeclaration = (org.eclipse.jdt.core.dom.AbstractTypeDeclaration) object;
+ if (typeDeclaration.getName().toString().equals(searchType.getElementName()))
+ return typeDeclaration;
+ }
+ }
+ return null;
+ }
+
+ public static int getSourceEndFixed(int sourceEnd, org.eclipse.jdt.internal.compiler.ast.ASTNode node) throws Exception {
+ if (sourceEnd == -1) {
+ org.eclipse.jdt.internal.compiler.ast.ASTNode object = (org.eclipse.jdt.internal.compiler.ast.ASTNode)node.getClass().getField("$generatedBy").get(node);
+ if (object != null) {
+ return object.sourceEnd;
+ }
+ }
+ return sourceEnd;
+ }
+
+ public static int fixRetrieveStartingCatchPosition(int original, int start) {
+ return original == -1 ? start : original;
+ }
+
+ public static int fixRetrieveIdentifierEndPosition(int original, int end) {
+ return original == -1 ? end : original;
+ }
+
+ public static int fixRetrieveEllipsisStartPosition(int original, int end) {
+ return original == -1 ? end : original;
+ }
+
+ public static int fixRetrieveRightBraceOrSemiColonPosition(int original, int end) {
+// if (original == -1) {
+// Thread.dumpStack();
+// }
+ return original == -1 ? end : original;
+ }
+
+ public static int fixRetrieveRightBraceOrSemiColonPosition(int retVal, AbstractMethodDeclaration amd) {
+ if (retVal != -1 || amd == null) return retVal;
+ boolean isGenerated = EclipseAugments.ASTNode_generatedBy.get(amd) != null;
+ if (isGenerated) return amd.declarationSourceEnd;
+ return -1;
+ }
+
+ public static int fixRetrieveRightBraceOrSemiColonPosition(int retVal, FieldDeclaration fd) {
+ if (retVal != -1 || fd == null) return retVal;
+ boolean isGenerated = EclipseAugments.ASTNode_generatedBy.get(fd) != null;
+ if (isGenerated) return fd.declarationSourceEnd;
+ return -1;
+ }
+
+ public static final int ALREADY_PROCESSED_FLAG = 0x800000; //Bit 24
+
+ public static boolean checkBit24(Object node) throws Exception {
+ int bits = (Integer)(node.getClass().getField("bits").get(node));
+ return (bits & ALREADY_PROCESSED_FLAG) != 0;
+ }
+
+ public static boolean skipRewritingGeneratedNodes(org.eclipse.jdt.core.dom.ASTNode node) throws Exception {
+ return ((Boolean) node.getClass().getField("$isGenerated").get(node)).booleanValue();
+ }
+
+ public static void setIsGeneratedFlag(org.eclipse.jdt.core.dom.ASTNode domNode,
+ org.eclipse.jdt.internal.compiler.ast.ASTNode internalNode) throws Exception {
+
+ if (internalNode == null || domNode == null) return;
+ boolean isGenerated = EclipseAugments.ASTNode_generatedBy.get(internalNode) != null;
+ if (isGenerated) domNode.getClass().getField("$isGenerated").set(domNode, true);
+ }
+
+ public static void setIsGeneratedFlagForName(org.eclipse.jdt.core.dom.Name name, Object internalNode) throws Exception {
+ if (internalNode instanceof org.eclipse.jdt.internal.compiler.ast.ASTNode) {
+ boolean isGenerated = EclipseAugments.ASTNode_generatedBy.get((org.eclipse.jdt.internal.compiler.ast.ASTNode) internalNode) != null;
+ if (isGenerated) name.getClass().getField("$isGenerated").set(name, true);
+ }
+ }
+
+ public static RewriteEvent[] listRewriteHandleGeneratedMethods(RewriteEvent parent) {
+ RewriteEvent[] children = parent.getChildren();
+ List<RewriteEvent> newChildren = new ArrayList<RewriteEvent>();
+ List<RewriteEvent> modifiedChildren = new ArrayList<RewriteEvent>();
+ for (int i = 0; i < children.length; i++) {
+ RewriteEvent child = children[i];
+ boolean isGenerated = isGenerated((org.eclipse.jdt.core.dom.ASTNode) child.getOriginalValue());
+ if (isGenerated) {
+ boolean isReplacedOrRemoved = child.getChangeKind() == RewriteEvent.REPLACED || child.getChangeKind() == RewriteEvent.REMOVED;
+ boolean convertingFromMethod = child.getOriginalValue() instanceof org.eclipse.jdt.core.dom.MethodDeclaration;
+ if (isReplacedOrRemoved && convertingFromMethod && child.getNewValue() != null) {
+ modifiedChildren.add(new NodeRewriteEvent(null, child.getNewValue()));
+ }
+ } else {
+ newChildren.add(child);
+ }
+ }
+ // Since Eclipse doesn't honor the "insert at specified location" for already existing members,
+ // we'll just add them last
+ newChildren.addAll(modifiedChildren);
+ return newChildren.toArray(new RewriteEvent[newChildren.size()]);
+ }
+
+ public static int getTokenEndOffsetFixed(TokenScanner scanner, int token, int startOffset, Object domNode) throws CoreException {
+ boolean isGenerated = false;
+ try {
+ isGenerated = (Boolean) domNode.getClass().getField("$isGenerated").get(domNode);
+ } catch (Exception e) {
+ // If this fails, better to break some refactor scripts than to crash eclipse.
+ }
+ if (isGenerated) return -1;
+ return scanner.getTokenEndOffset(token, startOffset);
+ }
+
+ public static IMethod[] removeGeneratedMethods(IMethod[] methods) throws Exception {
+ List<IMethod> result = new ArrayList<IMethod>();
+ for (IMethod m : methods) {
+ if (m.getNameRange().getLength() > 0 && !m.getNameRange().equals(m.getSourceRange())) result.add(m);
+ }
+ return result.size() == methods.length ? methods : result.toArray(new IMethod[result.size()]);
+ }
+
+ public static SearchMatch[] removeGenerated(SearchMatch[] returnValue) {
+ List<SearchMatch> result = new ArrayList<SearchMatch>();
+ for (int j = 0; j < returnValue.length; j++) {
+ SearchMatch searchResult = returnValue[j];
+ if (searchResult.getElement() instanceof IField) {
+ IField field = (IField) searchResult.getElement();
+
+ // can not check for value=lombok because annotation is
+ // not fully resolved
+ IAnnotation annotation = field.getAnnotation("Generated");
+ if (annotation != null) {
+ // Method generated at field location, skip
+ continue;
+ }
+
+ }
+ result.add(searchResult);
+ }
+ return result.toArray(new SearchMatch[result.size()]);
+ }
+
+ public static SearchResultGroup[] createFakeSearchResult(SearchResultGroup[] returnValue,
+ Object/*
+ * org.eclipse.jdt.internal.corext.refactoring.rename.
+ * RenameFieldProcessor
+ */ processor) throws Exception {
+ if (returnValue == null || returnValue.length == 0) {
+ // if no matches were found, check if Data annotation is present on the class
+ Field declaredField = processor.getClass().getDeclaredField("fField");
+ if (declaredField != null) {
+ declaredField.setAccessible(true);
+ SourceField fField = (SourceField) declaredField.get(processor);
+ IAnnotation dataAnnotation = fField.getDeclaringType().getAnnotation("Data");
+ if (dataAnnotation != null) {
+ // add fake item, to make refactoring checks pass
+ return new SearchResultGroup[] {new SearchResultGroup(null, new SearchMatch[1])};
+ }
+ }
+ }
+ return returnValue;
+ }
+
+ public static SimpleName[] removeGeneratedSimpleNames(SimpleName[] in) throws Exception {
+ Field f = SimpleName.class.getField("$isGenerated");
+
+ int count = 0;
+ for (int i = 0; i < in.length; i++) {
+ if (in[i] == null || !((Boolean)f.get(in[i])).booleanValue()) count++;
+ }
+ if (count == in.length) return in;
+ SimpleName[] newSimpleNames = new SimpleName[count];
+ count = 0;
+ for (int i = 0; i < in.length; i++) {
+ if (in[i] == null || !((Boolean)f.get(in[i])).booleanValue()) newSimpleNames[count++] = in[i];
+ }
+ return newSimpleNames;
+ }
+
+ public static Annotation[] convertAnnotations(Annotation[] out, IAnnotatable annotatable) {
+ IAnnotation[] in;
+
+ try {
+ in = annotatable.getAnnotations();
+ } catch (Exception e) {
+ return out;
+ }
+
+ if (out == null) return null;
+ int toWrite = 0;
+
+ for (int idx = 0; idx < out.length; idx++) {
+ String oName = new String(out[idx].type.getLastToken());
+ boolean found = false;
+ for (IAnnotation i : in) {
+ String name = i.getElementName();
+ int li = name.lastIndexOf('.');
+ if (li > -1) name = name.substring(li + 1);
+ if (name.equals(oName)) {
+ found = true;
+ break;
+ }
+ }
+ if (!found) out[idx] = null;
+ else toWrite++;
+ }
+
+ Annotation[] replace = out;
+ if (toWrite < out.length) {
+ replace = new Annotation[toWrite];
+ int idx = 0;
+ for (int i = 0; i < out.length; i++) {
+ if (out[i] == null) continue;
+ replace[idx++] = out[i];
+ }
+ }
+
+ return replace;
+ }
+ }
+}
diff --git a/src/installer/lombok/installer/IdeLocation.java b/src/installer/lombok/installer/IdeLocation.java
index 4e3a7e41..c3853867 100644
--- a/src/installer/lombok/installer/IdeLocation.java
+++ b/src/installer/lombok/installer/IdeLocation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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,7 +25,6 @@ import java.io.File;
import java.io.IOException;
import java.net.URL;
-import lombok.installer.eclipse.EclipseFinder;
import lombok.patcher.ClassRootFinder;
/**
@@ -46,7 +45,7 @@ public abstract class IdeLocation {
* a jar that wasn't accessed via the file-system, or if its started via e.g. unpacking the jar.
*/
public static File findOurJar() {
- return new File(ClassRootFinder.findClassRootOfClass(IdeFinder.class));
+ return new File(ClassRootFinder.findClassRootOfClass(OsUtils.class));
}
@Override public String toString() {
@@ -70,7 +69,7 @@ public abstract class IdeLocation {
private static final String LEGAL_PATH_CHARS_WINDOWS = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789.-_/:\\ ";
public static String escapePath(String path) {
StringBuilder out = new StringBuilder();
- String legalChars = IdeFinder.getOS() == EclipseFinder.OS.UNIX ? LEGAL_PATH_CHARS : LEGAL_PATH_CHARS_WINDOWS;
+ String legalChars = OsUtils.getOS() == OsUtils.OS.UNIX ? LEGAL_PATH_CHARS : LEGAL_PATH_CHARS_WINDOWS;
for (char c : path.toCharArray()) {
if (legalChars.indexOf(c) == -1) out.append('\\');
out.append(c);
diff --git a/src/installer/lombok/installer/IdeLocationProvider.java b/src/installer/lombok/installer/IdeLocationProvider.java
index 933a5989..c4b64141 100644
--- a/src/installer/lombok/installer/IdeLocationProvider.java
+++ b/src/installer/lombok/installer/IdeLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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,20 +21,30 @@
*/
package lombok.installer;
+import java.util.List;
import java.util.regex.Pattern;
-import lombok.installer.IdeFinder.OS;
-
public interface IdeLocationProvider {
/**
* @throws CorruptedIdeLocationException
* Only throw this exception if the location seems like a proper installation except there's something wrong with it.
* Do not throw it (just return {@code null}) if there's nothing there or it looks absolutely nothing like your IDE.
*/
- public abstract IdeLocation create(String path) throws CorruptedIdeLocationException;
+ IdeLocation create(String path) throws CorruptedIdeLocationException;
+
+ /**
+ * Return the usual name of the IDE executable or other obvious marker of an IDE installation on the current platform.
+ */
+ Pattern getLocationSelectors();
/**
- * Return the usual name of the IDE executable or other obvious marker of an IDE installation on the provided platform.
+ * Look for installations of your IDE in the usual places.
+ *
+ * @param locations Add to this list any valid locations that you found.
+ * @param problems
+ * Add to this list any locations that look like installations,
+ * but have problems that prevent you from installing/uninstalling from them. DONT add to this list
+ * any common locations that have no installation at all - only add near misses.
*/
- public abstract Pattern getLocationSelectors(OS os);
+ void findIdes(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems);
}
diff --git a/src/installer/lombok/installer/Installer.java b/src/installer/lombok/installer/Installer.java
index b9faeebd..94cc1a45 100644
--- a/src/installer/lombok/installer/Installer.java
+++ b/src/installer/lombok/installer/Installer.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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,7 +38,7 @@ import lombok.Lombok;
import lombok.core.LombokApp;
import lombok.core.SpiLoadUtil;
import lombok.core.Version;
-import lombok.installer.IdeFinder.OS;
+import lombok.installer.OsUtils.OS;
import lombok.patcher.ClassRootFinder;
import org.mangosdk.spi.ProviderFor;
@@ -56,7 +56,7 @@ import com.zwitserloot.cmdreader.Shorthand;
* and looks in some common places on Mac OS X, Linux and Windows.
*/
public class Installer {
- static final URI ABOUT_LOMBOK_URL = URI.create("http://projectlombok.org");
+ static final URI ABOUT_LOMBOK_URL = URI.create("https://projectlombok.org");
static final List<IdeLocationProvider> locationProviders;
static {
@@ -72,10 +72,9 @@ public class Installer {
}
static List<Pattern> getIdeExecutableNames() {
- OS os = IdeFinder.getOS();
List<Pattern> list = new ArrayList<Pattern>();
for (IdeLocationProvider provider : locationProviders) {
- Pattern p = provider.getLocationSelectors(os);
+ Pattern p = provider.getLocationSelectors();
if (p != null) list.add(p);
}
return list;
@@ -91,12 +90,8 @@ public class Installer {
}
static void autoDiscover(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) {
- try {
- for (IdeFinder finder : SpiLoadUtil.findServices(IdeFinder.class)) {
- finder.findIdes(locations, problems);
- }
- } catch (IOException e) {
- throw Lombok.sneakyThrow(e);
+ for (IdeLocationProvider provider : locationProviders) {
+ provider.findIdes(locations, problems);
}
}
@@ -160,7 +155,7 @@ public class Installer {
}
private static int guiInstaller() {
- if (IdeFinder.getOS() == OS.MAC_OS_X) {
+ if (OsUtils.getOS() == OS.MAC_OS_X) {
System.setProperty("com.apple.mrj.application.apple.menu.about.name", "Lombok Installer");
System.setProperty("com.apple.macos.use-file-dialog-packages", "true");
}
diff --git a/src/installer/lombok/installer/InstallerGUI.java b/src/installer/lombok/installer/InstallerGUI.java
index 5717948a..231e2d3c 100644
--- a/src/installer/lombok/installer/InstallerGUI.java
+++ b/src/installer/lombok/installer/InstallerGUI.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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
@@ -39,6 +39,8 @@ import java.awt.event.ActionListener;
import java.awt.font.TextAttribute;
import java.io.File;
import java.io.FilenameFilter;
+import java.io.InputStream;
+import java.io.InputStreamReader;
import java.net.URI;
import java.util.ArrayList;
import java.util.Collections;
@@ -62,12 +64,15 @@ import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
+import javax.swing.JTextPane;
import javax.swing.Scrollable;
import javax.swing.SwingUtilities;
+import javax.swing.UIManager;
import javax.swing.filechooser.FileFilter;
+import javax.swing.text.html.HTMLDocument;
import lombok.core.Version;
-import lombok.installer.IdeFinder.OS;
+import lombok.installer.OsUtils.OS;
/**
* The lombok GUI installer.
@@ -75,6 +80,7 @@ import lombok.installer.IdeFinder.OS;
* Also offers info on what this installer does in case people want to instrument their IDE manually.
*/
public class InstallerGUI {
+ private static final int INSTALLER_WINDOW_WIDTH = 662;
static final AtomicReference<Integer> exitMarker = new AtomicReference<Integer>();
private JFrame appWindow;
@@ -85,6 +91,7 @@ public class InstallerGUI {
private Component ideArea;
private Component uninstallArea;
private Component howIWorkArea;
+ private Component successArea;
private Box uninstallBox;
private JHyperLink uninstallButton;
@@ -101,6 +108,7 @@ public class InstallerGUI {
public InstallerGUI() {
appWindow = new JFrame(String.format("Project Lombok v%s - Installer", Version.getVersion()));
+ appWindow.setLocationByPlatform(true);
appWindow.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
appWindow.setResizable(false);
appWindow.setIconImage(Toolkit.getDefaultToolkit().getImage(Installer.class.getResource("lombokIcon.png")));
@@ -112,6 +120,8 @@ public class InstallerGUI {
uninstallArea.setVisible(false);
howIWorkArea = buildHowIWorkArea();
howIWorkArea.setVisible(false);
+ successArea = buildSuccessArea();
+ successArea.setVisible(false);
buildChrome(appWindow.getContentPane());
appWindow.pack();
} catch (Throwable t) {
@@ -152,6 +162,7 @@ public class InstallerGUI {
howIWorkArea.setVisible(false);
javacArea.setVisible(true);
ideArea.setVisible(true);
+ successArea.setVisible(false);
appWindow.pack();
}
});
@@ -159,9 +170,86 @@ public class InstallerGUI {
constraints.gridy = 2;
container.add(buttonBar, constraints);
+ container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
return container;
}
+ private void showSuccess(String installSpecific) {
+ successExplanation.setText(SUCCESS_EXPLANATION.replace("%%%", installSpecific));
+ howIWorkArea.setVisible(false);
+ javacArea.setVisible(false);
+ ideArea.setVisible(false);
+ successArea.setVisible(true);
+ appWindow.pack();
+ }
+
+ private JLabel successExplanation;
+
+ private Component buildSuccessArea() {
+ JPanel container = new JPanel();
+
+ container.setLayout(new GridBagLayout());
+ GridBagConstraints constraints = new GridBagConstraints();
+ constraints.anchor = GridBagConstraints.WEST;
+
+ JLabel title;
+ container.add(title = new JLabel(SUCCESS_TITLE), constraints);
+ title.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 20));
+ title.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 20));
+
+ constraints.gridy = 1;
+ constraints.insets = new Insets(8, 0, 0, 16);
+ container.add(successExplanation = new JLabel(SUCCESS_EXPLANATION), constraints);
+ successExplanation.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 175));
+ successExplanation.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 175));
+
+ constraints.gridy++;
+ constraints.fill = GridBagConstraints.BOTH;
+
+ JTextPane notes = new JTextPane();
+ notes.setContentType("text/html");
+ notes.setText(readChangeLog());
+ notes.setEditable(false);
+ notes.setOpaque(false);
+ notes.setBorder(null);
+ notes.setSelectionStart(0);
+ notes.setSelectionEnd(0);
+
+ Font font = UIManager.getFont("Label.font");
+ String bodyRule = "body { font-family: " + font.getFamily() + "; font-size: " + font.getSize() + "pt; }";
+ ((HTMLDocument) notes.getDocument()).getStyleSheet().addRule(bodyRule);
+ JScrollPane scroller = new JScrollPane(notes);
+ container.add(scroller, constraints);
+ scroller.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 200));
+ scroller.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH - 82, 200));
+ container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
+ return container;
+ }
+
+ private String readChangeLog() {
+ InputStream in = Installer.class.getResourceAsStream("/latestchanges.html");
+ try {
+ char[] buff = new char[8192];
+ StringBuilder contents = new StringBuilder();
+ InputStreamReader reader = new InputStreamReader(in, "UTF-8");
+ while (true) {
+ int read = reader.read(buff);
+ if (read == -1) break;
+ contents.append(buff, 0, read);
+ }
+ return "<html>" + contents + "</html>";
+ } catch (Exception e) {
+ return "No Changelog available";
+ }
+ finally {
+ try {
+ in.close();
+ } catch (Exception ignore){ /**/}
+ }
+ }
+
private Component buildUninstallArea() {
JPanel container = new JPanel();
@@ -209,6 +297,8 @@ public class InstallerGUI {
constraints.gridy = 4;
container.add(buttonBar, constraints);
+ container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 415));
return container;
}
@@ -231,6 +321,8 @@ public class InstallerGUI {
constraints.gridy = 2;
container.add(example, constraints);
+ container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 105));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 105));
return container;
}
@@ -288,11 +380,11 @@ public class InstallerGUI {
if (locations.size() + problems.size() == 0) {
JOptionPane.showMessageDialog(appWindow,
- "I can't find any IDEs on your computer.\n" +
- "If you have IDEs installed on this computer, please use the " +
- "'Specify Location...' button to manually point out the \n" +
- "location of your IDE installation to me. Thanks!",
- "Can't find IDE", JOptionPane.INFORMATION_MESSAGE);
+ "I can't find any IDEs on your computer.\n" +
+ "If you have IDEs installed on this computer, please use the " +
+ "'Specify Location...' button to manually point out the \n" +
+ "location of your IDE installation to me. Thanks!",
+ "Can't find IDE", JOptionPane.INFORMATION_MESSAGE);
}
}
});
@@ -312,7 +404,7 @@ public class InstallerGUI {
final List<Pattern> exeNames = Installer.getIdeExecutableNames();
String file = null;
- if (IdeFinder.getOS() == OS.MAC_OS_X) {
+ if (OsUtils.getOS() == OS.MAC_OS_X) {
FileDialog chooser = new FileDialog(appWindow);
chooser.setMode(FileDialog.LOAD);
@@ -418,7 +510,8 @@ public class InstallerGUI {
uninstallPlaceholder.setVisible(false);
container.add(uninstallPlaceholder, constraints);
-
+ container.setPreferredSize(new Dimension(INSTALLER_WINDOW_WIDTH, 296));
+ container.setMinimumSize(new Dimension(INSTALLER_WINDOW_WIDTH, 296));
return container;
}
@@ -426,6 +519,7 @@ public class InstallerGUI {
javacArea.setVisible(false);
ideArea.setVisible(false);
howIWorkArea.setVisible(true);
+ successArea.setVisible(false);
appWindow.pack();
}
@@ -452,6 +546,7 @@ public class InstallerGUI {
spinner.setOpaque(true);
spinner.setLayout(new FlowLayout());
spinner.add(new JLabel(new ImageIcon(Installer.class.getResource("loading.gif"))));
+ final Container appWindowContent = appWindow.getContentPane();
appWindow.setContentPane(spinner);
final AtomicInteger successes = new AtomicInteger();
@@ -499,20 +594,13 @@ public class InstallerGUI {
try {
SwingUtilities.invokeAndWait(new Runnable() {
@Override public void run() {
+ appWindow.setContentPane(appWindowContent);
+ appWindow.pack();
StringBuilder installSpecific = new StringBuilder();
for (String installSpecificMessage : installSpecificMessages) {
installSpecific.append("<br>").append(installSpecificMessage);
}
- JOptionPane.showMessageDialog(appWindow,
- "<html>Lombok has been installed on the selected IDE installations.<br>" +
- "Don't forget to add <code>lombok.jar</code> to your projects, and restart your IDE!" + installSpecific.toString() + "</html>",
- "Install successful",
- JOptionPane.INFORMATION_MESSAGE);
- appWindow.setVisible(false);
- synchronized (exitMarker) {
- exitMarker.set(0);
- exitMarker.notifyAll();
- }
+ showSuccess(installSpecific.toString());
}
});
} catch (Exception e) {
@@ -710,6 +798,8 @@ public class InstallerGUI {
appWindowContainer.add(howIWorkArea, constraints);
+ appWindowContainer.add(successArea, constraints);
+
constraints.gridy++;
constraints.gridwidth = 2;
constraints.gridx = 0;
@@ -718,9 +808,33 @@ public class InstallerGUI {
constraints.ipadx = 0;
constraints.ipady = 0;
constraints.fill = GridBagConstraints.HORIZONTAL;
- constraints.anchor = GridBagConstraints.SOUTHEAST;
+ constraints.anchor = GridBagConstraints.SOUTHWEST;
constraints.insets = new Insets(0, 16, 8, 8);
+
+ appWindow.add(buildButtonBar(), constraints);
+ }
+
+ private Box buildButtonBar() {
Box buttonBar = Box.createHorizontalBox();
+
+ JHyperLink aboutLink = new JHyperLink(Installer.ABOUT_LOMBOK_URL.toString());
+ aboutLink.addActionListener(openBrowser(aboutLink, Installer.ABOUT_LOMBOK_URL));
+ buttonBar.add(aboutLink);
+
+ buttonBar.add(Box.createRigidArea(new Dimension(16, 1)));
+
+ JLabel versionLabel = new JLabel();
+ versionLabel.setText("v" + Version.getVersion());
+
+ buttonBar.add(versionLabel);
+ buttonBar.add(Box.createRigidArea(new Dimension(16, 1)));
+
+ JHyperLink changelogLink = new JHyperLink("View full changelog");
+ changelogLink.addActionListener(openBrowser(changelogLink, Installer.ABOUT_LOMBOK_URL.resolve("/changelog.html")));
+ buttonBar.add(changelogLink);
+
+ buttonBar.add(Box.createHorizontalGlue());
+
JButton quitButton = new JButton("Quit Installer");
quitButton.addActionListener(new ActionListener() {
@Override public void actionPerformed(ActionEvent e) {
@@ -728,51 +842,48 @@ public class InstallerGUI {
System.exit(0);
}
});
- final JHyperLink hyperlink = new JHyperLink(Installer.ABOUT_LOMBOK_URL.toString());
- hyperlink.addActionListener(new ActionListener() {
+ buttonBar.add(quitButton);
+ return buttonBar;
+ }
+
+ private ActionListener openBrowser(final JHyperLink hyperlink, final URI location) {
+ return new ActionListener() {
@Override public void actionPerformed(ActionEvent event) {
hyperlink.setForeground(new Color(85, 145, 90));
try {
//java.awt.Desktop doesn't exist in 1.5.
Object desktop = Class.forName("java.awt.Desktop").getMethod("getDesktop").invoke(null);
- Class.forName("java.awt.Desktop").getMethod("browse", URI.class).invoke(desktop, Installer.ABOUT_LOMBOK_URL);
+ Class.forName("java.awt.Desktop").getMethod("browse", URI.class).invoke(desktop, location);
} catch (Exception e) {
Runtime rt = Runtime.getRuntime();
try {
- switch (IdeFinder.getOS()) {
+ switch (OsUtils.getOS()) {
case WINDOWS:
String[] cmd = new String[4];
cmd[0] = "cmd.exe";
cmd[1] = "/C";
cmd[2] = "start";
- cmd[3] = Installer.ABOUT_LOMBOK_URL.toString();
+ cmd[3] = location.toString();
rt.exec(cmd);
break;
case MAC_OS_X:
- rt.exec("open " + Installer.ABOUT_LOMBOK_URL.toString());
+ rt.exec("open " + location.toString());
break;
default:
case UNIX:
- rt.exec("firefox " + Installer.ABOUT_LOMBOK_URL.toString());
+ rt.exec("firefox " + location.toString());
break;
}
} catch (Exception e2) {
JOptionPane.showMessageDialog(appWindow,
"Well, this is embarrassing. I don't know how to open a webbrowser.\n" +
- "I guess you'll have to open it. Browse to:\n" + Installer.ABOUT_LOMBOK_URL +
+ "I guess you'll have to open it. Browse to:\n" + location +
" for more information about Lombok.",
"I'm embarrassed", JOptionPane.INFORMATION_MESSAGE);
}
}
}
- });
- buttonBar.add(hyperlink);
- buttonBar.add(Box.createRigidArea(new Dimension(16, 1)));
- buttonBar.add(new JLabel("<html><font size=\"-1\">v" + Version.getVersion() + "</font></html>"));
-
- buttonBar.add(Box.createHorizontalGlue());
- buttonBar.add(quitButton);
- appWindow.add(buttonBar, constraints);
+ };
}
/**
@@ -780,7 +891,7 @@ public class InstallerGUI {
*/
public void show() {
appWindow.setVisible(true);
- if (IdeFinder.getOS() == OS.MAC_OS_X) {
+ if (OsUtils.getOS() == OS.MAC_OS_X) {
try {
AppleNativeLook.go();
} catch (Throwable ignore) {
@@ -790,7 +901,7 @@ public class InstallerGUI {
}
private static final String IDE_TITLE =
- "<html><font size=\"+1\"><b><i>IDEs</i></b></font></html>";
+ "<html><font size=\"+1\"><b><i>IDEs </i></b></font></html>";
private static final String IDE_EXPLANATION =
"<html>Lombok can update your Eclipse or eclipse-based IDE to fully support all Lombok features.<br>" +
@@ -800,7 +911,7 @@ public class InstallerGUI {
"Scanning your drives for IDE installations...";
private static final String JAVAC_TITLE =
- "<html><font size=\"+1\"><b><i>Javac</i></b></font> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (and tools that invoke javac such as <i>ant</i> and <i>maven</i>)</html>";
+ "<html><font size=\"+1\"><b><i>Javac </i></b></font> &nbsp;&nbsp;&nbsp;&nbsp;&nbsp; (and tools that invoke javac such as <i>ant</i> and <i>maven</i>)</html>";
private static final String JAVAC_EXPLANATION =
"<html>Lombok works 'out of the box' with javac.<br>Just make sure the lombok.jar is in your classpath when you compile.";
@@ -809,23 +920,27 @@ public class InstallerGUI {
"<html>Example: <code>javac -cp lombok.jar MyCode.java</code></html>";
private static final String UNINSTALL_TITLE =
- "<html><font size=\"+1\"><b><i>Uninstall</i></b></font></html>";
+ "<html><font size=\"+1\"><b><i>Uninstall </i></b></font></html>";
private static final String UNINSTALL_EXPLANATION =
"<html>Uninstall Lombok from the following IDE Installations?</html>";
private static final String HOW_I_WORK_TITLE =
- "<html><font size=\"+1\"><b><i>What this installer does</i></b></font></html>";
+ "<html><font size=\"+1\"><b><i>What this installer does </i></b></font></html>";
private static final String HOW_I_WORK_EXPLANATION =
"<html><h2>Eclipse</h2><ol>" +
"<li>First, I copy myself (lombok.jar) to your Eclipse install directory.</li>" +
- "<li>Then, I edit the <i>eclipse.ini</i> file to add the following two entries:<br>" +
- "<pre>-Xbootclasspath/a:lombok.jar<br>" +
- "-javaagent:lombok.jar</pre></li></ol>" +
+ "<li>Then, I edit the <i>eclipse.ini</i> file to add the following entry:<br>" +
+ "<pre>-javaagent:lombok.jar</pre></li></ol>" +
"On Mac OS X, eclipse.ini is hidden in<br>" +
"<code>Eclipse.app/Contents/MacOS</code> so that's where I place the jar files.</html>";
+ private static final String SUCCESS_TITLE = "<html><font size=\"+1\"><b><i>Install successful </i></b></font></html>";
+ private static final String SUCCESS_EXPLANATION = "<html>Lombok has been installed on the selected IDE installations.<br>" +
+ "Don't forget to:<ul><li> add <code>lombok.jar</code> to your projects,<li><b>exit and start</b> your IDE,<li><b>rebuild</b> all projects!</ul>%%%</html>";
+
+
private static class JHyperLink extends JButton {
private static final long serialVersionUID = 1L;
diff --git a/src/installer/lombok/installer/IdeFinder.java b/src/installer/lombok/installer/OsUtils.java
index f68a0e4c..2da7de09 100644
--- a/src/installer/lombok/installer/IdeFinder.java
+++ b/src/installer/lombok/installer/OsUtils.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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
@@ -34,9 +34,13 @@ import lombok.core.Version;
/**
* Implement and provide this class to add auto-finding a certain brand of IDEs to the lombok installer.
*/
-public abstract class IdeFinder {
+public final class OsUtils {
private static final AtomicBoolean windowsDriveInfoLibLoaded = new AtomicBoolean(false);
+ private OsUtils() {
+ // Prevent instantiation
+ }
+
private static void loadWindowsDriveInfoLib() throws IOException {
if (!windowsDriveInfoLibLoaded.compareAndSet(false, true)) return;
@@ -63,7 +67,7 @@ public abstract class IdeFinder {
}
private static boolean unpackDLL(String dllName, File target) throws IOException {
- InputStream in = IdeFinder.class.getResourceAsStream(dllName);
+ InputStream in = OsUtils.class.getResourceAsStream(dllName);
try {
try {
FileOutputStream out = new FileOutputStream(target);
@@ -130,15 +134,4 @@ public abstract class IdeFinder {
return OS.UNIX;
}
-
- /**
- * Look for installations of your IDE in the usual places.
- *
- * @param locations Add to this list any valid locations that you found.
- * @param problems
- * Add to this list any locations that look like installations,
- * but have problems that prevent you from installing/uninstalling from them. DONT add to this list
- * any common locations that have no installation at all - only add near misses.
- */
- public abstract void findIdes(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems);
}
diff --git a/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java b/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java
index 914de588..fa2ce958 100644
--- a/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java
+++ b/src/installer/lombok/installer/eclipse/EclipseLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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,140 +21,24 @@
*/
package lombok.installer.eclipse;
-import static lombok.installer.IdeLocation.canonical;
+import java.util.Collections;
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
-
-import lombok.installer.IdeLocation;
import lombok.installer.IdeLocationProvider;
-import lombok.installer.CorruptedIdeLocationException;
-import lombok.installer.IdeFinder.OS;
import org.mangosdk.spi.ProviderFor;
@ProviderFor(IdeLocationProvider.class)
-public class EclipseLocationProvider implements IdeLocationProvider {
- @Override public IdeLocation create(String path) throws CorruptedIdeLocationException {
- return create0(path);
- }
-
- protected List<String> getEclipseExecutableNames() {
- return Arrays.asList("eclipse.app", "eclipse.exe", "eclipse");
- }
-
- protected String getIniName() {
- return "eclipse.ini";
- }
-
- protected IdeLocation makeLocation(String name, File ini) throws CorruptedIdeLocationException {
- return new EclipseLocation(name, ini);
- }
-
- protected String getMacAppName() {
- return "Eclipse.app";
- }
-
- protected String getUnixAppName() {
- return "eclipse";
- }
-
- /**
- * Create a new EclipseLocation by pointing at either the directory contains the Eclipse executable, or the executable itself,
- * or an eclipse.ini file.
- *
- * @throws NotAnIdeLocationException
- * If this isn't an Eclipse executable or a directory with an
- * Eclipse executable.
- */
- protected IdeLocation create0(String path) throws CorruptedIdeLocationException {
- if (path == null) throw new NullPointerException("path");
- File p = new File(path);
-
- if (!p.exists()) return null;
- if (p.isDirectory()) {
- for (String possibleExeName : getEclipseExecutableNames()) {
- File f = new File(p, possibleExeName);
- if (f.exists()) return findEclipseIniFromExe(f, 0);
- }
-
- File f = new File(p, getIniName());
- if (f.exists()) return new EclipseLocation(canonical(p), f);
- }
-
- if (p.isFile()) {
- if (p.getName().equalsIgnoreCase(getIniName())) {
- return new EclipseLocation(canonical(p.getParentFile()), p);
- }
- }
-
- if (getEclipseExecutableNames().contains(p.getName().toLowerCase())) {
- return findEclipseIniFromExe(p, 0);
- }
-
- return null;
- }
-
- private IdeLocation findEclipseIniFromExe(File exePath, int loopCounter) throws CorruptedIdeLocationException {
- /* Try looking for eclipse.ini as sibling to the executable */ {
- File ini = new File(exePath.getParentFile(), getIniName());
- if (ini.isFile()) return makeLocation(canonical(exePath), ini);
- }
-
- /* Try looking for Eclipse/app/Contents/MacOS/eclipse.ini as sibling to executable; this works on Mac OS X. */ {
- File ini = new File(exePath.getParentFile(), getMacAppName() + "/Contents/MacOS/" + getIniName());
- if (ini.isFile()) return makeLocation(canonical(exePath), ini);
- }
-
- /* If executable is a soft link, follow it and retry. */ {
- if (loopCounter < 50) {
- try {
- String oPath = exePath.getAbsolutePath();
- String nPath = exePath.getCanonicalPath();
- if (!oPath.equals(nPath)) try {
- IdeLocation loc = findEclipseIniFromExe(new File(nPath), loopCounter + 1);
- if (loc != null) return loc;
- } catch (CorruptedIdeLocationException ignore) {
- // Unlinking didn't help find an eclipse, so continue.
- }
- } catch (IOException ignore) { /* okay, that didn't work, assume it isn't a soft link then. */ }
- }
- }
-
- /* If executable is a linux LSB-style path, then look in the usual places that package managers like apt-get use.*/ {
- String path = exePath.getAbsolutePath();
- try {
- path = exePath.getCanonicalPath();
- } catch (IOException ignore) { /* We'll stick with getAbsolutePath()'s result then. */ }
-
- if (path.equals("/usr/bin/" + getUnixAppName()) || path.equals("/bin/" + getUnixAppName()) || path.equals("/usr/local/bin/" + getUnixAppName())) {
- File ini = new File("/usr/lib/" + getUnixAppName() + "/" + getIniName());
- if (ini.isFile()) return makeLocation(path, ini);
- ini = new File("/usr/local/lib/" + getUnixAppName() + "/" + getIniName());
- if (ini.isFile()) return makeLocation(path, ini);
- ini = new File("/usr/local/etc/" + getUnixAppName() + "/" + getIniName());
- if (ini.isFile()) return makeLocation(path, ini);
- ini = new File("/etc/" + getIniName());
- if (ini.isFile()) return makeLocation(path, ini);
- }
- }
-
- /* If we get this far, we lose. */
- return null;
- }
-
- @Override public Pattern getLocationSelectors(OS os) {
- switch (os) {
- case MAC_OS_X:
- return Pattern.compile("^(eclipse|eclipse\\.ini|eclipse\\.app)$", Pattern.CASE_INSENSITIVE);
- case WINDOWS:
- return Pattern.compile("^(eclipse\\.exe|eclipse\\.ini)$", Pattern.CASE_INSENSITIVE);
- default:
- case UNIX:
- return Pattern.compile("^(eclipse|eclipse\\.ini)$", Pattern.CASE_INSENSITIVE);
- }
+public class EclipseLocationProvider extends EclipseProductLocationProvider {
+
+ private static final EclipseProductDescriptor ECLIPSE = new StandardProductDescriptor(
+ "Eclipse",
+ "eclipse",
+ "eclipse",
+ EclipseLocationProvider.class.getResource("eclipse.png"),
+ Collections.<String>emptySet()
+ );
+
+ public EclipseLocationProvider() {
+ super(ECLIPSE);
}
}
diff --git a/src/installer/lombok/installer/eclipse/STSLocation.java b/src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java
index 40ade40a..8f736a57 100644
--- a/src/installer/lombok/installer/eclipse/STSLocation.java
+++ b/src/installer/lombok/installer/eclipse/EclipseProductDescriptor.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2016 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,25 +21,21 @@
*/
package lombok.installer.eclipse;
-import java.io.File;
import java.net.URL;
+import java.util.List;
+import java.util.regex.Pattern;
-import lombok.installer.CorruptedIdeLocationException;
-
-public class STSLocation extends EclipseLocation {
- public STSLocation(String nameOfLocation, File pathToEclipseIni) throws CorruptedIdeLocationException {
- super(nameOfLocation, pathToEclipseIni);
- }
-
- @Override public URL getIdeIcon() {
- return STSLocation.class.getResource("STS.png");
- }
-
- @Override protected String getIniFileName() {
- return "STS.ini";
- }
-
- @Override protected String getTypeName() {
- return "STS";
- }
-}
+public interface EclipseProductDescriptor {
+ String getProductName();
+ String getWindowsExecutableName();
+ String getUnixAppName();
+ String getMacAppName();
+ String getDirectoryName();
+ List<String> getExecutableNames();
+ List<String> getSourceDirsOnWindows();
+ List<String> getSourceDirsOnMac();
+ List<String> getSourceDirsOnUnix();
+ String getIniFileName();
+ Pattern getLocationSelectors();
+ URL getIdeIcon();
+} \ No newline at end of file
diff --git a/src/installer/lombok/installer/eclipse/EclipseLocation.java b/src/installer/lombok/installer/eclipse/EclipseProductLocation.java
index e347cd98..aa97a3e5 100644
--- a/src/installer/lombok/installer/eclipse/EclipseLocation.java
+++ b/src/installer/lombok/installer/eclipse/EclipseProductLocation.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-2017 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,7 +35,7 @@ import java.util.regex.Matcher;
import java.util.regex.Pattern;
import lombok.installer.CorruptedIdeLocationException;
-import lombok.installer.IdeFinder;
+import lombok.installer.OsUtils;
import lombok.installer.IdeLocation;
import lombok.installer.InstallException;
import lombok.installer.Installer;
@@ -46,30 +46,35 @@ import lombok.installer.UninstallException;
* An instance can figure out if an Eclipse installation has been lombok-ified, and can
* install and uninstall lombok from the Eclipse installation.
*/
-public class EclipseLocation extends IdeLocation {
- private final String name;
- private final File eclipseIniPath;
- private volatile boolean hasLombok;
-
- private static final String OS_NEWLINE = IdeFinder.getOS().getLineEnding();
+public final class EclipseProductLocation extends IdeLocation {
- protected String getTypeName() {
- return "eclipse";
- }
+ private static final String OS_NEWLINE = OsUtils.getOS().getLineEnding();
- protected String getIniFileName() {
- return "eclipse.ini";
- }
+ private final EclipseProductDescriptor descriptor;
+ private final String name;
+ private final File eclipseIniPath;
+ private final String pathToLombokJarPrefix;
+ private final boolean hasLombok;
- EclipseLocation(String nameOfLocation, File pathToEclipseIni) throws CorruptedIdeLocationException {
+ EclipseProductLocation(EclipseProductDescriptor descriptor, String nameOfLocation, File pathToEclipseIni) throws CorruptedIdeLocationException {
+ this.descriptor = descriptor;
this.name = nameOfLocation;
this.eclipseIniPath = pathToEclipseIni;
+ File p1 = pathToEclipseIni.getParentFile();
+ File p2 = p1 == null ? null : p1.getParentFile();
+ File p3 = p2 == null ? null : p2.getParentFile();
+ if (p1 != null && p1.getName().equals("Eclipse") && p2 != null && p2.getName().equals("Contents") && p3 != null && p3.getName().endsWith(".app")) {
+ this.pathToLombokJarPrefix = "../Eclipse/";
+ } else {
+ this.pathToLombokJarPrefix = "";
+ }
+
try {
this.hasLombok = checkForLombok(eclipseIniPath);
} catch (IOException e) {
throw new CorruptedIdeLocationException(
- "I can't read the configuration file of the " + getTypeName() + " installed at " + name + "\n" +
- "You may need to run this installer with root privileges if you want to modify that " + getTypeName() + ".", getTypeName(), e);
+ "I can't read the configuration file of the " + descriptor.getProductName() + " installed at " + name + "\n" +
+ "You may need to run this installer with root privileges if you want to modify that " + descriptor.getProductName() + ".", descriptor.getProductName(), e);
}
}
@@ -78,8 +83,8 @@ public class EclipseLocation extends IdeLocation {
}
@Override public boolean equals(Object o) {
- if (!(o instanceof EclipseLocation)) return false;
- return ((EclipseLocation)o).eclipseIniPath.equals(eclipseIniPath);
+ if (!(o instanceof EclipseProductLocation)) return false;
+ return ((EclipseProductLocation)o).eclipseIniPath.equals(eclipseIniPath);
}
/**
@@ -98,13 +103,13 @@ public class EclipseLocation extends IdeLocation {
return hasLombok;
}
- private final Pattern JAVA_AGENT_LINE_MATCHER = Pattern.compile(
+ private static final Pattern JAVA_AGENT_LINE_MATCHER = Pattern.compile(
"^\\-javaagent\\:.*lombok.*\\.jar$", Pattern.CASE_INSENSITIVE);
- private final Pattern BOOTCLASSPATH_LINE_MATCHER = Pattern.compile(
+ private static final Pattern BOOTCLASSPATH_LINE_MATCHER = Pattern.compile(
"^\\-Xbootclasspath\\/a\\:(.*lombok.*\\.jar.*)$", Pattern.CASE_INSENSITIVE);
- private boolean checkForLombok(File iniFile) throws IOException {
+ private static boolean checkForLombok(File iniFile) throws IOException {
if (!iniFile.exists()) return false;
FileInputStream fis = new FileInputStream(iniFile);
try {
@@ -196,7 +201,7 @@ public class EclipseLocation extends IdeLocation {
File lombokJar = new File(dir, "lombok.jar");
if (lombokJar.exists()) {
if (!lombokJar.delete()) {
- if (IdeFinder.getOS() == IdeFinder.OS.WINDOWS && Installer.isSelf(lombokJar.getAbsolutePath())) {
+ if (OsUtils.getOS() == OsUtils.OS.WINDOWS && Installer.isSelf(lombokJar.getAbsolutePath())) {
lombokJarsForWhichCantDeleteSelf.add(lombokJar);
} else {
throw new UninstallException(
@@ -218,14 +223,14 @@ public class EclipseLocation extends IdeLocation {
throw new UninstallException(true, String.format(
"lombok.jar cannot delete itself on windows.\nHowever, lombok has been uncoupled from your %s.\n" +
"You can safely delete this jar file. You can find it at:\n%s",
- getTypeName(), lombokJarsForWhichCantDeleteSelf.get(0).getAbsolutePath()), null);
+ descriptor.getProductName(), lombokJarsForWhichCantDeleteSelf.get(0).getAbsolutePath()), null);
}
}
private static String generateWriteErrorMessage() {
String osSpecificError;
- switch (IdeFinder.getOS()) {
+ switch (OsUtils.getOS()) {
default:
case MAC_OS_X:
case UNIX:
@@ -251,11 +256,11 @@ public class EclipseLocation extends IdeLocation {
*/
@Override
public String install() throws InstallException {
- // For whatever reason, relative paths in your eclipse.ini file don't work on linux, but only for -javaagent.
- // If someone knows how to fix this, please do so, as this current hack solution (putting the absolute path
- // to the jar files in your eclipse.ini) means you can't move your eclipse around on linux without lombok
- // breaking it. NB: rerunning lombok.jar installer and hitting 'update' will fix it if you do that.
- boolean fullPathRequired = IdeFinder.getOS() == EclipseFinder.OS.UNIX || System.getProperty("lombok.installer.fullpath") != null;
+ // On Linux, for whatever reason, relative paths in your eclipse.ini file don't work, but only for -javaagent.
+ // On Windows, since the Oomph, the generated shortcut starts in the wrong directory.
+ // So the default is to use absolute paths, breaking lombok when you move the eclipse directory.
+ // Or not break when you copy your directory, but break later when you remove the original one.
+ boolean fullPathRequired = !"false".equals(System.getProperty("lombok.installer.fullpath", "true"));
boolean installSucceeded = false;
StringBuilder newContents = new StringBuilder();
@@ -293,7 +298,7 @@ public class EclipseLocation extends IdeLocation {
"I can't read my own jar file. I think you've found a bug in this installer!\nI suggest you restart it " +
"and use the 'what do I do' link, to manually install lombok. Also, tell us about this at:\n" +
"http://groups.google.com/group/project-lombok - Thanks!", e);
- throw new InstallException("I can't write to your " + getTypeName() + " directory at " + name + generateWriteErrorMessage(), e);
+ throw new InstallException("I can't write to your " + descriptor.getProductName() + " directory at " + name + generateWriteErrorMessage(), e);
}
}
@@ -333,12 +338,15 @@ public class EclipseLocation extends IdeLocation {
fis.close();
}
- String fullPathToLombok = fullPathRequired ? (lombokJar.getParentFile().getCanonicalPath() + File.separator) : "";
+ String pathPrefix;
+ if (fullPathRequired) {
+ pathPrefix = lombokJar.getParentFile().getCanonicalPath() + File.separator;
+ } else {
+ pathPrefix = pathToLombokJarPrefix;
+ }
newContents.append(String.format(
- "-javaagent:%s", escapePath(fullPathToLombok + "lombok.jar"))).append(OS_NEWLINE);
- newContents.append(String.format(
- "-Xbootclasspath/a:%s", escapePath(fullPathToLombok + "lombok.jar"))).append(OS_NEWLINE);
+ "-javaagent:%s", escapePath(pathPrefix + "lombok.jar"))).append(OS_NEWLINE);
FileOutputStream fos = new FileOutputStream(eclipseIniPath);
try {
@@ -356,15 +364,14 @@ public class EclipseLocation extends IdeLocation {
}
if (!installSucceeded) {
- throw new InstallException("I can't find the " + getIniFileName() + " file. Is this a real " + getTypeName() + " installation?", null);
+ throw new InstallException("I can't find the " + descriptor.getIniFileName() + " file. Is this a real " + descriptor.getProductName() + " installation?", null);
}
- return "If you start " + getTypeName() + " with a custom -vm parameter, you'll need to add:<br>" +
- "<code>-vmargs -Xbootclasspath/a:lombok.jar -javaagent:lombok.jar</code><br>" +
- "as parameter as well.";
+ return "If you start " + descriptor.getProductName() + " with a custom -vm parameter, you'll need to add:<br>" +
+ "<code>-vmargs -javaagent:lombok.jar</code><br>as parameter as well.";
}
@Override public URL getIdeIcon() {
- return EclipseLocation.class.getResource("eclipse.png");
+ return descriptor.getIdeIcon();
}
}
diff --git a/src/installer/lombok/installer/eclipse/EclipseFinder.java b/src/installer/lombok/installer/eclipse/EclipseProductLocationProvider.java
index 8a1a689a..b807f02b 100644
--- a/src/installer/lombok/installer/eclipse/EclipseFinder.java
+++ b/src/installer/lombok/installer/eclipse/EclipseProductLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2011 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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
@@ -22,109 +22,130 @@
package lombok.installer.eclipse;
import static java.util.Arrays.asList;
+import static lombok.installer.IdeLocation.canonical;
import java.io.File;
+import java.io.IOException;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collections;
import java.util.List;
+import java.util.regex.Pattern;
-import lombok.installer.IdeFinder;
-import lombok.installer.IdeLocation;
import lombok.installer.CorruptedIdeLocationException;
+import lombok.installer.OsUtils;
+import lombok.installer.IdeLocation;
+import lombok.installer.IdeLocationProvider;
-import org.mangosdk.spi.ProviderFor;
+public class EclipseProductLocationProvider implements IdeLocationProvider {
+ private final EclipseProductDescriptor descriptor;
-@ProviderFor(IdeFinder.class)
-public class EclipseFinder extends IdeFinder {
- /** should be lowercase! */
- protected String getDirName() {
- return "eclipse";
- }
-
- protected String getWindowsExecutableName() {
- return "eclipse.exe";
- }
-
- protected String getUnixExecutableName() {
- return "eclipse";
- }
-
- protected String getMacExecutableName() {
- return "Eclipse.app";
+ EclipseProductLocationProvider(EclipseProductDescriptor descriptor) {
+ this.descriptor = descriptor;
}
- protected IdeLocation createLocation(String guess) throws CorruptedIdeLocationException {
- return new EclipseLocationProvider().create0(guess);
- }
-
- protected List<String> getSourceDirsOnWindows() {
- return Arrays.asList("\\", "\\Program Files", "\\Program Files (x86)", System.getProperty("user.home", "."));
+ @Override public final IdeLocation create(String path) throws CorruptedIdeLocationException {
+ return create0(path);
}
/**
- * Returns a list of paths of Eclipse installations.
+ * Create a new EclipseLocation by pointing at either the directory contains the Eclipse executable, or the executable itself,
+ * or an eclipse.ini file.
*
- * 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.
+ * @throws NotAnIdeLocationException
+ * If this isn't an Eclipse executable or a directory with an
+ * Eclipse executable.
*/
- private List<String> getSourceDirsOnWindowsWithDriveLetters() {
- List<String> driveLetters = asList("C");
- try {
- driveLetters = getDrivesOnWindows();
- } catch (Throwable ignore) {
- ignore.printStackTrace();
+ private IdeLocation create0(String path) throws CorruptedIdeLocationException {
+ if (path == null) throw new NullPointerException("path");
+ String iniName = descriptor.getIniFileName();
+ File p = new File(path);
+
+ if (!p.exists()) return null;
+ if (p.isDirectory()) {
+ for (String possibleExeName : descriptor.getExecutableNames()) {
+ File f = new File(p, possibleExeName);
+ if (f.exists()) return findEclipseIniFromExe(f, 0);
+ }
+
+ File f = new File(p, iniName);
+ if (f.exists()) return makeLocation(canonical(p), f);
}
- List<String> sourceDirs = new ArrayList<String>();
- for (String letter : driveLetters) {
- for (String possibleSource : getSourceDirsOnWindows()) {
- if (!isDriveSpecificOnWindows(possibleSource)) {
- sourceDirs.add(letter + ":" + possibleSource);
- }
+
+ if (p.isFile()) {
+ if (p.getName().equalsIgnoreCase(iniName)) {
+ return makeLocation(canonical(p.getParentFile()), p);
}
}
- for (String possibleSource : getSourceDirsOnWindows()) {
- if (isDriveSpecificOnWindows(possibleSource)) sourceDirs.add(possibleSource);
+
+ if (descriptor.getExecutableNames().contains(p.getName().toLowerCase())) {
+ return findEclipseIniFromExe(p, 0);
}
- return sourceDirs;
+ return null;
}
- public boolean isDriveSpecificOnWindows(String path) {
- return path.length() > 1 && path.charAt(1) == ':';
- }
-
- protected List<String> getSourceDirsOnMac() {
- return Arrays.asList("/Applications", System.getProperty("user.home", "."));
- }
-
- protected List<String> getSourceDirsOnUnix() {
- return Arrays.asList(System.getProperty("user.home", "."));
- }
-
- private List<File> transformToFiles(List<String> fileNames) {
- List<File> files = new ArrayList<File>();
- for (String fileName : fileNames) {
- files.add(new File(fileName));
+ private IdeLocation findEclipseIniFromExe(File exePath, int loopCounter) throws CorruptedIdeLocationException {
+ String iniName = descriptor.getIniFileName();
+ /* Try looking for eclipse.ini as sibling to the executable */ {
+ File ini = new File(exePath.getParentFile(), iniName);
+ if (ini.isFile()) return makeLocation(canonical(exePath), ini);
}
- return files;
+
+ String macAppName = descriptor.getMacAppName();
+ /* Try looking for Eclipse.app/Contents/MacOS/eclipse.ini as sibling to executable; this works on Mac OS X. */ {
+ File ini = new File(exePath.getParentFile(), macAppName + "/Contents/MacOS/" + iniName);
+ if (ini.isFile()) return makeLocation(canonical(exePath), ini);
+ }
+
+ /* Starting with Eclipse Mars (with the oomph installer), the structure has changed, and it's now at Eclipse.app/Contents/Eclipse/eclipse.ini*/ {
+ File ini = new File(exePath.getParentFile(), macAppName + "/Contents/Eclipse/" + iniName);
+ if (ini.isFile()) return makeLocation(canonical(exePath), ini);
+ }
+
+ /* If executable is a soft link, follow it and retry. */ {
+ if (loopCounter < 50) {
+ try {
+ String oPath = exePath.getAbsolutePath();
+ String nPath = exePath.getCanonicalPath();
+ if (!oPath.equals(nPath)) try {
+ IdeLocation loc = findEclipseIniFromExe(new File(nPath), loopCounter + 1);
+ if (loc != null) return loc;
+ } catch (CorruptedIdeLocationException ignore) {
+ // Unlinking didn't help find an eclipse, so continue.
+ }
+ } catch (IOException ignore) { /* okay, that didn't work, assume it isn't a soft link then. */ }
+ }
+ }
+
+ /* If executable is a linux LSB-style path, then look in the usual places that package managers like apt-get use.*/ {
+ String path = exePath.getAbsolutePath();
+ try {
+ path = exePath.getCanonicalPath();
+ } catch (IOException ignore) { /* We'll stick with getAbsolutePath()'s result then. */ }
+
+ String unixAppName = descriptor.getUnixAppName();
+ if (path.equals("/usr/bin/" + unixAppName) || path.equals("/bin/" + unixAppName) || path.equals("/usr/local/bin/" + unixAppName)) {
+ File ini = new File("/usr/lib/" + unixAppName + "/" + iniName);
+ if (ini.isFile()) return makeLocation(path, ini);
+ ini = new File("/usr/local/lib/" + unixAppName + "/" + iniName);
+ if (ini.isFile()) return makeLocation(path, ini);
+ ini = new File("/usr/local/etc/" + unixAppName + "/" + iniName);
+ if (ini.isFile()) return makeLocation(path, ini);
+ ini = new File("/etc/" + iniName);
+ if (ini.isFile()) return makeLocation(path, ini);
+ }
+ }
+
+ /* If we get this far, we lose. */
+ return null;
}
- private List<File> getFlatSourceLocationsOnUnix() {
- List<File> dirs = new ArrayList<File>();
- dirs.add(new File("/usr/bin/"));
- dirs.add(new File("/usr/local/bin/"));
- dirs.add(new File(System.getProperty("user.home", "."), "bin/"));
- return dirs;
+ private IdeLocation makeLocation(String name, File ini) throws CorruptedIdeLocationException {
+ return new EclipseProductLocation(descriptor, name, ini);
}
- private List<File> getNestedSourceLocationOnUnix() {
- List<File> dirs = new ArrayList<File>();
- dirs.add(new File("/usr/local/share"));
- dirs.add(new File("/usr/local"));
- dirs.add(new File("/usr/share"));
- return dirs;
+ @Override public Pattern getLocationSelectors() {
+ return descriptor.getLocationSelectors();
}
/**
@@ -141,7 +162,7 @@ public class EclipseFinder extends IdeFinder {
*/
@Override
public void findIdes(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) {
- switch (getOS()) {
+ switch (OsUtils.getOS()) {
case WINDOWS:
new WindowsFinder().findEclipse(locations, problems);
break;
@@ -155,17 +176,74 @@ public class EclipseFinder extends IdeFinder {
}
}
+ private List<File> transformToFiles(List<String> fileNames) {
+ List<File> files = new ArrayList<File>();
+ for (String fileName : fileNames) {
+ files.add(new File(fileName));
+ }
+ return files;
+ }
+
+ private List<File> getFlatSourceLocationsOnUnix() {
+ List<File> dirs = new ArrayList<File>();
+ dirs.add(new File("/usr/bin/"));
+ dirs.add(new File("/usr/local/bin/"));
+ dirs.add(new File(System.getProperty("user.home", "."), "bin/"));
+ return dirs;
+ }
+
+ private List<File> getNestedSourceLocationOnUnix() {
+ List<File> dirs = new ArrayList<File>();
+ dirs.add(new File("/usr/local/share"));
+ dirs.add(new File("/usr/local"));
+ dirs.add(new File("/usr/share"));
+ return dirs;
+ }
+
private class UnixFinder extends DirectoryFinder {
UnixFinder() {
super(getNestedSourceLocationOnUnix(), getFlatSourceLocationsOnUnix());
}
@Override protected String findEclipseOnPlatform(File dir) {
- File possible = new File(dir, getUnixExecutableName());
+ File possible = new File(dir, descriptor.getUnixAppName());
return (possible.exists()) ? possible.getAbsolutePath() : null;
}
}
+ /**
+ * Returns a list of paths of Eclipse installations.
+ *
+ * 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<String> getSourceDirsOnWindowsWithDriveLetters() {
+ List<String> driveLetters = asList("C");
+ try {
+ driveLetters = OsUtils.getDrivesOnWindows();
+ } catch (Throwable ignore) {
+ ignore.printStackTrace();
+ }
+ List<String> sourceDirs = new ArrayList<String>();
+ for (String letter : driveLetters) {
+ for (String possibleSource : descriptor.getSourceDirsOnWindows()) {
+ if (!isDriveSpecificOnWindows(possibleSource)) {
+ sourceDirs.add(letter + ":" + possibleSource);
+ }
+ }
+ }
+ for (String possibleSource : descriptor.getSourceDirsOnWindows()) {
+ if (isDriveSpecificOnWindows(possibleSource)) sourceDirs.add(possibleSource);
+ }
+
+ return sourceDirs;
+ }
+
+ private boolean isDriveSpecificOnWindows(String path) {
+ return path.length() > 1 && path.charAt(1) == ':';
+ }
+
private class WindowsFinder extends DirectoryFinder {
WindowsFinder() {
super(transformToFiles(getSourceDirsOnWindowsWithDriveLetters()), Collections.<File>emptyList());
@@ -174,20 +252,20 @@ public class EclipseFinder extends IdeFinder {
/** Checks if the provided directory contains 'eclipse.exe', and if so, returns the directory, otherwise null. */
@Override
protected String findEclipseOnPlatform(File dir) {
- File possible = new File(dir, getWindowsExecutableName());
+ File possible = new File(dir, descriptor.getWindowsExecutableName());
return (possible.isFile()) ? dir.getAbsolutePath() : null;
}
}
private class MacFinder extends DirectoryFinder {
MacFinder() {
- super(transformToFiles(getSourceDirsOnMac()), Collections.<File>emptyList());
+ super(transformToFiles(descriptor.getSourceDirsOnMac()), Collections.<File>emptyList());
}
protected String findEclipseOnPlatform(File dir) {
- if (dir.getName().toLowerCase().equals(getMacExecutableName().toLowerCase())) return dir.getParent();
- if (dir.getName().toLowerCase().contains(getDirName())) {
- if (new File(dir, getMacExecutableName()).exists()) return dir.toString();
+ if (dir.getName().toLowerCase().equals(descriptor.getMacAppName().toLowerCase())) return dir.getParent();
+ if (dir.getName().toLowerCase().contains(descriptor.getDirectoryName())) {
+ if (new File(dir, descriptor.getMacAppName()).exists()) return dir.toString();
}
return null;
}
@@ -202,18 +280,18 @@ public class EclipseFinder extends IdeFinder {
this.flatSourceDirs = flatSourceDirs;
}
- public void findEclipse(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) {
+ void findEclipse(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems) {
for (File dir : nestedSourceDirs) recurseDirectory(locations, problems, dir);
for (File dir : flatSourceDirs) findEclipse(locations, problems, dir);
}
- protected abstract String findEclipseOnPlatform(File dir);
+ abstract String findEclipseOnPlatform(File dir);
- protected void recurseDirectory(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems, File dir) {
- recurseDirectory0(locations, problems, dir, 0);
+ void recurseDirectory(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems, File dir) {
+ recurseDirectory0(locations, problems, dir, 0, false);
}
- private void recurseDirectory0(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems, File f, int loopCounter) {
+ private void recurseDirectory0(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems, File f, int loopCounter, boolean nameFound) {
//Various try/catch/ignore statements are in this for loop. Weird conditions on the disk can cause exceptions,
//such as an unformatted drive causing a NullPointerException on listFiles. Best action is almost invariably to just
//continue onwards.
@@ -223,19 +301,19 @@ public class EclipseFinder extends IdeFinder {
for (File dir : listFiles) {
if (!dir.isDirectory()) continue;
try {
- if (dir.getName().toLowerCase().contains(getDirName())) {
+ if (nameFound || dir.getName().toLowerCase().contains(descriptor.getDirectoryName())) {
findEclipse(locations, problems, dir);
- if (loopCounter < 50) recurseDirectory0(locations, problems, dir, loopCounter + 1);
+ if (loopCounter < 50) recurseDirectory0(locations, problems, dir, loopCounter + 1, true);
}
} catch (Exception ignore) {}
}
}
-
+
private void findEclipse(List<IdeLocation> locations, List<CorruptedIdeLocationException> problems, File dir) {
String eclipseLocation = findEclipseOnPlatform(dir);
if (eclipseLocation != null) {
try {
- IdeLocation newLocation = createLocation(eclipseLocation);
+ IdeLocation newLocation = create(eclipseLocation);
if (newLocation != null) locations.add(newLocation);
} catch (CorruptedIdeLocationException e) {
problems.add(e);
diff --git a/src/installer/lombok/installer/eclipse/JbdsFinder.java b/src/installer/lombok/installer/eclipse/JbdsFinder.java
deleted file mode 100644
index 2dfaacba..00000000
--- a/src/installer/lombok/installer/eclipse/JbdsFinder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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<String> getSourceDirsOnWindows() {
- return Arrays.asList("\\", "\\Program Files", "\\Program Files (x86)", System.getProperty("user.home", "."));
- }
-
- @Override protected List<String> getSourceDirsOnMac() {
- return Arrays.asList("/Applications", System.getProperty("user.home", "."));
- }
-
- @Override protected List<String> getSourceDirsOnUnix() {
- return Arrays.asList(System.getProperty("user.home", "."));
- }
-}
diff --git a/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java b/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java
index e6df0e43..635f304a 100644
--- a/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java
+++ b/src/installer/lombok/installer/eclipse/JbdsLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2013-2016 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,49 +21,24 @@
*/
package lombok.installer.eclipse;
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
+import java.util.Collections;
-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<String> 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";
- }
+public class JbdsLocationProvider extends EclipseProductLocationProvider {
- @Override protected String getUnixAppName() {
- return "jbdevstudio";
- }
+ private static final EclipseProductDescriptor JBDS = new StandardProductDescriptor(
+ "JBoss Developer Studio",
+ "jbdevstudio",
+ "studio",
+ JbdsLocationProvider.class.getResource("jbds.png"),
+ Collections.<String>emptySet()
+ );
- @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);
- }
+ public JbdsLocationProvider() {
+ super(JBDS);
}
}
diff --git a/src/installer/lombok/installer/eclipse/JbdsLocation.java b/src/installer/lombok/installer/eclipse/MyEclipseLocationProvider.java
index 81fb5261..298cabd6 100644
--- a/src/installer/lombok/installer/eclipse/JbdsLocation.java
+++ b/src/installer/lombok/installer/eclipse/MyEclipseLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2013 The Project Lombok Authors.
+ * Copyright (C) 2016 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,25 +21,24 @@
*/
package lombok.installer.eclipse;
-import java.io.File;
-import java.net.URL;
+import java.util.Collections;
-import lombok.installer.CorruptedIdeLocationException;
+import lombok.installer.IdeLocationProvider;
-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");
- }
+import org.mangosdk.spi.ProviderFor;
+
+@ProviderFor(IdeLocationProvider.class)
+public class MyEclipseLocationProvider extends EclipseProductLocationProvider {
- @Override protected String getIniFileName() {
- return "jbdevstudio.ini";
- }
+ private static final EclipseProductDescriptor MY_ECLIPSE = new StandardProductDescriptor(
+ "MyEclipse",
+ "myeclipse",
+ "myeclipse",
+ MyEclipseLocationProvider.class.getResource("myeclipse.png"),
+ Collections.<String>emptySet()
+ );
- @Override protected String getTypeName() {
- return "JBoss Developer Studio";
+ public MyEclipseLocationProvider() {
+ super(MY_ECLIPSE);
}
}
diff --git a/src/installer/lombok/installer/eclipse/RhdsLocationProvider.java b/src/installer/lombok/installer/eclipse/RhdsLocationProvider.java
new file mode 100644
index 00000000..5e1d303d
--- /dev/null
+++ b/src/installer/lombok/installer/eclipse/RhdsLocationProvider.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2013-2016 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.Collections;
+
+import lombok.installer.IdeLocationProvider;
+
+import org.mangosdk.spi.ProviderFor;
+
+@ProviderFor(IdeLocationProvider.class)
+public class RhdsLocationProvider extends EclipseProductLocationProvider {
+
+ private static final EclipseProductDescriptor RHDS = new StandardProductDescriptor(
+ "Red Hat JBoss Developer Studio",
+ "devstudio",
+ "studio",
+ RhdsLocationProvider.class.getResource("rhds.png"),
+ Collections.<String>emptySet()
+ );
+
+ public RhdsLocationProvider() {
+ super(RHDS);
+ }
+}
diff --git a/src/installer/lombok/installer/eclipse/STS4LocationProvider.java b/src/installer/lombok/installer/eclipse/STS4LocationProvider.java
new file mode 100644
index 00000000..47a07bdd
--- /dev/null
+++ b/src/installer/lombok/installer/eclipse/STS4LocationProvider.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 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
+ * 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.Collections;
+
+import lombok.installer.IdeLocationProvider;
+
+import org.mangosdk.spi.ProviderFor;
+
+@ProviderFor(IdeLocationProvider.class)
+public class STS4LocationProvider extends EclipseProductLocationProvider {
+
+ private static final EclipseProductDescriptor STS4 = new StandardProductDescriptor("Spring Tools Suite 4",
+ "SpringToolSuite4",
+ "sts",
+ STS4LocationProvider.class.getResource("STS.png"),
+ Collections.unmodifiableList(Arrays.asList("springsource", "spring-tool-suite"))
+ );
+
+ public STS4LocationProvider() {
+ super(STS4);
+ }
+}
diff --git a/src/installer/lombok/installer/eclipse/STSFinder.java b/src/installer/lombok/installer/eclipse/STSFinder.java
deleted file mode 100644
index 82bc9b80..00000000
--- a/src/installer/lombok/installer/eclipse/STSFinder.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * Copyright (C) 2009 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;
-
-/**
- * STS (Springsource Tool Suite) 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 STSFinder extends EclipseFinder {
- @Override protected IdeLocation createLocation(String guess) throws CorruptedIdeLocationException {
- return new STSLocationProvider().create0(guess);
- }
-
- @Override protected String getDirName() {
- return "sts";
- }
-
- @Override protected String getMacExecutableName() {
- return "STS.app";
- }
-
- @Override protected String getUnixExecutableName() {
- return "STS";
- }
-
- @Override protected String getWindowsExecutableName() {
- return "STS.exe";
- }
-
- @Override protected List<String> getSourceDirsOnWindows() {
- 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<String> getSourceDirsOnMac() {
- return Arrays.asList("/Applications", "/Applications/springsource", System.getProperty("user.home", "."), System.getProperty("user.home", ".") + "/springsource");
- }
-
- @Override protected List<String> getSourceDirsOnUnix() {
- return Arrays.asList(System.getProperty("user.home", "."), System.getProperty("user.home", ".") + "/springsource");
- }
-}
diff --git a/src/installer/lombok/installer/eclipse/STSLocationProvider.java b/src/installer/lombok/installer/eclipse/STSLocationProvider.java
index 7d129838..d2efb956 100644
--- a/src/installer/lombok/installer/eclipse/STSLocationProvider.java
+++ b/src/installer/lombok/installer/eclipse/STSLocationProvider.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009 The Project Lombok Authors.
+ * Copyright (C) 2009-2016 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,49 +21,23 @@
*/
package lombok.installer.eclipse;
-import java.io.File;
-import java.util.Arrays;
-import java.util.List;
-import java.util.regex.Pattern;
+import java.util.Collections;
-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 STSLocationProvider extends EclipseLocationProvider {
- @Override protected List<String> getEclipseExecutableNames() {
- return Arrays.asList("sts.app", "sts.exe", "stsc.exe", "sts");
- }
-
- @Override protected String getIniName() {
- return "STS.ini";
- }
-
- @Override protected IdeLocation makeLocation(String name, File ini) throws CorruptedIdeLocationException {
- return new STSLocation(name, ini);
- }
-
- @Override protected String getMacAppName() {
- return "STS.app";
- }
+public class STSLocationProvider extends EclipseProductLocationProvider {
- @Override protected String getUnixAppName() {
- return "STS";
- }
+ private static final EclipseProductDescriptor STS = new StandardProductDescriptor("STS",
+ "STS",
+ "sts",
+ STSLocationProvider.class.getResource("STS.png"),
+ Collections.singleton("springsource")
+ );
- @Override public Pattern getLocationSelectors(OS os) {
- switch (os) {
- case MAC_OS_X:
- return Pattern.compile("^(sts|sts\\.ini|sts\\.app)$", Pattern.CASE_INSENSITIVE);
- case WINDOWS:
- return Pattern.compile("^(stsc?\\.exe|sts\\.ini)$", Pattern.CASE_INSENSITIVE);
- default:
- case UNIX:
- return Pattern.compile("^(sts|sts\\.ini)$", Pattern.CASE_INSENSITIVE);
- }
+ public STSLocationProvider() {
+ super(STS);
}
}
diff --git a/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java b/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java
new file mode 100644
index 00000000..47e103aa
--- /dev/null
+++ b/src/installer/lombok/installer/eclipse/StandardProductDescriptor.java
@@ -0,0 +1,158 @@
+/*
+ * Copyright (C) 2016 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.net.URL;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import lombok.installer.OsUtils;
+
+public class StandardProductDescriptor implements EclipseProductDescriptor {
+
+ private static final String USER_HOME = System.getProperty("user.home", ".");
+ private static final String[] WINDOWS_ROOTS = {"\\", "\\Program Files", "\\Program Files (x86)", USER_HOME};
+ private static final String[] MAC_ROOTS = {"/Applications", USER_HOME};
+ private static final String[] UNIX_ROOTS = {USER_HOME};
+
+ private final String productName;
+ private final String windowsName;
+ private final String unixName;
+ private final String macAppName;
+ private final List<String> executableNames;
+ private final List<String> sourceDirsOnWindows;
+ private final List<String> sourceDirsOnMac;
+ private final List<String> sourceDirsOnUnix;
+ private final String iniFileName;
+ private final Pattern locationSelectors;
+ private final String directoryName;
+ private final URL ideIcon;
+
+ public StandardProductDescriptor(String productName, String baseName, String directoryName, URL ideIcon, Collection<String> alternativeDirectoryNames) {
+ this.productName = productName;
+ this.windowsName = baseName + ".exe";
+ this.unixName = baseName;
+ this.macAppName = baseName + ".app";
+ this.executableNames = executableNames(baseName);
+ this.sourceDirsOnWindows = generateAlternatives(WINDOWS_ROOTS, "\\", alternativeDirectoryNames);
+ this.sourceDirsOnMac = generateAlternatives(MAC_ROOTS, "/", alternativeDirectoryNames);
+ this.sourceDirsOnUnix = generateAlternatives(UNIX_ROOTS, "/", alternativeDirectoryNames);
+ this.iniFileName = baseName + ".ini";
+ this.locationSelectors = getLocationSelectors(baseName);
+ this.directoryName = directoryName.toLowerCase();
+ this.ideIcon = ideIcon;
+ }
+
+ @Override public String getProductName() {
+ return productName;
+ }
+
+ @Override public String getWindowsExecutableName() {
+ return windowsName;
+ }
+
+ @Override public String getUnixAppName() {
+ return unixName;
+ }
+
+ @Override public String getMacAppName() {
+ return macAppName;
+ }
+
+ @Override public String getDirectoryName() {
+ return directoryName;
+ }
+
+ @Override public List<String> getExecutableNames() {
+ return executableNames;
+ }
+
+ @Override public List<String> getSourceDirsOnWindows() {
+ return sourceDirsOnWindows;
+ }
+
+ @Override public List<String> getSourceDirsOnMac() {
+ return sourceDirsOnMac;
+ }
+
+ @Override public List<String> getSourceDirsOnUnix() {
+ return sourceDirsOnUnix;
+ }
+
+ @Override public String getIniFileName() {
+ return iniFileName;
+ }
+
+ @Override public Pattern getLocationSelectors() {
+ return locationSelectors;
+ }
+
+ @Override public URL getIdeIcon() {
+ return ideIcon;
+ }
+
+ private static Pattern getLocationSelectors(String baseName) {
+ return Pattern.compile(String.format(platformPattern(), baseName.toLowerCase()), Pattern.CASE_INSENSITIVE);
+ }
+
+ private static String platformPattern() {
+ switch (OsUtils.getOS()) {
+ case MAC_OS_X:
+ return "^(%s|%<s\\.ini|%<s\\.app)$";
+ case WINDOWS:
+ return "^(%sc?\\.exe|%<s\\.ini)$";
+ default:
+ case UNIX:
+ return "^(%s|%<s\\.ini)$";
+ }
+ }
+
+ private static List<String> executableNames(String baseName) {
+ String base = baseName.toLowerCase();
+ return Collections.unmodifiableList(Arrays.asList(base, base + ".app", base + ".exe", base + "c.exe"));
+ }
+
+ private static List<String> generateAlternatives(String[] roots, String pathSeparator, Collection<String> alternatives) {
+ List<String> result = new ArrayList<String>();
+ for (String root : roots) {
+ result.add(concat(root, pathSeparator, ""));
+ for (String alternative : alternatives) {
+ result.add(concat(root, pathSeparator, alternative));
+ }
+ }
+ return Collections.unmodifiableList(result);
+ }
+
+ private static String concat(String base, String pathSeparator, String alternative) {
+ if (alternative.isEmpty()) {
+ return base;
+ }
+ if (base.endsWith(pathSeparator)) {
+ return base + alternative.replaceAll("[\\/]", "\\" + pathSeparator);
+ }
+ return base + pathSeparator + alternative.replaceAll("[\\/]", "\\" + pathSeparator);
+ }
+}
diff --git a/src/installer/lombok/installer/eclipse/myeclipse.png b/src/installer/lombok/installer/eclipse/myeclipse.png
new file mode 100644
index 00000000..49c4fab3
--- /dev/null
+++ b/src/installer/lombok/installer/eclipse/myeclipse.png
Binary files differ
diff --git a/src/installer/lombok/installer/eclipse/rhds.png b/src/installer/lombok/installer/eclipse/rhds.png
new file mode 100644
index 00000000..ca7738e6
--- /dev/null
+++ b/src/installer/lombok/installer/eclipse/rhds.png
Binary files differ
diff --git a/src/j9stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java b/src/j9stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
new file mode 100644
index 00000000..ffb99030
--- /dev/null
+++ b/src/j9stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mapstruct.ap.spi;
+
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A contract to be implemented by other annotation processors which - against the design philosophy of JSR 269 - alter
+ * the types under compilation.
+ * <p>
+ * This contract will be queried by MapStruct when examining types referenced by mappers to be generated, most notably
+ * the source and target types of mapping methods. If at least one AST-modifying processor announces further changes to
+ * such type, the generation of the affected mapper(s) will be deferred to a future round in the annnotation processing
+ * cycle.
+ * <p>
+ * Implementations are discovered via the service loader, i.e. a JAR providing an AST-modifying processor needs to
+ * declare its implementation in a file {@code META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor}.
+ *
+ * @author Gunnar Morling
+ */
+//@org.mapstruct.util.Experimental
+public interface AstModifyingAnnotationProcessor {
+
+ /**
+ * Whether the specified type has been fully processed by this processor or not (i.e. this processor will amend the
+ * given type's structure after this invocation).
+ *
+ * @param type The type of interest
+ * @return {@code true} if this processor has fully processed the given type, {@code false} otherwise.
+ */
+ boolean isTypeComplete(TypeMirror type);
+} \ No newline at end of file
diff --git a/src/launch/lombok/launch/Agent.java b/src/launch/lombok/launch/Agent.java
new file mode 100644
index 00000000..7989e51f
--- /dev/null
+++ b/src/launch/lombok/launch/Agent.java
@@ -0,0 +1,47 @@
+/*
+ * Copyright (C) 2014 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.launch;
+
+import java.lang.instrument.Instrumentation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+
+final class Agent {
+ public static void agentmain(String agentArgs, Instrumentation instrumentation) throws Throwable {
+ runLauncher(agentArgs, instrumentation, true);
+ }
+
+ public static void premain(String agentArgs, Instrumentation instrumentation) throws Throwable {
+ runLauncher(agentArgs, instrumentation, false);
+ }
+
+ private static void runLauncher(String agentArgs, Instrumentation instrumentation, boolean injected) throws Throwable {
+ ClassLoader cl = Main.createShadowClassLoader();
+ try {
+ Class<?> c = cl.loadClass("lombok.core.AgentLauncher");
+ Method m = c.getDeclaredMethod("runAgents", String.class, Instrumentation.class, boolean.class, Class.class);
+ m.invoke(null, agentArgs, instrumentation, injected, Agent.class);
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+ }
+}
diff --git a/src/launch/lombok/launch/AnnotationProcessor.java b/src/launch/lombok/launch/AnnotationProcessor.java
new file mode 100644
index 00000000..c4f922b9
--- /dev/null
+++ b/src/launch/lombok/launch/AnnotationProcessor.java
@@ -0,0 +1,129 @@
+/*
+ * 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
+ * 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.launch;
+
+import java.lang.reflect.Field;
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.Completion;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+import org.mapstruct.ap.spi.AstModifyingAnnotationProcessor;
+
+import sun.misc.Unsafe;
+
+class AnnotationProcessorHider {
+ public static class AstModificationNotifier implements AstModifyingAnnotationProcessor {
+ @Override public boolean isTypeComplete(TypeMirror type) {
+ if (System.getProperty("lombok.disable") != null) return true;
+ return AstModificationNotifierData.lombokInvoked;
+ }
+ }
+
+ static class AstModificationNotifierData {
+ volatile static boolean lombokInvoked = false;
+ }
+
+ public static class AnnotationProcessor extends AbstractProcessor {
+ private final AbstractProcessor instance = createWrappedInstance();
+
+ @Override public Set<String> getSupportedOptions() {
+ return instance.getSupportedOptions();
+ }
+
+ @Override public Set<String> getSupportedAnnotationTypes() {
+ return instance.getSupportedAnnotationTypes();
+ }
+
+ @Override public SourceVersion getSupportedSourceVersion() {
+ return instance.getSupportedSourceVersion();
+ }
+
+ @Override public void init(ProcessingEnvironment processingEnv) {
+ disableJava9SillyWarning();
+ AstModificationNotifierData.lombokInvoked = true;
+ instance.init(processingEnv);
+ super.init(processingEnv);
+ }
+
+ // sunapi suppresses javac's warning about using Unsafe; 'all' suppresses eclipse's warning about the unspecified 'sunapi' key. Leave them both.
+ // Yes, javac's definition of the word 'all' is quite contrary to what the dictionary says it means. 'all' does NOT include 'sunapi' according to javac.
+ @SuppressWarnings({"sunapi", "all"})
+ private void disableJava9SillyWarning() {
+ // JVM9 complains about using reflection to access packages from a module that aren't exported. This makes no sense; the whole point of reflection
+ // is to get past such issues. The only comment from the jigsaw team lead on this was some unspecified mumbling about security which makes no sense,
+ // as the SecurityManager is invoked to check such things. Therefore this warning is a bug, so we shall patch java to fix it.
+
+ try {
+ Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
+ theUnsafe.setAccessible(true);
+ Unsafe u = (Unsafe) theUnsafe.get(null);
+
+ Class<?> cls = Class.forName("jdk.internal.module.IllegalAccessLogger");
+ Field logger = cls.getDeclaredField("logger");
+ u.putObjectVolatile(cls, u.staticFieldOffset(logger), null);
+ } catch (Throwable t) {
+ // We shall ignore it; the effect of this code failing is that the user gets to see a warning they remove with various --add-opens magic.
+ }
+ }
+
+ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ return instance.process(annotations, roundEnv);
+ }
+
+ @Override public Iterable<? extends Completion> getCompletions(Element element, AnnotationMirror annotation, ExecutableElement member, String userText) {
+ return instance.getCompletions(element, annotation, member, userText);
+ }
+
+ private static AbstractProcessor createWrappedInstance() {
+ ClassLoader cl = Main.createShadowClassLoader();
+ try {
+ Class<?> mc = cl.loadClass("lombok.core.AnnotationProcessor");
+ return (AbstractProcessor) mc.getDeclaredConstructor().newInstance();
+ } catch (Throwable t) {
+ if (t instanceof Error) throw (Error) t;
+ if (t instanceof RuntimeException) throw (RuntimeException) t;
+ throw new RuntimeException(t);
+ }
+ }
+ }
+
+ @SupportedAnnotationTypes("lombok.*")
+ public static class ClaimingProcessor extends AbstractProcessor {
+ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ return true;
+ }
+
+ @Override public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latest();
+ }
+ }
+}
diff --git a/src/launch/lombok/launch/Main.java b/src/launch/lombok/launch/Main.java
new file mode 100644
index 00000000..b81b6268
--- /dev/null
+++ b/src/launch/lombok/launch/Main.java
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2014-2015 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.launch;
+
+import java.lang.reflect.InvocationTargetException;
+import java.util.Arrays;
+
+class Main {
+ static ClassLoader createShadowClassLoader() {
+ return new ShadowClassLoader(Main.class.getClassLoader(), "lombok", null, Arrays.<String>asList(), Arrays.asList("lombok.patcher.Symbols"));
+ }
+
+ public static void main(String[] args) throws Throwable {
+ ClassLoader cl = createShadowClassLoader();
+ Class<?> mc = cl.loadClass("lombok.core.Main");
+ try {
+ mc.getMethod("main", String[].class).invoke(null, new Object[] {args});
+ } catch (InvocationTargetException e) {
+ throw e.getCause();
+ }
+ }
+}
diff --git a/src/launch/lombok/launch/ShadowClassLoader.java b/src/launch/lombok/launch/ShadowClassLoader.java
new file mode 100644
index 00000000..72f006e8
--- /dev/null
+++ b/src/launch/lombok/launch/ShadowClassLoader.java
@@ -0,0 +1,485 @@
+/*
+ * Copyright (C) 2014-2015 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.launch;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.UnsupportedEncodingException;
+import java.net.MalformedURLException;
+import java.net.URI;
+import java.net.URL;
+import java.net.URLDecoder;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import java.util.Vector;
+import java.util.WeakHashMap;
+import java.util.Map.Entry;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+
+/**
+ * The shadow classloader serves to completely hide almost all classes in a given jar file by using a different file ending.
+ *
+ * The shadow classloader also serves to link in a project as it is being developed (a 'bin' dir from an IDE for example).
+ * <p>
+ * Classes loaded by the shadowloader use ".SCL.<em>sclSuffix</em>" in addition to ".class". In other words, most of the class files in a given jar end in this suffix, which
+ * serves to hide them from any tool that isn't aware of the suffix (such as IDEs generating auto-complete dialogs, and javac's classpath in general). Only shadowloader can actually
+ * load these classes.
+ * <p>
+ * The shadowloader will pick up an alternate (priority) classpath, using normal class files, from the system property "<code>shadow.override.<em>sclSuffix</em></code>".
+ * This shadow classpath looks just like a normal java classpath; the path separator is applied (semi-colon on windows, colon elsewhere), and entries can consist of directories,
+ * jar files, or directories ending in "/*" to pick up all jars inside it.
+ * <p>
+ * Load order is as follows if at least one override is present:
+ * <li>First, if the resource is found in one of the paths stated in the shadow classpath, find that.
+ * <li>Next, ask the <code>parent</code> loader, which is passed during construction of the ShadowClassLoader.
+ * <li>Notably, this jar's contents are always skipped! (The idea of the shadow classpath is that this jar only functions as a launcher, not as a source of your actual application).
+ * </ul>
+ *
+ * If no overrides are present, the load order is as follows:
+ * <li>First, if the resource is found in our own jar (trying ".SCL.<em>sclSuffix</em>" first for any resource request ending in ".class"), return that.
+ * <li>Next, ask the <code>parent</code> loader.
+ * </ul>
+ *
+ * Use ShadowClassLoader to accomplish the following things:<ul>
+ * <li>Avoid contaminating the namespace of any project using an SCL-based jar. Autocompleters in IDEs will NOT suggest anything other than actual public API.
+ * <li>Like jarjar, allows folding in dependencies such as ASM without foisting these dependencies on projects that use this jar. shadowloader obviates the need for jarjar.
+ * <li>Allows an agent (which MUST be in jar form) to still load everything except this loader infrastructure from class files generated by the IDE, which should
+ * considerably help debugging, as you can now rely on the IDE's built-in auto-recompile features instead of having to run a full build everytime, and it should help
+ * with hot code replace and the like (this is what the {@code shadow.override} feature is for).
+ * </ul>
+ *
+ * Implementation note: {@code lombok.eclipse.agent.EclipseLoaderPatcher} <em>relies</em> on this class having no dependencies on any other class except the JVM boot class, notably
+ * including any other classes in this package, <strong>including</strong> inner classes. So, don't write closures, anonymous inner class literals,
+ * enums, or anything else that could cause the compilation of this file to produce more than 1 class file. In general, actually passing load control to this loader is a bit tricky
+ * so ensure that this class has zero dependencies on anything except java core classes.
+ */
+class ShadowClassLoader extends ClassLoader {
+ private static final String SELF_NAME = "lombok/launch/ShadowClassLoader.class";
+ private static final ConcurrentMap<String, Class<?>> highlanderMap = new ConcurrentHashMap<String, Class<?>>();
+
+ private final String SELF_BASE;
+ private final File SELF_BASE_FILE;
+ private final int SELF_BASE_LENGTH;
+
+ private final List<File> override = new ArrayList<File>();
+ private final String sclSuffix;
+ private final List<String> parentExclusion = new ArrayList<String>();
+ private final List<String> highlanders = new ArrayList<String>();
+
+ /**
+ * @param source The 'parent' classloader.
+ * @param sclSuffix The suffix of the shadowed class files in our own jar. For example, if this is {@code lombok}, then the class files in your jar should be {@code foo/Bar.SCL.lombok} and not {@code foo/Bar.class}.
+ * @param selfBase The (preferably absolute) path to our own jar. This jar will be searched for class/SCL.sclSuffix files.
+ * @param parentExclusion For example {@code "lombok."}; upon invocation of loadClass of this loader, the parent loader ({@code source}) will NOT be invoked if the class to be loaded begins with anything in the parent exclusion list. No exclusion is applied for getResource(s).
+ * @param highlanders SCL will put in extra effort to ensure that these classes (in simple class spec, so {@code foo.bar.baz.ClassName}) are only loaded once as a class, even if many different classloaders try to load classes, such as equinox/OSGi.
+ */
+ ShadowClassLoader(ClassLoader source, String sclSuffix, String selfBase, List<String> parentExclusion, List<String> highlanders) {
+ super(source);
+ this.sclSuffix = sclSuffix;
+ if (parentExclusion != null) for (String pe : parentExclusion) {
+ pe = pe.replace(".", "/");
+ if (!pe.endsWith("/")) pe = pe + "/";
+ this.parentExclusion.add(pe);
+ }
+ if (highlanders != null) for (String hl : highlanders) {
+ this.highlanders.add(hl);
+ }
+
+ if (selfBase != null) {
+ SELF_BASE = selfBase;
+ SELF_BASE_LENGTH = selfBase.length();
+ } else {
+ URL sclClassUrl = ShadowClassLoader.class.getResource("ShadowClassLoader.class");
+ String sclClassStr = sclClassUrl == null ? null : sclClassUrl.toString();
+ if (sclClassStr == null || !sclClassStr.endsWith(SELF_NAME)) {
+ ClassLoader cl = ShadowClassLoader.class.getClassLoader();
+ throw new RuntimeException("ShadowLoader can't find itself. SCL loader type: " + (cl == null ? "*NULL*" : cl.getClass().toString()));
+ }
+ SELF_BASE_LENGTH = sclClassStr.length() - SELF_NAME.length();
+ String decoded;
+ try {
+ decoded = URLDecoder.decode(sclClassStr.substring(0, SELF_BASE_LENGTH), "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw new InternalError("UTF-8 not available");
+ }
+ SELF_BASE = decoded;
+ }
+
+ if (SELF_BASE.startsWith("jar:file:") && SELF_BASE.endsWith("!/")) SELF_BASE_FILE = new File(SELF_BASE.substring(9, SELF_BASE.length() - 2));
+ else if (SELF_BASE.startsWith("file:")) SELF_BASE_FILE = new File(SELF_BASE.substring(5));
+ else SELF_BASE_FILE = new File(SELF_BASE);
+ String scl = System.getProperty("shadow.override." + sclSuffix);
+ if (scl != null && !scl.isEmpty()) {
+ for (String part : scl.split("\\s*" + (File.pathSeparatorChar == ';' ? ";" : ":") + "\\s*")) {
+ if (part.endsWith("/*") || part.endsWith(File.separator + "*")) {
+ addOverrideJarDir(part.substring(0, part.length() - 2));
+ } else {
+ addOverrideClasspathEntry(part);
+ }
+ }
+ }
+ }
+
+ private final Map<String, Object> mapJarPathToTracker = new HashMap<String, Object>();
+ private static final Map<Object, String> mapTrackerToJarPath = new WeakHashMap<Object, String>();
+ private static final Map<Object, Set<String>> mapTrackerToJarContents = new WeakHashMap<Object, Set<String>>();
+
+ /**
+ * This cache ensures that any given jar file is only opened once in order to determine the full contents of it.
+ * We use 'trackers' to make sure that the bulk of the memory taken up by this cache (the list of strings representing the content of a jar file)
+ * gets garbage collected if all ShadowClassLoaders that ever tried to request a listing of this jar file, are garbage collected.
+ */
+ private Set<String> getOrMakeJarListing(final String absolutePathToJar) {
+ synchronized (mapTrackerToJarPath) {
+ /*
+ * 1) Check our private instance JarPath-to-Tracker Mappings:
+ */
+ Object ourTracker = mapJarPathToTracker.get(absolutePathToJar);
+ if (ourTracker != null) {
+ /*
+ * Yes, we are already tracking this Jar. Just return its contents...
+ */
+ return mapTrackerToJarContents.get(ourTracker);
+ }
+
+ /*
+ * 2) Not tracked by us as yet. Check statically whether others have tracked this JarPath:
+ */
+ for (Entry<Object, String> entry : mapTrackerToJarPath.entrySet()) {
+ if (entry.getValue().equals(absolutePathToJar)) {
+ /*
+ * Yes, 3rd party is tracking this jar. We must track too, then return its contents.
+ */
+ Object otherTracker = entry.getKey();
+ mapJarPathToTracker.put(absolutePathToJar, otherTracker);
+ return mapTrackerToJarContents.get(otherTracker);
+ }
+ }
+
+ /*
+ * 3) Not tracked by anyone so far. Build, publish, track & return Jar contents...
+ */
+ Object newTracker = new Object();
+ Set<String> jarMembers = getJarMemberSet(absolutePathToJar);
+
+ mapTrackerToJarContents.put(newTracker, jarMembers);
+ mapTrackerToJarPath.put(newTracker, absolutePathToJar);
+ mapJarPathToTracker.put(absolutePathToJar, newTracker);
+
+ return jarMembers;
+ }
+ }
+
+ /**
+ * Return a {@link Set} of members in the Jar identified by {@code absolutePathToJar}.
+ *
+ * @param absolutePathToJar Cache key
+ * @return a Set with the Jar member-names
+ */
+ private Set<String> getJarMemberSet(String absolutePathToJar) {
+ /*
+ * Note:
+ * Our implementation returns a HashSet. initialCapacity and loadFactor are carefully tweaked for speed and RAM optimization purposes.
+ *
+ * Benchmark:
+ * The HashSet implementation is about 10% slower to build (only happens once) than the ArrayList.
+ * The HashSet with shiftBits = 1 was about 33 times(!) faster than the ArrayList for retrievals.
+ */
+ try {
+ int shiftBits = 1; // (fast, but big) 0 <= shiftBits <= 5, say (slower & compact)
+ JarFile jar = new JarFile(absolutePathToJar);
+
+ /*
+ * Find the first power of 2 >= JarSize (as calculated in HashSet constructor)
+ */
+ int jarSizePower2 = Integer.highestOneBit(jar.size());
+ if (jarSizePower2 != jar.size()) jarSizePower2 <<= 1;
+ if (jarSizePower2 == 0) jarSizePower2 = 1;
+
+ Set<String> jarMembers = new HashSet<String>(jarSizePower2 >> shiftBits, 1 << shiftBits);
+ try {
+ Enumeration<JarEntry> entries = jar.entries();
+ while (entries.hasMoreElements()) {
+ JarEntry jarEntry = entries.nextElement();
+ if (jarEntry.isDirectory()) continue;
+ jarMembers.add(jarEntry.getName());
+ }
+ } catch (Exception ignore) {
+ // ignored; if the jar can't be read, treating it as if the jar contains no classes is just what we want.
+ } finally {
+ jar.close();
+ }
+ return jarMembers;
+ }
+ catch (Exception newJarFileException) {
+ return Collections.emptySet();
+ }
+ }
+
+ /**
+ * Looks up {@code altName} in {@code location}, and if that isn't found, looks up {@code name}; {@code altName} can be null in which case it is skipped.
+ */
+ private URL getResourceFromLocation(String name, String altName, File location) {
+ if (location.isDirectory()) {
+ try {
+ if (altName != null) {
+ File f = new File(location, altName);
+ if (f.isFile() && f.canRead()) return f.toURI().toURL();
+ }
+
+ File f = new File(location, name);
+ if (f.isFile() && f.canRead()) return f.toURI().toURL();
+ return null;
+ } catch (MalformedURLException e) {
+ return null;
+ }
+ }
+
+ if (!location.isFile() || !location.canRead()) return null;
+
+ File absoluteFile; {
+ try {
+ absoluteFile = location.getCanonicalFile();
+ } catch (Exception e) {
+ absoluteFile = location.getAbsoluteFile();
+ }
+ }
+ Set<String> jarContents = getOrMakeJarListing(absoluteFile.getAbsolutePath());
+
+ String absoluteUri = absoluteFile.toURI().toString();
+
+ try {
+ if (jarContents.contains(altName)) {
+ return new URI("jar:" + absoluteUri + "!/" + altName).toURL();
+ }
+ } catch (Exception ignore) {
+ // intentional fallthrough
+ }
+
+ try {
+ if (jarContents.contains(name)) {
+ return new URI("jar:" + absoluteUri + "!/" + name).toURL();
+ }
+ } catch(Exception ignore) {
+ // intentional fallthrough
+ }
+
+ return null;
+ }
+
+ /**
+ * Checks if the stated item is located inside the same classpath root as the jar that hosts ShadowClassLoader.class. {@code item} and {@code name} refer to the same thing.
+ */
+ private boolean inOwnBase(URL item, String name) {
+ if (item == null) return false;
+ String itemString = item.toString();
+ return (itemString.length() == SELF_BASE_LENGTH + name.length()) && SELF_BASE.regionMatches(0, itemString, 0, SELF_BASE_LENGTH);
+ }
+
+ @Override public Enumeration<URL> getResources(String name) throws IOException {
+ String altName = null;
+ if (name.endsWith(".class")) altName = name.substring(0, name.length() - 6) + ".SCL." + sclSuffix;
+
+ // Vector? Yes, we need one:
+ // * We can NOT make inner classes here (this class is loaded with special voodoo magic in eclipse, as a one off, it's not a full loader.
+ // * We need to return an enumeration.
+ // * We can't make one on the fly.
+ // * ArrayList can't make these.
+ Vector<URL> vector = new Vector<URL>();
+
+ for (File ce : override) {
+ URL url = getResourceFromLocation(name, altName, ce);
+ if (url != null) vector.add(url);
+ }
+
+ if (override.isEmpty()) {
+ URL fromSelf = getResourceFromLocation(name, altName, SELF_BASE_FILE);
+ if (fromSelf != null) vector.add(fromSelf);
+ }
+
+ Enumeration<URL> sec = super.getResources(name);
+ while (sec.hasMoreElements()) {
+ URL item = sec.nextElement();
+ if (!inOwnBase(item, name)) vector.add(item);
+ }
+
+ if (altName != null) {
+ Enumeration<URL> tern = super.getResources(altName);
+ while (tern.hasMoreElements()) {
+ URL item = tern.nextElement();
+ if (!inOwnBase(item, altName)) vector.add(item);
+ }
+ }
+
+ return vector.elements();
+ }
+
+ @Override public URL getResource(String name) {
+ return getResource_(name, false);
+ }
+
+ private URL getResource_(String name, boolean noSuper) {
+ String altName = null;
+ if (name.endsWith(".class")) altName = name.substring(0, name.length() - 6) + ".SCL." + sclSuffix;
+ for (File ce : override) {
+ URL url = getResourceFromLocation(name, altName, ce);
+ if (url != null) return url;
+ }
+
+ if (!override.isEmpty()) {
+ if (noSuper) return null;
+ if (altName != null) {
+ try {
+ URL res = getResourceSkippingSelf(altName);
+ if (res != null) return res;
+ } catch (IOException ignore) {}
+ }
+
+ try {
+ return getResourceSkippingSelf(name);
+ } catch (IOException e) {
+ return null;
+ }
+ }
+
+ URL url = getResourceFromLocation(name, altName, SELF_BASE_FILE);
+ if (url != null) return url;
+
+ if (altName != null) {
+ URL res = super.getResource(altName);
+ if (res != null && (!noSuper || inOwnBase(res, altName))) return res;
+ }
+
+ URL res = super.getResource(name);
+ if (res != null && (!noSuper || inOwnBase(res, name))) return res;
+ return null;
+ }
+
+ private boolean exclusionListMatch(String name) {
+ for (String pe : parentExclusion) {
+ if (name.startsWith(pe)) return true;
+ }
+ return false;
+ }
+
+ private URL getResourceSkippingSelf(String name) throws IOException {
+ URL candidate = super.getResource(name);
+ if (candidate == null) return null;
+ if (!inOwnBase(candidate, name)) return candidate;
+
+ Enumeration<URL> en = super.getResources(name);
+ while (en.hasMoreElements()) {
+ candidate = en.nextElement();
+ if (!inOwnBase(candidate, name)) return candidate;
+ }
+
+ return null;
+ }
+
+ @Override public Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {
+ {
+ Class<?> alreadyLoaded = findLoadedClass(name);
+ if (alreadyLoaded != null) return alreadyLoaded;
+ }
+
+ if (highlanders.contains(name)) {
+ Class<?> c = highlanderMap.get(name);
+ if (c != null) return c;
+ }
+
+ String fileNameOfClass = name.replace(".", "/") + ".class";
+ URL res = getResource_(fileNameOfClass, true);
+ if (res == null) {
+ if (!exclusionListMatch(fileNameOfClass)) return super.loadClass(name, resolve);
+ throw new ClassNotFoundException(name);
+ }
+
+ byte[] b;
+ int p = 0;
+ try {
+ InputStream in = res.openStream();
+
+ try {
+ b = new byte[65536];
+ while (true) {
+ int r = in.read(b, p, b.length - p);
+ if (r == -1) break;
+ p += r;
+ if (p == b.length) {
+ byte[] nb = new byte[b.length * 2];
+ System.arraycopy(b, 0, nb, 0, p);
+ b = nb;
+ }
+ }
+ } finally {
+ in.close();
+ }
+ } catch (IOException e) {
+ throw new ClassNotFoundException("I/O exception reading class " + name, e);
+ }
+
+ Class<?> c;
+ try {
+ c = defineClass(name, b, 0, p);
+ } catch (LinkageError e) {
+ if (highlanders.contains(name)) {
+ Class<?> alreadyDefined = highlanderMap.get(name);
+ if (alreadyDefined != null) return alreadyDefined;
+ }
+ try {
+ c = this.findLoadedClass(name);
+ } catch (LinkageError e2) {
+ throw e;
+ }
+ if (c == null) throw e;
+ }
+
+ if (highlanders.contains(name)) {
+ Class<?> alreadyDefined = highlanderMap.putIfAbsent(name, c);
+ if (alreadyDefined != null) c = alreadyDefined;
+ }
+
+ if (resolve) resolveClass(c);
+ return c;
+ }
+
+ public void addOverrideJarDir(String dir) {
+ File f = new File(dir);
+ for (File j : f.listFiles()) {
+ if (j.getName().toLowerCase().endsWith(".jar") && j.canRead() && j.isFile()) override.add(j);
+ }
+ }
+
+ public void addOverrideClasspathEntry(String entry) {
+ override.add(new File(entry));
+ }
+}
diff --git a/src/stubs/com/sun/tools/javac/code/Symbol.java b/src/stubs/com/sun/tools/javac/code/Symbol.java
new file mode 100644
index 00000000..4aef63ad
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/code/Symbol.java
@@ -0,0 +1,84 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
+package com.sun.tools.javac.code;
+
+import java.lang.annotation.Annotation;
+import java.util.Set;
+
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ElementVisitor;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.Modifier;
+import javax.lang.model.element.NestingKind;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.element.TypeParameterElement;
+import javax.lang.model.element.VariableElement;
+import javax.lang.model.type.TypeMirror;
+
+import com.sun.tools.javac.util.Name;
+
+public abstract class Symbol implements Element {
+ public Type type;
+ public Name name;
+
+ public long flags() { return 0; }
+ public boolean isStatic() { return false; }
+ public boolean isConstructor() { return false; }
+ public boolean isLocal() { return false; }
+ public Name flatName() { return null; }
+ public Name getQualifiedName() { return null; }
+ public <A extends Annotation> A[] getAnnotationsByType(Class<A> annoType) { return null; }
+ @Override public java.util.List<Attribute.Compound> getAnnotationMirrors() { return null; }
+ @Override public TypeMirror asType() { return null; }
+ public <A extends java.lang.annotation.Annotation> A getAnnotation(Class<A> annoType) { return null; }
+ @Override public Name getSimpleName() { return null; }
+ @Override public java.util.List<Symbol> getEnclosedElements() { return null; }
+ @Override public Element getEnclosingElement() { return null; }
+
+ public static abstract class TypeSymbol extends Symbol {}
+
+ public static class MethodSymbol extends Symbol implements ExecutableElement {
+ public MethodSymbol(long flags, Name name, Type type, Symbol owner) {}
+ @Override public ElementKind getKind() { return null; }
+ @Override public Set<Modifier> getModifiers() { return null; }
+ @Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
+ @Override public java.util.List<? extends TypeParameterElement> getTypeParameters() { return null; }
+ @Override public TypeMirror getReturnType() { return null; }
+ @Override public java.util.List<? extends VariableElement> getParameters() { return null; }
+ @Override public boolean isVarArgs() { return false; }
+ @Override public java.util.List<? extends TypeMirror> getThrownTypes() { return null; }
+ @Override public AnnotationValue getDefaultValue() { return null; }
+ public TypeMirror getReceiverType() { return null; }
+ public boolean isDefault() { return false; }
+ public com.sun.tools.javac.util.List<VarSymbol> params() { return null; }
+ }
+
+ public static class VarSymbol extends Symbol implements VariableElement {
+ public Type type;
+ @Override public ElementKind getKind() { return null; }
+ @Override public Set<Modifier> getModifiers() { return null; }
+ @Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
+ @Override public Object getConstantValue() { return null; }
+ }
+
+ public static class ClassSymbol extends TypeSymbol implements TypeElement {
+ @Override public Name getQualifiedName() { return null; }
+ @Override public java.util.List<? extends TypeMirror> getInterfaces() { return null; }
+ @Override public TypeMirror getSuperclass() { return null; }
+ @Override public ElementKind getKind() { return null; }
+ @Override public Set<Modifier> getModifiers() { return null; }
+ @Override public NestingKind getNestingKind() { return null; }
+ @Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
+ @Override public java.util.List<? extends TypeParameterElement> getTypeParameters() { return null; }
+ }
+
+ // JDK9
+ public static class ModuleSymbol extends TypeSymbol {
+ @Override public ElementKind getKind() { return null; }
+ @Override public Set<Modifier> getModifiers() { return null; }
+ @Override public <R, P> R accept(ElementVisitor<R, P> v, P p) { return null; }
+ }
+}
diff --git a/src/stubs/com/sun/tools/javac/code/Symtab.java b/src/stubs/com/sun/tools/javac/code/Symtab.java
new file mode 100644
index 00000000..2b524e4c
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/code/Symtab.java
@@ -0,0 +1,20 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
+package com.sun.tools.javac.code;
+
+import com.sun.tools.javac.code.Symbol.ClassSymbol;
+import com.sun.tools.javac.code.Symbol.ModuleSymbol;
+import com.sun.tools.javac.util.Context;
+
+public class Symtab {
+ // Shared by JDK6-9
+ public ClassSymbol methodClass;
+ public Type iterableType;
+ public Type objectType;
+ public static Symtab instance(Context context) {return null;}
+ public Type unknownType;
+
+ // JDK 9
+ public ModuleSymbol unnamedModule;
+}
diff --git a/src/stubs/com/sun/tools/javac/file/BaseFileManager.java b/src/stubs/com/sun/tools/javac/file/BaseFileManager.java
new file mode 100644
index 00000000..a56a2430
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/file/BaseFileManager.java
@@ -0,0 +1,18 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
+package com.sun.tools.javac.file;
+
+import javax.tools.JavaFileManager;
+
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.util.Context;
+
+import java.nio.charset.Charset;
+import java.util.Map;
+
+public abstract class BaseFileManager implements JavaFileManager {
+ protected BaseFileManager(Charset charset) {}
+ public void setContext(Context context) {}
+ public boolean handleOptions(Map<Option, String> deferredFileManagerOptions) { return false; }
+}
diff --git a/src/stubs/com/sun/tools/javac/file/PathFileObject.java b/src/stubs/com/sun/tools/javac/file/PathFileObject.java
new file mode 100644
index 00000000..c1ee6074
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/file/PathFileObject.java
@@ -0,0 +1,12 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
+package com.sun.tools.javac.file;
+
+import java.nio.file.Path;
+
+import javax.tools.JavaFileObject;
+
+public abstract class PathFileObject implements JavaFileObject {
+ protected PathFileObject(BaseFileManager fileManager, Path path) {}
+}
diff --git a/src/stubs/com/sun/tools/javac/main/Arguments.java b/src/stubs/com/sun/tools/javac/main/Arguments.java
new file mode 100644
index 00000000..ea866b6e
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/main/Arguments.java
@@ -0,0 +1,13 @@
+package com.sun.tools.javac.main;
+
+import java.util.Map;
+
+import com.sun.tools.javac.util.Context;
+
+public class Arguments {
+ public static final Context.Key<Arguments> argsKey = new Context.Key<Arguments>();
+ public static Arguments instance(Context context) { return null; }
+ public void init(String ownName, String... argv) {}
+ public Map<Option, String> getDeferredFileManagerOptions() { return null; }
+ public boolean validate() { return false; }
+}
diff --git a/src/stubs/com/sun/tools/javac/main/JavaCompiler.java b/src/stubs/com/sun/tools/javac/main/JavaCompiler.java
new file mode 100644
index 00000000..d0e7b38f
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/main/JavaCompiler.java
@@ -0,0 +1,37 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
+package com.sun.tools.javac.main;
+
+import java.io.IOException;
+import java.util.Collection;
+import javax.annotation.processing.Processor;
+import javax.tools.JavaFileObject;
+
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.util.Context;
+import com.sun.tools.javac.util.List;
+import com.sun.tools.javac.comp.Todo;
+
+public class JavaCompiler {
+ // Shared by JDK6-9
+ public boolean keepComments;
+ public boolean genEndPos;
+ public Todo todo;
+
+ public JavaCompiler(Context context) {}
+ public int errorCount() { return 0; }
+ public static String version() { return "<stub>"; }
+ public JCCompilationUnit parse(String fileName) throws IOException { return null; }
+ public List<JCCompilationUnit> enterTrees(List<JCCompilationUnit> roots) {return null;}
+
+ //JDK up to 8
+ public void initProcessAnnotations(Iterable<? extends Processor> processors) throws IOException {}
+ public JavaCompiler processAnnotations(List<JCCompilationUnit> roots, List<String> classnames) {return this;}
+
+ // JDK 9
+ public void initProcessAnnotations(Iterable<? extends Processor> processors, Collection<? extends JavaFileObject> initialFiles, Collection<String> initialClassNames) {}
+ public void processAnnotations(List<JCCompilationUnit> roots, Collection<String> classnames) {}
+ public void close() {}
+ public List<JCCompilationUnit> initModules(List<JCCompilationUnit> roots) { return null; }
+}
diff --git a/src/stubs/com/sun/tools/javac/main/Option.java b/src/stubs/com/sun/tools/javac/main/Option.java
index f3229c78..ae955772 100644
--- a/src/stubs/com/sun/tools/javac/main/Option.java
+++ b/src/stubs/com/sun/tools/javac/main/Option.java
@@ -7,4 +7,5 @@ package com.sun.tools.javac.main;
public enum Option {
;
public String text;
+ public String primaryName;
}
diff --git a/src/stubs/com/sun/tools/javac/parser/JavacParser.java b/src/stubs/com/sun/tools/javac/parser/JavacParser.java
index da42f37a..4f1f3380 100644
--- a/src/stubs/com/sun/tools/javac/parser/JavacParser.java
+++ b/src/stubs/com/sun/tools/javac/parser/JavacParser.java
@@ -1,3 +1,6 @@
+/*
+ * These are stub versions of various bits of javac-internal API (for various different versions of javac). Lombok is compiled against these.
+ */
package com.sun.tools.javac.parser;
import com.sun.tools.javac.tree.JCTree;
@@ -6,6 +9,9 @@ public class JavacParser {
protected JavacParser(ParserFactory fac, Lexer S, boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions) {
}
+ protected JavacParser(ParserFactory fac, Lexer S, boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions, boolean parseModuleInfo) {
+ }
+
public JCTree.JCCompilationUnit parseCompilationUnit() {
return null;
}
diff --git a/src/stubs/com/sun/tools/javac/util/Options.java b/src/stubs/com/sun/tools/javac/util/Options.java
new file mode 100644
index 00000000..e7ba8960
--- /dev/null
+++ b/src/stubs/com/sun/tools/javac/util/Options.java
@@ -0,0 +1,20 @@
+package com.sun.tools.javac.util;
+
+import java.util.Set;
+
+import com.sun.tools.javac.main.Option;
+import com.sun.tools.javac.main.OptionName;
+import com.sun.tools.javac.main.JavacOption;
+
+public class Options {
+ public Options(Context context) {}
+ public static final Context.Key<Options> optionsKey = new Context.Key<Options>();
+ public static Options instance(Context context) { return null; }
+ public String get(String key) { return null; }
+ public String get(Option opt) { return null; }
+ public String get(OptionName name) { return null; }
+ public String get(JavacOption.Option opt) { return null; }
+ public void putAll(Options o) {}
+ public void put(String key, String value) {}
+ public Set<String> keySet() { return null; }
+}
diff --git a/src/stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java b/src/stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
new file mode 100644
index 00000000..ffb99030
--- /dev/null
+++ b/src/stubs/org/mapstruct/ap/spi/AstModifyingAnnotationProcessor.java
@@ -0,0 +1,48 @@
+/**
+ * Copyright 2012-2017 Gunnar Morling (http://www.gunnarmorling.de/)
+ * and/or other contributors as indicated by the @authors tag. See the
+ * copyright.txt file in the distribution for a full listing of all
+ * contributors.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.mapstruct.ap.spi;
+
+import javax.lang.model.type.TypeMirror;
+
+/**
+ * A contract to be implemented by other annotation processors which - against the design philosophy of JSR 269 - alter
+ * the types under compilation.
+ * <p>
+ * This contract will be queried by MapStruct when examining types referenced by mappers to be generated, most notably
+ * the source and target types of mapping methods. If at least one AST-modifying processor announces further changes to
+ * such type, the generation of the affected mapper(s) will be deferred to a future round in the annnotation processing
+ * cycle.
+ * <p>
+ * Implementations are discovered via the service loader, i.e. a JAR providing an AST-modifying processor needs to
+ * declare its implementation in a file {@code META-INF/services/org.mapstruct.ap.spi.AstModifyingAnnotationProcessor}.
+ *
+ * @author Gunnar Morling
+ */
+//@org.mapstruct.util.Experimental
+public interface AstModifyingAnnotationProcessor {
+
+ /**
+ * Whether the specified type has been fully processed by this processor or not (i.e. this processor will amend the
+ * given type's structure after this invocation).
+ *
+ * @param type The type of interest
+ * @return {@code true} if this processor has fully processed the given type, {@code false} otherwise.
+ */
+ boolean isTypeComplete(TypeMirror type);
+} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/code/Attribute.java b/src/stubsstubs/com/sun/tools/javac/code/Attribute.java
new file mode 100644
index 00000000..29bd54a9
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/code/Attribute.java
@@ -0,0 +1,15 @@
+package com.sun.tools.javac.code;
+
+import java.util.Map;
+
+import javax.lang.model.element.AnnotationMirror;
+import javax.lang.model.element.AnnotationValue;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.type.DeclaredType;
+
+public abstract class Attribute {
+ public static class Compound extends Attribute implements AnnotationMirror {
+ public DeclaredType getAnnotationType() { return null; }
+ public Map<? extends ExecutableElement, ? extends AnnotationValue> getElementValues() { return null; }
+ }
+} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/code/Type.java b/src/stubsstubs/com/sun/tools/javac/code/Type.java
new file mode 100644
index 00000000..c130ae9c
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/code/Type.java
@@ -0,0 +1,3 @@
+package com.sun.tools.javac.code;
+
+public class Type {} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/comp/Todo.java b/src/stubsstubs/com/sun/tools/javac/comp/Todo.java
new file mode 100644
index 00000000..006a7fd3
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/comp/Todo.java
@@ -0,0 +1,3 @@
+package com.sun.tools.javac.comp;
+
+public class Todo {} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/main/JavacOption.java b/src/stubsstubs/com/sun/tools/javac/main/JavacOption.java
new file mode 100644
index 00000000..8e74d3d3
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/main/JavacOption.java
@@ -0,0 +1,5 @@
+package com.sun.tools.javac.main;
+
+public class JavacOption {
+ public static class Option {}
+} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/main/Option.java b/src/stubsstubs/com/sun/tools/javac/main/Option.java
new file mode 100644
index 00000000..45988e4c
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/main/Option.java
@@ -0,0 +1,3 @@
+package com.sun.tools.javac.main;
+
+public class Option {} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/main/OptionName.java b/src/stubsstubs/com/sun/tools/javac/main/OptionName.java
new file mode 100644
index 00000000..b1866633
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/main/OptionName.java
@@ -0,0 +1,3 @@
+package com.sun.tools.javac.main;
+
+public class OptionName {} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/util/Context.java b/src/stubsstubs/com/sun/tools/javac/util/Context.java
new file mode 100644
index 00000000..a090714e
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/util/Context.java
@@ -0,0 +1,5 @@
+package com.sun.tools.javac.util;
+
+public class Context {
+ public static class Key<T> {}
+} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/util/List.java b/src/stubsstubs/com/sun/tools/javac/util/List.java
new file mode 100644
index 00000000..16418a2b
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/util/List.java
@@ -0,0 +1,3 @@
+package com.sun.tools.javac.util;
+
+public class List<T> {} \ No newline at end of file
diff --git a/src/stubsstubs/com/sun/tools/javac/util/Name.java b/src/stubsstubs/com/sun/tools/javac/util/Name.java
new file mode 100644
index 00000000..c0e81926
--- /dev/null
+++ b/src/stubsstubs/com/sun/tools/javac/util/Name.java
@@ -0,0 +1,8 @@
+package com.sun.tools.javac.util;
+
+public class Name implements javax.lang.model.element.Name {
+ public boolean contentEquals(CharSequence cs) { return false; }
+ public int length() { return 0; }
+ public char charAt(int idx) { return '\0'; }
+ public CharSequence subSequence(int a, int b) { return null; }
+} \ No newline at end of file
diff --git a/src/testAP/org/projectlombok/testAp/ExampleAnnotation.java b/src/testAP/org/projectlombok/testAp/ExampleAnnotation.java
new file mode 100644
index 00000000..b419326b
--- /dev/null
+++ b/src/testAP/org/projectlombok/testAp/ExampleAnnotation.java
@@ -0,0 +1,10 @@
+package org.projectlombok.testAp;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+@Retention(RetentionPolicy.CLASS)
+@Target(ElementType.TYPE)
+public @interface ExampleAnnotation {}
diff --git a/src/testAP/org/projectlombok/testAp/TestAp.java b/src/testAP/org/projectlombok/testAp/TestAp.java
new file mode 100644
index 00000000..b5f20d21
--- /dev/null
+++ b/src/testAP/org/projectlombok/testAp/TestAp.java
@@ -0,0 +1,77 @@
+/*
+ * Copyright (C) 2016 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 org.projectlombok.testAp;
+
+import java.util.Set;
+
+import javax.annotation.processing.AbstractProcessor;
+import javax.annotation.processing.ProcessingEnvironment;
+import javax.annotation.processing.RoundEnvironment;
+import javax.annotation.processing.SupportedAnnotationTypes;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.Element;
+import javax.lang.model.element.ElementKind;
+import javax.lang.model.element.ExecutableElement;
+import javax.lang.model.element.TypeElement;
+import javax.lang.model.type.TypeMirror;
+
+@SupportedAnnotationTypes("org.projectlombok.testAp.ExampleAnnotation")
+public final class TestAp extends AbstractProcessor {
+ private int roundCounter = 0;
+ private static final long START = System.currentTimeMillis();
+
+ private void log(String txt) {
+ System.out.printf("***[%3d]: %s\n", System.currentTimeMillis() - START, txt);
+ }
+
+ @Override public void init(ProcessingEnvironment processingEnv) {
+ log("TestAP in init");
+ super.init(processingEnv);
+ }
+
+ @Override public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ roundCounter++;
+ log("TestAP in round " + roundCounter);
+ boolean foundGetTest = false;
+ int annotatedElemCount = 0;
+ for (Element annotated : roundEnv.getElementsAnnotatedWith(ExampleAnnotation.class)) {
+ annotatedElemCount++;
+ for (Element child : annotated.getEnclosedElements()) {
+ if (child.getSimpleName().toString().equals("getTest") && child.getKind() == ElementKind.METHOD) foundGetTest = true;
+ if (child instanceof ExecutableElement) {
+ TypeMirror returnType = ((ExecutableElement) child).getReturnType();
+ System.out.println("RETURN TYPE for " + child.getSimpleName() + ": " + returnType.getClass() + " -- " + returnType.toString());
+ }
+ }
+ }
+
+ if (foundGetTest) log("RESULT: POSITIVE -- found the getTest method");
+ else if (annotatedElemCount > 0) log("RESULT: NEGATIVE -- found the example class but there's no getTest method in it according to the type mirror.");
+ else log("RESULT: AMBIVALENT -- The example class is not provided by 'getElementsAnnotatedWith' in this round. Not an issue, unless previously you got a NEGATIVE result.");
+
+ return false;
+ }
+
+ @Override public SourceVersion getSupportedSourceVersion() {
+ return SourceVersion.latestSupported();
+ }
+}
diff --git a/src/useTestAP/UseTestAp.java b/src/useTestAP/UseTestAp.java
new file mode 100644
index 00000000..2d7eab7b
--- /dev/null
+++ b/src/useTestAP/UseTestAp.java
@@ -0,0 +1,13 @@
+@org.projectlombok.testAp.ExampleAnnotation
+//@lombok.experimental.Accessors(chain=true)
+public class UseTestAp {
+ @lombok.Setter @lombok.Getter String test;
+
+ public void confirmGetTestExists() {
+ System.out.println(getTest());
+ }
+
+ public UseTestAp returningSelf() {
+ return this;
+ }
+}
diff --git a/src/utils/lombok/core/LombokImmutableList.java b/src/utils/lombok/core/LombokImmutableList.java
index e0e1136c..4603f2ad 100644
--- a/src/utils/lombok/core/LombokImmutableList.java
+++ b/src/utils/lombok/core/LombokImmutableList.java
@@ -80,6 +80,12 @@ public final class LombokImmutableList<T> implements Iterable<T> {
return copyOf(list);
}
+ public static <T> LombokImmutableList<T> copyOf(T[] array) {
+ Object[] content = new Object[array.length];
+ System.arraycopy(array, 0, content, 0, array.length);
+ return new LombokImmutableList<T>(content);
+ }
+
private LombokImmutableList(Object[] content) {
this.content = content;
}
diff --git a/src/utils/lombok/eclipse/Eclipse.java b/src/utils/lombok/eclipse/Eclipse.java
index c2a863d5..18b22256 100644
--- a/src/utils/lombok/eclipse/Eclipse.java
+++ b/src/utils/lombok/eclipse/Eclipse.java
@@ -98,15 +98,20 @@ public class Eclipse {
* string containing the same fully qualified name with dots in the string.
*/
public static boolean nameEquals(char[][] typeName, String string) {
- StringBuilder sb = new StringBuilder();
- boolean first = true;
- for (char[] elem : typeName) {
- if (first) first = false;
- else sb.append('.');
- sb.append(elem);
+ int pos = 0, len = string.length();
+ for (int i = 0; i < typeName.length; i++) {
+ char[] t = typeName[i];
+ if (i > 0) {
+ if (pos == len) return false;
+ if (string.charAt(pos++) != '.') return false;
+ }
+ for (int j = 0; j < t.length; j++) {
+ if (pos == len) return false;
+ if (string.charAt(pos++) != t[j]) return false;
+ }
}
- return string.contentEquals(sb);
+ return true;
}
public static boolean hasClinit(TypeDeclaration parent) {
diff --git a/src/utils/lombok/javac/CommentCatcher.java b/src/utils/lombok/javac/CommentCatcher.java
index c32da68b..afbd7b52 100644
--- a/src/utils/lombok/javac/CommentCatcher.java
+++ b/src/utils/lombok/javac/CommentCatcher.java
@@ -95,8 +95,10 @@ public class CommentCatcher {
parserFactory = Class.forName("lombok.javac.java6.CommentCollectingParserFactory");
} else if (javaCompilerVersion == 7) {
parserFactory = Class.forName("lombok.javac.java7.CommentCollectingParserFactory");
- } else {
+ } else if (javaCompilerVersion == 8) {
parserFactory = Class.forName("lombok.javac.java8.CommentCollectingParserFactory");
+ } else {
+ parserFactory = Class.forName("lombok.javac.java9.CommentCollectingParserFactory");
}
parserFactory.getMethod("setInCompiler", JavaCompiler.class, Context.class).invoke(null, compiler, context);
} catch (InvocationTargetException e) {
diff --git a/src/utils/lombok/javac/Javac.java b/src/utils/lombok/javac/Javac.java
index e207c44a..9ff4d22f 100644
--- a/src/utils/lombok/javac/Javac.java
+++ b/src/utils/lombok/javac/Javac.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
@@ -40,6 +40,7 @@ import lombok.javac.JavacTreeMaker.TreeTag;
import lombok.javac.JavacTreeMaker.TypeTag;
import com.sun.tools.javac.code.Source;
+import com.sun.tools.javac.code.Symtab;
import com.sun.tools.javac.code.Type;
import com.sun.tools.javac.main.JavaCompiler;
import com.sun.tools.javac.tree.JCTree;
@@ -62,8 +63,8 @@ public class Javac {
/** Matches any of the 8 primitive names, such as {@code boolean}. */
private static final Pattern PRIMITIVE_TYPE_NAME_PATTERN = Pattern.compile("^(boolean|byte|short|int|long|float|double|char)$");
- private static final Pattern VERSION_PARSER = Pattern.compile("^(\\d{1,6})\\.(\\d{1,6}).*$");
- private static final Pattern SOURCE_PARSER = Pattern.compile("^JDK(\\d{1,6})_(\\d{1,6}).*$");
+ private static final Pattern VERSION_PARSER = Pattern.compile("^(\\d{1,6})\\.?(\\d{1,6})?.*$");
+ private static final Pattern SOURCE_PARSER = Pattern.compile("^JDK(\\d{1,6})_?(\\d{1,6})?.*$");
private static final AtomicInteger compilerVersion = new AtomicInteger(-1);
@@ -78,11 +79,11 @@ public class Javac {
Matcher m = VERSION_PARSER.matcher(JavaCompiler.version());
if (m.matches()) {
int major = Integer.parseInt(m.group(1));
- int minor = Integer.parseInt(m.group(2));
if (major == 1) {
- compilerVersion.set(minor);
- return minor;
+ int minor = Integer.parseInt(m.group(2));
+ return setVersion(minor);
}
+ if (major >= 9) return setVersion(major);
}
}
@@ -91,16 +92,19 @@ public class Javac {
Matcher m = SOURCE_PARSER.matcher(name);
if (m.matches()) {
int major = Integer.parseInt(m.group(1));
- int minor = Integer.parseInt(m.group(2));
if (major == 1) {
- compilerVersion.set(minor);
- return minor;
+ int minor = Integer.parseInt(m.group(2));
+ return setVersion(minor);
}
+ if (major >= 9) return setVersion(major);
}
}
-
- compilerVersion.set(6);
- return 6;
+ return setVersion(6);
+ }
+
+ private static int setVersion(int version) {
+ compilerVersion.set(version);
+ return version;
}
private static final Class<?> DOCCOMMENTTABLE_CLASS;
@@ -162,9 +166,16 @@ public class Javac {
public static final TypeTag CTC_VOID = typeTag("VOID");
public static final TypeTag CTC_NONE = typeTag("NONE");
public static final TypeTag CTC_BOT = typeTag("BOT");
+ public static final TypeTag CTC_ERROR = typeTag("ERROR");
+ public static final TypeTag CTC_UNKNOWN = typeTag("UNKNOWN");
+ public static final TypeTag CTC_UNDETVAR = typeTag("UNDETVAR");
public static final TypeTag CTC_CLASS = typeTag("CLASS");
public static final TreeTag CTC_NOT_EQUAL = treeTag("NE");
+ public static final TreeTag CTC_LESS_THAN = treeTag("LT");
+ public static final TreeTag CTC_GREATER_THAN = treeTag("GT");
+ public static final TreeTag CTC_LESS_OR_EQUAL= treeTag("LE");
+ public static final TreeTag CTC_GREATER_OR_EQUAL = treeTag("GE");
public static final TreeTag CTC_POS = treeTag("POS");
public static final TreeTag CTC_NEG = treeTag("NEG");
public static final TreeTag CTC_NOT = treeTag("NOT");
@@ -172,10 +183,14 @@ public class Javac {
public static final TreeTag CTC_BITXOR = treeTag("BITXOR");
public static final TreeTag CTC_UNSIGNED_SHIFT_RIGHT = treeTag("USR");
public static final TreeTag CTC_MUL = treeTag("MUL");
+ public static final TreeTag CTC_DIV = treeTag("DIV");
public static final TreeTag CTC_PLUS = treeTag("PLUS");
+ public static final TreeTag CTC_MINUS = treeTag("MINUS");
public static final TreeTag CTC_EQUAL = treeTag("EQ");
public static final TreeTag CTC_PREINC = treeTag("PREINC");
public static final TreeTag CTC_PREDEC = treeTag("PREDEC");
+ public static final TreeTag CTC_POSTINC = treeTag("POSTINC");
+ public static final TreeTag CTC_POSTDEC = treeTag("POSTDEC");
private static final Method getExtendsClause, getEndPosition, storeEnd;
@@ -298,7 +313,21 @@ public class Javac {
JC_NO_TYPE = c;
}
- public static Type createVoidType(JavacTreeMaker maker, TypeTag tag) {
+ private static final Field symtabVoidType = getFieldIfExists(Symtab.class, "voidType");
+
+ private static Field getFieldIfExists(Class<?> c, String fieldName) {
+ try {
+ return c.getField("voidType");
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public static Type createVoidType(Symtab symbolTable, TypeTag tag) {
+ if (symtabVoidType != null) try {
+ return (Type) symtabVoidType.get(symbolTable);
+ } catch (IllegalAccessException ignore) {}
+
if (Javac.getJavaCompilerVersion() < 8) {
return new JCNoType(((Integer) tag.value).intValue());
} else {
diff --git a/src/utils/lombok/javac/JavacTreeMaker.java b/src/utils/lombok/javac/JavacTreeMaker.java
index 12baf5af..5f4fb09c 100644
--- a/src/utils/lombok/javac/JavacTreeMaker.java
+++ b/src/utils/lombok/javac/JavacTreeMaker.java
@@ -226,6 +226,7 @@ public class JavacTreeMaker {
}
public static TypeTag typeTag(Type t) {
+ if (t == null) return Javac.CTC_VOID;
try {
return new TypeTag(getFieldCached(FIELD_CACHE, t, "tag"));
} catch (NoSuchFieldException e) {
diff --git a/src/utils/lombok/javac/PackageName.java b/src/utils/lombok/javac/PackageName.java
new file mode 100644
index 00000000..e4dd6b20
--- /dev/null
+++ b/src/utils/lombok/javac/PackageName.java
@@ -0,0 +1,55 @@
+/*
+ * Copyright (C) 2017 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.javac;
+
+import java.lang.reflect.Method;
+
+import com.sun.tools.javac.tree.JCTree;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+import com.sun.tools.javac.tree.JCTree.JCFieldAccess;
+import com.sun.tools.javac.tree.JCTree.JCIdent;
+
+// Supports JDK6-9
+public class PackageName {
+ private static final Method packageNameMethod = getPackageNameMethod();
+
+ private static Method getPackageNameMethod() {
+ try {
+ return JCCompilationUnit.class.getDeclaredMethod("getPackageName");
+ } catch (Exception e) {
+ return null;
+ }
+ }
+
+ public static String getPackageName(JCCompilationUnit cu) {
+ JCTree t = getPackageNode(cu);
+ return t != null ? t.toString() : null;
+ }
+
+ public static JCTree getPackageNode(JCCompilationUnit cu) {
+ if (packageNameMethod != null) try {
+ Object pkg = packageNameMethod.invoke(cu);
+ return (pkg instanceof JCFieldAccess || pkg instanceof JCIdent) ? (JCTree) pkg : null;
+ } catch (Exception e) {}
+ return cu.pid instanceof JCFieldAccess || cu.pid instanceof JCIdent ? cu.pid : null;
+ }
+}
diff --git a/src/utils/lombok/javac/TreeMirrorMaker.java b/src/utils/lombok/javac/TreeMirrorMaker.java
index 23ec2406..8cd8cffe 100644
--- a/src/utils/lombok/javac/TreeMirrorMaker.java
+++ b/src/utils/lombok/javac/TreeMirrorMaker.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2010-2011 The Project Lombok Authors.
+ * Copyright (C) 2010-2015 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
@@ -26,11 +26,15 @@ import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Map;
+import static lombok.javac.Javac.*;
+import lombok.javac.JavacTreeMaker.TypeTag;
+
import com.sun.source.tree.LabeledStatementTree;
import com.sun.source.tree.VariableTree;
import com.sun.tools.javac.tree.JCTree;
import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
import com.sun.tools.javac.tree.TreeCopier;
+import com.sun.tools.javac.util.Context;
import com.sun.tools.javac.util.List;
/**
@@ -46,7 +50,7 @@ import com.sun.tools.javac.util.List;
public class TreeMirrorMaker extends TreeCopier<Void> {
private final IdentityHashMap<JCTree, JCTree> originalToCopy = new IdentityHashMap<JCTree, JCTree>();
- public TreeMirrorMaker(JavacTreeMaker maker) {
+ public TreeMirrorMaker(JavacTreeMaker maker, Context context) {
super(maker.getUnderlyingTreeMaker());
}
@@ -86,15 +90,32 @@ public class TreeMirrorMaker extends TreeCopier<Void> {
return Collections.unmodifiableMap(originalToCopy);
}
- // Fix for NPE in HandleVal. See http://code.google.com/p/projectlombok/issues/detail?id=205
- // Maybe this should be done elsewhere...
+ // Monitor the following issues when making changes here.
+ // - https://github.com/rzwitserloot/lombok/issues/278
+ // - https://github.com/rzwitserloot/lombok/issues/729
@Override public JCTree visitVariable(VariableTree node, Void p) {
+ JCVariableDecl original = node instanceof JCVariableDecl ? (JCVariableDecl) node : null;
JCVariableDecl copy = (JCVariableDecl) super.visitVariable(node, p);
- copy.sym = ((JCVariableDecl) node).sym;
+ if (original == null) return copy;
+ copy.sym = original.sym;
+ if (copy.sym != null) copy.type = original.type;
+ if (copy.type != null) {
+ boolean wipeSymAndType = copy.type.isErroneous();
+ if (!wipeSymAndType) {
+ TypeTag typeTag = TypeTag.typeTag(copy.type);
+ wipeSymAndType = (CTC_NONE.equals(typeTag) || CTC_ERROR.equals(typeTag) || CTC_UNKNOWN.equals(typeTag) || CTC_UNDETVAR.equals(typeTag));
+ }
+
+ if (wipeSymAndType) {
+ copy.sym = null;
+ copy.type = null;
+ }
+ }
+
return copy;
}
- // Fix for NPE in HandleVal. See http://code.google.com/p/projectlombok/issues/detail?id=299
+ // Fix for NPE in HandleVal. See https://github.com/rzwitserloot/lombok/issues/372
// This and visitVariable is rather hacky but we're working around evident bugs or at least inconsistencies in javac.
@Override public JCTree visitLabeledStatement(LabeledStatementTree node, Void p) {
return node.getStatement().accept(this, p);
diff --git a/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
index 45f865ad..2fdaddfe 100644
--- a/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
+++ b/src/utils/lombok/javac/java8/CommentCollectingParserFactory.java
@@ -52,6 +52,16 @@ public class CommentCollectingParserFactory extends ParserFactory {
//Either way this will work out.
}
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) {
+ ScannerFactory scannerFactory = ScannerFactory.instance(context);
+ Lexer lexer = scannerFactory.newScanner(input, true);
+ Object x = new CommentCollectingParser(this, lexer, true, keepLineMap, keepEndPos);
+ return (JavacParser) x;
+ // CCP is based on a stub which extends nothing, but at runtime the stub is replaced with either
+ //javac6's EndPosParser which extends Parser, or javac8's JavacParser which implements Parser.
+ //Either way this will work out.
+ }
+
public static void setInCompiler(JavaCompiler compiler, Context context) {
context.put(CommentCollectingParserFactory.key(), (ParserFactory) null);
Field field;
diff --git a/src/utils/lombok/javac/java9/CommentCollectingParser.java b/src/utils/lombok/javac/java9/CommentCollectingParser.java
new file mode 100644
index 00000000..307be405
--- /dev/null
+++ b/src/utils/lombok/javac/java9/CommentCollectingParser.java
@@ -0,0 +1,53 @@
+/*
+ * Copyright (C) 2013-2017 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.javac.java9;
+
+import static lombok.javac.CommentCatcher.JCCompilationUnit_comments;
+
+import java.util.List;
+
+import lombok.javac.CommentInfo;
+import lombok.javac.java8.CommentCollectingScanner;
+
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.tree.JCTree.JCCompilationUnit;
+
+class CommentCollectingParser extends JavacParser {
+ private final Lexer lexer;
+
+ protected CommentCollectingParser(ParserFactory fac, Lexer S,
+ boolean keepDocComments, boolean keepLineMap, boolean keepEndPositions, boolean parseModuleInfo) {
+ super(fac, S, keepDocComments, keepLineMap, keepEndPositions, parseModuleInfo);
+ lexer = S;
+ }
+
+ public JCCompilationUnit parseCompilationUnit() {
+ JCCompilationUnit result = super.parseCompilationUnit();
+ if (lexer instanceof CommentCollectingScanner) {
+ List<CommentInfo> comments = ((CommentCollectingScanner)lexer).getComments();
+ JCCompilationUnit_comments.set(result, comments);
+ }
+ return result;
+ }
+} \ No newline at end of file
diff --git a/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java b/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java
new file mode 100644
index 00000000..5af4a419
--- /dev/null
+++ b/src/utils/lombok/javac/java9/CommentCollectingParserFactory.java
@@ -0,0 +1,70 @@
+/*
+ * Copyright (C) 2013-2017 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.javac.java9;
+
+import java.lang.reflect.Field;
+
+import com.sun.tools.javac.main.JavaCompiler;
+import com.sun.tools.javac.parser.JavacParser;
+import com.sun.tools.javac.parser.Lexer;
+import com.sun.tools.javac.parser.ParserFactory;
+import com.sun.tools.javac.parser.ScannerFactory;
+import com.sun.tools.javac.util.Context;
+
+public class CommentCollectingParserFactory extends ParserFactory {
+ private final Context context;
+
+ static Context.Key<ParserFactory> key() {
+ return parserFactoryKey;
+ }
+
+ protected CommentCollectingParserFactory(Context context) {
+ super(context);
+ this.context = context;
+ }
+
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap) {
+ return newParser(input, keepDocComments, keepEndPos, keepLineMap, false);
+ }
+
+ public JavacParser newParser(CharSequence input, boolean keepDocComments, boolean keepEndPos, boolean keepLineMap, boolean parseModuleInfo) {
+ ScannerFactory scannerFactory = ScannerFactory.instance(context);
+ Lexer lexer = scannerFactory.newScanner(input, true);
+ Object x = new CommentCollectingParser(this, lexer, true, keepLineMap, keepEndPos, parseModuleInfo);
+ return (JavacParser) x;
+ // CCP is based on a stub which extends nothing, but at runtime the stub is replaced with either
+ //javac6's EndPosParser which extends Parser, or javac-9's JavacParser which implements Parser.
+ //Either way this will work out.
+ }
+
+ public static void setInCompiler(JavaCompiler compiler, Context context) {
+ context.put(CommentCollectingParserFactory.key(), (ParserFactory) null);
+ Field field;
+ try {
+ field = JavaCompiler.class.getDeclaredField("parserFactory");
+ field.setAccessible(true);
+ field.set(compiler, new CommentCollectingParserFactory(context));
+ } catch (Exception e) {
+ throw new IllegalStateException("Could not set comment sensitive parser in the compiler", e);
+ }
+ }
+} \ No newline at end of file
diff --git a/src/website/log4j.properties b/src/website/log4j.properties
new file mode 100644
index 00000000..9cafcc3b
--- /dev/null
+++ b/src/website/log4j.properties
@@ -0,0 +1,6 @@
+log4j.rootLogger=INFO, stdout
+
+log4j.appender.stdout=org.apache.log4j.ConsoleAppender
+log4j.appender.stdout.Target=System.out
+log4j.appender.stdout.layout=org.apache.log4j.PatternLayout
+log4j.appender.stdout.layout.ConversionPattern=%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n
diff --git a/src/website/lombok/website/CompileChangelog.java b/src/website/lombok/website/CompileChangelog.java
new file mode 100644
index 00000000..8912434e
--- /dev/null
+++ b/src/website/lombok/website/CompileChangelog.java
@@ -0,0 +1,147 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.StringReader;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import com.petebevin.markdown.MarkdownProcessor;
+
+public class CompileChangelog {
+ public static void main(String[] args) {
+ String fileIn = args[0];
+ String fileOut = args[1];
+ boolean edge = args.length > 3 && "-edge".equals(args[2]);
+ boolean latest = args.length > 3 && "-latest".equals(args[2]);
+ String version = args.length > 3 ? args[3] : null;
+
+ try {
+ FileInputStream in = new FileInputStream(fileIn);
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+
+ byte[] b = new byte[65536];
+ while (true) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ out.write(b, 0, r);
+ }
+ in.close();
+ String markdown = new String(out.toByteArray(), "UTF-8");
+
+ String result;
+ if (edge) {
+ result = buildEdge(sectionByVersion(markdown, version));
+ } else if (latest) {
+ result = buildLatest(sectionByVersion(markdown, version));
+ } else {
+ result = markdownToHtml(sectionStartingAt(markdown, version));
+ }
+
+ FileOutputStream file = new FileOutputStream(fileOut);
+ file.write(result.getBytes("UTF-8"));
+ file.close();
+ System.exit(0);
+ } catch (Throwable e) {
+ e.printStackTrace();
+ System.exit(1);
+ }
+ }
+
+ public static String getHtmlForEdge(File root, String edgeVersion) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return buildEdge(sectionByVersion(raw, edgeVersion));
+ }
+
+ public static String getHtmlForLatest(File root, String latestVersion) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return buildLatest(sectionByVersion(raw, latestVersion));
+ }
+
+ public static String getHtml(File root) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return markdownToHtml(raw);
+ }
+
+ public static String getHtmlStartingAtSection(File root, String version) throws IOException {
+ File f = new File(root, "doc/changelog.markdown");
+ String raw = readFile(f);
+ return markdownToHtml(sectionStartingAt(raw, version));
+ }
+
+ private static String readFile(File f) throws IOException {
+ byte[] b = new byte[65536];
+ FileInputStream in = new FileInputStream(f);
+ try {
+ ByteArrayOutputStream out = new ByteArrayOutputStream();
+ while (true) {
+ int r = in.read(b);
+ if ( r == -1 ) break;
+ out.write(b, 0, r);
+ }
+ in.close();
+ return new String(out.toByteArray(), "UTF-8");
+ } finally {
+ in.close();
+ }
+ }
+
+ private static String markdownToHtml(String markdown) {
+ return new MarkdownProcessor().markdown(markdown);
+ }
+
+ private static String buildEdge(String section) {
+ String latest = section != null ? section : "* No changelog records for this edge release.";
+ return markdownToHtml(latest);
+ }
+
+ private static String buildLatest(String section) {
+ String latest = section != null ? section : "* No changelog records for this release.";
+ String noIssueLinks = latest.replaceAll("\\[[^]]*[Ii]ssue[^]]*\\]\\([^)]*\\)", "");
+ String noLinks = noIssueLinks.replaceAll("\\[([^]]*)\\]\\([^)]*\\)", "$1");
+ return markdownToHtml(noLinks);
+ }
+
+ private static String sectionStartingAt(String markdown, String version) {
+ if (version.toUpperCase().endsWith("-HEAD") || version.toUpperCase().endsWith("-EDGE")) {
+ version = version.substring(0, version.length() - 5);
+ }
+
+ Pattern p = Pattern.compile("^.*###\\s*v(.*)$");
+ BufferedReader br = new BufferedReader(new StringReader(markdown));
+ StringBuilder out = new StringBuilder();
+ int state = 0;
+ try {
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ if (state < 2) {
+ Matcher m = p.matcher(line);
+ if (m.matches()) state = m.group(1).startsWith(version) ? 2 : 1;
+ }
+ if (state != 1) {
+ out.append(line);
+ out.append("\n");
+ }
+ }
+ return out.toString();
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+
+ private static String sectionByVersion(String markdown, String version) {
+ if (version.toUpperCase().endsWith("-HEAD") || version.toUpperCase().endsWith("-EDGE")) {
+ version = version.substring(0, version.length() - 5);
+ }
+
+ Pattern p = Pattern.compile("(?is-m)^.*###\\s*v" + version + ".*?\n(.*?)(?:###\\s*v.*)?$");
+ Matcher m = p.matcher(markdown);
+ return m.matches() ? m.group(1) : null;
+ }
+} \ No newline at end of file
diff --git a/src/website/lombok/website/FetchCurrentVersion.java b/src/website/lombok/website/FetchCurrentVersion.java
new file mode 100644
index 00000000..0d789256
--- /dev/null
+++ b/src/website/lombok/website/FetchCurrentVersion.java
@@ -0,0 +1,33 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.net.URL;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+public class FetchCurrentVersion {
+ private FetchCurrentVersion() {}
+
+ private static final Pattern VERSION_PATTERN = Pattern.compile("^.*<\\s*span\\s+id\\s*=\\s*[\"'](currentVersion|currentVersionFull)[\"'](?:\\s+style\\s*=\\s*[\"']display\\s*:\\s*none;?[\"'])?\\s*>\\s*([^\t<]+)\\s*<\\s*/\\s*span\\s*>.*$");
+
+ public static void main(String[] args) throws IOException {
+ System.out.print(fetchVersionFromSite(args.length == 0 || args[0].equals("full")));
+ }
+
+ public static String fetchVersionFromSite(boolean fetchFull) throws IOException {
+ InputStream in = new URL("https://projectlombok.org/download").openStream();
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ Matcher m = VERSION_PATTERN.matcher(line);
+ if (m.matches() && m.group(1).equals("currentVersionFull") == fetchFull) return m.group(2).replace("&quot;", "\"");
+ }
+ throw new IOException("Expected a span with id 'currentVersion'");
+ } finally {
+ in.close();
+ }
+ }
+}
diff --git a/src/website/lombok/website/WebsiteMaker.java b/src/website/lombok/website/WebsiteMaker.java
new file mode 100644
index 00000000..88556b97
--- /dev/null
+++ b/src/website/lombok/website/WebsiteMaker.java
@@ -0,0 +1,403 @@
+package lombok.website;
+
+import java.io.BufferedReader;
+import java.io.BufferedWriter;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+
+import de.java2html.Java2Html;
+import freemarker.cache.FileTemplateLoader;
+import freemarker.cache.TemplateLoader;
+import freemarker.core.HTMLOutputFormat;
+import freemarker.template.Configuration;
+import freemarker.template.Template;
+import freemarker.template.TemplateExceptionHandler;
+
+public class WebsiteMaker {
+ private final String version, fullVersion;
+ private final File baseDir, outputDir;
+
+ public WebsiteMaker(String version, String fullVersion, File baseDir, File outputDir) {
+ this.version = version;
+ this.fullVersion = fullVersion;
+ this.baseDir = baseDir;
+ this.outputDir = outputDir;
+ }
+
+ private static final class VersionFinder {
+ public static String getVersion() {
+ return getVersion0("getVersion");
+ }
+
+ public static String getFullVersion() {
+ return getVersion0("getFullVersion");
+ }
+
+ private static String getVersion0(String mName) {
+ try {
+ Class<?> c = Class.forName("lombok.core.Version");
+ Method m = c.getMethod(mName);
+ return (String) m.invoke(null);
+ } catch (ClassNotFoundException e) {
+ System.err.println("You need to specify the version string, and the full version string, as first 2 arguments.");
+ System.exit(1);
+ return null;
+ } catch (Exception e) {
+ if (e instanceof RuntimeException) throw (RuntimeException) e;
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ private static void buildAll(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website");
+ } else {
+ out = new File(in, "output");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out);
+ maker.buildWebsite();
+ }
+
+ private static void buildChangelog(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website/changelog.html");
+ } else {
+ out = new File(in, "output/changelog.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildChangelog(out);
+ }
+
+ private static void buildDownloadEdge(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/website-edge/download-edge.html");
+ } else {
+ out = new File(in, "output/download-edge.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildDownloadEdge(out);
+ }
+
+ private static void buildChangelogLatest(String version, String fullVersion, String argIn, String argOut) throws Exception {
+ File in, out;
+ if (argIn == null) {
+ in = new File(".");
+ if (new File(in, "build.xml").isFile() && new File(in, "website").isDirectory()) in = new File(in, "website");
+ } else {
+ in = new File(argIn);
+ }
+
+ if (argOut == null) {
+ if (new File("./build.xml").isFile() && new File("./website").isDirectory() && new File("./build").isDirectory()) {
+ out = new File("./build/latestchanges.html");
+ } else {
+ out = new File(in, "output/latestchanges.html");
+ }
+ } else {
+ out = new File(argOut);
+ }
+ WebsiteMaker maker = new WebsiteMaker(version, fullVersion, in, out.getParentFile());
+ maker.buildChangelogLatest(out);
+ }
+
+ public static void main(String[] args) throws Exception {
+ String version, fullVersion;
+
+ if (args.length < 2) {
+ version = VersionFinder.getVersion();
+ fullVersion = VersionFinder.getFullVersion();
+ } else {
+ version = args[0];
+ fullVersion = args[1];
+ }
+
+ if (args.length < 3 || args[2].equalsIgnoreCase("all")) {
+ buildAll(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else if (args[2].equalsIgnoreCase("changelog")) {
+ buildChangelog(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else if (args[2].equalsIgnoreCase("download-edge")) {
+ buildDownloadEdge(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else if (args[2].equalsIgnoreCase("changelog-latest")) {
+ buildChangelogLatest(version, fullVersion, args.length < 4 ? null : args[3], args.length < 5 ? null : args[4]);
+ } else {
+ throw new IllegalArgumentException("3rd argument must be one of 'all', 'changelog', 'download-edge', 'changelog-latest'");
+ }
+ }
+
+ private Configuration makeFreemarkerConfig() throws IOException {
+ Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_25);
+ freemarkerConfig.setEncoding(Locale.ENGLISH, "UTF-8");
+ freemarkerConfig.setOutputEncoding("UTF-8");
+ freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ freemarkerConfig.setTemplateLoader(createLoader());
+ freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+ return freemarkerConfig;
+ }
+
+ public void buildChangelog(File out) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+ outputDir.mkdirs();
+ convertChangelog(freemarkerConfig, out);
+ }
+
+ public void buildChangelogLatest(File out) throws Exception {
+ outputDir.mkdirs();
+ String htmlForLatest = CompileChangelog.getHtmlForLatest(baseDir.getParentFile(), version);
+ FileOutputStream fos = new FileOutputStream(out);
+ try {
+ BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(fos, "UTF-8"));
+ bw.write(htmlForLatest);
+ bw.close();
+ } finally {
+ fos.close();
+ }
+ }
+
+ public void buildDownloadEdge(File out) throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+
+ outputDir.mkdirs();
+ convertDownloadEdge(freemarkerConfig, out);
+ }
+
+ public void buildHtAccess(File out) throws Exception {
+ Configuration freemarkerConfig = new Configuration(Configuration.VERSION_2_3_25);
+ freemarkerConfig.setEncoding(Locale.ENGLISH, "UTF-8");
+ freemarkerConfig.setOutputEncoding("UTF-8");
+ freemarkerConfig.setOutputFormat(HTMLOutputFormat.INSTANCE);
+ freemarkerConfig.setTemplateLoader(createLoader("extra"));
+ freemarkerConfig.setTemplateExceptionHandler(TemplateExceptionHandler.RETHROW_HANDLER);
+
+ outputDir.mkdirs();
+ convertHtAccess(freemarkerConfig, out);
+ }
+
+ public void buildWebsite() throws Exception {
+ Configuration freemarkerConfig = makeFreemarkerConfig();
+
+ outputDir.mkdirs();
+ convertTemplates(freemarkerConfig);
+ buildHtAccess(new File(outputDir, ".htaccess"));
+ }
+
+ private TemplateLoader createLoader() throws IOException {
+ return createLoader("templates");
+ }
+
+ private TemplateLoader createLoader(String base) throws IOException {
+ return new FileTemplateLoader(new File(baseDir, base));
+ }
+
+ private void convertHtAccess(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = new HashMap<String, Object>();
+ dataModel.put("setupPages", listHtmlNames(new File(outputDir, "setup")));
+ dataModel.put("featurePages", listHtmlNames(new File(outputDir, "features")));
+ dataModel.put("experimentalPages", listHtmlNames(new File(outputDir, "features/experimental")));
+ Template template = freemarker.getTemplate("htaccess");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private List<String> listHtmlNames(File dir) {
+ List<String> out = new ArrayList<String>();
+ for (String s : dir.list()) {
+ if (s.endsWith(".html") && !s.equals("index.html")) out.add(s.substring(0, s.length() - 5));
+ }
+ return out;
+ }
+
+ private void convertChangelog(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = createBasicDataModel();
+
+ Template template = freemarker.getTemplate("changelog.html");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private void convertDownloadEdge(Configuration freemarker, File outFile) throws Exception {
+ Map<String, Object> dataModel = createBasicDataModel();
+
+ Template template = freemarker.getTemplate("_download-edge.html");
+ FileOutputStream fileOut = new FileOutputStream(outFile);
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+
+ private void convertTemplates(Configuration freemarker) throws Exception {
+ File basePagesLoc = new File(baseDir, "templates");
+ Map<String, Object> dataModel = createBasicDataModel();
+ dataModel.putAll(createExtendedDataModel());
+ convertTemplates_(freemarker, "", basePagesLoc, outputDir, 0, dataModel);
+ }
+
+ private void convertTemplates_(Configuration freemarker, String prefix, File from, File to, int depth, Map<String, Object> dataModel) throws Exception {
+ if (depth > 50) throw new IllegalArgumentException("50 levels is too deep: " + from);
+
+ for (File f : from.listFiles()) {
+ if (f.isDirectory()) convertTemplates_(freemarker, prefix + f.getName() + "/", f, new File(to, f.getName()), depth + 1, dataModel);
+ if (!f.isFile() || !f.getName().endsWith(".html") || f.getName().startsWith("_")) continue;
+ to.mkdirs();
+ Template template = freemarker.getTemplate(prefix + f.getName());
+ FileOutputStream fileOut = new FileOutputStream(new File(to, f.getName()));
+ try {
+ Writer wr = new BufferedWriter(new OutputStreamWriter(fileOut, "UTF-8"));
+ template.process(dataModel, wr);
+ wr.close();
+ } finally {
+ fileOut.close();
+ }
+ }
+ }
+
+ private Map<String, Object> createBasicDataModel() throws IOException {
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss 'UTC'");
+ sdf.setTimeZone(TimeZone.getTimeZone("UTC"));
+ String currentTime = sdf.format(new Date());
+
+ data.put("version", version);
+ data.put("fullVersion", fullVersion);
+ data.put("timestampString", currentTime);
+ data.put("year", "" + new GregorianCalendar().get(Calendar.YEAR));
+ data.put("changelog", CompileChangelog.getHtmlStartingAtSection(baseDir.getParentFile(), version));
+ data.put("changelogEdge", CompileChangelog.getHtmlForEdge(baseDir.getParentFile(), version));
+
+ return data;
+ }
+
+ private static final Pattern LOMBOK_LINK = Pattern.compile("^.*<a(?: (?:id|class|rel|rev|download|target|type)(?:=\"[^\"]*\")?)* href=\"(downloads/[^\"]+)\"(?: (?:id|class|rel|rev|download|target|type)(?:=\"[^\"]*\")?)*>([^<]+)</a>.*$");
+ private Map<String, Object> createExtendedDataModel() throws IOException {
+ Map<String, Object> data = new HashMap<String, Object>();
+
+ data.put("usages", new HtmlMaker(new File(baseDir, "usageExamples")));
+ InputStream in = new URL("https://projectlombok.org/all-versions.html").openStream();
+ ArrayList<List<String>> links = new ArrayList<List<String>>();
+ try {
+ BufferedReader br = new BufferedReader(new InputStreamReader(in, "UTF-8"));
+ for (String line = br.readLine(); line != null; line = br.readLine()) {
+ Matcher m = LOMBOK_LINK.matcher(line);
+ if (m.matches()) links.add(Arrays.asList(m.group(1), m.group(2)));
+ }
+ } finally {
+ in.close();
+ }
+
+ data.put("linksToVersions", links);
+
+ return data;
+ }
+
+ public static class HtmlMaker {
+ private final File usagesDir;
+
+ HtmlMaker(File usagesDir) {
+ this.usagesDir = usagesDir;
+ }
+
+ public String pre(String name) throws IOException {
+ return convert(new File(usagesDir, name + "Example_pre.jpage"));
+ }
+
+ public String post(String name) throws IOException {
+ return convert(new File(usagesDir, name + "Example_post.jpage"));
+ }
+
+ public String convert(File file) throws IOException {
+ String rawJava = readFully(file);
+ return Java2Html.convertToHtml(rawJava);
+ }
+ }
+
+ public static String readFully(File file) throws IOException {
+ FileInputStream fis = new FileInputStream(file);
+ try {
+ InputStreamReader isr = new InputStreamReader(fis, "UTF-8");
+ StringBuilder out = new StringBuilder();
+ char[] b = new char[65536];
+ while (true) {
+ int r = isr.read(b);
+ if (r == -1) break;
+ out.append(b, 0, r);
+ }
+ return out.toString();
+ } finally {
+ fis.close();
+ }
+ }
+}
diff --git a/ssh.knownHosts b/ssh.knownHosts
new file mode 100644
index 00000000..873e852f
--- /dev/null
+++ b/ssh.knownHosts
@@ -0,0 +1,2 @@
+projectlombok.org:22:ECDSA:X.509:MIIBMzCB7AYHKoZIzj0CATCB4AIBATAsBgcqhkjOPQEBAiEA/////wAAAAEAAAAAAAAAAAAAAAD///////////////8wRAQg/////wAAAAEAAAAAAAAAAAAAAAD///////////////wEIFrGNdiqOpPns+u9VXaYhrxlHQawzFOw9jvOPD4n0mBLBEEEaxfR8uEsQkf4vOblY6RA8ncDfYEt6zOg9KE5RdiYwpZP40Li/hp/m47n60p8D54WK84zV2sxXs7LtkBoN79R9QIhAP////8AAAAA//////////+85vqtpxeehPO5ysL8YyVRAgEBA0IABKwMbAFQuRwz9+PnuBOlc1OqPAYVhg0VBTGQ1G5V6JVfb0CU5GH4NEFp+jEAoGCZNrghB0XLB3d3egfF06ihDgE=
+
diff --git a/test/configuration/resource/configurationRoot/out.txt b/test/configuration/resource/configurationRoot/out.txt
index 625115a4..8100fadb 100644
--- a/test/configuration/resource/configurationRoot/out.txt
+++ b/test/configuration/resource/configurationRoot/out.txt
@@ -6,15 +6,15 @@ lombok.accessors.flagUsage = ERROR
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/d1/d11/lombok.config:
-# 3: lombok.accessors.flagUsage = ERROR
+# 4: lombok.accessors.flagUsage = ERROR
-# Generate setters that return 'this' instead of 'void'.
+# Generate setters that return 'this' instead of 'void' (default: false).
lombok.accessors.chain = false
# BASE/d1/lombok.config:
# <'lombok.accessors.chain' not mentioned>
#
# BASE/d1/d11/lombok.config:
-# 2: lombok.accessors.chain = false
+# 3: lombok.accessors.chain = false
# Strip this field prefix, like 'f' or 'm_', from the names of generated getters and setters.
lombok.accessors.prefix += f
@@ -22,9 +22,9 @@ lombok.accessors.prefix += f
# <'lombok.accessors.prefix' not mentioned>
#
# BASE/d1/d11/lombok.config:
-# 4: lombok.accessors.prefix += f
+# 5: lombok.accessors.prefix += f
-# Use this name for the generated logger fields (default: 'log')
+# Use this name for the generated logger fields (default: 'log').
clear lombok.log.fieldName
@@ -38,18 +38,18 @@ lombok.accessors.flagUsage = ERROR
# <'lombok.accessors.flagUsage' not mentioned>
#
# BASE/d1/d11/lombok.config:
-# 3: lombok.accessors.flagUsage = ERROR
+# 4: lombok.accessors.flagUsage = ERROR
#
# BASE/d1/d11/d111/lombok.config:
# <'lombok.accessors.flagUsage' not mentioned>
-# Generate setters that return 'this' instead of 'void'.
+# Generate setters that return 'this' instead of 'void' (default: false).
clear lombok.accessors.chain
# BASE/d1/lombok.config:
# <'lombok.accessors.chain' not mentioned>
#
# BASE/d1/d11/lombok.config:
-# 2: lombok.accessors.chain = false
+# 3: lombok.accessors.chain = false
#
# BASE/d1/d11/d111/lombok.config:
# 1: clear lombok.accessors.chain
@@ -61,12 +61,12 @@ lombok.accessors.prefix += m_
# <'lombok.accessors.prefix' not mentioned>
#
# BASE/d1/d11/lombok.config:
-# 4: lombok.accessors.prefix += f
+# 5: lombok.accessors.prefix += f
#
# BASE/d1/d11/d111/lombok.config:
# 2: lombok.accessors.prefix += m_
-# Use this name for the generated logger fields (default: 'log')
+# Use this name for the generated logger fields (default: 'log').
clear lombok.log.fieldName
@@ -75,16 +75,16 @@ Configuration for 'BASE/d1/d12'.
# Emit a warning or error if @Accessors is used.
clear lombok.accessors.flagUsage
-# Generate setters that return 'this' instead of 'void'.
+# Generate setters that return 'this' instead of 'void' (default: false).
lombok.accessors.chain = true
# BASE/d1/lombok.config:
# <'lombok.accessors.chain' not mentioned>
#
# BASE/d1/d12/lombok.config:
-# 2: lombok.accessors.chain = true
+# 3: lombok.accessors.chain = true
# Strip this field prefix, like 'f' or 'm_', from the names of generated getters and setters.
clear lombok.accessors.prefix
-# Use this name for the generated logger fields (default: 'log')
+# Use this name for the generated logger fields (default: 'log').
clear lombok.log.fieldName \ No newline at end of file
diff --git a/test/core/src/lombok/AbstractRunTests.java b/test/core/src/lombok/AbstractRunTests.java
index a1f535b4..1a454585 100644
--- a/test/core/src/lombok/AbstractRunTests.java
+++ b/test/core/src/lombok/AbstractRunTests.java
@@ -35,9 +35,11 @@ import java.util.Collection;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
+import java.util.Map;
import org.junit.Assert;
+import lombok.DirectoryRunner.FileTester;
import lombok.core.AST;
import lombok.core.LombokConfiguration;
import lombok.core.LombokImmutableList;
@@ -53,51 +55,51 @@ public abstract class AbstractRunTests {
this.dumpActualFilesHere = findPlaceToDumpActualFiles();
}
- public boolean compareFile(DirectoryRunner.TestParams params, File file) throws Throwable {
+ public final FileTester createTester(final DirectoryRunner.TestParams params, final File file, String platform, int version) throws IOException {
ConfigurationKeysLoader.LoaderLoader.loadAllConfigurationKeys();
- final LombokTestSource sourceDirectives = LombokTestSource.readDirectives(file);
- if (sourceDirectives.isIgnore()) return false;
- if (!sourceDirectives.versionWithinLimit(params.getVersion())) return false;
- if (!sourceDirectives.versionWithinLimit(getClasspathVersion())) return false;
+ AssertionError directiveFailure = null;
+ LombokTestSource sourceDirectives = null;
+ try {
+ sourceDirectives = LombokTestSource.readDirectives(file);
+ if (sourceDirectives.isIgnore()) return null;
+ if (!sourceDirectives.versionWithinLimit(version)) return null;
+ if (!sourceDirectives.runOnPlatform(platform)) return null;
+ } catch (AssertionError ae) {
+ directiveFailure = ae;
+ }
String fileName = file.getName();
- LombokTestSource expected = LombokTestSource.read(params.getAfterDirectory(), params.getMessagesDirectory(), fileName);
+ final LombokTestSource expected = LombokTestSource.read(params.getAfterDirectory(), params.getMessagesDirectory(), fileName);
- if (expected.isIgnore()) return false;
- if (!expected.versionWithinLimit(params.getVersion())) return false;
+ if (expected.isIgnore()) return null;
+ if (!expected.versionWithinLimit(params.getVersion())) return null;
+ if (!expected.versionWithinLimit(version)) return null;
- LinkedHashSet<CompilerMessage> messages = new LinkedHashSet<CompilerMessage>();
- StringWriter writer = new StringWriter();
-
- LombokConfiguration.overrideConfigurationResolverFactory(new ConfigurationResolverFactory() {
- @Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
- return sourceDirectives.getConfiguration();
+ final LombokTestSource sourceDirectives_ = sourceDirectives;
+ final AssertionError directiveFailure_ = directiveFailure;
+ return new FileTester() {
+ @Override public void runTest() throws Throwable {
+ if (directiveFailure_ != null) throw directiveFailure_;
+ LinkedHashSet<CompilerMessage> messages = new LinkedHashSet<CompilerMessage>();
+ StringWriter writer = new StringWriter();
+
+ LombokConfiguration.overrideConfigurationResolverFactory(new ConfigurationResolverFactory() {
+ @Override public ConfigurationResolver createResolver(AST<?, ?, ?> ast) {
+ return sourceDirectives_.getConfiguration();
+ }
+ });
+
+ boolean changed = transformCode(messages, writer, file, sourceDirectives_.getSpecifiedEncoding(), sourceDirectives_.getFormatPreferences());
+ boolean forceUnchanged = sourceDirectives_.forceUnchanged() || sourceDirectives_.isSkipCompareContent();
+ if (params.expectChanges() && !forceUnchanged && !changed) messages.add(new CompilerMessage(-1, -1, true, "not flagged modified"));
+ if (!params.expectChanges() && changed) messages.add(new CompilerMessage(-1, -1, true, "unexpected modification"));
+
+ compare(file.getName(), expected, writer.toString(), messages, params.printErrors(), sourceDirectives_.isSkipCompareContent() || expected.isSkipCompareContent());
}
- });
-
- transformCode(messages, writer, file);
-
- compare(file.getName(), expected, writer.toString(), messages, params.printErrors(), sourceDirectives.isSkipCompareContent() || expected.isSkipCompareContent());
- return true;
- }
-
- private static int getClasspathVersion() {
- try {
- Class.forName("java.lang.AutoCloseable");
- } catch (ClassNotFoundException e) {
- return 6;
- }
-
- try {
- Class.forName("java.util.stream.Stream");
- } catch (ClassNotFoundException e) {
- return 7;
- }
-
- return 8;
+ };
}
- protected abstract void transformCode(Collection<CompilerMessage> messages, StringWriter result, File file) throws Throwable;
+ protected abstract boolean transformCode(Collection<CompilerMessage> messages, StringWriter result, File file, String encoding, Map<String, String> formatPreferences) throws Throwable;
protected String readFile(File file) throws IOException {
BufferedReader reader;
diff --git a/test/core/src/lombok/DirectoryRunner.java b/test/core/src/lombok/DirectoryRunner.java
index 9062f523..72f01de1 100644
--- a/test/core/src/lombok/DirectoryRunner.java
+++ b/test/core/src/lombok/DirectoryRunner.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2014 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -23,6 +23,7 @@ package lombok;
import java.io.File;
import java.io.FileFilter;
+import java.io.IOException;
import java.util.Map;
import java.util.TreeMap;
@@ -69,6 +70,8 @@ public class DirectoryRunner extends Runner {
public boolean accept(File file) {
return true;
}
+
+ public abstract boolean expectChanges();
}
private static final FileFilter JAVA_FILE_FILTER = new FileFilter() {
@@ -114,19 +117,29 @@ public class DirectoryRunner extends Runner {
@Override
public void run(RunNotifier notifier) {
if (failure != null) {
- notifier.fireTestStarted(description);
- notifier.fireTestFailure(new Failure(description, failure));
- notifier.fireTestFinished(description);
+ reportInitializationFailure(notifier, description, failure);
return;
}
for (Map.Entry<String, Description> entry : tests.entrySet()) {
Description testDescription = entry.getValue();
+
+ FileTester tester;
+ try {
+ tester = createTester(entry.getKey());
+ } catch (IOException e) {
+ reportInitializationFailure(notifier, testDescription, e);
+ continue;
+ }
+
+ if (tester == null) {
+ notifier.fireTestIgnored(testDescription);
+ continue;
+ }
+
notifier.fireTestStarted(testDescription);
try {
- if (!runTest(entry.getKey())) {
- notifier.fireTestIgnored(testDescription);
- }
+ tester.runTest();
} catch (Throwable t) {
notifier.fireTestFailure(new Failure(testDescription, t));
}
@@ -134,17 +147,26 @@ public class DirectoryRunner extends Runner {
}
}
- private boolean runTest(String fileName) throws Throwable {
+ private void reportInitializationFailure(RunNotifier notifier, Description description, Throwable throwable) {
+ notifier.fireTestStarted(description);
+ notifier.fireTestFailure(new Failure(description, throwable));
+ notifier.fireTestFinished(description);
+ }
+
+ private FileTester createTester(String fileName) throws IOException {
File file = new File(params.getBeforeDirectory(), fileName);
-
switch (params.getCompiler()) {
case DELOMBOK:
- return new RunTestsViaDelombok().compareFile(params, file);
+ return new RunTestsViaDelombok().createTester(params, file, "javac", params.getVersion());
case ECJ:
- return new RunTestsViaEcj().compareFile(params, file);
+ return new RunTestsViaEcj().createTester(params, file, "ecj", params.getVersion());
default:
case JAVAC:
throw new UnsupportedOperationException();
}
}
+
+ public interface FileTester {
+ void runTest() throws Throwable;
+ }
}
diff --git a/test/core/src/lombok/LombokTestSource.java b/test/core/src/lombok/LombokTestSource.java
index 402001e9..31f7db3e 100644
--- a/test/core/src/lombok/LombokTestSource.java
+++ b/test/core/src/lombok/LombokTestSource.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2014 The Project Lombok Authors.
+ * Copyright (C) 2014-2015 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
@@ -26,10 +26,14 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
+import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.Collections;
+import java.util.HashMap;
import java.util.List;
+import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
@@ -45,10 +49,20 @@ public class LombokTestSource {
private final File file;
private final String content;
private final LombokImmutableList<CompilerMessageMatcher> messages;
+ private final Map<String, String> formatPreferences;
private final boolean ignore;
private final boolean skipCompareContent;
+ private final boolean unchanged;
private final int versionLowerLimit, versionUpperLimit;
private final ConfigurationResolver configuration;
+ private final String specifiedEncoding;
+ private final List<String> platforms;
+
+ public boolean runOnPlatform(String platform) {
+ if (platforms == null || platforms.isEmpty()) return true;
+ for (String pl : platforms) if (pl.equalsIgnoreCase(platform)) return true;
+ return false;
+ }
public boolean versionWithinLimit(int version) {
return version >= versionLowerLimit && version <= versionUpperLimit;
@@ -70,14 +84,26 @@ public class LombokTestSource {
return ignore;
}
+ public boolean forceUnchanged() {
+ return unchanged;
+ }
+
public boolean isSkipCompareContent() {
return skipCompareContent;
}
+ public String getSpecifiedEncoding() {
+ return specifiedEncoding;
+ }
+
public ConfigurationResolver getConfiguration() {
return configuration;
}
+ public Map<String, String> getFormatPreferences() {
+ return formatPreferences;
+ }
+
private static final Pattern VERSION_STYLE_1 = Pattern.compile("^(\\d+)$");
private static final Pattern VERSION_STYLE_2 = Pattern.compile("^\\:(\\d+)$");
private static final Pattern VERSION_STYLE_3 = Pattern.compile("^(\\d+):$");
@@ -111,7 +137,8 @@ public class LombokTestSource {
}
private static final Pattern IGNORE_PATTERN = Pattern.compile("^\\s*ignore\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE);
- private static final Pattern SKIP_COMPARE_CONTENT_PATTERN = Pattern.compile("^\\s*skip[- ]?compare[- ]?content\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE);
+ private static final Pattern UNCHANGED_PATTERN = Pattern.compile("^\\s*unchanged\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE);
+ private static final Pattern SKIP_COMPARE_CONTENT_PATTERN = Pattern.compile("^\\s*skip[- ]?compare[- ]?contents?\\s*(?:[-:].*)?$", Pattern.CASE_INSENSITIVE);
private LombokTestSource(File file, String content, List<CompilerMessageMatcher> messages, List<String> directives) {
this.file = file;
@@ -123,6 +150,10 @@ public class LombokTestSource {
int versionUpper = Integer.MAX_VALUE;
boolean ignore = false;
boolean skipCompareContent = false;
+ boolean unchanged = false;
+ String encoding = null;
+ Map<String, String> formats = new HashMap<String, String>();
+ String[] platformLimit = null;
for (String directive : directives) {
directive = directive.trim();
@@ -132,11 +163,24 @@ public class LombokTestSource {
continue;
}
+ if (UNCHANGED_PATTERN.matcher(directive).matches()) {
+ unchanged = true;
+ continue;
+ }
+
if (SKIP_COMPARE_CONTENT_PATTERN.matcher(directive).matches()) {
skipCompareContent = true;
continue;
}
+ if (lc.startsWith("platform ")) {
+ String platformDesc = lc.substring("platform ".length());
+ int idx = platformDesc.indexOf(':');
+ if (idx != -1) platformDesc = platformDesc.substring(0, idx).trim();
+ platformLimit = platformDesc.split("\\s*,\\s*");
+ continue;
+ }
+
if (lc.startsWith("version ")) {
int[] limits = parseVersionLimit(lc.substring(7).trim());
if (limits == null) {
@@ -154,14 +198,33 @@ public class LombokTestSource {
continue;
}
+ if (lc.startsWith("encoding:")) {
+ encoding = directive.substring(9).trim();
+ continue;
+ }
+
+ if (lc.startsWith("format:")) {
+ String formatLine = directive.substring(7).trim();
+ int idx = formatLine.indexOf('=');
+ if (idx == -1) throw new IllegalArgumentException("To add a format directive, use: \"//FORMAT: javaLangAsFQN = skip\"");
+ String key = formatLine.substring(0, idx).trim();
+ String value = formatLine.substring(idx + 1).trim();
+ formats.put(key.toLowerCase(), value);
+ continue;
+ }
+
+ if (lc.startsWith("issue ")) continue;
+
Assert.fail("Directive line \"" + directive + "\" in '" + file.getAbsolutePath() + "' invalid: unrecognized directive.");
throw new RuntimeException();
}
-
+ this.specifiedEncoding = encoding;
this.versionLowerLimit = versionLower;
this.versionUpperLimit = versionUpper;
this.ignore = ignore;
this.skipCompareContent = skipCompareContent;
+ this.unchanged = unchanged;
+ this.platforms = platformLimit == null ? null : Arrays.asList(platformLimit);
ConfigurationProblemReporter reporter = new ConfigurationProblemReporter() {
@Override public void report(String sourceDescription, String problem, int lineNumber, CharSequence line) {
Assert.fail("Problem on directive line: " + problem + " at conf line #" + lineNumber + " (" + line + ")");
@@ -169,55 +232,76 @@ public class LombokTestSource {
};
this.configuration = new BubblingConfigurationResolver(Collections.singleton(StringConfigurationSource.forString(conf, reporter, file.getAbsolutePath())));
+ this.formatPreferences = Collections.unmodifiableMap(formats);
}
public static LombokTestSource readDirectives(File file) throws IOException {
List<String> directives = new ArrayList<String>();
{
- @Cleanup val rawIn = new FileInputStream(file);
- BufferedReader in = new BufferedReader(new InputStreamReader(rawIn, "UTF-8"));
- for (String i = in.readLine(); i != null; i = in.readLine()) {
- if (i.isEmpty()) continue;
-
- if (i.startsWith("//")) {
- directives.add(i.substring(2));
- } else {
- break;
+ InputStream rawIn = new FileInputStream(file);
+ try {
+ BufferedReader in = new BufferedReader(new InputStreamReader(rawIn, "UTF-8"));
+ try {
+ for (String i = in.readLine(); i != null; i = in.readLine()) {
+ if (i.isEmpty()) continue;
+
+ if (i.startsWith("//")) {
+ directives.add(i.substring(2));
+ } else {
+ break;
+ }
+ }
}
+ finally {
+ in.close();
+ }
+ }
+ finally {
+ rawIn.close();
}
- in.close();
- rawIn.close();
}
return new LombokTestSource(file, "", null, directives);
}
public static LombokTestSource read(File sourceFolder, File messagesFolder, String fileName) throws IOException {
+ return read0(sourceFolder, messagesFolder, fileName, "UTF-8");
+ }
+
+ private static LombokTestSource read0(File sourceFolder, File messagesFolder, String fileName, String encoding) throws IOException {
StringBuilder content = null;
List<String> directives = new ArrayList<String>();
File sourceFile = new File(sourceFolder, fileName);
if (sourceFile.exists()) {
- @Cleanup val rawIn = new FileInputStream(sourceFile);
- BufferedReader in = new BufferedReader(new InputStreamReader(rawIn, "UTF-8"));
- for (String i = in.readLine(); i != null; i = in.readLine()) {
- if (content != null) {
- content.append(i).append("\n");
- continue;
+ InputStream rawIn = new FileInputStream(sourceFile);
+ try {
+ BufferedReader in = new BufferedReader(new InputStreamReader(rawIn, encoding));
+ try {
+ for (String i = in.readLine(); i != null; i = in.readLine()) {
+ if (content != null) {
+ content.append(i).append("\n");
+ continue;
+ }
+
+ if (i.isEmpty()) continue;
+
+ if (i.startsWith("//")) {
+ directives.add(i.substring(2));
+ } else {
+ content = new StringBuilder();
+ content.append(i).append("\n");
+ }
+ }
}
-
- if (i.isEmpty()) continue;
-
- if (i.startsWith("//")) {
- directives.add(i.substring(2));
- } else {
- content = new StringBuilder();
- content.append(i).append("\n");
+ finally {
+ in.close();
}
}
- in.close();
- rawIn.close();
+ finally {
+ rawIn.close();
+ }
}
if (content == null) content = new StringBuilder();
@@ -226,14 +310,27 @@ public class LombokTestSource {
if (messagesFolder != null) {
File messagesFile = new File(messagesFolder, fileName + ".messages");
try {
- @Cleanup val rawIn = new FileInputStream(messagesFile);
- messages = CompilerMessageMatcher.readAll(rawIn);
- rawIn.close();
+ InputStream rawIn = new FileInputStream(messagesFile);
+ try {
+ messages = CompilerMessageMatcher.readAll(rawIn);
+ }
+ finally {
+ rawIn.close();
+ }
} catch (FileNotFoundException e) {
messages = null;
}
}
- return new LombokTestSource(sourceFile, content.toString(), messages, directives);
+ LombokTestSource source = new LombokTestSource(sourceFile, content.toString(), messages, directives);
+ String specifiedEncoding = source.getSpecifiedEncoding();
+
+ // The source file has an 'encoding' header to test encoding issues. Of course, reading the encoding header
+ // requires knowing the encoding of the file first. In practice we get away with it, because UTF-8 and US-ASCII are compatible enough.
+ // The fix is therefore to read in as UTF-8 initially, and if the file requests that it should be read as another encoding, toss it all
+ // and reread that way.
+
+ if (specifiedEncoding == null || specifiedEncoding.equalsIgnoreCase(encoding)) return source;
+ return read0(sourceFolder, messagesFolder, fileName, specifiedEncoding);
}
}
diff --git a/test/core/src/lombok/RunAllTests.java b/test/core/src/lombok/RunAllTests.java
index 9f56b45b..1ca76af5 100644
--- a/test/core/src/lombok/RunAllTests.java
+++ b/test/core/src/lombok/RunAllTests.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2011-2014 The Project Lombok Authors.
+ * Copyright (C) 2011-2015 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
@@ -26,6 +26,6 @@ import org.junit.runners.Suite;
import org.junit.runners.Suite.SuiteClasses;
@RunWith(Suite.class)
-@SuiteClasses({lombok.transform.RunTransformTests.class, lombok.bytecode.RunBytecodeTests.class, lombok.core.configuration.RunConfigurationTests.class})
+@SuiteClasses({lombok.transform.RunTransformTests.class, lombok.bytecode.RunBytecodeTests.class, lombok.core.configuration.RunConfigurationTests.class, lombok.core.RunCoreTests.class})
public class RunAllTests {
}
diff --git a/test/core/src/lombok/RunTestsViaDelombok.java b/test/core/src/lombok/RunTestsViaDelombok.java
index 6a08642b..0887de32 100644
--- a/test/core/src/lombok/RunTestsViaDelombok.java
+++ b/test/core/src/lombok/RunTestsViaDelombok.java
@@ -21,10 +21,14 @@
*/
package lombok;
+import java.io.ByteArrayOutputStream;
import java.io.File;
+import java.io.PrintStream;
import java.io.StringWriter;
+import java.io.UnsupportedEncodingException;
import java.util.Collection;
import java.util.Locale;
+import java.util.Map;
import lombok.delombok.Delombok;
import lombok.javac.CapturingDiagnosticListener;
@@ -34,10 +38,13 @@ public class RunTestsViaDelombok extends AbstractRunTests {
private Delombok delombok = new Delombok();
@Override
- public void transformCode(Collection<CompilerMessage> messages, StringWriter result, final File file) throws Throwable {
- delombok.setVerbose(false);
+ public boolean transformCode(Collection<CompilerMessage> messages, StringWriter result, final File file, String encoding, Map<String, String> formatPreferences) throws Throwable {
+ delombok.setVerbose(true);
+ ChangedChecker cc = new ChangedChecker();
+ delombok.setFeedback(cc.feedback);
delombok.setForceProcess(true);
- delombok.setCharset("UTF-8");
+ delombok.setCharset(encoding == null ? "UTF-8" : encoding);
+ delombok.setFormatPreferences(formatPreferences);
delombok.setDiagnosticsListener(new CapturingDiagnosticListener(file, messages));
@@ -50,8 +57,23 @@ public class RunTestsViaDelombok extends AbstractRunTests {
try {
Locale.setDefault(Locale.ENGLISH);
delombok.delombok();
+ return cc.isChanged();
} finally {
Locale.setDefault(originalLocale);
}
}
+
+ static class ChangedChecker {
+ private final ByteArrayOutputStream bytes = new ByteArrayOutputStream();
+ private final PrintStream feedback;
+
+ ChangedChecker() throws UnsupportedEncodingException {
+ feedback = new PrintStream(bytes, true, "UTF-8");
+ }
+
+ boolean isChanged() throws UnsupportedEncodingException {
+ feedback.flush();
+ return bytes.toString("UTF-8").endsWith("[delomboked]\n");
+ }
+ }
}
diff --git a/test/core/src/lombok/RunTestsViaEcj.java b/test/core/src/lombok/RunTestsViaEcj.java
index f4584493..6ed1e950 100644
--- a/test/core/src/lombok/RunTestsViaEcj.java
+++ b/test/core/src/lombok/RunTestsViaEcj.java
@@ -24,7 +24,6 @@ package lombok;
import java.io.File;
import java.io.StringWriter;
import java.util.ArrayList;
-import java.util.Arrays;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
@@ -93,7 +92,7 @@ public class RunTestsViaEcj extends AbstractRunTests {
}
@Override
- public void transformCode(Collection<CompilerMessage> messages, StringWriter result, File file) throws Throwable {
+ public boolean transformCode(Collection<CompilerMessage> messages, StringWriter result, File file, String encoding, Map<String, String> formatPreferences) throws Throwable {
final AtomicReference<CompilationResult> compilationResult_ = new AtomicReference<CompilationResult>();
final AtomicReference<CompilationUnitDeclaration> compilationUnit_ = new AtomicReference<CompilationUnitDeclaration>();
ICompilerRequestor bitbucketRequestor = new ICompilerRequestor() {
@@ -103,7 +102,7 @@ public class RunTestsViaEcj extends AbstractRunTests {
};
String source = readFile(file);
- final CompilationUnit sourceUnit = new CompilationUnit(source.toCharArray(), file.getName(), "UTF-8");
+ final CompilationUnit sourceUnit = new CompilationUnit(source.toCharArray(), file.getName(), encoding == null ? "UTF-8" : encoding);
Compiler ecjCompiler = new Compiler(createFileSystem(file), ecjErrorHandlingPolicy(), ecjCompilerOptions(), bitbucketRequestor, new DefaultProblemFactory(Locale.ENGLISH)) {
@Override protected synchronized void addCompilationUnit(ICompilationUnit inUnit, CompilationUnitDeclaration parsedUnit) {
@@ -112,8 +111,6 @@ public class RunTestsViaEcj extends AbstractRunTests {
}
};
- // TODO: Create a configuration based on confLines and set this up so that this compile run will use them.
-
ecjCompiler.compile(new ICompilationUnit[] {sourceUnit});
CompilationResult compilationResult = compilationResult_.get();
@@ -127,22 +124,28 @@ public class RunTestsViaEcj extends AbstractRunTests {
if (cud == null) result.append("---- NO CompilationUnit provided by ecj ----");
else result.append(cud.toString());
+
+ return true;
}
private FileSystem createFileSystem(File file) {
List<String> classpath = new ArrayList<String>();
- classpath.addAll(Arrays.asList(System.getProperty("sun.boot.class.path").split(File.pathSeparator)));
for (Iterator<String> i = classpath.iterator(); i.hasNext();) {
if (FileSystem.getClasspath(i.next(), "UTF-8", null) == null) {
i.remove();
}
}
+ if (new File("bin").exists()) classpath.add("bin");
classpath.add("dist/lombok.jar");
+ classpath.add("lib/oracleJDK8Environment/rt.jar");
classpath.add("lib/test/commons-logging-commons-logging.jar");
classpath.add("lib/test/org.slf4j-slf4j-api.jar");
classpath.add("lib/test/org.slf4j-slf4j-ext.jar");
classpath.add("lib/test/log4j-log4j.jar");
classpath.add("lib/test/org.apache.logging.log4j-log4j-api.jar");
+ classpath.add("lib/test/org.jboss.logging-jboss-logging.jar");
+ classpath.add("lib/test/com.google.guava-guava.jar");
+ classpath.add("lib/test/com.google.code.findbugs-findbugs.jar");
return new FileSystem(classpath.toArray(new String[0]), new String[] {file.getAbsolutePath()}, "UTF-8");
}
}
diff --git a/test/core/src/lombok/core/RunCoreTests.java b/test/core/src/lombok/core/RunCoreTests.java
new file mode 100644
index 00000000..8ac7cf81
--- /dev/null
+++ b/test/core/src/lombok/core/RunCoreTests.java
@@ -0,0 +1,31 @@
+/*
+ * Copyright (C) 2015 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 org.junit.runner.RunWith;
+import org.junit.runners.Suite;
+import org.junit.runners.Suite.SuiteClasses;
+
+@RunWith(Suite.class)
+@SuiteClasses({TestSingulars.class})
+public class RunCoreTests {
+}
diff --git a/test/core/src/lombok/core/TestSingulars.java b/test/core/src/lombok/core/TestSingulars.java
new file mode 100644
index 00000000..4560615d
--- /dev/null
+++ b/test/core/src/lombok/core/TestSingulars.java
@@ -0,0 +1,56 @@
+/*
+ * Copyright (C) 2015-2017 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 static lombok.core.handlers.Singulars.autoSingularize;
+import static org.junit.Assert.*;
+
+import org.junit.Test;
+
+public class TestSingulars {
+ @Test
+ public void testSingulars() {
+ assertNull("axes", autoSingularize("axes"));
+ assertEquals("adjective", autoSingularize("adjectives"));
+ assertEquals("bus", autoSingularize("buses"));
+ assertEquals("octopus", autoSingularize("octopodes"));
+ assertNull("octopi", autoSingularize("octopi"));
+ assertEquals("elf", autoSingularize("elves"));
+ assertEquals("jack", autoSingularize("jacks"));
+ assertEquals("colloquy", autoSingularize("colloquies"));
+ assertNull("series", autoSingularize("series"));
+ assertEquals("man", autoSingularize("men"));
+ assertNull("highwaymen", autoSingularize("highwaymen"));
+ assertEquals("caveMan", autoSingularize("caveMen"));
+ assertNull("jackss", autoSingularize("jackss"));
+ assertNull("virus", autoSingularize("virus"));
+ assertEquals("quiz", autoSingularize("quizzes"));
+ assertEquals("database", autoSingularize("databases"));
+ assertEquals("dataBase", autoSingularize("dataBases"));
+ assertEquals("Query", autoSingularize("Queries"));
+ assertEquals("Movie", autoSingularize("Movies"));
+ assertEquals("cafe", autoSingularize("cafes"));
+ assertNull("caves", autoSingularize("caves"));
+ assertEquals("leaf", autoSingularize("leaves"));
+ assertEquals("autosave", autoSingularize("autosaves"));
+ }
+}
diff --git a/test/pretty/resource/after/Cast.java b/test/pretty/resource/after/Cast.java
index 95237b0f..e32150c3 100644
--- a/test/pretty/resource/after/Cast.java
+++ b/test/pretty/resource/after/Cast.java
@@ -1,6 +1,6 @@
import java.util.*;
public class Cast {
public void test(List<?> list) {
- RandomAccess r = (/*before*/ RandomAccess /*after*/)list;
+ RandomAccess r = (/*before*/ RandomAccess /*after*/) list;
}
} \ No newline at end of file
diff --git a/test/pretty/resource/after/CastWithIntersection.java b/test/pretty/resource/after/CastWithIntersection.java
index 2eebdee1..dc0904f6 100644
--- a/test/pretty/resource/after/CastWithIntersection.java
+++ b/test/pretty/resource/after/CastWithIntersection.java
@@ -1,6 +1,6 @@
import java.util.*;
public class CastWithIntersection {
public void test(List<?> list) {
- RandomAccess r = (RandomAccess & java.io.Serializable)list;
+ RandomAccess r = (RandomAccess & java.io.Serializable) list;
}
} \ No newline at end of file
diff --git a/test/pretty/resource/after/DefaultMethod.java b/test/pretty/resource/after/DefaultMethod.java
index 864ba60f..fe9594b8 100644
--- a/test/pretty/resource/after/DefaultMethod.java
+++ b/test/pretty/resource/after/DefaultMethod.java
@@ -3,6 +3,6 @@ interface DefaultMethod {
default boolean isEmpty() {
return size() == 0;
}
- default strictfp void run() {
+ strictfp default void run() {
}
} \ No newline at end of file
diff --git a/test/pretty/resource/after/Enum.java b/test/pretty/resource/after/Enum.java
index dd738b5b..a3b2b643 100644
--- a/test/pretty/resource/after/Enum.java
+++ b/test/pretty/resource/after/Enum.java
@@ -1,13 +1,8 @@
enum Ranks {
- CLUBS,
- HEARTS,
- DIAMONDS,
- SPADES;
+ CLUBS, HEARTS, DIAMONDS, SPADES;
}
enum Complex {
- RED("ff0000"),
- GREEN("00ff00"),
- BLUE("0000f");
+ RED("ff0000"), GREEN("00ff00"), BLUE("0000f");
private final String webColour;
Complex(String webColour) {
this.webColour = webColour;
diff --git a/test/pretty/resource/after/ExoticJava.java b/test/pretty/resource/after/ExoticJava.java
new file mode 100644
index 00000000..fb9a9131
--- /dev/null
+++ b/test/pretty/resource/after/ExoticJava.java
@@ -0,0 +1,46 @@
+import static java.lang.String.*;
+import java.io.*;
+class ExoticJava<V> {
+ public <T> ExoticJava(T genericsInConstructor, V genericsInType) {
+ System.out.println(new <String>ExoticJava<Integer>("Hello", 5));
+ }
+ public void test() {
+ int x = 5;
+ int[] y = {10};
+ ;
+ class MethodLocal implements Serializable, java.util.RandomAccess {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ public final strictfp int foo() {
+ int x = super.hashCode();
+ x <<= 5;
+ do {
+ x <<= 5;
+ } while (Boolean.FALSE);
+ return x;
+ }
+ }
+ for (int i = 10, j[] = {20}; i < 5; i++, j[0]++) {
+ String z = "";
+ try (
+ PrintWriter pw = new PrintWriter(System.out);
+ PrintWriter p2 = new PrintWriter(System.out)) {
+ pw.println();
+ } finally {
+ synchronized (z) {
+ System.out.println(z);
+ }
+ }
+ if ((y == null)) {
+ }
+ if (((y == null))) ;
+ {
+ ;
+ }
+ java.util.List<String> list = new java.util.ArrayList<>();
+ assert Boolean.TRUE : "That\'s weird";
+ double d = -1.8E12;
+ long loooong = 305441741;
+ int octal = 87;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pretty/resource/after/ForLoop.java b/test/pretty/resource/after/ForLoop.java
index 615f6e8a..f3b1bf4e 100644
--- a/test/pretty/resource/after/ForLoop.java
+++ b/test/pretty/resource/after/ForLoop.java
@@ -8,4 +8,11 @@ public class ForLoop {
}
// after loop
}
+
+ {
+ int i;
+ for (i = 0; i < 10; i++) {
+ System.out.println(i);
+ }
+ }
}
diff --git a/test/pretty/resource/after/Interfaces.java b/test/pretty/resource/after/Interfaces.java
index 6c0a6770..f7f386c0 100644
--- a/test/pretty/resource/after/Interfaces.java
+++ b/test/pretty/resource/after/Interfaces.java
@@ -1,10 +1,7 @@
@SuppressWarnings("all")
interface Interfaces {
enum Ranks {
- CLUBS,
- HEARTS,
- DIAMONDS,
- SPADES;
+ CLUBS, HEARTS, DIAMONDS, SPADES;
}
int x = 10;
void y();
diff --git a/test/pretty/resource/after/Lambda.java b/test/pretty/resource/after/Lambda.java
index 54d7caa0..949c4c04 100644
--- a/test/pretty/resource/after/Lambda.java
+++ b/test/pretty/resource/after/Lambda.java
@@ -4,4 +4,15 @@ public class Lambda {
java.util.Comparator<Integer> c2 = (Integer a, Integer b) -> {
return a - b;
};
-} \ No newline at end of file
+ java.util.function.Function<String, String> fnc = (String c) -> c;
+ void testLambdaInArgsList(String name, java.util.function.Function<String, String> f) {
+ }
+ void testLambdaInArgsList2(java.util.function.Function<String, String> f, String name) {
+ }
+ void test() {
+ testLambdaInArgsList("hello", (String c) -> c);
+ testLambdaInArgsList("hello", c -> c);
+ testLambdaInArgsList2((String c) -> c, "hello");
+ testLambdaInArgsList2(c -> c, "hello");
+ }
+}
diff --git a/test/pretty/resource/after/TypeAnnotations.java b/test/pretty/resource/after/TypeAnnotations.java
new file mode 100644
index 00000000..760b5ef8
--- /dev/null
+++ b/test/pretty/resource/after/TypeAnnotations.java
@@ -0,0 +1,22 @@
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Map;
+public class TypeAnnotations {
+ @Target({ElementType.TYPE_USE, ElementType.LOCAL_VARIABLE})
+ @interface Foo {
+ }
+ @Target(ElementType.TYPE_USE)
+ @interface Bar {
+ }
+ public List<@Foo String> test(@Foo String param) {
+ @Bar
+ String local = "bar";
+ @Foo
+ java.io.@Foo File[] array = {};
+ return new java.util.@Foo ArrayList<java.lang.@Foo String>();
+ }
+ public <@Foo T extends java.lang.@Foo Number> T test2(@Bar String... varargs) {
+ return null;
+ }
+}
diff --git a/test/pretty/resource/before/Cast.java b/test/pretty/resource/before/Cast.java
index 95237b0f..e32150c3 100644
--- a/test/pretty/resource/before/Cast.java
+++ b/test/pretty/resource/before/Cast.java
@@ -1,6 +1,6 @@
import java.util.*;
public class Cast {
public void test(List<?> list) {
- RandomAccess r = (/*before*/ RandomAccess /*after*/)list;
+ RandomAccess r = (/*before*/ RandomAccess /*after*/) list;
}
} \ No newline at end of file
diff --git a/test/pretty/resource/before/ExoticJava.java b/test/pretty/resource/before/ExoticJava.java
new file mode 100644
index 00000000..a0e27c79
--- /dev/null
+++ b/test/pretty/resource/before/ExoticJava.java
@@ -0,0 +1,46 @@
+//VERSION 7:
+import static java.lang.String.*;
+
+import java.io.*;
+
+class ExoticJava<V> {
+ public <T> ExoticJava(T genericsInConstructor, V genericsInType) {
+ System.out.println(new <String>ExoticJava<Integer>("Hello", 5));
+ }
+ ;;;;
+ public void test() {
+ int x = 5, y[] = {10};
+ ;
+ class MethodLocal implements Serializable, java.util.RandomAccess {
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ strictfp public final int foo() {
+ int x = super.hashCode();
+ x <<= 5;
+ do {
+ x <<= 5;
+ } while (Boolean.FALSE);
+ return x;
+ }
+ }
+
+ for (int i = 10, j[] = {20}; i < 5; i++, j[0]++) {
+ String z = "";
+ try (PrintWriter pw = new PrintWriter(System.out); PrintWriter p2 = new PrintWriter(System.out)) {
+ pw.println();
+ } finally {
+ synchronized (z) {
+ System.out.println(z);
+ }
+ }
+
+ if ((y == null)) {}
+ if (((y == null))) ;
+ {;}
+ java.util.List<String> list = new java.util.ArrayList<>();
+ assert Boolean.TRUE : "That's weird";
+ double d = -1.8e12;
+ long loooong = 0x1234ABCD;
+ int octal = 0127;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/pretty/resource/before/ForLoop.java b/test/pretty/resource/before/ForLoop.java
index 2bed7f9b..8a58cbf2 100644
--- a/test/pretty/resource/before/ForLoop.java
+++ b/test/pretty/resource/before/ForLoop.java
@@ -9,4 +9,11 @@ public class ForLoop {
}
// after loop
}
+
+ {
+ int i;
+ for (i = 0; i < 10; i++) {
+ System.out.println(i);
+ }
+ }
}
diff --git a/test/pretty/resource/before/Lambda.java b/test/pretty/resource/before/Lambda.java
index e7784df5..b9f8c719 100644
--- a/test/pretty/resource/before/Lambda.java
+++ b/test/pretty/resource/before/Lambda.java
@@ -5,4 +5,20 @@ public class Lambda {
java.util.Comparator<Integer> c2 = (Integer a, Integer b) -> {
return a - b;
};
-} \ No newline at end of file
+ java.util.function.Function<String, String> fnc = (String c) -> c;
+
+ void testLambdaInArgsList(String name, java.util.function.Function<String, String> f) {
+
+ }
+
+ void testLambdaInArgsList2(java.util.function.Function<String, String> f, String name) {
+
+ }
+
+ void test() {
+ testLambdaInArgsList("hello", (String c) -> c);
+ testLambdaInArgsList("hello", c -> c);
+ testLambdaInArgsList2((String c) -> c, "hello");
+ testLambdaInArgsList2(c -> c, "hello");
+ }
+}
diff --git a/test/pretty/resource/before/TypeAnnotations.java b/test/pretty/resource/before/TypeAnnotations.java
new file mode 100644
index 00000000..a39337da
--- /dev/null
+++ b/test/pretty/resource/before/TypeAnnotations.java
@@ -0,0 +1,23 @@
+// version 8:
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+import java.util.List;
+import java.util.Map;
+
+public class TypeAnnotations {
+ @Target({ElementType.TYPE_USE, ElementType.LOCAL_VARIABLE})
+ @interface Foo {}
+
+ @Target(ElementType.TYPE_USE)
+ @interface Bar {}
+
+ public List<@Foo String> test(@Foo String param) {
+ @Bar String local = "bar";
+ @Foo java.io.@Foo File[] array = {};
+ return new java.util.@Foo ArrayList<java.lang.@Foo String>();
+ }
+
+ public <@Foo T extends java.lang.@Foo Number> T test2(@Bar String... varargs) {
+ return null;
+ }
+}
diff --git a/test/transform/knownBroken/before/I1132RecursiveGenerics.java b/test/transform/knownBroken/before/I1132RecursiveGenerics.java
new file mode 100644
index 00000000..781886a7
--- /dev/null
+++ b/test/transform/knownBroken/before/I1132RecursiveGenerics.java
@@ -0,0 +1,19 @@
+// Compile with javac, it'll think the T in the generated build() method isn't type compatible.
+// Yet, when you take the delomboked output (which delombok will give, but with errors), THAT does compile.
+
+public class I1132RecursiveGenerics {
+ public static class Recursive<T extends Recursive<T>> {}
+ public static final class Rec extends Recursive<Rec> {}
+
+ @lombok.Builder(builderClassName = "MethodBuilder")
+ public static <T extends Recursive<T>> T create() {
+ return null;
+ }
+
+ public static void main(String[] args) {
+ final MethodBuilder<Rec> builder = I1132RecursiveGenerics.builder();
+ final Rec rec = builder.build();
+// final Rec rec = I1132RecursiveGenerics.<Rec>builder().build();
+ }
+}
+
diff --git a/test/transform/knownBroken/before/I1302BuilderInInstanceInnerClass.java b/test/transform/knownBroken/before/I1302BuilderInInstanceInnerClass.java
new file mode 100644
index 00000000..cf37abc4
--- /dev/null
+++ b/test/transform/knownBroken/before/I1302BuilderInInstanceInnerClass.java
@@ -0,0 +1,5 @@
+public class I1302BuilderInInstanceInnerClass {
+ @lombok.Builder public class NonStaticInner {
+ private int test;
+ }
+}
diff --git a/test/transform/resource/after-delombok/Accessors.java b/test/transform/resource/after-delombok/Accessors.java
index 0d15fe43..2773a17b 100644
--- a/test/transform/resource/after-delombok/Accessors.java
+++ b/test/transform/resource/after-delombok/Accessors.java
@@ -70,8 +70,8 @@ class AccessorsPrefix3 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof AccessorsPrefix3)) return false;
- final AccessorsPrefix3 other = (AccessorsPrefix3)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final AccessorsPrefix3 other = (AccessorsPrefix3) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$fName = this.getName();
final java.lang.Object other$fName = other.getName();
if (this$fName == null ? other$fName != null : !this$fName.equals(other$fName)) return false;
@@ -87,7 +87,7 @@ class AccessorsPrefix3 {
final int PRIME = 59;
int result = 1;
final java.lang.Object $fName = this.getName();
- result = result * PRIME + ($fName == null ? 0 : $fName.hashCode());
+ result = result * PRIME + ($fName == null ? 43 : $fName.hashCode());
return result;
}
}
@@ -112,4 +112,4 @@ class AccessorsFluentStatic<T extends Number> {
public static void name(final String name) {
AccessorsFluentStatic.name = name;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/AccessorsConfiguration.java b/test/transform/resource/after-delombok/AccessorsConfiguration.java
index fd60b152..f6604970 100644
--- a/test/transform/resource/after-delombok/AccessorsConfiguration.java
+++ b/test/transform/resource/after-delombok/AccessorsConfiguration.java
@@ -23,4 +23,4 @@ class AccessorsConfiguration3 {
this.fFieldName = fFieldName;
return this;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/BuilderChainAndFluent.java b/test/transform/resource/after-delombok/BuilderChainAndFluent.java
deleted file mode 100644
index d4975bff..00000000
--- a/test/transform/resource/after-delombok/BuilderChainAndFluent.java
+++ /dev/null
@@ -1,31 +0,0 @@
-class BuilderChainAndFluent {
- private final int yes;
- @java.lang.SuppressWarnings("all")
- BuilderChainAndFluent(final int yes) {
- this.yes = yes;
- }
- @java.lang.SuppressWarnings("all")
- public static class BuilderChainAndFluentBuilder {
- private int yes;
- @java.lang.SuppressWarnings("all")
- BuilderChainAndFluentBuilder() {
- }
- @java.lang.SuppressWarnings("all")
- public void setYes(final int yes) {
- this.yes = yes;
- }
- @java.lang.SuppressWarnings("all")
- public BuilderChainAndFluent build() {
- return new BuilderChainAndFluent(yes);
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public java.lang.String toString() {
- return "BuilderChainAndFluent.BuilderChainAndFluentBuilder(yes=" + this.yes + ")";
- }
- }
- @java.lang.SuppressWarnings("all")
- public static BuilderChainAndFluentBuilder builder() {
- return new BuilderChainAndFluentBuilder();
- }
-} \ No newline at end of file
diff --git a/test/transform/resource/after-delombok/BuilderComplex.java b/test/transform/resource/after-delombok/BuilderComplex.java
index 3c97f92a..a89d7114 100644
--- a/test/transform/resource/after-delombok/BuilderComplex.java
+++ b/test/transform/resource/after-delombok/BuilderComplex.java
@@ -4,9 +4,13 @@ class BuilderComplex {
}
@java.lang.SuppressWarnings("all")
public static class VoidBuilder<T extends Number> {
+ @java.lang.SuppressWarnings("all")
private T number;
+ @java.lang.SuppressWarnings("all")
private int arg2;
+ @java.lang.SuppressWarnings("all")
private String arg3;
+ @java.lang.SuppressWarnings("all")
private BuilderComplex selfRef;
@java.lang.SuppressWarnings("all")
VoidBuilder() {
@@ -45,4 +49,4 @@ class BuilderComplex {
public static <T extends Number> VoidBuilder<T> builder() {
return new VoidBuilder<T>();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/BuilderDefaults.java b/test/transform/resource/after-delombok/BuilderDefaults.java
new file mode 100644
index 00000000..b916b725
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderDefaults.java
@@ -0,0 +1,111 @@
+public final class BuilderDefaults {
+ private final int x;
+ private final String name;
+ private final long z;
+ @java.lang.SuppressWarnings("all")
+ private static int $default$x() {
+ return 10;
+ }
+ @java.lang.SuppressWarnings("all")
+ private static long $default$z() {
+ return System.currentTimeMillis();
+ }
+ @java.lang.SuppressWarnings("all")
+ BuilderDefaults(final int x, final String name, final long z) {
+ this.x = x;
+ this.name = name;
+ this.z = z;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderDefaultsBuilder {
+ @java.lang.SuppressWarnings("all")
+ private boolean x$set;
+ @java.lang.SuppressWarnings("all")
+ private int x;
+ @java.lang.SuppressWarnings("all")
+ private String name;
+ @java.lang.SuppressWarnings("all")
+ private boolean z$set;
+ @java.lang.SuppressWarnings("all")
+ private long z;
+ @java.lang.SuppressWarnings("all")
+ BuilderDefaultsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsBuilder x(final int x) {
+ this.x = x;
+ x$set = true;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsBuilder z(final long z) {
+ this.z = z;
+ z$set = true;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaults build() {
+ int x = this.x;
+ if (!x$set) x = BuilderDefaults.$default$x();
+ long z = this.z;
+ if (!z$set) z = BuilderDefaults.$default$z();
+ return new BuilderDefaults(x, name, z);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderDefaults.BuilderDefaultsBuilder(x=" + this.x + ", name=" + this.name + ", z=" + this.z + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderDefaultsBuilder builder() {
+ return new BuilderDefaultsBuilder();
+ }
+ @java.lang.SuppressWarnings("all")
+ public int getX() {
+ return this.x;
+ }
+ @java.lang.SuppressWarnings("all")
+ public String getName() {
+ return this.name;
+ }
+ @java.lang.SuppressWarnings("all")
+ public long getZ() {
+ return this.z;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof BuilderDefaults)) return false;
+ final BuilderDefaults other = (BuilderDefaults) o;
+ if (this.getX() != other.getX()) return false;
+ final java.lang.Object this$name = this.getName();
+ final java.lang.Object other$name = other.getName();
+ if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
+ if (this.getZ() != other.getZ()) return false;
+ return true;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.getX();
+ final java.lang.Object $name = this.getName();
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
+ final long $z = this.getZ();
+ result = result * PRIME + (int) ($z >>> 32 ^ $z);
+ return result;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderDefaults(x=" + this.getX() + ", name=" + this.getName() + ", z=" + this.getZ() + ")";
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java b/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java
new file mode 100644
index 00000000..b88a61be
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderDefaultsGenerics.java
@@ -0,0 +1,79 @@
+import java.util.*;
+public class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> {
+ private java.util.concurrent.Callable<N> callable;
+ private T tee;
+ private R arrr;
+ @java.lang.SuppressWarnings("all")
+ private static <N extends Number, T, R extends List<T>> java.util.concurrent.Callable<N> $default$callable() {
+ return null;
+ }
+ @java.lang.SuppressWarnings("all")
+ private static <N extends Number, T, R extends List<T>> T $default$tee() {
+ return null;
+ }
+ @java.lang.SuppressWarnings("all")
+ private static <N extends Number, T, R extends List<T>> R $default$arrr() {
+ return null;
+ }
+ @java.lang.SuppressWarnings("all")
+ BuilderDefaultsGenerics(final java.util.concurrent.Callable<N> callable, final T tee, final R arrr) {
+ this.callable = callable;
+ this.tee = tee;
+ this.arrr = arrr;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderDefaultsGenericsBuilder<N extends Number, T, R extends List<T>> {
+ @java.lang.SuppressWarnings("all")
+ private boolean callable$set;
+ @java.lang.SuppressWarnings("all")
+ private java.util.concurrent.Callable<N> callable;
+ @java.lang.SuppressWarnings("all")
+ private boolean tee$set;
+ @java.lang.SuppressWarnings("all")
+ private T tee;
+ @java.lang.SuppressWarnings("all")
+ private boolean arrr$set;
+ @java.lang.SuppressWarnings("all")
+ private R arrr;
+ @java.lang.SuppressWarnings("all")
+ BuilderDefaultsGenericsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsGenericsBuilder<N, T, R> callable(final java.util.concurrent.Callable<N> callable) {
+ this.callable = callable;
+ callable$set = true;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsGenericsBuilder<N, T, R> tee(final T tee) {
+ this.tee = tee;
+ tee$set = true;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsGenericsBuilder<N, T, R> arrr(final R arrr) {
+ this.arrr = arrr;
+ arrr$set = true;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsGenerics<N, T, R> build() {
+ java.util.concurrent.Callable<N> callable = this.callable;
+ if (!callable$set) callable = BuilderDefaultsGenerics.<N, T, R>$default$callable();
+ T tee = this.tee;
+ if (!tee$set) tee = BuilderDefaultsGenerics.<N, T, R>$default$tee();
+ R arrr = this.arrr;
+ if (!arrr$set) arrr = BuilderDefaultsGenerics.<N, T, R>$default$arrr();
+ return new BuilderDefaultsGenerics<N, T, R>(callable, tee, arrr);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable=" + this.callable + ", tee=" + this.tee + ", arrr=" + this.arrr + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <N extends Number, T, R extends List<T>> BuilderDefaultsGenericsBuilder<N, T, R> builder() {
+ return new BuilderDefaultsGenericsBuilder<N, T, R>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderDefaultsWarnings.java b/test/transform/resource/after-delombok/BuilderDefaultsWarnings.java
new file mode 100644
index 00000000..7e645dc1
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderDefaultsWarnings.java
@@ -0,0 +1,99 @@
+public class BuilderDefaultsWarnings {
+ long x = System.currentTimeMillis();
+ final int y = 5;
+ int z;
+ java.util.List<String> items;
+ @java.lang.SuppressWarnings("all")
+ BuilderDefaultsWarnings(final long x, final int z, final java.util.List<String> items) {
+ this.x = x;
+ this.z = z;
+ this.items = items;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderDefaultsWarningsBuilder {
+ @java.lang.SuppressWarnings("all")
+ private long x;
+ @java.lang.SuppressWarnings("all")
+ private int z;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> items;
+ @java.lang.SuppressWarnings("all")
+ BuilderDefaultsWarningsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsWarningsBuilder x(final long x) {
+ this.x = x;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsWarningsBuilder z(final int z) {
+ this.z = z;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsWarningsBuilder item(final String item) {
+ if (this.items == null) this.items = new java.util.ArrayList<String>();
+ this.items.add(item);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsWarningsBuilder items(final java.util.Collection<? extends String> items) {
+ if (this.items == null) this.items = new java.util.ArrayList<String>();
+ this.items.addAll(items);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsWarningsBuilder clearItems() {
+ if (this.items != null) this.items.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderDefaultsWarnings build() {
+ java.util.List<String> items;
+ switch (this.items == null ? 0 : this.items.size()) {
+ case 0:
+ items = java.util.Collections.emptyList();
+ break;
+ case 1:
+ items = java.util.Collections.singletonList(this.items.get(0));
+ break;
+ default:
+ items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.items));
+ }
+ return new BuilderDefaultsWarnings(x, z, items);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderDefaultsWarnings.BuilderDefaultsWarningsBuilder(x=" + this.x + ", z=" + this.z + ", items=" + this.items + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderDefaultsWarningsBuilder builder() {
+ return new BuilderDefaultsWarningsBuilder();
+ }
+}
+class NoBuilderButHasDefaults {
+ private final long z = 5;
+ public NoBuilderButHasDefaults() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class NoBuilderButHasDefaultsBuilder {
+ @java.lang.SuppressWarnings("all")
+ NoBuilderButHasDefaultsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public NoBuilderButHasDefaults build() {
+ return new NoBuilderButHasDefaults();
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "NoBuilderButHasDefaults.NoBuilderButHasDefaultsBuilder()";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static NoBuilderButHasDefaultsBuilder builder() {
+ return new NoBuilderButHasDefaultsBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderGenericMethod.java b/test/transform/resource/after-delombok/BuilderGenericMethod.java
new file mode 100644
index 00000000..f70ae871
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderGenericMethod.java
@@ -0,0 +1,40 @@
+import java.util.List;
+import java.util.*;
+class BuilderGenericMethod<T> {
+ public <N extends Number> Map<N, T> foo(int a, long b) {
+ return null;
+ }
+ @java.lang.SuppressWarnings("all")
+ public class MapBuilder<N extends Number> {
+ @java.lang.SuppressWarnings("all")
+ private int a;
+ @java.lang.SuppressWarnings("all")
+ private long b;
+ @java.lang.SuppressWarnings("all")
+ MapBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public MapBuilder<N> a(final int a) {
+ this.a = a;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public MapBuilder<N> b(final long b) {
+ this.b = b;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public Map<N, T> build() {
+ return BuilderGenericMethod.this.<N>foo(a, b);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderGenericMethod.MapBuilder(a=" + this.a + ", b=" + this.b + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public <N extends Number> MapBuilder<N> builder() {
+ return new MapBuilder<N>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderInstanceMethod.java b/test/transform/resource/after-delombok/BuilderInstanceMethod.java
new file mode 100644
index 00000000..12b76a8f
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderInstanceMethod.java
@@ -0,0 +1,53 @@
+import java.util.List;
+class BuilderInstanceMethod<T> {
+ public String create(int show, final int yes, List<T> also, int $andMe) {
+ return "" + show + yes + also + $andMe;
+ }
+ @java.lang.SuppressWarnings("all")
+ public class StringBuilder {
+ @java.lang.SuppressWarnings("all")
+ private int show;
+ @java.lang.SuppressWarnings("all")
+ private int yes;
+ @java.lang.SuppressWarnings("all")
+ private List<T> also;
+ @java.lang.SuppressWarnings("all")
+ private int $andMe;
+ @java.lang.SuppressWarnings("all")
+ StringBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public StringBuilder show(final int show) {
+ this.show = show;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public StringBuilder yes(final int yes) {
+ this.yes = yes;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public StringBuilder also(final List<T> also) {
+ this.also = also;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public StringBuilder $andMe(final int $andMe) {
+ this.$andMe = $andMe;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public String build() {
+ return BuilderInstanceMethod.this.create(show, yes, also, $andMe);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderInstanceMethod.StringBuilder(show=" + this.show + ", yes=" + this.yes + ", also=" + this.also + ", $andMe=" + this.$andMe + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public StringBuilder builder() {
+ return new StringBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSimple.java b/test/transform/resource/after-delombok/BuilderSimple.java
index 11c0e58c..e3821c9a 100644
--- a/test/transform/resource/after-delombok/BuilderSimple.java
+++ b/test/transform/resource/after-delombok/BuilderSimple.java
@@ -11,7 +11,9 @@ class BuilderSimple<T> {
}
@java.lang.SuppressWarnings("all")
public static class BuilderSimpleBuilder<T> {
+ @java.lang.SuppressWarnings("all")
private int yes;
+ @java.lang.SuppressWarnings("all")
private List<T> also;
@java.lang.SuppressWarnings("all")
BuilderSimpleBuilder() {
diff --git a/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java b/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java
new file mode 100644
index 00000000..cf90e883
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularGuavaListsSets.java
@@ -0,0 +1,140 @@
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableTable;
+class BuilderSingularGuavaListsSets<T> {
+ private ImmutableList<T> cards;
+ private ImmutableCollection<? extends Number> frogs;
+ @SuppressWarnings("all")
+ private ImmutableSet rawSet;
+ private ImmutableSortedSet<String> passes;
+ private ImmutableTable<? extends Number, ? extends Number, String> users;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularGuavaListsSets(final ImmutableList<T> cards, final ImmutableCollection<? extends Number> frogs, final ImmutableSet rawSet, final ImmutableSortedSet<String> passes, final ImmutableTable<? extends Number, ? extends Number, String> users) {
+ this.cards = cards;
+ this.frogs = frogs;
+ this.rawSet = rawSet;
+ this.passes = passes;
+ this.users = users;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularGuavaListsSetsBuilder<T> {
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableList.Builder<T> cards;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableList.Builder<Number> frogs;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableSet.Builder<java.lang.Object> rawSet;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableSortedSet.Builder<String> passes;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableTable.Builder<Number, Number, String> users;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularGuavaListsSetsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> card(final T card) {
+ if (this.cards == null) this.cards = com.google.common.collect.ImmutableList.builder();
+ this.cards.add(card);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> cards(final java.lang.Iterable<? extends T> cards) {
+ if (this.cards == null) this.cards = com.google.common.collect.ImmutableList.builder();
+ this.cards.addAll(cards);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> clearCards() {
+ this.cards = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> frog(final Number frog) {
+ if (this.frogs == null) this.frogs = com.google.common.collect.ImmutableList.builder();
+ this.frogs.add(frog);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> frogs(final java.lang.Iterable<? extends Number> frogs) {
+ if (this.frogs == null) this.frogs = com.google.common.collect.ImmutableList.builder();
+ this.frogs.addAll(frogs);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> clearFrogs() {
+ this.frogs = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> rawSet(final java.lang.Object rawSet) {
+ if (this.rawSet == null) this.rawSet = com.google.common.collect.ImmutableSet.builder();
+ this.rawSet.add(rawSet);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> rawSet(final java.lang.Iterable<?> rawSet) {
+ if (this.rawSet == null) this.rawSet = com.google.common.collect.ImmutableSet.builder();
+ this.rawSet.addAll(rawSet);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> clearRawSet() {
+ this.rawSet = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> pass(final String pass) {
+ if (this.passes == null) this.passes = com.google.common.collect.ImmutableSortedSet.naturalOrder();
+ this.passes.add(pass);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> passes(final java.lang.Iterable<? extends String> passes) {
+ if (this.passes == null) this.passes = com.google.common.collect.ImmutableSortedSet.naturalOrder();
+ this.passes.addAll(passes);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> clearPasses() {
+ this.passes = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> user(final Number rowKey, final Number columnKey, final String value) {
+ if (this.users == null) this.users = com.google.common.collect.ImmutableTable.builder();
+ this.users.put(rowKey, columnKey, value);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> users(final com.google.common.collect.Table<? extends Number, ? extends Number, ? extends String> users) {
+ if (this.users == null) this.users = com.google.common.collect.ImmutableTable.builder();
+ this.users.putAll(users);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSetsBuilder<T> clearUsers() {
+ this.users = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaListsSets<T> build() {
+ com.google.common.collect.ImmutableList<T> cards = this.cards == null ? com.google.common.collect.ImmutableList.<T>of() : this.cards.build();
+ com.google.common.collect.ImmutableCollection<Number> frogs = this.frogs == null ? com.google.common.collect.ImmutableList.<Number>of() : this.frogs.build();
+ com.google.common.collect.ImmutableSet<java.lang.Object> rawSet = this.rawSet == null ? com.google.common.collect.ImmutableSet.<java.lang.Object>of() : this.rawSet.build();
+ com.google.common.collect.ImmutableSortedSet<String> passes = this.passes == null ? com.google.common.collect.ImmutableSortedSet.<String>of() : this.passes.build();
+ com.google.common.collect.ImmutableTable<Number, Number, String> users = this.users == null ? com.google.common.collect.ImmutableTable.<Number, Number, String>of() : this.users.build();
+ return new BuilderSingularGuavaListsSets<T>(cards, frogs, rawSet, passes, users);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularGuavaListsSets.BuilderSingularGuavaListsSetsBuilder(cards=" + this.cards + ", frogs=" + this.frogs + ", rawSet=" + this.rawSet + ", passes=" + this.passes + ", users=" + this.users + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <T> BuilderSingularGuavaListsSetsBuilder<T> builder() {
+ return new BuilderSingularGuavaListsSetsBuilder<T>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java b/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java
new file mode 100644
index 00000000..e29c7e94
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularGuavaMaps.java
@@ -0,0 +1,94 @@
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableSortedMap;
+class BuilderSingularGuavaMaps<K, V> {
+ private ImmutableMap<K, V> battleaxes;
+ private ImmutableSortedMap<Integer, ? extends V> vertices;
+ @SuppressWarnings("all")
+ private ImmutableBiMap rawMap;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularGuavaMaps(final ImmutableMap<K, V> battleaxes, final ImmutableSortedMap<Integer, ? extends V> vertices, final ImmutableBiMap rawMap) {
+ this.battleaxes = battleaxes;
+ this.vertices = vertices;
+ this.rawMap = rawMap;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularGuavaMapsBuilder<K, V> {
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableMap.Builder<K, V> battleaxes;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableSortedMap.Builder<Integer, V> vertices;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableBiMap.Builder<java.lang.Object, java.lang.Object> rawMap;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularGuavaMapsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> battleaxe(final K key, final V value) {
+ if (this.battleaxes == null) this.battleaxes = com.google.common.collect.ImmutableMap.builder();
+ this.battleaxes.put(key, value);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> battleaxes(final java.util.Map<? extends K, ? extends V> battleaxes) {
+ if (this.battleaxes == null) this.battleaxes = com.google.common.collect.ImmutableMap.builder();
+ this.battleaxes.putAll(battleaxes);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> clearBattleaxes() {
+ this.battleaxes = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> vertex(final Integer key, final V value) {
+ if (this.vertices == null) this.vertices = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.vertices.put(key, value);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> vertices(final java.util.Map<? extends Integer, ? extends V> vertices) {
+ if (this.vertices == null) this.vertices = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.vertices.putAll(vertices);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> clearVertices() {
+ this.vertices = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> rawMap(final java.lang.Object key, final java.lang.Object value) {
+ if (this.rawMap == null) this.rawMap = com.google.common.collect.ImmutableBiMap.builder();
+ this.rawMap.put(key, value);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> rawMap(final java.util.Map<?, ?> rawMap) {
+ if (this.rawMap == null) this.rawMap = com.google.common.collect.ImmutableBiMap.builder();
+ this.rawMap.putAll(rawMap);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMapsBuilder<K, V> clearRawMap() {
+ this.rawMap = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularGuavaMaps<K, V> build() {
+ com.google.common.collect.ImmutableMap<K, V> battleaxes = this.battleaxes == null ? com.google.common.collect.ImmutableMap.<K, V>of() : this.battleaxes.build();
+ com.google.common.collect.ImmutableSortedMap<Integer, V> vertices = this.vertices == null ? com.google.common.collect.ImmutableSortedMap.<Integer, V>of() : this.vertices.build();
+ com.google.common.collect.ImmutableBiMap<java.lang.Object, java.lang.Object> rawMap = this.rawMap == null ? com.google.common.collect.ImmutableBiMap.<java.lang.Object, java.lang.Object>of() : this.rawMap.build();
+ return new BuilderSingularGuavaMaps<K, V>(battleaxes, vertices, rawMap);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularGuavaMaps.BuilderSingularGuavaMapsBuilder(battleaxes=" + this.battleaxes + ", vertices=" + this.vertices + ", rawMap=" + this.rawMap + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <K, V> BuilderSingularGuavaMapsBuilder<K, V> builder() {
+ return new BuilderSingularGuavaMapsBuilder<K, V>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularLists.java b/test/transform/resource/after-delombok/BuilderSingularLists.java
new file mode 100644
index 00000000..a0be0c12
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularLists.java
@@ -0,0 +1,123 @@
+import java.util.List;
+import java.util.Collection;
+class BuilderSingularLists<T> {
+ private List<T> children;
+ private Collection<? extends Number> scarves;
+ @SuppressWarnings("all")
+ private List rawList;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularLists(final List<T> children, final Collection<? extends Number> scarves, final List rawList) {
+ this.children = children;
+ this.scarves = scarves;
+ this.rawList = rawList;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularListsBuilder<T> {
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<T> children;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<Number> scarves;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<java.lang.Object> rawList;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularListsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> child(final T child) {
+ if (this.children == null) this.children = new java.util.ArrayList<T>();
+ this.children.add(child);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> children(final java.util.Collection<? extends T> children) {
+ if (this.children == null) this.children = new java.util.ArrayList<T>();
+ this.children.addAll(children);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> clearChildren() {
+ if (this.children != null) this.children.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> scarf(final Number scarf) {
+ if (this.scarves == null) this.scarves = new java.util.ArrayList<Number>();
+ this.scarves.add(scarf);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> scarves(final java.util.Collection<? extends Number> scarves) {
+ if (this.scarves == null) this.scarves = new java.util.ArrayList<Number>();
+ this.scarves.addAll(scarves);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> clearScarves() {
+ if (this.scarves != null) this.scarves.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> rawList(final java.lang.Object rawList) {
+ if (this.rawList == null) this.rawList = new java.util.ArrayList<java.lang.Object>();
+ this.rawList.add(rawList);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> rawList(final java.util.Collection<?> rawList) {
+ if (this.rawList == null) this.rawList = new java.util.ArrayList<java.lang.Object>();
+ this.rawList.addAll(rawList);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularListsBuilder<T> clearRawList() {
+ if (this.rawList != null) this.rawList.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularLists<T> build() {
+ java.util.List<T> children;
+ switch (this.children == null ? 0 : this.children.size()) {
+ case 0:
+ children = java.util.Collections.emptyList();
+ break;
+ case 1:
+ children = java.util.Collections.singletonList(this.children.get(0));
+ break;
+ default:
+ children = java.util.Collections.unmodifiableList(new java.util.ArrayList<T>(this.children));
+ }
+ java.util.Collection<Number> scarves;
+ switch (this.scarves == null ? 0 : this.scarves.size()) {
+ case 0:
+ scarves = java.util.Collections.emptyList();
+ break;
+ case 1:
+ scarves = java.util.Collections.singletonList(this.scarves.get(0));
+ break;
+ default:
+ scarves = java.util.Collections.unmodifiableList(new java.util.ArrayList<Number>(this.scarves));
+ }
+ java.util.List<java.lang.Object> rawList;
+ switch (this.rawList == null ? 0 : this.rawList.size()) {
+ case 0:
+ rawList = java.util.Collections.emptyList();
+ break;
+ case 1:
+ rawList = java.util.Collections.singletonList(this.rawList.get(0));
+ break;
+ default:
+ rawList = java.util.Collections.unmodifiableList(new java.util.ArrayList<java.lang.Object>(this.rawList));
+ }
+ return new BuilderSingularLists<T>(children, scarves, rawList);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularLists.BuilderSingularListsBuilder(children=" + this.children + ", scarves=" + this.scarves + ", rawList=" + this.rawList + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <T> BuilderSingularListsBuilder<T> builder() {
+ return new BuilderSingularListsBuilder<T>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularMaps.java b/test/transform/resource/after-delombok/BuilderSingularMaps.java
new file mode 100644
index 00000000..6520568b
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularMaps.java
@@ -0,0 +1,213 @@
+import java.util.Map;
+import java.util.SortedMap;
+class BuilderSingularMaps<K, V> {
+ private Map<K, V> women;
+ private SortedMap<K, ? extends Number> men;
+ @SuppressWarnings("all")
+ private Map rawMap;
+ private Map<String, V> stringMap;
+ @SuppressWarnings("all")
+ BuilderSingularMaps(Map<K, V> women, SortedMap<K, ? extends Number> men, Map rawMap, Map<String, V> stringMap) {
+ this.women = women;
+ this.men = men;
+ this.rawMap = rawMap;
+ this.stringMap = stringMap;
+ }
+ @SuppressWarnings("all")
+ public static class BuilderSingularMapsBuilder<K, V> {
+ @SuppressWarnings("all")
+ private java.util.ArrayList<K> women$key;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<V> women$value;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<K> men$key;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<Number> men$value;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<Object> rawMap$key;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<Object> rawMap$value;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<String> stringMap$key;
+ @SuppressWarnings("all")
+ private java.util.ArrayList<V> stringMap$value;
+ @SuppressWarnings("all")
+ BuilderSingularMapsBuilder() {
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> woman(K womanKey, V womanValue) {
+ if (this.women$key == null) {
+ this.women$key = new java.util.ArrayList<K>();
+ this.women$value = new java.util.ArrayList<V>();
+ }
+ this.women$key.add(womanKey);
+ this.women$value.add(womanValue);
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> women(java.util.Map<? extends K, ? extends V> women) {
+ if (this.women$key == null) {
+ this.women$key = new java.util.ArrayList<K>();
+ this.women$value = new java.util.ArrayList<V>();
+ }
+ for (java.util.Map.Entry<? extends K, ? extends V> $lombokEntry : women.entrySet()) {
+ this.women$key.add($lombokEntry.getKey());
+ this.women$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> clearWomen() {
+ if (this.women$key != null) {
+ this.women$key.clear();
+ this.women$value.clear();
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> man(K manKey, Number manValue) {
+ if (this.men$key == null) {
+ this.men$key = new java.util.ArrayList<K>();
+ this.men$value = new java.util.ArrayList<Number>();
+ }
+ this.men$key.add(manKey);
+ this.men$value.add(manValue);
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> men(java.util.Map<? extends K, ? extends Number> men) {
+ if (this.men$key == null) {
+ this.men$key = new java.util.ArrayList<K>();
+ this.men$value = new java.util.ArrayList<Number>();
+ }
+ for (java.util.Map.Entry<? extends K, ? extends Number> $lombokEntry : men.entrySet()) {
+ this.men$key.add($lombokEntry.getKey());
+ this.men$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> clearMen() {
+ if (this.men$key != null) {
+ this.men$key.clear();
+ this.men$value.clear();
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> rawMap(Object rawMapKey, Object rawMapValue) {
+ if (this.rawMap$key == null) {
+ this.rawMap$key = new java.util.ArrayList<Object>();
+ this.rawMap$value = new java.util.ArrayList<Object>();
+ }
+ this.rawMap$key.add(rawMapKey);
+ this.rawMap$value.add(rawMapValue);
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> rawMap(java.util.Map<?, ?> rawMap) {
+ if (this.rawMap$key == null) {
+ this.rawMap$key = new java.util.ArrayList<Object>();
+ this.rawMap$value = new java.util.ArrayList<Object>();
+ }
+ for (java.util.Map.Entry<?, ?> $lombokEntry : rawMap.entrySet()) {
+ this.rawMap$key.add($lombokEntry.getKey());
+ this.rawMap$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> clearRawMap() {
+ if (this.rawMap$key != null) {
+ this.rawMap$key.clear();
+ this.rawMap$value.clear();
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> stringMap(String stringMapKey, V stringMapValue) {
+ if (this.stringMap$key == null) {
+ this.stringMap$key = new java.util.ArrayList<String>();
+ this.stringMap$value = new java.util.ArrayList<V>();
+ }
+ this.stringMap$key.add(stringMapKey);
+ this.stringMap$value.add(stringMapValue);
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> stringMap(java.util.Map<? extends String, ? extends V> stringMap) {
+ if (this.stringMap$key == null) {
+ this.stringMap$key = new java.util.ArrayList<String>();
+ this.stringMap$value = new java.util.ArrayList<V>();
+ }
+ for (java.util.Map.Entry<? extends String, ? extends V> $lombokEntry : stringMap.entrySet()) {
+ this.stringMap$key.add($lombokEntry.getKey());
+ this.stringMap$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMapsBuilder<K, V> clearStringMap() {
+ if (this.stringMap$key != null) {
+ this.stringMap$key.clear();
+ this.stringMap$value.clear();
+ }
+ return this;
+ }
+ @SuppressWarnings("all")
+ public BuilderSingularMaps<K, V> build() {
+ java.util.Map<K, V> women;
+ switch (this.women$key == null ? 0 : this.women$key.size()) {
+ case 0:
+ women = java.util.Collections.emptyMap();
+ break;
+ case 1:
+ women = java.util.Collections.singletonMap(this.women$key.get(0), this.women$value.get(0));
+ break;
+ default:
+ women = new java.util.LinkedHashMap<K, V>(this.women$key.size() < 1073741824 ? 1 + this.women$key.size() + (this.women$key.size() - 3) / 3 : Integer.MAX_VALUE);
+ for (int $i = 0; $i < this.women$key.size(); $i++) women.put(this.women$key.get($i), (V) this.women$value.get($i));
+ women = java.util.Collections.unmodifiableMap(women);
+ }
+ java.util.SortedMap<K, Number> men = new java.util.TreeMap<K, Number>();
+ if (this.men$key != null) for (int $i = 0; $i < (this.men$key == null ? 0 : this.men$key.size()); $i++) men.put(this.men$key.get($i), (Number) this.men$value.get($i));
+ men = java.util.Collections.unmodifiableSortedMap(men);
+ java.util.Map<Object, Object> rawMap;
+ switch (this.rawMap$key == null ? 0 : this.rawMap$key.size()) {
+ case 0:
+ rawMap = java.util.Collections.emptyMap();
+ break;
+ case 1:
+ rawMap = java.util.Collections.singletonMap(this.rawMap$key.get(0), this.rawMap$value.get(0));
+ break;
+ default:
+ rawMap = new java.util.LinkedHashMap<Object, Object>(this.rawMap$key.size() < 1073741824 ? 1 + this.rawMap$key.size() + (this.rawMap$key.size() - 3) / 3 : Integer.MAX_VALUE);
+ for (int $i = 0; $i < this.rawMap$key.size(); $i++) rawMap.put(this.rawMap$key.get($i), (Object) this.rawMap$value.get($i));
+ rawMap = java.util.Collections.unmodifiableMap(rawMap);
+ }
+ java.util.Map<String, V> stringMap;
+ switch (this.stringMap$key == null ? 0 : this.stringMap$key.size()) {
+ case 0:
+ stringMap = java.util.Collections.emptyMap();
+ break;
+ case 1:
+ stringMap = java.util.Collections.singletonMap(this.stringMap$key.get(0), this.stringMap$value.get(0));
+ break;
+ default:
+ stringMap = new java.util.LinkedHashMap<String, V>(this.stringMap$key.size() < 1073741824 ? 1 + this.stringMap$key.size() + (this.stringMap$key.size() - 3) / 3 : Integer.MAX_VALUE);
+ for (int $i = 0; $i < this.stringMap$key.size(); $i++) stringMap.put(this.stringMap$key.get($i), (V) this.stringMap$value.get($i));
+ stringMap = java.util.Collections.unmodifiableMap(stringMap);
+ }
+ return new BuilderSingularMaps<K, V>(women, men, rawMap, stringMap);
+ }
+ @Override
+ @SuppressWarnings("all")
+ public String toString() {
+ return "BuilderSingularMaps.BuilderSingularMapsBuilder(women$key=" + this.women$key + ", women$value=" + this.women$value + ", men$key=" + this.men$key + ", men$value=" + this.men$value + ", rawMap$key=" + this.rawMap$key + ", rawMap$value=" + this.rawMap$value + ", stringMap$key=" + this.stringMap$key + ", stringMap$value=" + this.stringMap$value + ")";
+ }
+ }
+ @SuppressWarnings("all")
+ public static <K, V> BuilderSingularMapsBuilder<K, V> builder() {
+ return new BuilderSingularMapsBuilder<K, V>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularNoAuto.java b/test/transform/resource/after-delombok/BuilderSingularNoAuto.java
new file mode 100644
index 00000000..189408da
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularNoAuto.java
@@ -0,0 +1,121 @@
+import java.util.List;
+class BuilderSingularNoAuto {
+ private List<String> things;
+ private List<String> widgets;
+ private List<String> items;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularNoAuto(final List<String> things, final List<String> widgets, final List<String> items) {
+ this.things = things;
+ this.widgets = widgets;
+ this.items = items;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularNoAutoBuilder {
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> things;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> widgets;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> items;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularNoAutoBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder things(final String things) {
+ if (this.things == null) this.things = new java.util.ArrayList<String>();
+ this.things.add(things);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder things(final java.util.Collection<? extends String> things) {
+ if (this.things == null) this.things = new java.util.ArrayList<String>();
+ this.things.addAll(things);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder clearThings() {
+ if (this.things != null) this.things.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder widget(final String widget) {
+ if (this.widgets == null) this.widgets = new java.util.ArrayList<String>();
+ this.widgets.add(widget);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder widgets(final java.util.Collection<? extends String> widgets) {
+ if (this.widgets == null) this.widgets = new java.util.ArrayList<String>();
+ this.widgets.addAll(widgets);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder clearWidgets() {
+ if (this.widgets != null) this.widgets.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder items(final String items) {
+ if (this.items == null) this.items = new java.util.ArrayList<String>();
+ this.items.add(items);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder items(final java.util.Collection<? extends String> items) {
+ if (this.items == null) this.items = new java.util.ArrayList<String>();
+ this.items.addAll(items);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAutoBuilder clearItems() {
+ if (this.items != null) this.items.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularNoAuto build() {
+ java.util.List<String> things;
+ switch (this.things == null ? 0 : this.things.size()) {
+ case 0:
+ things = java.util.Collections.emptyList();
+ break;
+ case 1:
+ things = java.util.Collections.singletonList(this.things.get(0));
+ break;
+ default:
+ things = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.things));
+ }
+ java.util.List<String> widgets;
+ switch (this.widgets == null ? 0 : this.widgets.size()) {
+ case 0:
+ widgets = java.util.Collections.emptyList();
+ break;
+ case 1:
+ widgets = java.util.Collections.singletonList(this.widgets.get(0));
+ break;
+ default:
+ widgets = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.widgets));
+ }
+ java.util.List<String> items;
+ switch (this.items == null ? 0 : this.items.size()) {
+ case 0:
+ items = java.util.Collections.emptyList();
+ break;
+ case 1:
+ items = java.util.Collections.singletonList(this.items.get(0));
+ break;
+ default:
+ items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.items));
+ }
+ return new BuilderSingularNoAuto(things, widgets, items);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularNoAuto.BuilderSingularNoAutoBuilder(things=" + this.things + ", widgets=" + this.widgets + ", items=" + this.items + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderSingularNoAutoBuilder builder() {
+ return new BuilderSingularNoAutoBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java b/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java
new file mode 100644
index 00000000..938f3bbc
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularRedirectToGuava.java
@@ -0,0 +1,93 @@
+import java.util.Set;
+import java.util.NavigableMap;
+import java.util.Collection;
+class BuilderSingularRedirectToGuava {
+ private Set<String> dangerMice;
+ private NavigableMap<Integer, Number> things;
+ private Collection<Class<?>> doohickeys;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularRedirectToGuava(final Set<String> dangerMice, final NavigableMap<Integer, Number> things, final Collection<Class<?>> doohickeys) {
+ this.dangerMice = dangerMice;
+ this.things = things;
+ this.doohickeys = doohickeys;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularRedirectToGuavaBuilder {
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableSet.Builder<String> dangerMice;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableSortedMap.Builder<Integer, Number> things;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableList.Builder<Class<?>> doohickeys;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularRedirectToGuavaBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder dangerMouse(final String dangerMouse) {
+ if (this.dangerMice == null) this.dangerMice = com.google.common.collect.ImmutableSet.builder();
+ this.dangerMice.add(dangerMouse);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder dangerMice(final java.lang.Iterable<? extends String> dangerMice) {
+ if (this.dangerMice == null) this.dangerMice = com.google.common.collect.ImmutableSet.builder();
+ this.dangerMice.addAll(dangerMice);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder clearDangerMice() {
+ this.dangerMice = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder thing(final Integer key, final Number value) {
+ if (this.things == null) this.things = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.things.put(key, value);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder things(final java.util.Map<? extends Integer, ? extends Number> things) {
+ if (this.things == null) this.things = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.things.putAll(things);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder clearThings() {
+ this.things = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder doohickey(final Class<?> doohickey) {
+ if (this.doohickeys == null) this.doohickeys = com.google.common.collect.ImmutableList.builder();
+ this.doohickeys.add(doohickey);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder doohickeys(final java.lang.Iterable<? extends Class<?>> doohickeys) {
+ if (this.doohickeys == null) this.doohickeys = com.google.common.collect.ImmutableList.builder();
+ this.doohickeys.addAll(doohickeys);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuavaBuilder clearDoohickeys() {
+ this.doohickeys = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularRedirectToGuava build() {
+ java.util.Set<String> dangerMice = this.dangerMice == null ? com.google.common.collect.ImmutableSet.<String>of() : this.dangerMice.build();
+ java.util.NavigableMap<Integer, Number> things = this.things == null ? com.google.common.collect.ImmutableSortedMap.<Integer, Number>of() : this.things.build();
+ java.util.Collection<Class<?>> doohickeys = this.doohickeys == null ? com.google.common.collect.ImmutableList.<Class<?>>of() : this.doohickeys.build();
+ return new BuilderSingularRedirectToGuava(dangerMice, things, doohickeys);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularRedirectToGuava.BuilderSingularRedirectToGuavaBuilder(dangerMice=" + this.dangerMice + ", things=" + this.things + ", doohickeys=" + this.doohickeys + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderSingularRedirectToGuavaBuilder builder() {
+ return new BuilderSingularRedirectToGuavaBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularSets.java b/test/transform/resource/after-delombok/BuilderSingularSets.java
new file mode 100644
index 00000000..2d75b294
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularSets.java
@@ -0,0 +1,153 @@
+import java.util.Set;
+import java.util.SortedSet;
+class BuilderSingularSets<T> {
+ private Set<T> dangerMice;
+ private SortedSet<? extends Number> octopodes;
+ @SuppressWarnings("all")
+ private Set rawSet;
+ private Set<String> stringSet;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularSets(final Set<T> dangerMice, final SortedSet<? extends Number> octopodes, final Set rawSet, final Set<String> stringSet) {
+ this.dangerMice = dangerMice;
+ this.octopodes = octopodes;
+ this.rawSet = rawSet;
+ this.stringSet = stringSet;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularSetsBuilder<T> {
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<T> dangerMice;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<Number> octopodes;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<java.lang.Object> rawSet;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> stringSet;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularSetsBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> dangerMouse(final T dangerMouse) {
+ if (this.dangerMice == null) this.dangerMice = new java.util.ArrayList<T>();
+ this.dangerMice.add(dangerMouse);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> dangerMice(final java.util.Collection<? extends T> dangerMice) {
+ if (this.dangerMice == null) this.dangerMice = new java.util.ArrayList<T>();
+ this.dangerMice.addAll(dangerMice);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> clearDangerMice() {
+ if (this.dangerMice != null) this.dangerMice.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> octopus(final Number octopus) {
+ if (this.octopodes == null) this.octopodes = new java.util.ArrayList<Number>();
+ this.octopodes.add(octopus);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> octopodes(final java.util.Collection<? extends Number> octopodes) {
+ if (this.octopodes == null) this.octopodes = new java.util.ArrayList<Number>();
+ this.octopodes.addAll(octopodes);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> clearOctopodes() {
+ if (this.octopodes != null) this.octopodes.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> rawSet(final java.lang.Object rawSet) {
+ if (this.rawSet == null) this.rawSet = new java.util.ArrayList<java.lang.Object>();
+ this.rawSet.add(rawSet);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> rawSet(final java.util.Collection<?> rawSet) {
+ if (this.rawSet == null) this.rawSet = new java.util.ArrayList<java.lang.Object>();
+ this.rawSet.addAll(rawSet);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> clearRawSet() {
+ if (this.rawSet != null) this.rawSet.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> stringSet(final String stringSet) {
+ if (this.stringSet == null) this.stringSet = new java.util.ArrayList<String>();
+ this.stringSet.add(stringSet);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> stringSet(final java.util.Collection<? extends String> stringSet) {
+ if (this.stringSet == null) this.stringSet = new java.util.ArrayList<String>();
+ this.stringSet.addAll(stringSet);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSetsBuilder<T> clearStringSet() {
+ if (this.stringSet != null) this.stringSet.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularSets<T> build() {
+ java.util.Set<T> dangerMice;
+ switch (this.dangerMice == null ? 0 : this.dangerMice.size()) {
+ case 0:
+ dangerMice = java.util.Collections.emptySet();
+ break;
+ case 1:
+ dangerMice = java.util.Collections.singleton(this.dangerMice.get(0));
+ break;
+ default:
+ dangerMice = new java.util.LinkedHashSet<T>(this.dangerMice.size() < 1073741824 ? 1 + this.dangerMice.size() + (this.dangerMice.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
+ dangerMice.addAll(this.dangerMice);
+ dangerMice = java.util.Collections.unmodifiableSet(dangerMice);
+ }
+ java.util.SortedSet<Number> octopodes = new java.util.TreeSet<Number>();
+ if (this.octopodes != null) octopodes.addAll(this.octopodes);
+ octopodes = java.util.Collections.unmodifiableSortedSet(octopodes);
+ java.util.Set<java.lang.Object> rawSet;
+ switch (this.rawSet == null ? 0 : this.rawSet.size()) {
+ case 0:
+ rawSet = java.util.Collections.emptySet();
+ break;
+ case 1:
+ rawSet = java.util.Collections.singleton(this.rawSet.get(0));
+ break;
+ default:
+ rawSet = new java.util.LinkedHashSet<java.lang.Object>(this.rawSet.size() < 1073741824 ? 1 + this.rawSet.size() + (this.rawSet.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
+ rawSet.addAll(this.rawSet);
+ rawSet = java.util.Collections.unmodifiableSet(rawSet);
+ }
+ java.util.Set<String> stringSet;
+ switch (this.stringSet == null ? 0 : this.stringSet.size()) {
+ case 0:
+ stringSet = java.util.Collections.emptySet();
+ break;
+ case 1:
+ stringSet = java.util.Collections.singleton(this.stringSet.get(0));
+ break;
+ default:
+ stringSet = new java.util.LinkedHashSet<String>(this.stringSet.size() < 1073741824 ? 1 + this.stringSet.size() + (this.stringSet.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
+ stringSet.addAll(this.stringSet);
+ stringSet = java.util.Collections.unmodifiableSet(stringSet);
+ }
+ return new BuilderSingularSets<T>(dangerMice, octopodes, rawSet, stringSet);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularSets.BuilderSingularSetsBuilder(dangerMice=" + this.dangerMice + ", octopodes=" + this.octopodes + ", rawSet=" + this.rawSet + ", stringSet=" + this.stringSet + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <T> BuilderSingularSetsBuilder<T> builder() {
+ return new BuilderSingularSetsBuilder<T>();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderSingularWithPrefixes.java b/test/transform/resource/after-delombok/BuilderSingularWithPrefixes.java
new file mode 100644
index 00000000..e103d6dd
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderSingularWithPrefixes.java
@@ -0,0 +1,56 @@
+class BuilderSingularWithPrefixes {
+ private java.util.List<String> _elems;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularWithPrefixes(final java.util.List<String> elems) {
+ this._elems = elems;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderSingularWithPrefixesBuilder {
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> elems;
+ @java.lang.SuppressWarnings("all")
+ BuilderSingularWithPrefixesBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularWithPrefixesBuilder elem(final String elem) {
+ if (this.elems == null) this.elems = new java.util.ArrayList<String>();
+ this.elems.add(elem);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularWithPrefixesBuilder elems(final java.util.Collection<? extends String> elems) {
+ if (this.elems == null) this.elems = new java.util.ArrayList<String>();
+ this.elems.addAll(elems);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularWithPrefixesBuilder clearElems() {
+ if (this.elems != null) this.elems.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderSingularWithPrefixes build() {
+ java.util.List<String> elems;
+ switch (this.elems == null ? 0 : this.elems.size()) {
+ case 0:
+ elems = java.util.Collections.emptyList();
+ break;
+ case 1:
+ elems = java.util.Collections.singletonList(this.elems.get(0));
+ break;
+ default:
+ elems = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.elems));
+ }
+ return new BuilderSingularWithPrefixes(elems);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderSingularWithPrefixes.BuilderSingularWithPrefixesBuilder(elems=" + this.elems + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderSingularWithPrefixesBuilder builder() {
+ return new BuilderSingularWithPrefixesBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderValueData.java b/test/transform/resource/after-delombok/BuilderValueData.java
new file mode 100644
index 00000000..e1c107da
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderValueData.java
@@ -0,0 +1,109 @@
+import java.util.List;
+final class BuilderAndValue {
+ private final int zero = 0;
+ @java.lang.SuppressWarnings("all")
+ BuilderAndValue() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderAndValueBuilder {
+ @java.lang.SuppressWarnings("all")
+ BuilderAndValueBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderAndValue build() {
+ return new BuilderAndValue();
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderAndValue.BuilderAndValueBuilder()";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderAndValueBuilder builder() {
+ return new BuilderAndValueBuilder();
+ }
+ @java.lang.SuppressWarnings("all")
+ public int getZero() {
+ return this.zero;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof BuilderAndValue)) return false;
+ final BuilderAndValue other = (BuilderAndValue) o;
+ if (this.getZero() != other.getZero()) return false;
+ return true;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.getZero();
+ return result;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderAndValue(zero=" + this.getZero() + ")";
+ }
+}
+
+class BuilderAndData {
+ private final int zero = 0;
+ @java.lang.SuppressWarnings("all")
+ BuilderAndData() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderAndDataBuilder {
+ @java.lang.SuppressWarnings("all")
+ BuilderAndDataBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderAndData build() {
+ return new BuilderAndData();
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderAndData.BuilderAndDataBuilder()";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderAndDataBuilder builder() {
+ return new BuilderAndDataBuilder();
+ }
+ @java.lang.SuppressWarnings("all")
+ public int getZero() {
+ return this.zero;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof BuilderAndData)) return false;
+ final BuilderAndData other = (BuilderAndData) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ if (this.getZero() != other.getZero()) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof BuilderAndData;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.getZero();
+ return result;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderAndData(zero=" + this.getZero() + ")";
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderWithAccessors.java b/test/transform/resource/after-delombok/BuilderWithAccessors.java
index 503c33be..e6a6da79 100644
--- a/test/transform/resource/after-delombok/BuilderWithAccessors.java
+++ b/test/transform/resource/after-delombok/BuilderWithAccessors.java
@@ -12,54 +12,49 @@ class BuilderWithAccessors {
}
@java.lang.SuppressWarnings("all")
public static class BuilderWithAccessorsBuilder {
+ @java.lang.SuppressWarnings("all")
private int plower;
+ @java.lang.SuppressWarnings("all")
private int upper;
+ @java.lang.SuppressWarnings("all")
private int foo;
+ @java.lang.SuppressWarnings("all")
private int _bar;
-
@java.lang.SuppressWarnings("all")
BuilderWithAccessorsBuilder() {
-
}
-
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder plower(final int plower) {
this.plower = plower;
return this;
}
-
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder upper(final int upper) {
this.upper = upper;
return this;
}
-
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder foo(final int foo) {
this.foo = foo;
return this;
}
-
@java.lang.SuppressWarnings("all")
public BuilderWithAccessorsBuilder _bar(final int _bar) {
this._bar = _bar;
return this;
}
-
@java.lang.SuppressWarnings("all")
public BuilderWithAccessors build() {
return new BuilderWithAccessors(plower, upper, foo, _bar);
}
-
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
return "BuilderWithAccessors.BuilderWithAccessorsBuilder(plower=" + this.plower + ", upper=" + this.upper + ", foo=" + this.foo + ", _bar=" + this._bar + ")";
}
}
-
@java.lang.SuppressWarnings("all")
public static BuilderWithAccessorsBuilder builder() {
return new BuilderWithAccessorsBuilder();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/BuilderWithDeprecated.java b/test/transform/resource/after-delombok/BuilderWithDeprecated.java
new file mode 100644
index 00000000..cd887529
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderWithDeprecated.java
@@ -0,0 +1,111 @@
+import com.google.common.collect.ImmutableList;
+public class BuilderWithDeprecated {
+ /**
+ * @deprecated
+ */
+ String dep1;
+ @Deprecated
+ int dep2;
+ @Deprecated
+ java.util.List<String> strings;
+ @Deprecated
+ ImmutableList<Integer> numbers;
+ @java.lang.SuppressWarnings("all")
+ BuilderWithDeprecated(final String dep1, final int dep2, final java.util.List<String> strings, final ImmutableList<Integer> numbers) {
+ this.dep1 = dep1;
+ this.dep2 = dep2;
+ this.strings = strings;
+ this.numbers = numbers;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderWithDeprecatedBuilder {
+ @java.lang.SuppressWarnings("all")
+ private String dep1;
+ @java.lang.SuppressWarnings("all")
+ private int dep2;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<String> strings;
+ @java.lang.SuppressWarnings("all")
+ private com.google.common.collect.ImmutableList.Builder<Integer> numbers;
+ @java.lang.SuppressWarnings("all")
+ BuilderWithDeprecatedBuilder() {
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder dep1(final String dep1) {
+ this.dep1 = dep1;
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder dep2(final int dep2) {
+ this.dep2 = dep2;
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder string(final String string) {
+ if (this.strings == null) this.strings = new java.util.ArrayList<String>();
+ this.strings.add(string);
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder strings(final java.util.Collection<? extends String> strings) {
+ if (this.strings == null) this.strings = new java.util.ArrayList<String>();
+ this.strings.addAll(strings);
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder clearStrings() {
+ if (this.strings != null) this.strings.clear();
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder number(final Integer number) {
+ if (this.numbers == null) this.numbers = com.google.common.collect.ImmutableList.builder();
+ this.numbers.add(number);
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder numbers(final java.lang.Iterable<? extends Integer> numbers) {
+ if (this.numbers == null) this.numbers = com.google.common.collect.ImmutableList.builder();
+ this.numbers.addAll(numbers);
+ return this;
+ }
+ @java.lang.Deprecated
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecatedBuilder clearNumbers() {
+ this.numbers = null;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithDeprecated build() {
+ java.util.List<String> strings;
+ switch (this.strings == null ? 0 : this.strings.size()) {
+ case 0:
+ strings = java.util.Collections.emptyList();
+ break;
+ case 1:
+ strings = java.util.Collections.singletonList(this.strings.get(0));
+ break;
+ default:
+ strings = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.strings));
+ }
+ com.google.common.collect.ImmutableList<Integer> numbers = this.numbers == null ? com.google.common.collect.ImmutableList.<Integer>of() : this.numbers.build();
+ return new BuilderWithDeprecated(dep1, dep2, strings, numbers);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderWithDeprecated.BuilderWithDeprecatedBuilder(dep1=" + this.dep1 + ", dep2=" + this.dep2 + ", strings=" + this.strings + ", numbers=" + this.numbers + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderWithDeprecatedBuilder builder() {
+ return new BuilderWithDeprecatedBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderWithExistingBuilderClass.java b/test/transform/resource/after-delombok/BuilderWithExistingBuilderClass.java
index 1d40dbfa..0a5edacd 100644
--- a/test/transform/resource/after-delombok/BuilderWithExistingBuilderClass.java
+++ b/test/transform/resource/after-delombok/BuilderWithExistingBuilderClass.java
@@ -3,7 +3,9 @@ class BuilderWithExistingBuilderClass<T, K extends Number> {
return null;
}
public static class BuilderWithExistingBuilderClassBuilder<Z extends Number> {
+ @java.lang.SuppressWarnings("all")
private boolean arg2;
+ @java.lang.SuppressWarnings("all")
private String arg3;
private Z arg1;
public void arg2(boolean arg) {
@@ -22,7 +24,7 @@ class BuilderWithExistingBuilderClass<T, K extends Number> {
return this;
}
@java.lang.SuppressWarnings("all")
- public BuilderWithExistingBuilderClass build() {
+ public BuilderWithExistingBuilderClass<String, Z> build() {
return BuilderWithExistingBuilderClass.<Z>staticMethod(arg1, arg2, arg3);
}
@java.lang.Override
@@ -35,4 +37,4 @@ class BuilderWithExistingBuilderClass<T, K extends Number> {
public static <Z extends Number> BuilderWithExistingBuilderClassBuilder<Z> builder() {
return new BuilderWithExistingBuilderClassBuilder<Z>();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/BuilderWithRecursiveGenerics.java b/test/transform/resource/after-delombok/BuilderWithRecursiveGenerics.java
new file mode 100644
index 00000000..7fb300e4
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderWithRecursiveGenerics.java
@@ -0,0 +1,85 @@
+import java.util.Set;
+public class BuilderWithRecursiveGenerics {
+ interface Inter<T, U extends Inter<T, U>> {
+ }
+ public static final class Test<Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>> {
+ private final Foo foo;
+ private final Bar bar;
+ @java.lang.SuppressWarnings("all")
+ Test(final Foo foo, final Bar bar) {
+ this.foo = foo;
+ this.bar = bar;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class TestBuilder<Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>> {
+ @java.lang.SuppressWarnings("all")
+ private Foo foo;
+ @java.lang.SuppressWarnings("all")
+ private Bar bar;
+ @java.lang.SuppressWarnings("all")
+ TestBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public TestBuilder<Foo, Bar, Quz> foo(final Foo foo) {
+ this.foo = foo;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public TestBuilder<Foo, Bar, Quz> bar(final Bar bar) {
+ this.bar = bar;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public Test<Foo, Bar, Quz> build() {
+ return new Test<Foo, Bar, Quz>(foo, bar);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderWithRecursiveGenerics.Test.TestBuilder(foo=" + this.foo + ", bar=" + this.bar + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>> TestBuilder<Foo, Bar, Quz> builder() {
+ return new TestBuilder<Foo, Bar, Quz>();
+ }
+ @java.lang.SuppressWarnings("all")
+ public Foo getFoo() {
+ return this.foo;
+ }
+ @java.lang.SuppressWarnings("all")
+ public Bar getBar() {
+ return this.bar;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof BuilderWithRecursiveGenerics.Test)) return false;
+ final BuilderWithRecursiveGenerics.Test<?, ?, ?> other = (BuilderWithRecursiveGenerics.Test<?, ?, ?>) o;
+ final java.lang.Object this$foo = this.getFoo();
+ final java.lang.Object other$foo = other.getFoo();
+ if (this$foo == null ? other$foo != null : !this$foo.equals(other$foo)) return false;
+ final java.lang.Object this$bar = this.getBar();
+ final java.lang.Object other$bar = other.getBar();
+ if (this$bar == null ? other$bar != null : !this$bar.equals(other$bar)) return false;
+ return true;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final java.lang.Object $foo = this.getFoo();
+ result = result * PRIME + ($foo == null ? 43 : $foo.hashCode());
+ final java.lang.Object $bar = this.getBar();
+ result = result * PRIME + ($bar == null ? 43 : $bar.hashCode());
+ return result;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderWithRecursiveGenerics.Test(foo=" + this.getFoo() + ", bar=" + this.getBar() + ")";
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderWithToBuilder.java b/test/transform/resource/after-delombok/BuilderWithToBuilder.java
new file mode 100644
index 00000000..46387f0f
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderWithToBuilder.java
@@ -0,0 +1,185 @@
+import java.util.List;
+class BuilderWithToBuilder<T> {
+ private String mOne;
+ private String mTwo;
+ private T foo;
+ private List<T> bars;
+ public static <K> K rrr(BuilderWithToBuilder<K> x) {
+ return x.foo;
+ }
+ @java.lang.SuppressWarnings("all")
+ BuilderWithToBuilder(final String one, final String two, final T foo, final List<T> bars) {
+ this.mOne = one;
+ this.mTwo = two;
+ this.foo = foo;
+ this.bars = bars;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class BuilderWithToBuilderBuilder<T> {
+ @java.lang.SuppressWarnings("all")
+ private String one;
+ @java.lang.SuppressWarnings("all")
+ private String two;
+ @java.lang.SuppressWarnings("all")
+ private T foo;
+ @java.lang.SuppressWarnings("all")
+ private java.util.ArrayList<T> bars;
+ @java.lang.SuppressWarnings("all")
+ BuilderWithToBuilderBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> one(final String one) {
+ this.one = one;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> two(final String two) {
+ this.two = two;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> foo(final T foo) {
+ this.foo = foo;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> bar(final T bar) {
+ if (this.bars == null) this.bars = new java.util.ArrayList<T>();
+ this.bars.add(bar);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> bars(final java.util.Collection<? extends T> bars) {
+ if (this.bars == null) this.bars = new java.util.ArrayList<T>();
+ this.bars.addAll(bars);
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> clearBars() {
+ if (this.bars != null) this.bars.clear();
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilder<T> build() {
+ java.util.List<T> bars;
+ switch (this.bars == null ? 0 : this.bars.size()) {
+ case 0:
+ bars = java.util.Collections.emptyList();
+ break;
+ case 1:
+ bars = java.util.Collections.singletonList(this.bars.get(0));
+ break;
+ default:
+ bars = java.util.Collections.unmodifiableList(new java.util.ArrayList<T>(this.bars));
+ }
+ return new BuilderWithToBuilder<T>(one, two, foo, bars);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderWithToBuilder.BuilderWithToBuilderBuilder(one=" + this.one + ", two=" + this.two + ", foo=" + this.foo + ", bars=" + this.bars + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <T> BuilderWithToBuilderBuilder<T> builder() {
+ return new BuilderWithToBuilderBuilder<T>();
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithToBuilderBuilder<T> toBuilder() {
+ return new BuilderWithToBuilderBuilder<T>().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars);
+ }
+}
+class ConstructorWithToBuilder<T> {
+ private String mOne;
+ private String mTwo;
+ private T foo;
+ @lombok.Singular
+ private List<T> bars;
+ public ConstructorWithToBuilder(String mOne, T bar) {
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class ConstructorWithToBuilderBuilder<T> {
+ @java.lang.SuppressWarnings("all")
+ private String mOne;
+ @java.lang.SuppressWarnings("all")
+ private T bar;
+ @java.lang.SuppressWarnings("all")
+ ConstructorWithToBuilderBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public ConstructorWithToBuilderBuilder<T> mOne(final String mOne) {
+ this.mOne = mOne;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public ConstructorWithToBuilderBuilder<T> bar(final T bar) {
+ this.bar = bar;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public ConstructorWithToBuilder<T> build() {
+ return new ConstructorWithToBuilder<T>(mOne, bar);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "ConstructorWithToBuilder.ConstructorWithToBuilderBuilder(mOne=" + this.mOne + ", bar=" + this.bar + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <T> ConstructorWithToBuilderBuilder<T> builder() {
+ return new ConstructorWithToBuilderBuilder<T>();
+ }
+ @java.lang.SuppressWarnings("all")
+ public ConstructorWithToBuilderBuilder<T> toBuilder() {
+ return new ConstructorWithToBuilderBuilder<T>().mOne(this.mOne).bar(this.foo);
+ }
+}
+class StaticWithToBuilder<T, K> {
+ private String mOne;
+ private String mTwo;
+ private T foo;
+ private K bar;
+ @lombok.Singular
+ private List<T> bars;
+ public static <Z> StaticWithToBuilder<Z, String> test(String mOne, Z bar) {
+ return new StaticWithToBuilder<Z, String>();
+ }
+ @java.lang.SuppressWarnings("all")
+ public static class StaticWithToBuilderBuilder<Z> {
+ @java.lang.SuppressWarnings("all")
+ private String mOne;
+ @java.lang.SuppressWarnings("all")
+ private Z bar;
+ @java.lang.SuppressWarnings("all")
+ StaticWithToBuilderBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public StaticWithToBuilderBuilder<Z> mOne(final String mOne) {
+ this.mOne = mOne;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public StaticWithToBuilderBuilder<Z> bar(final Z bar) {
+ this.bar = bar;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public StaticWithToBuilder<Z, String> build() {
+ return StaticWithToBuilder.<Z>test(mOne, bar);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "StaticWithToBuilder.StaticWithToBuilderBuilder(mOne=" + this.mOne + ", bar=" + this.bar + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ public static <Z> StaticWithToBuilderBuilder<Z> builder() {
+ return new StaticWithToBuilderBuilder<Z>();
+ }
+ @java.lang.SuppressWarnings("all")
+ public StaticWithToBuilderBuilder<T> toBuilder() {
+ return new StaticWithToBuilderBuilder<T>().mOne(this.mOne).bar(this.foo);
+ }
+}
diff --git a/test/transform/resource/after-delombok/BuilderWithTolerate.java b/test/transform/resource/after-delombok/BuilderWithTolerate.java
new file mode 100644
index 00000000..6ec7c091
--- /dev/null
+++ b/test/transform/resource/after-delombok/BuilderWithTolerate.java
@@ -0,0 +1,40 @@
+import lombok.experimental.Tolerate;
+public class BuilderWithTolerate {
+ private final int value;
+ public static void main(String[] args) {
+ BuilderWithTolerate.builder().value("42").build();
+ }
+ public static class BuilderWithTolerateBuilder {
+ @java.lang.SuppressWarnings("all")
+ private int value;
+ @Tolerate
+ public BuilderWithTolerateBuilder value(String s) {
+ return this.value(Integer.parseInt(s));
+ }
+ @java.lang.SuppressWarnings("all")
+ BuilderWithTolerateBuilder() {
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithTolerateBuilder value(final int value) {
+ this.value = value;
+ return this;
+ }
+ @java.lang.SuppressWarnings("all")
+ public BuilderWithTolerate build() {
+ return new BuilderWithTolerate(value);
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "BuilderWithTolerate.BuilderWithTolerateBuilder(value=" + this.value + ")";
+ }
+ }
+ @java.lang.SuppressWarnings("all")
+ BuilderWithTolerate(final int value) {
+ this.value = value;
+ }
+ @java.lang.SuppressWarnings("all")
+ public static BuilderWithTolerateBuilder builder() {
+ return new BuilderWithTolerateBuilder();
+ }
+}
diff --git a/test/transform/resource/after-delombok/ConflictingStaticConstructorNames.java b/test/transform/resource/after-delombok/ConflictingStaticConstructorNames.java
index ae0c46bc..30aefaa0 100644
--- a/test/transform/resource/after-delombok/ConflictingStaticConstructorNames.java
+++ b/test/transform/resource/after-delombok/ConflictingStaticConstructorNames.java
@@ -4,8 +4,8 @@ class ConflictingStaticConstructorNames {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof ConflictingStaticConstructorNames)) return false;
- final ConflictingStaticConstructorNames other = (ConflictingStaticConstructorNames)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final ConflictingStaticConstructorNames other = (ConflictingStaticConstructorNames) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@@ -26,4 +26,4 @@ class ConflictingStaticConstructorNames {
@java.lang.SuppressWarnings("all")
public ConflictingStaticConstructorNames() {
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/Constructors.java b/test/transform/resource/after-delombok/Constructors.java
index 4ffdc62b..b2e51c40 100644
--- a/test/transform/resource/after-delombok/Constructors.java
+++ b/test/transform/resource/after-delombok/Constructors.java
@@ -1,7 +1,6 @@
class RequiredArgsConstructor1 {
final int x;
String name;
- @java.beans.ConstructorProperties({"x"})
@java.lang.SuppressWarnings("all")
public RequiredArgsConstructor1(final int x) {
this.x = x;
@@ -10,7 +9,6 @@ class RequiredArgsConstructor1 {
class RequiredArgsConstructorAccess {
final int x;
String name;
- @java.beans.ConstructorProperties({"x"})
@java.lang.SuppressWarnings("all")
protected RequiredArgsConstructorAccess(final int x) {
this.x = x;
@@ -31,7 +29,6 @@ class RequiredArgsConstructorStaticName {
class RequiredArgsConstructorWithAnnotations {
final int x;
String name;
- @java.beans.ConstructorProperties({"x"})
@Deprecated
@java.lang.SuppressWarnings("all")
public RequiredArgsConstructorWithAnnotations(final int x) {
@@ -41,7 +38,6 @@ class RequiredArgsConstructorWithAnnotations {
class AllArgsConstructor1 {
final int x;
String name;
- @java.beans.ConstructorProperties({"x", "name"})
@java.lang.SuppressWarnings("all")
public AllArgsConstructor1(final int x, final String name) {
this.x = x;
@@ -86,3 +82,21 @@ class AllArgsConstructorPackageAccess {
this.x = x;
}
}
+class NoArgsConstructor2 {
+ final int x;
+ final double y;
+ final char c;
+ final boolean b;
+ final float f;
+ final String s;
+ byte z;
+ @java.lang.SuppressWarnings("all")
+ public NoArgsConstructor2() {
+ this.x = 0;
+ this.y = 0.0;
+ this.c = '\000';
+ this.b = false;
+ this.f = 0.0F;
+ this.s = null;
+ }
+}
diff --git a/test/transform/resource/after-delombok/ConstructorsConfiguration.java b/test/transform/resource/after-delombok/ConstructorsConfiguration.java
index 5bec3ae3..47b0cc16 100644
--- a/test/transform/resource/after-delombok/ConstructorsConfiguration.java
+++ b/test/transform/resource/after-delombok/ConstructorsConfiguration.java
@@ -5,11 +5,3 @@ class ConstructorsConfiguration {
this.x = x;
}
}
-class ConstructorsConfigurationExplicit {
- int x;
- @java.beans.ConstructorProperties({"x"})
- @java.lang.SuppressWarnings("all")
- public ConstructorsConfigurationExplicit(final int x) {
- this.x = x;
- }
-}
diff --git a/test/transform/resource/after-delombok/ConstructorsWithAccessors.java b/test/transform/resource/after-delombok/ConstructorsWithAccessors.java
index 9937c7ee..dd4ce12f 100644
--- a/test/transform/resource/after-delombok/ConstructorsWithAccessors.java
+++ b/test/transform/resource/after-delombok/ConstructorsWithAccessors.java
@@ -4,7 +4,6 @@ class ConstructorsWithAccessors {
int _huh;
int __huh2;
- @java.beans.ConstructorProperties({"plower", "upper", "huh", "_huh2"})
@java.lang.SuppressWarnings("all")
public ConstructorsWithAccessors(final int plower, final int upper, final int huh, final int _huh2) {
this.plower = plower;
@@ -13,3 +12,34 @@ class ConstructorsWithAccessors {
this.__huh2 = _huh2;
}
}
+
+class ConstructorsWithAccessorsNonNull {
+ @lombok.NonNull
+ Integer plower;
+ @lombok.NonNull
+ Integer pUpper;
+ @lombok.NonNull
+ Integer _huh;
+ @lombok.NonNull
+ final Integer __huh2;
+
+ @java.lang.SuppressWarnings("all")
+ public ConstructorsWithAccessorsNonNull(@lombok.NonNull final Integer plower, @lombok.NonNull final Integer upper, @lombok.NonNull final Integer huh, @lombok.NonNull final Integer _huh2) {
+ if (plower == null) {
+ throw new java.lang.NullPointerException("plower");
+ }
+ if (upper == null) {
+ throw new java.lang.NullPointerException("upper");
+ }
+ if (huh == null) {
+ throw new java.lang.NullPointerException("huh");
+ }
+ if (_huh2 == null) {
+ throw new java.lang.NullPointerException("_huh2");
+ }
+ this.plower = plower;
+ this.pUpper = upper;
+ this._huh = huh;
+ this.__huh2 = _huh2;
+ }
+}
diff --git a/test/transform/resource/after-delombok/DataConfiguration.java b/test/transform/resource/after-delombok/DataConfiguration.java
index 230083ec..b71e1c81 100644
--- a/test/transform/resource/after-delombok/DataConfiguration.java
+++ b/test/transform/resource/after-delombok/DataConfiguration.java
@@ -13,9 +13,9 @@ class DataConfiguration {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof DataConfiguration)) return false;
- final DataConfiguration other = (DataConfiguration)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
- if (this.getX() != other.getX()) return false;
+ final DataConfiguration other = (DataConfiguration) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ if (this.x != other.x) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@@ -27,12 +27,12 @@ class DataConfiguration {
public int hashCode() {
final int PRIME = 59;
int result = 1;
- result = result * PRIME + this.getX();
+ result = result * PRIME + this.x;
return result;
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
- return "DataConfiguration(x=" + this.getX() + ")";
+ return "DataConfiguration(x=" + this.x + ")";
}
}
diff --git a/test/transform/resource/after-delombok/DataExtended.java b/test/transform/resource/after-delombok/DataExtended.java
index 6a5e7fa2..bcbf2293 100644
--- a/test/transform/resource/after-delombok/DataExtended.java
+++ b/test/transform/resource/after-delombok/DataExtended.java
@@ -16,8 +16,8 @@ class DataExtended {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof DataExtended)) return false;
- final DataExtended other = (DataExtended)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final DataExtended other = (DataExtended) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
return true;
}
@@ -38,4 +38,4 @@ class DataExtended {
public java.lang.String toString() {
return "DataExtended(x=" + this.x + ")";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DataIgnore.java b/test/transform/resource/after-delombok/DataIgnore.java
index 922de01b..309d8150 100644
--- a/test/transform/resource/after-delombok/DataIgnore.java
+++ b/test/transform/resource/after-delombok/DataIgnore.java
@@ -1,7 +1,6 @@
class DataIgnore {
final int x;
String $name;
- @java.beans.ConstructorProperties({"x"})
@java.lang.SuppressWarnings("all")
public DataIgnore(final int x) {
this.x = x;
@@ -15,8 +14,8 @@ class DataIgnore {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof DataIgnore)) return false;
- final DataIgnore other = (DataIgnore)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final DataIgnore other = (DataIgnore) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
return true;
}
@@ -37,4 +36,4 @@ class DataIgnore {
public java.lang.String toString() {
return "DataIgnore(x=" + this.getX() + ")";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DataOnEnum.java b/test/transform/resource/after-delombok/DataOnEnum.java
index 5cfe8823..2486646b 100644
--- a/test/transform/resource/after-delombok/DataOnEnum.java
+++ b/test/transform/resource/after-delombok/DataOnEnum.java
@@ -14,4 +14,4 @@ public enum DataOnEnum {
private DataOnEnum(final String someField) {
this.someField = someField;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DataOnLocalClass.java b/test/transform/resource/after-delombok/DataOnLocalClass.java
index 5d73e584..84817897 100644
--- a/test/transform/resource/after-delombok/DataOnLocalClass.java
+++ b/test/transform/resource/after-delombok/DataOnLocalClass.java
@@ -24,8 +24,8 @@ class DataOnLocalClass1 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Local)) return false;
- final Local other = (Local)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Local other = (Local) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
@@ -43,7 +43,7 @@ class DataOnLocalClass1 {
int result = 1;
result = result * PRIME + this.getX();
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -85,8 +85,8 @@ class DataOnLocalClass2 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Local.InnerLocal)) return false;
- final InnerLocal other = (InnerLocal)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Local.InnerLocal other = (Local.InnerLocal) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
@@ -102,7 +102,7 @@ class DataOnLocalClass2 {
final int PRIME = 59;
int result = 1;
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -124,8 +124,8 @@ class DataOnLocalClass2 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Local)) return false;
- final Local other = (Local)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Local other = (Local) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
return true;
}
@@ -148,4 +148,4 @@ class DataOnLocalClass2 {
}
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DataPlain.java b/test/transform/resource/after-delombok/DataPlain.java
index 8988dc6f..d54baef1 100644
--- a/test/transform/resource/after-delombok/DataPlain.java
+++ b/test/transform/resource/after-delombok/DataPlain.java
@@ -1,7 +1,6 @@
class Data1 {
final int x;
String name;
- @java.beans.ConstructorProperties({"x"})
@java.lang.SuppressWarnings("all")
public Data1(final int x) {
this.x = x;
@@ -23,8 +22,8 @@ class Data1 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Data1)) return false;
- final Data1 other = (Data1)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Data1 other = (Data1) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
@@ -42,7 +41,7 @@ class Data1 {
int result = 1;
result = result * PRIME + this.getX();
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -54,7 +53,6 @@ class Data1 {
class Data2 {
final int x;
String name;
- @java.beans.ConstructorProperties({"x"})
@java.lang.SuppressWarnings("all")
public Data2(final int x) {
this.x = x;
@@ -76,8 +74,8 @@ class Data2 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Data2)) return false;
- final Data2 other = (Data2)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Data2 other = (Data2) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
@@ -95,7 +93,7 @@ class Data2 {
int result = 1;
result = result * PRIME + this.getX();
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -107,7 +105,6 @@ class Data2 {
final class Data3 {
final int x;
String name;
- @java.beans.ConstructorProperties({"x"})
@java.lang.SuppressWarnings("all")
public Data3(final int x) {
this.x = x;
@@ -129,7 +126,7 @@ final class Data3 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Data3)) return false;
- final Data3 other = (Data3)o;
+ final Data3 other = (Data3) o;
if (this.getX() != other.getX()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
@@ -143,7 +140,7 @@ final class Data3 {
int result = 1;
result = result * PRIME + this.getX();
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -174,8 +171,8 @@ final class Data4 extends java.util.Timer {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Data4)) return false;
- final Data4 other = (Data4)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Data4 other = (Data4) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (!super.equals(o)) return false;
if (this.getX() != other.getX()) return false;
return true;
@@ -188,8 +185,7 @@ final class Data4 extends java.util.Timer {
@java.lang.SuppressWarnings("all")
public int hashCode() {
final int PRIME = 59;
- int result = 1;
- result = result * PRIME + super.hashCode();
+ int result = super.hashCode();
result = result * PRIME + this.getX();
return result;
}
@@ -203,8 +199,8 @@ class Data5 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Data5)) return false;
- final Data5 other = (Data5)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Data5 other = (Data5) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@@ -245,4 +241,4 @@ final class Data6 {
public java.lang.String toString() {
return "Data6()";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DataWithGetter.java b/test/transform/resource/after-delombok/DataWithGetter.java
index 91f392ec..b4107bb3 100644
--- a/test/transform/resource/after-delombok/DataWithGetter.java
+++ b/test/transform/resource/after-delombok/DataWithGetter.java
@@ -2,7 +2,6 @@ class DataWithGetter {
private int x;
private int y;
private final String z;
- @java.beans.ConstructorProperties({"z"})
@java.lang.SuppressWarnings("all")
public DataWithGetter(final String z) {
this.z = z;
@@ -20,8 +19,8 @@ class DataWithGetter {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof DataWithGetter)) return false;
- final DataWithGetter other = (DataWithGetter)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final DataWithGetter other = (DataWithGetter) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
if (this.getY() != other.getY()) return false;
final java.lang.Object this$z = this.getZ();
@@ -41,7 +40,7 @@ class DataWithGetter {
result = result * PRIME + this.getX();
result = result * PRIME + this.getY();
final java.lang.Object $z = this.getZ();
- result = result * PRIME + ($z == null ? 0 : $z.hashCode());
+ result = result * PRIME + ($z == null ? 43 : $z.hashCode());
return result;
}
@java.lang.Override
@@ -61,4 +60,4 @@ class DataWithGetter {
public String getZ() {
return this.z;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DataWithGetterNone.java b/test/transform/resource/after-delombok/DataWithGetterNone.java
index 5986ee9f..4467e407 100644
--- a/test/transform/resource/after-delombok/DataWithGetterNone.java
+++ b/test/transform/resource/after-delombok/DataWithGetterNone.java
@@ -2,7 +2,6 @@ class DataWithGetterNone {
private int x;
private int y;
private final String z;
- @java.beans.ConstructorProperties({"z"})
@java.lang.SuppressWarnings("all")
public DataWithGetterNone(final String z) {
this.z = z;
@@ -20,8 +19,8 @@ class DataWithGetterNone {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof DataWithGetterNone)) return false;
- final DataWithGetterNone other = (DataWithGetterNone)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final DataWithGetterNone other = (DataWithGetterNone) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.x != other.x) return false;
if (this.y != other.y) return false;
final java.lang.Object this$z = this.z;
@@ -41,7 +40,7 @@ class DataWithGetterNone {
result = result * PRIME + this.x;
result = result * PRIME + this.y;
final java.lang.Object $z = this.z;
- result = result * PRIME + ($z == null ? 0 : $z.hashCode());
+ result = result * PRIME + ($z == null ? 43 : $z.hashCode());
return result;
}
@java.lang.Override
@@ -49,4 +48,4 @@ class DataWithGetterNone {
public java.lang.String toString() {
return "DataWithGetterNone(x=" + this.x + ", y=" + this.y + ", z=" + this.z + ")";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DelegateOnGetter.java b/test/transform/resource/after-delombok/DelegateOnGetter.java
index e8d01a49..f41259df 100644
--- a/test/transform/resource/after-delombok/DelegateOnGetter.java
+++ b/test/transform/resource/after-delombok/DelegateOnGetter.java
@@ -11,7 +11,7 @@ class DelegateOnGetter {
synchronized (this.bar) {
value = this.bar.get();
if (value == null) {
- final Bar actualValue = new Bar(){
+ final Bar actualValue = new Bar() {
public void setList(java.util.ArrayList<String> list) {
}
public int getInt() {
@@ -23,7 +23,7 @@ class DelegateOnGetter {
}
}
}
- return (Bar)(value == this.bar ? null : value);
+ return (Bar) (value == this.bar ? null : value);
}
@java.lang.SuppressWarnings("all")
public void setList(final java.util.ArrayList<java.lang.String> list) {
@@ -33,4 +33,4 @@ class DelegateOnGetter {
public int getInt() {
return this.getBar().getInt();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DelegateOnGetterNone.java b/test/transform/resource/after-delombok/DelegateOnGetterNone.java
index 9f9411f4..1f6eb5be 100644
--- a/test/transform/resource/after-delombok/DelegateOnGetterNone.java
+++ b/test/transform/resource/after-delombok/DelegateOnGetterNone.java
@@ -12,4 +12,4 @@ class DelegateOnGetterNone {
public int getInt() {
return this.bar.getInt();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DelegateOnMethods.java b/test/transform/resource/after-delombok/DelegateOnMethods.java
index b900f140..eb94c6d2 100644
--- a/test/transform/resource/after-delombok/DelegateOnMethods.java
+++ b/test/transform/resource/after-delombok/DelegateOnMethods.java
@@ -6,7 +6,9 @@ abstract class DelegateOnMethods {
}
@java.lang.SuppressWarnings("all")
+
+
public void bar(final java.util.ArrayList<java.lang.String> list) {
this.getBar().bar(list);
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DelegateTypesAndExcludes.java b/test/transform/resource/after-delombok/DelegateTypesAndExcludes.java
index 3f6f555d..921669c7 100644
--- a/test/transform/resource/after-delombok/DelegateTypesAndExcludes.java
+++ b/test/transform/resource/after-delombok/DelegateTypesAndExcludes.java
@@ -24,12 +24,16 @@ class DelegatePlain {
}
@java.lang.SuppressWarnings("all")
+
+
public void bar(final java.util.ArrayList<java.lang.String> list) {
this.bar.bar(list);
}
@java.lang.SuppressWarnings("all")
+
+
public void foo() {
this.foo.foo();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DelegateWithDeprecated.java b/test/transform/resource/after-delombok/DelegateWithDeprecated.java
index f7bd1e6d..f487dc87 100644
--- a/test/transform/resource/after-delombok/DelegateWithDeprecated.java
+++ b/test/transform/resource/after-delombok/DelegateWithDeprecated.java
@@ -23,4 +23,4 @@ class DelegateWithDeprecated {
public void notDeprecated() {
this.bar.notDeprecated();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/DelegateWithVarargs.java b/test/transform/resource/after-delombok/DelegateWithVarargs.java
new file mode 100644
index 00000000..dadbb4ee
--- /dev/null
+++ b/test/transform/resource/after-delombok/DelegateWithVarargs.java
@@ -0,0 +1,25 @@
+class DelegateWithVarargs {
+ private Bar bar;
+ private interface Bar {
+ void justOneParameter(int... varargs);
+ void multipleParameters(String first, int... varargs);
+ void array(int[] array);
+ void arrayVarargs(int[]... arrayVarargs);
+ }
+ @java.lang.SuppressWarnings("all")
+ public void justOneParameter(final int... varargs) {
+ this.bar.justOneParameter(varargs);
+ }
+ @java.lang.SuppressWarnings("all")
+ public void multipleParameters(final java.lang.String first, final int... varargs) {
+ this.bar.multipleParameters(first, varargs);
+ }
+ @java.lang.SuppressWarnings("all")
+ public void array(final int[] array) {
+ this.bar.array(array);
+ }
+ @java.lang.SuppressWarnings("all")
+ public void arrayVarargs(final int[]... arrayVarargs) {
+ this.bar.arrayVarargs(arrayVarargs);
+ }
+}
diff --git a/test/transform/resource/after-delombok/EncodingUsAscii.java b/test/transform/resource/after-delombok/EncodingUsAscii.java
new file mode 100644
index 00000000..ec352056
--- /dev/null
+++ b/test/transform/resource/after-delombok/EncodingUsAscii.java
@@ -0,0 +1,9 @@
+//ENCODING: US-ASCII
+class EncodingUsAscii {
+ String foo\u0e51\u0e51 = "\016\t\b ";
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "EncodingUsAscii(foo\u0e51\u0e51=" + this.foo\u0e51\u0e51 + ")";
+ }
+}
diff --git a/test/transform/resource/after-delombok/EncodingUtf8.java b/test/transform/resource/after-delombok/EncodingUtf8.java
new file mode 100644
index 00000000..1c7751b5
--- /dev/null
+++ b/test/transform/resource/after-delombok/EncodingUtf8.java
@@ -0,0 +1,8 @@
+class EncodingUtf8 {
+ String foo๑๑ = "\016\t\b ";
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "EncodingUtf8(foo๑๑=" + this.foo๑๑ + ")";
+ }
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCode.java b/test/transform/resource/after-delombok/EqualsAndHashCode.java
index 02ca2c42..eed77b39 100644
--- a/test/transform/resource/after-delombok/EqualsAndHashCode.java
+++ b/test/transform/resource/after-delombok/EqualsAndHashCode.java
@@ -9,8 +9,8 @@ class EqualsAndHashCode {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode)) return false;
- final EqualsAndHashCode other = (EqualsAndHashCode)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCode other = (EqualsAndHashCode) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.x != other.x) return false;
if (!java.util.Arrays.equals(this.y, other.y)) return false;
if (!java.util.Arrays.deepEquals(this.z, other.z)) return false;
@@ -35,9 +35,9 @@ class EqualsAndHashCode {
result = result * PRIME + java.util.Arrays.hashCode(this.y);
result = result * PRIME + java.util.Arrays.deepHashCode(this.z);
final java.lang.Object $a = this.a;
- result = result * PRIME + ($a == null ? 0 : $a.hashCode());
+ result = result * PRIME + ($a == null ? 43 : $a.hashCode());
final java.lang.Object $b = this.b;
- result = result * PRIME + ($b == null ? 0 : $b.hashCode());
+ result = result * PRIME + ($b == null ? 43 : $b.hashCode());
return result;
}
}
@@ -52,7 +52,7 @@ final class EqualsAndHashCode2 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode2)) return false;
- final EqualsAndHashCode2 other = (EqualsAndHashCode2)o;
+ final EqualsAndHashCode2 other = (EqualsAndHashCode2) o;
if (this.x != other.x) return false;
if (this.y != other.y) return false;
if (java.lang.Float.compare(this.f, other.f) != 0) return false;
@@ -67,10 +67,10 @@ final class EqualsAndHashCode2 {
int result = 1;
result = result * PRIME + this.x;
final long $y = this.y;
- result = result * PRIME + (int)($y >>> 32 ^ $y);
+ result = result * PRIME + (int) ($y >>> 32 ^ $y);
result = result * PRIME + java.lang.Float.floatToIntBits(this.f);
final long $d = java.lang.Double.doubleToLongBits(this.d);
- result = result * PRIME + (int)($d >>> 32 ^ $d);
+ result = result * PRIME + (int) ($d >>> 32 ^ $d);
result = result * PRIME + (this.b ? 79 : 97);
return result;
}
@@ -81,8 +81,8 @@ final class EqualsAndHashCode3 extends EqualsAndHashCode {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode3)) return false;
- final EqualsAndHashCode3 other = (EqualsAndHashCode3)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCode3 other = (EqualsAndHashCode3) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
return true;
}
@java.lang.SuppressWarnings("all")
@@ -102,8 +102,8 @@ class EqualsAndHashCode4 extends EqualsAndHashCode {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCode4)) return false;
- final EqualsAndHashCode4 other = (EqualsAndHashCode4)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCode4 other = (EqualsAndHashCode4) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (!super.equals(o)) return false;
return true;
}
@@ -114,9 +114,7 @@ class EqualsAndHashCode4 extends EqualsAndHashCode {
@java.lang.Override
@java.lang.SuppressWarnings("all")
public int hashCode() {
- final int PRIME = 59;
- int result = 1;
- result = result * PRIME + super.hashCode();
+ int result = super.hashCode();
return result;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys1.java b/test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys1.java
new file mode 100644
index 00000000..82a5a42d
--- /dev/null
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys1.java
@@ -0,0 +1,46 @@
+class EqualsAndHashCodeConfigKeys1Parent {
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeConfigKeys1Parent)) return false;
+ final EqualsAndHashCodeConfigKeys1Parent other = (EqualsAndHashCodeConfigKeys1Parent) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeConfigKeys1Parent;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ int result = 1;
+ return result;
+ }
+}
+class EqualsAndHashCodeConfigKeys1 extends EqualsAndHashCodeConfigKeys1Parent {
+ int x;
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeConfigKeys1)) return false;
+ final EqualsAndHashCodeConfigKeys1 other = (EqualsAndHashCodeConfigKeys1) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ if (this.x != other.x) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeConfigKeys1;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.x;
+ return result;
+ }
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys2.java b/test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys2.java
new file mode 100644
index 00000000..c46c7f1c
--- /dev/null
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeConfigKeys2.java
@@ -0,0 +1,68 @@
+class EqualsAndHashCodeConfigKeys2Object extends Object {
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeConfigKeys2Object)) return false;
+ final EqualsAndHashCodeConfigKeys2Object other = (EqualsAndHashCodeConfigKeys2Object) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeConfigKeys2Object;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ int result = 1;
+ return result;
+ }
+}
+class EqualsAndHashCodeConfigKeys2Parent {
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeConfigKeys2Parent)) return false;
+ final EqualsAndHashCodeConfigKeys2Parent other = (EqualsAndHashCodeConfigKeys2Parent) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeConfigKeys2Parent;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ int result = 1;
+ return result;
+ }
+}
+class EqualsAndHashCodeConfigKeys2 extends EqualsAndHashCodeConfigKeys2Parent {
+ int x;
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeConfigKeys2)) return false;
+ final EqualsAndHashCodeConfigKeys2 other = (EqualsAndHashCodeConfigKeys2) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ if (!super.equals(o)) return false;
+ if (this.x != other.x) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeConfigKeys2;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = super.hashCode();
+ result = result * PRIME + this.x;
+ return result;
+ }
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeNestedShadow.java b/test/transform/resource/after-delombok/EqualsAndHashCodeNestedShadow.java
new file mode 100644
index 00000000..0b479c2d
--- /dev/null
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeNestedShadow.java
@@ -0,0 +1,50 @@
+interface EqualsAndHashCodeNestedShadow {
+ interface Foo {
+ }
+ class Bar {
+ public static class Foo extends Bar implements EqualsAndHashCodeNestedShadow.Foo {
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeNestedShadow.Bar.Foo)) return false;
+ final EqualsAndHashCodeNestedShadow.Bar.Foo other = (EqualsAndHashCodeNestedShadow.Bar.Foo) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeNestedShadow.Bar.Foo;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ int result = 1;
+ return result;
+ }
+ }
+ }
+ class Baz {
+ public static class Foo<T> extends Bar implements EqualsAndHashCodeNestedShadow.Foo {
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeNestedShadow.Baz.Foo)) return false;
+ final EqualsAndHashCodeNestedShadow.Baz.Foo<?> other = (EqualsAndHashCodeNestedShadow.Baz.Foo<?>) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeNestedShadow.Baz.Foo;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ int result = 1;
+ return result;
+ }
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeOfAndExclude.java b/test/transform/resource/after-delombok/EqualsAndHashCodeOfAndExclude.java
new file mode 100644
index 00000000..895da4db
--- /dev/null
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeOfAndExclude.java
@@ -0,0 +1,42 @@
+final class EqualsAndHashCodeOf {
+ int x;
+ int y;
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeOf)) return false;
+ final EqualsAndHashCodeOf other = (EqualsAndHashCodeOf) o;
+ if (this.x != other.x) return false;
+ return true;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.x;
+ return result;
+ }
+}
+final class EqualsAndHashCodeExclude {
+ int x;
+ int y;
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeExclude)) return false;
+ final EqualsAndHashCodeExclude other = (EqualsAndHashCodeExclude) o;
+ if (this.x != other.x) return false;
+ return true;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.x;
+ return result;
+ }
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithExistingMethods.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithExistingMethods.java
index ac189f42..dcad0263 100644
--- a/test/transform/resource/after-delombok/EqualsAndHashCodeWithExistingMethods.java
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithExistingMethods.java
@@ -20,8 +20,8 @@ final class EqualsAndHashCodeWithExistingMethods3 extends EqualsAndHashCodeWithE
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCodeWithExistingMethods3)) return false;
- final EqualsAndHashCodeWithExistingMethods3 other = (EqualsAndHashCodeWithExistingMethods3)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCodeWithExistingMethods3 other = (EqualsAndHashCodeWithExistingMethods3) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (!super.equals(o)) return false;
if (this.x != other.x) return false;
return true;
@@ -30,9 +30,8 @@ final class EqualsAndHashCodeWithExistingMethods3 extends EqualsAndHashCodeWithE
@java.lang.SuppressWarnings("all")
public int hashCode() {
final int PRIME = 59;
- int result = 1;
- result = result * PRIME + super.hashCode();
+ int result = super.hashCode();
result = result * PRIME + this.x;
return result;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java
new file mode 100644
index 00000000..501d45a1
--- /dev/null
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithGenericsOnInners.java
@@ -0,0 +1,28 @@
+public class EqualsAndHashCodeWithGenericsOnInners<A> {
+ class Inner<B> {
+ int x;
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeWithGenericsOnInners.Inner)) return false;
+ final EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?> other = (EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?>) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ if (this.x != other.x) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof EqualsAndHashCodeWithGenericsOnInners.Inner;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = result * PRIME + this.x;
+ return result;
+ }
+ }
+}
+
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java
index d8d8b025..91c62b0f 100644
--- a/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithOnParam.java
@@ -12,8 +12,8 @@ class EqualsAndHashCodeWithOnParam {
public boolean equals(@Nullable final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCodeWithOnParam)) return false;
- final EqualsAndHashCodeWithOnParam other = (EqualsAndHashCodeWithOnParam)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCodeWithOnParam other = (EqualsAndHashCodeWithOnParam) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.x != other.x) return false;
if (!java.util.Arrays.equals(this.y, other.y)) return false;
if (!java.util.Arrays.deepEquals(this.z, other.z)) return false;
@@ -38,9 +38,9 @@ class EqualsAndHashCodeWithOnParam {
result = result * PRIME + java.util.Arrays.hashCode(this.y);
result = result * PRIME + java.util.Arrays.deepHashCode(this.z);
final java.lang.Object $a = this.a;
- result = result * PRIME + ($a == null ? 0 : $a.hashCode());
+ result = result * PRIME + ($a == null ? 43 : $a.hashCode());
final java.lang.Object $b = this.b;
- result = result * PRIME + ($b == null ? 0 : $b.hashCode());
+ result = result * PRIME + ($b == null ? 43 : $b.hashCode());
return result;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/EqualsAndHashCodeWithSomeExistingMethods.java b/test/transform/resource/after-delombok/EqualsAndHashCodeWithSomeExistingMethods.java
index 37eeb8df..b3a1fb0d 100644
--- a/test/transform/resource/after-delombok/EqualsAndHashCodeWithSomeExistingMethods.java
+++ b/test/transform/resource/after-delombok/EqualsAndHashCodeWithSomeExistingMethods.java
@@ -28,8 +28,8 @@ class EqualsAndHashCodeWithSomeExistingMethods2 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCodeWithSomeExistingMethods2)) return false;
- final EqualsAndHashCodeWithSomeExistingMethods2 other = (EqualsAndHashCodeWithSomeExistingMethods2)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCodeWithSomeExistingMethods2 other = (EqualsAndHashCodeWithSomeExistingMethods2) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.x != other.x) return false;
return true;
}
@@ -75,8 +75,8 @@ class EqualsAndHashCodeWithNoExistingMethods {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof EqualsAndHashCodeWithNoExistingMethods)) return false;
- final EqualsAndHashCodeWithNoExistingMethods other = (EqualsAndHashCodeWithNoExistingMethods)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final EqualsAndHashCodeWithNoExistingMethods other = (EqualsAndHashCodeWithNoExistingMethods) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.x != other.x) return false;
return true;
}
diff --git a/test/transform/resource/after-delombok/ExtensionMethodPlain.java b/test/transform/resource/after-delombok/ExtensionMethodPlain.java
index 707a0258..4a3cc347 100644
--- a/test/transform/resource/after-delombok/ExtensionMethodPlain.java
+++ b/test/transform/resource/after-delombok/ExtensionMethodPlain.java
@@ -14,4 +14,4 @@ class ExtensionMethodPlain {
return "" + Character.toTitleCase(in.charAt(0)) + in.substring(1).toLowerCase();
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/FieldDefaults.java b/test/transform/resource/after-delombok/FieldDefaults.java
index 8a84f442..19fb9d39 100644
--- a/test/transform/resource/after-delombok/FieldDefaults.java
+++ b/test/transform/resource/after-delombok/FieldDefaults.java
@@ -1,4 +1,5 @@
class FieldDefaults1 {
+ static int STATIC = 3;
final int x;
int y;
FieldDefaults1(int x) {
@@ -6,6 +7,7 @@ class FieldDefaults1 {
}
}
class FieldDefaults2 {
+ static int STATIC = 3;
int x;
private int y;
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/FieldDefaultsNoop.java b/test/transform/resource/after-delombok/FieldDefaultsNoop.java
index 275fa0e7..59c377ed 100644
--- a/test/transform/resource/after-delombok/FieldDefaultsNoop.java
+++ b/test/transform/resource/after-delombok/FieldDefaultsNoop.java
@@ -1,2 +1,2 @@
class FieldDefaultsNoop {
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/FieldDefaultsViaConfig.java b/test/transform/resource/after-delombok/FieldDefaultsViaConfig.java
new file mode 100644
index 00000000..96191005
--- /dev/null
+++ b/test/transform/resource/after-delombok/FieldDefaultsViaConfig.java
@@ -0,0 +1,11 @@
+class FieldDefaultsViaConfig1 {
+ private final int x;
+ private int y;
+ FieldDefaultsViaConfig1(int x) {
+ this.x = x;
+ }
+}
+class FieldDefaultsViaConfig2 {
+ final int x = 2;
+ protected final int y = 0;
+}
diff --git a/test/transform/resource/after-delombok/FieldDefaultsViaConfigAndRequiredArgsConstructor.java b/test/transform/resource/after-delombok/FieldDefaultsViaConfigAndRequiredArgsConstructor.java
new file mode 100644
index 00000000..959bb1e0
--- /dev/null
+++ b/test/transform/resource/after-delombok/FieldDefaultsViaConfigAndRequiredArgsConstructor.java
@@ -0,0 +1,7 @@
+class FieldDefaultsViaConfigAndRequiredArgsConstructor {
+ final int x;
+ @java.lang.SuppressWarnings("all")
+ public FieldDefaultsViaConfigAndRequiredArgsConstructor(final int x) {
+ this.x = x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GenerateSuppressFBWarnings.java b/test/transform/resource/after-delombok/GenerateSuppressFBWarnings.java
new file mode 100644
index 00000000..e78ee55c
--- /dev/null
+++ b/test/transform/resource/after-delombok/GenerateSuppressFBWarnings.java
@@ -0,0 +1,9 @@
+//VERSION 7:
+class GenerateSuppressFBWarnings {
+ int y;
+ @java.lang.SuppressWarnings("all")
+ @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code")
+ public int getY() {
+ return this.y;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GeneratedJavaxOff.java b/test/transform/resource/after-delombok/GeneratedJavaxOff.java
new file mode 100644
index 00000000..ca50f3d2
--- /dev/null
+++ b/test/transform/resource/after-delombok/GeneratedJavaxOff.java
@@ -0,0 +1,7 @@
+class GeneratedJavaxOff {
+ int x;
+ @java.lang.SuppressWarnings("all")
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GeneratedJavaxOnLombokOn.java b/test/transform/resource/after-delombok/GeneratedJavaxOnLombokOn.java
new file mode 100644
index 00000000..2ca96e7c
--- /dev/null
+++ b/test/transform/resource/after-delombok/GeneratedJavaxOnLombokOn.java
@@ -0,0 +1,10 @@
+//version :8
+class GeneratedJavaxOnLombokOn {
+ int x;
+ @java.lang.SuppressWarnings("all")
+ @javax.annotation.Generated("lombok")
+ @lombok.Generated
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GeneratedOff.java b/test/transform/resource/after-delombok/GeneratedOff.java
new file mode 100644
index 00000000..0e4ecf7d
--- /dev/null
+++ b/test/transform/resource/after-delombok/GeneratedOff.java
@@ -0,0 +1,7 @@
+class GeneratedOff {
+ int x;
+ @java.lang.SuppressWarnings("all")
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GeneratedOffJavaxOn.java b/test/transform/resource/after-delombok/GeneratedOffJavaxOn.java
new file mode 100644
index 00000000..4b10c708
--- /dev/null
+++ b/test/transform/resource/after-delombok/GeneratedOffJavaxOn.java
@@ -0,0 +1,9 @@
+//version :8
+class GeneratedOffJavaxOn {
+ int x;
+ @java.lang.SuppressWarnings("all")
+ @javax.annotation.Generated("lombok")
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GeneratedOffLombokOn.java b/test/transform/resource/after-delombok/GeneratedOffLombokOn.java
new file mode 100644
index 00000000..03e23d66
--- /dev/null
+++ b/test/transform/resource/after-delombok/GeneratedOffLombokOn.java
@@ -0,0 +1,8 @@
+class GeneratedOffLombokOn {
+ int x;
+ @java.lang.SuppressWarnings("all")
+ @lombok.Generated
+ public int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GetterAccessLevel.java b/test/transform/resource/after-delombok/GetterAccessLevel.java
index 6d977d87..2574340a 100644
--- a/test/transform/resource/after-delombok/GetterAccessLevel.java
+++ b/test/transform/resource/after-delombok/GetterAccessLevel.java
@@ -46,4 +46,4 @@ class GetterAccessLevel {
public String getValue() {
return this.value;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterAlreadyExists.java b/test/transform/resource/after-delombok/GetterAlreadyExists.java
index 8389ae31..d7f32ff1 100644
--- a/test/transform/resource/after-delombok/GetterAlreadyExists.java
+++ b/test/transform/resource/after-delombok/GetterAlreadyExists.java
@@ -145,4 +145,4 @@ class Getter18 {
static String getFoo() {
return "";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterBoolean.java b/test/transform/resource/after-delombok/GetterBoolean.java
index 42b4319d..6ac91512 100644
--- a/test/transform/resource/after-delombok/GetterBoolean.java
+++ b/test/transform/resource/after-delombok/GetterBoolean.java
@@ -30,4 +30,4 @@ class YetMoreGetter {
boolean getFoo() {
return true;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterDeprecated.java b/test/transform/resource/after-delombok/GetterDeprecated.java
index 09ea9929..af123509 100644
--- a/test/transform/resource/after-delombok/GetterDeprecated.java
+++ b/test/transform/resource/after-delombok/GetterDeprecated.java
@@ -18,4 +18,4 @@ class GetterDeprecated {
public int getJavadoc() {
return this.javadoc;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterEnum.java b/test/transform/resource/after-delombok/GetterEnum.java
index 3c6e6e0c..272a2ee6 100644
--- a/test/transform/resource/after-delombok/GetterEnum.java
+++ b/test/transform/resource/after-delombok/GetterEnum.java
@@ -15,4 +15,4 @@ enum GetterEnum {
public String getName() {
return this.name;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterLazy.java b/test/transform/resource/after-delombok/GetterLazy.java
index 4f6f2c03..25a71848 100644
--- a/test/transform/resource/after-delombok/GetterLazy.java
+++ b/test/transform/resource/after-delombok/GetterLazy.java
@@ -15,6 +15,6 @@ class GetterLazy {
}
}
}
- return (ValueType)(value == this.fieldName ? null : value);
+ return (ValueType) (value == this.fieldName ? null : value);
}
}
diff --git a/test/transform/resource/after-delombok/GetterLazyBoolean.java b/test/transform/resource/after-delombok/GetterLazyBoolean.java
index f684fc07..3ca127e3 100644
--- a/test/transform/resource/after-delombok/GetterLazyBoolean.java
+++ b/test/transform/resource/after-delombok/GetterLazyBoolean.java
@@ -9,8 +9,8 @@ class GetterLazyBoolean {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof GetterLazyBoolean)) return false;
- final GetterLazyBoolean other = (GetterLazyBoolean)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final GetterLazyBoolean other = (GetterLazyBoolean) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.isBooleanValue() != other.isBooleanValue()) return false;
return true;
}
@@ -44,7 +44,7 @@ class GetterLazyBoolean {
}
}
}
- return (java.lang.Boolean)value;
+ return (java.lang.Boolean) value;
}
@java.lang.SuppressWarnings("all")
public boolean isOtherBooleanValue() {
@@ -59,6 +59,6 @@ class GetterLazyBoolean {
}
}
}
- return (java.lang.Boolean)value;
+ return (java.lang.Boolean) value;
}
}
diff --git a/test/transform/resource/after-delombok/GetterLazyEahcToString.java b/test/transform/resource/after-delombok/GetterLazyEahcToString.java
index 65c63fba..e0a0f6b2 100644
--- a/test/transform/resource/after-delombok/GetterLazyEahcToString.java
+++ b/test/transform/resource/after-delombok/GetterLazyEahcToString.java
@@ -8,8 +8,8 @@ class GetterLazyEahcToString {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof GetterLazyEahcToString)) return false;
- final GetterLazyEahcToString other = (GetterLazyEahcToString)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final GetterLazyEahcToString other = (GetterLazyEahcToString) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
final java.lang.Object this$value = this.getValue();
final java.lang.Object other$value = other.getValue();
if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;
@@ -20,6 +20,8 @@ class GetterLazyEahcToString {
}
@java.lang.SuppressWarnings("all")
+
+
protected boolean canEqual(final java.lang.Object other) {
return other instanceof GetterLazyEahcToString;
}
@@ -30,9 +32,9 @@ class GetterLazyEahcToString {
final int PRIME = 59;
int result = 1;
final java.lang.Object $value = this.getValue();
- result = result * PRIME + ($value == null ? 0 : $value.hashCode());
+ result = result * PRIME + ($value == null ? 43 : $value.hashCode());
final java.lang.Object $value2 = this.value2;
- result = result * PRIME + ($value2 == null ? 0 : $value2.hashCode());
+ result = result * PRIME + ($value2 == null ? 43 : $value2.hashCode());
return result;
}
@@ -43,6 +45,8 @@ class GetterLazyEahcToString {
}
@java.lang.SuppressWarnings("all")
+
+
public String getValue() {
java.lang.Object value = this.value.get();
if (value == null) {
@@ -55,11 +59,11 @@ class GetterLazyEahcToString {
}
}
}
- return (String)(value == this.value ? null : value);
+ return (String) (value == this.value ? null : value);
}
@java.lang.SuppressWarnings("all")
public String getValue2() {
return this.value2;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterLazyInvalid.java b/test/transform/resource/after-delombok/GetterLazyInvalid.java
index 25963921..81d87c3c 100644
--- a/test/transform/resource/after-delombok/GetterLazyInvalid.java
+++ b/test/transform/resource/after-delombok/GetterLazyInvalid.java
@@ -22,4 +22,4 @@ class GetterLazyInvalidNoInit {
GetterLazyInvalidNoInit() {
this.fieldName = "foo";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterLazyNative.java b/test/transform/resource/after-delombok/GetterLazyNative.java
index eb31991a..b9d471ff 100644
--- a/test/transform/resource/after-delombok/GetterLazyNative.java
+++ b/test/transform/resource/after-delombok/GetterLazyNative.java
@@ -21,7 +21,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Boolean)value;
+ return (java.lang.Boolean) value;
}
@java.lang.SuppressWarnings("all")
public byte getByteField() {
@@ -36,7 +36,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Byte)value;
+ return (java.lang.Byte) value;
}
@java.lang.SuppressWarnings("all")
public short getShortField() {
@@ -51,7 +51,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Short)value;
+ return (java.lang.Short) value;
}
@java.lang.SuppressWarnings("all")
public int getIntField() {
@@ -66,7 +66,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Integer)value;
+ return (java.lang.Integer) value;
}
@java.lang.SuppressWarnings("all")
public long getLongField() {
@@ -81,7 +81,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Long)value;
+ return (java.lang.Long) value;
}
@java.lang.SuppressWarnings("all")
public float getFloatField() {
@@ -96,7 +96,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Float)value;
+ return (java.lang.Float) value;
}
@java.lang.SuppressWarnings("all")
public double getDoubleField() {
@@ -111,7 +111,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Double)value;
+ return (java.lang.Double) value;
}
@java.lang.SuppressWarnings("all")
public char getCharField() {
@@ -126,7 +126,7 @@ class GetterLazyNative {
}
}
}
- return (java.lang.Character)value;
+ return (java.lang.Character) value;
}
@java.lang.SuppressWarnings("all")
public int[] getIntArrayField() {
@@ -135,12 +135,12 @@ class GetterLazyNative {
synchronized (this.intArrayField) {
value = this.intArrayField.get();
if (value == null) {
- final int[] actualValue = new int[]{1};
+ final int[] actualValue = new int[] {1};
value = actualValue == null ? this.intArrayField : actualValue;
this.intArrayField.set(value);
}
}
}
- return (int[])(value == this.intArrayField ? null : value);
+ return (int[]) (value == this.intArrayField ? null : value);
}
}
diff --git a/test/transform/resource/after-delombok/GetterLazyTransient.java b/test/transform/resource/after-delombok/GetterLazyTransient.java
new file mode 100644
index 00000000..49093ed1
--- /dev/null
+++ b/test/transform/resource/after-delombok/GetterLazyTransient.java
@@ -0,0 +1,24 @@
+class GetterLazyTransient {
+ private final java.util.concurrent.atomic.AtomicReference<java.lang.Object> nonTransientField = new java.util.concurrent.atomic.AtomicReference<java.lang.Object>();
+ private final transient int transientField = 2;
+ private final transient int nonLazyTransientField = 3;
+ @java.lang.SuppressWarnings("all")
+ public int getNonTransientField() {
+ java.lang.Object value = this.nonTransientField.get();
+ if (value == null) {
+ synchronized (this.nonTransientField) {
+ value = this.nonTransientField.get();
+ if (value == null) {
+ final int actualValue = 1;
+ value = actualValue;
+ this.nonTransientField.set(value);
+ }
+ }
+ }
+ return (java.lang.Integer) value;
+ }
+ @java.lang.SuppressWarnings("all")
+ public int getNonLazyTransientField() {
+ return this.nonLazyTransientField;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GetterNone.java b/test/transform/resource/after-delombok/GetterNone.java
index 11b4fd09..5666f6fe 100644
--- a/test/transform/resource/after-delombok/GetterNone.java
+++ b/test/transform/resource/after-delombok/GetterNone.java
@@ -5,4 +5,4 @@ class GetterNone {
public int getI() {
return this.i;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterOnClass.java b/test/transform/resource/after-delombok/GetterOnClass.java
index bd15ce35..f0025370 100644
--- a/test/transform/resource/after-delombok/GetterOnClass.java
+++ b/test/transform/resource/after-delombok/GetterOnClass.java
@@ -56,4 +56,4 @@ class GetterOnClass6 {
public String getNonNull() {
return this.nonNull;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterOnMethodErrors.java b/test/transform/resource/after-delombok/GetterOnMethodErrors.java
index 86813bd2..a69966ec 100644
--- a/test/transform/resource/after-delombok/GetterOnMethodErrors.java
+++ b/test/transform/resource/after-delombok/GetterOnMethodErrors.java
@@ -6,4 +6,4 @@ class GetterOnMethodErrors {
public int getTest() {
return this.test;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterPlain.java b/test/transform/resource/after-delombok/GetterPlain.java
index 359d46e2..ceae2aac 100644
--- a/test/transform/resource/after-delombok/GetterPlain.java
+++ b/test/transform/resource/after-delombok/GetterPlain.java
@@ -9,4 +9,4 @@ class GetterPlain {
public int getFoo() {
return this.foo;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/GetterSetterJavadoc.java b/test/transform/resource/after-delombok/GetterSetterJavadoc.java
index 7a782434..019b3c37 100644
--- a/test/transform/resource/after-delombok/GetterSetterJavadoc.java
+++ b/test/transform/resource/after-delombok/GetterSetterJavadoc.java
@@ -29,8 +29,8 @@ class GetterSetterJavadoc1 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof GetterSetterJavadoc1)) return false;
- final GetterSetterJavadoc1 other = (GetterSetterJavadoc1)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final GetterSetterJavadoc1 other = (GetterSetterJavadoc1) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getFieldName() != other.getFieldName()) return false;
return true;
}
@@ -97,4 +97,54 @@ class GetterSetterJavadoc3 {
public void setFieldName(final int fieldName) {
this.fieldName = fieldName;
}
-} \ No newline at end of file
+}
+class GetterSetterJavadoc4 {
+ /**
+ * Some text
+ */
+ private int fieldName;
+ /**
+ * Some text
+ *
+ * @return Sky is blue4
+ */
+ @java.lang.SuppressWarnings("all")
+ public int fieldName() {
+ return this.fieldName;
+ }
+ /**
+ * Some text
+ *
+ * @param fieldName Hello, World5
+ * @return this
+ */
+ @java.lang.SuppressWarnings("all")
+ public GetterSetterJavadoc4 fieldName(final int fieldName) {
+ this.fieldName = fieldName;
+ return this;
+ }
+}
+class GetterSetterJavadoc5 {
+ /**
+ * Some text
+ */
+ private int fieldName;
+ /**
+ * Getter section
+ * @return Sky is blue5
+ */
+ @java.lang.SuppressWarnings("all")
+ public int fieldName() {
+ return this.fieldName;
+ }
+ /**
+ * Setter section
+ * @param fieldName Hello, World5
+ * @return Sky is blue5
+ */
+ @java.lang.SuppressWarnings("all")
+ public GetterSetterJavadoc5 fieldName(final int fieldName) {
+ this.fieldName = fieldName;
+ return this;
+ }
+}
diff --git a/test/transform/resource/after-delombok/GetterWithDollar.java b/test/transform/resource/after-delombok/GetterWithDollar.java
index 520f4ea5..56435665 100644
--- a/test/transform/resource/after-delombok/GetterWithDollar.java
+++ b/test/transform/resource/after-delombok/GetterWithDollar.java
@@ -16,4 +16,4 @@ class GetterWithDollar2 {
public int getI() {
return this.i;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/Helper.java b/test/transform/resource/after-delombok/Helper.java
new file mode 100644
index 00000000..64ecb492
--- /dev/null
+++ b/test/transform/resource/after-delombok/Helper.java
@@ -0,0 +1,19 @@
+class HelperTest {
+ {
+ final int z = 5;
+ if (Boolean.TRUE) {
+ class H1 {
+ void foo(int x) {
+ System.out.println("Hello, " + (x + z));
+ }
+ }
+ final H1 $H1 = new H1();
+ $H1.foo(10);
+ class H2 {
+ void bar() {
+ $H1.foo(12);
+ }
+ }
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/InjectField.java b/test/transform/resource/after-delombok/InjectField.java
index 59896400..98f9762b 100644
--- a/test/transform/resource/after-delombok/InjectField.java
+++ b/test/transform/resource/after-delombok/InjectField.java
@@ -1,10 +1,11 @@
import java.util.logging.Level;
enum InjectField1 {
- A,
- B;
+ A, B;
@java.lang.SuppressWarnings("all")
+
+
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(InjectField1.class.getName());
@java.lang.SuppressWarnings("all")
private final java.lang.Object $lock = new java.lang.Object[0];
@@ -59,4 +60,4 @@ class InjectField3 {
static {
log.log(Level.FINE, "static initializer");
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/InnerClass.java b/test/transform/resource/after-delombok/InnerClass.java
new file mode 100644
index 00000000..6d42bb79
--- /dev/null
+++ b/test/transform/resource/after-delombok/InnerClass.java
@@ -0,0 +1,51 @@
+class A {
+ class B {
+ String s;
+ @java.lang.SuppressWarnings("all")
+ public B(final String s) {
+ this.s = s;
+ }
+ }
+}
+class C {
+ final class D {
+ private final A a;
+ A.B test(String s) {
+ return a.new B(s) {
+ };
+ }
+ @java.lang.SuppressWarnings("all")
+ public D(final A a) {
+ this.a = a;
+ }
+ @java.lang.SuppressWarnings("all")
+ public A getA() {
+ return this.a;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof C.D)) return false;
+ final C.D other = (C.D) o;
+ final java.lang.Object this$a = this.getA();
+ final java.lang.Object other$a = other.getA();
+ if (this$a == null ? other$a != null : !this$a.equals(other$a)) return false;
+ return true;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final java.lang.Object $a = this.getA();
+ result = result * PRIME + ($a == null ? 43 : $a.hashCode());
+ return result;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "C.D(a=" + this.getA() + ")";
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-delombok/JavadocGenerally.java b/test/transform/resource/after-delombok/JavadocGenerally.java
index 729cdce3..ec9483bc 100644
--- a/test/transform/resource/after-delombok/JavadocGenerally.java
+++ b/test/transform/resource/after-delombok/JavadocGenerally.java
@@ -9,6 +9,9 @@ package testPackage;
class JavadocGenerally {
/**
* Doc on field
+ * <pre>
+ * // code
+ * </pre>
*/
private int someField;
/**
diff --git a/test/transform/resource/after-delombok/LoggerCommons.java b/test/transform/resource/after-delombok/LoggerCommons.java
index 32ace53a..954e730b 100644
--- a/test/transform/resource/after-delombok/LoggerCommons.java
+++ b/test/transform/resource/after-delombok/LoggerCommons.java
@@ -9,4 +9,4 @@ class LoggerCommonsWithImport {
class LoggerCommonsWithDifferentName {
@java.lang.SuppressWarnings("all")
private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("DifferentName");
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerConfig.java b/test/transform/resource/after-delombok/LoggerConfig.java
index ba955638..d0944126 100644
--- a/test/transform/resource/after-delombok/LoggerConfig.java
+++ b/test/transform/resource/after-delombok/LoggerConfig.java
@@ -1,4 +1,4 @@
class LoggerWithConfig {
@java.lang.SuppressWarnings("all")
private final org.slf4j.Logger myLogger = org.slf4j.LoggerFactory.getLogger(LoggerWithConfig.class);
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerJBossLog.java b/test/transform/resource/after-delombok/LoggerJBossLog.java
new file mode 100644
index 00000000..41c18805
--- /dev/null
+++ b/test/transform/resource/after-delombok/LoggerJBossLog.java
@@ -0,0 +1,19 @@
+class LoggerJBossLog {
+ @java.lang.SuppressWarnings("all")
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLog.class);
+}
+class LoggerJBossLogWithImport {
+ @java.lang.SuppressWarnings("all")
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLogWithImport.class);
+}
+class LoggerJBossLogOuter {
+ static class Inner {
+ @java.lang.SuppressWarnings("all")
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(Inner.class);
+ }
+}
+
+class LoggerJBossLogWithDifferentLoggerName {
+ @java.lang.SuppressWarnings("all")
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger("DifferentLogger");
+}
diff --git a/test/transform/resource/after-delombok/LoggerJul.java b/test/transform/resource/after-delombok/LoggerJul.java
index ad119777..63f96733 100644
--- a/test/transform/resource/after-delombok/LoggerJul.java
+++ b/test/transform/resource/after-delombok/LoggerJul.java
@@ -9,4 +9,4 @@ class LoggerJulWithImport {
class LoggerJulWithDifferentName {
@java.lang.SuppressWarnings("all")
private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger("DifferentName");
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerLog4j.java b/test/transform/resource/after-delombok/LoggerLog4j.java
index 99eac34f..7d9d4409 100644
--- a/test/transform/resource/after-delombok/LoggerLog4j.java
+++ b/test/transform/resource/after-delombok/LoggerLog4j.java
@@ -9,4 +9,4 @@ class LoggerLog4jWithImport {
class LoggerLog4jWithDifferentName {
@java.lang.SuppressWarnings("all")
private static final org.apache.log4j.Logger log = org.apache.log4j.Logger.getLogger("DifferentName");
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerLog4j2.java b/test/transform/resource/after-delombok/LoggerLog4j2.java
index 8473134b..3d8b7b5b 100644
--- a/test/transform/resource/after-delombok/LoggerLog4j2.java
+++ b/test/transform/resource/after-delombok/LoggerLog4j2.java
@@ -9,4 +9,4 @@ class LoggerLog4j2WithImport {
class LoggerLog4j2WithDifferentName {
@java.lang.SuppressWarnings("all")
private static final org.apache.logging.log4j.Logger log = org.apache.logging.log4j.LogManager.getLogger("DifferentName");
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerSlf4j.java b/test/transform/resource/after-delombok/LoggerSlf4j.java
index 3c6e6d2f..68d685f0 100644
--- a/test/transform/resource/after-delombok/LoggerSlf4j.java
+++ b/test/transform/resource/after-delombok/LoggerSlf4j.java
@@ -16,4 +16,4 @@ class LoggerSlf4jOuter {
class LoggerSlf4jWithDifferentLoggerName {
@java.lang.SuppressWarnings("all")
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger("DifferentLogger");
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerSlf4jAlreadyExists.java b/test/transform/resource/after-delombok/LoggerSlf4jAlreadyExists.java
index a7cd9409..2b9e4bcb 100644
--- a/test/transform/resource/after-delombok/LoggerSlf4jAlreadyExists.java
+++ b/test/transform/resource/after-delombok/LoggerSlf4jAlreadyExists.java
@@ -1,3 +1,3 @@
class LoggerSlf4jAlreadyExists {
int log;
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerSlf4jTypes.java b/test/transform/resource/after-delombok/LoggerSlf4jTypes.java
index 5ea59924..6730e805 100644
--- a/test/transform/resource/after-delombok/LoggerSlf4jTypes.java
+++ b/test/transform/resource/after-delombok/LoggerSlf4jTypes.java
@@ -3,7 +3,7 @@ interface LoggerSlf4jTypesInterface {
@interface LoggerSlf4jTypesAnnotation {
}
enum LoggerSlf4jTypesEnum {
-;
+ ;
@java.lang.SuppressWarnings("all")
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LoggerSlf4jTypesEnum.class);
}
@@ -17,4 +17,4 @@ interface LoggerSlf4jTypesInterfaceOuter {
@java.lang.SuppressWarnings("all")
private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(Inner.class);
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/LoggerXSlf4j.java b/test/transform/resource/after-delombok/LoggerXSlf4j.java
index d0654b51..781733cf 100644
--- a/test/transform/resource/after-delombok/LoggerXSlf4j.java
+++ b/test/transform/resource/after-delombok/LoggerXSlf4j.java
@@ -9,4 +9,4 @@ class LoggerXSlf4jWithImport {
class LoggerXSlf4jWithDifferentName {
@java.lang.SuppressWarnings("all")
private static final org.slf4j.ext.XLogger log = org.slf4j.ext.XLoggerFactory.getXLogger("DifferentName");
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/MixGetterVal.java b/test/transform/resource/after-delombok/MixGetterVal.java
index abc60d56..a2b44ea0 100644
--- a/test/transform/resource/after-delombok/MixGetterVal.java
+++ b/test/transform/resource/after-delombok/MixGetterVal.java
@@ -12,4 +12,4 @@ class MixGetterVal {
public int getX() {
return this.x;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/MultiFieldGetter.java b/test/transform/resource/after-delombok/MultiFieldGetter.java
index ed84f4ed..3586a7e6 100644
--- a/test/transform/resource/after-delombok/MultiFieldGetter.java
+++ b/test/transform/resource/after-delombok/MultiFieldGetter.java
@@ -21,4 +21,4 @@ class MultiFieldGetter2 {
int getY() {
return this.y;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/NoArgsConstructorForce.java b/test/transform/resource/after-delombok/NoArgsConstructorForce.java
new file mode 100644
index 00000000..3336ca19
--- /dev/null
+++ b/test/transform/resource/after-delombok/NoArgsConstructorForce.java
@@ -0,0 +1,13 @@
+
+public class NoArgsConstructorForce {
+ private final int[] i;
+ private final Object[] o;
+ private final java.util.List<?>[] fullQualifiedList;
+
+ @java.lang.SuppressWarnings("all")
+ public NoArgsConstructorForce() {
+ this.i = null;
+ this.o = null;
+ this.fullQualifiedList = null;
+ }
+}
diff --git a/test/transform/resource/after-delombok/NonNullOnParameterAbstract.java b/test/transform/resource/after-delombok/NonNullOnParameterAbstract.java
index e0330bd6..62fd878a 100644
--- a/test/transform/resource/after-delombok/NonNullOnParameterAbstract.java
+++ b/test/transform/resource/after-delombok/NonNullOnParameterAbstract.java
@@ -7,4 +7,4 @@ abstract class NonNullOnParameterAbstract {
}
public abstract void test2(@lombok.NonNull String arg);
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/NonNullOnParameterOfDefaultMethod.java b/test/transform/resource/after-delombok/NonNullOnParameterOfDefaultMethod.java
new file mode 100644
index 00000000..e220296f
--- /dev/null
+++ b/test/transform/resource/after-delombok/NonNullOnParameterOfDefaultMethod.java
@@ -0,0 +1,10 @@
+// version 8:
+interface NonNullOnParameterOfDefaultMethod {
+ void test(@lombok.NonNull String arg);
+ default void test2(@lombok.NonNull String arg) {
+ if (arg == null) {
+ throw new java.lang.NullPointerException("arg");
+ }
+ System.out.println(arg);
+ }
+}
diff --git a/test/transform/resource/after-delombok/NonNullPlain.java b/test/transform/resource/after-delombok/NonNullPlain.java
index b7d27ef3..f6b8037e 100644
--- a/test/transform/resource/after-delombok/NonNullPlain.java
+++ b/test/transform/resource/after-delombok/NonNullPlain.java
@@ -10,7 +10,6 @@ class NonNullPlain {
@Retention(RetentionPolicy.CLASS)
public @interface NotNull {
}
- @java.beans.ConstructorProperties({"i", "s"})
@java.lang.SuppressWarnings("all")
public NonNullPlain(@lombok.NonNull final int i, @lombok.NonNull final String s) {
if (s == null) {
diff --git a/test/transform/resource/after-delombok/NonNullWithAlternateException.java b/test/transform/resource/after-delombok/NonNullWithAlternateException.java
index 686a1219..76c6406a 100644
--- a/test/transform/resource/after-delombok/NonNullWithAlternateException.java
+++ b/test/transform/resource/after-delombok/NonNullWithAlternateException.java
@@ -14,4 +14,4 @@ public class NonNullWithAlternateException {
}
this.test = test;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/NonNullWithSneakyThrows.java b/test/transform/resource/after-delombok/NonNullWithSneakyThrows.java
index 91646468..97de0d8a 100644
--- a/test/transform/resource/after-delombok/NonNullWithSneakyThrows.java
+++ b/test/transform/resource/after-delombok/NonNullWithSneakyThrows.java
@@ -9,4 +9,4 @@ class NonNullWithSneakyThrows {
throw lombok.Lombok.sneakyThrow($ex);
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/OnXJava7Style.java b/test/transform/resource/after-delombok/OnXJava7Style.java
new file mode 100644
index 00000000..7ebf65a3
--- /dev/null
+++ b/test/transform/resource/after-delombok/OnXJava7Style.java
@@ -0,0 +1,38 @@
+//version :7
+public class OnXJava7Style {
+ @interface Foo {
+ String value() default "";
+ }
+ @interface Bar {
+ String stuff() default "";
+ }
+ String a;
+ String b;
+ String c;
+ String d;
+ String e;
+ @Foo
+ @java.lang.SuppressWarnings("all")
+ public String getA() {
+ return this.a;
+ }
+ @Foo
+ @java.lang.SuppressWarnings("all")
+ public void setB(final String b) {
+ this.b = b;
+ }
+ @java.lang.SuppressWarnings("all")
+ public void setC(@Foo("a") final String c) {
+ this.c = c;
+ }
+ @java.lang.SuppressWarnings("all")
+ public void setD(@Bar(stuff = "b") final String d) {
+ this.d = d;
+ }
+ @Foo("c")
+ @Bar(stuff = "d")
+ @java.lang.SuppressWarnings("all")
+ public String getE() {
+ return this.e;
+ }
+}
diff --git a/test/transform/resource/after-delombok/OnXJava8Style.java b/test/transform/resource/after-delombok/OnXJava8Style.java
new file mode 100644
index 00000000..d2f76e10
--- /dev/null
+++ b/test/transform/resource/after-delombok/OnXJava8Style.java
@@ -0,0 +1,38 @@
+//version 8:
+public class OnXJava8Style {
+ @interface Foo {
+ String value() default "";
+ }
+ @interface Bar {
+ String stuff() default "";
+ }
+ String a;
+ String b;
+ String c;
+ String d;
+ String e;
+ @Foo
+ @java.lang.SuppressWarnings("all")
+ public String getA() {
+ return this.a;
+ }
+ @Foo
+ @java.lang.SuppressWarnings("all")
+ public void setB(final String b) {
+ this.b = b;
+ }
+ @java.lang.SuppressWarnings("all")
+ public void setC(@Foo("a") final String c) {
+ this.c = c;
+ }
+ @java.lang.SuppressWarnings("all")
+ public void setD(@Bar(stuff = "b") final String d) {
+ this.d = d;
+ }
+ @Foo("c")
+ @Bar(stuff = "d")
+ @java.lang.SuppressWarnings("all")
+ public String getE() {
+ return this.e;
+ }
+}
diff --git a/test/transform/resource/after-delombok/SetterAccessLevel.java b/test/transform/resource/after-delombok/SetterAccessLevel.java
index 45df2b35..51a58e8e 100644
--- a/test/transform/resource/after-delombok/SetterAccessLevel.java
+++ b/test/transform/resource/after-delombok/SetterAccessLevel.java
@@ -25,4 +25,4 @@ class SetterAccessLevel {
public void setValue(final boolean value) {
this.value = value;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SetterAlreadyExists.java b/test/transform/resource/after-delombok/SetterAlreadyExists.java
index 5bfc1f83..a62f20da 100644
--- a/test/transform/resource/after-delombok/SetterAlreadyExists.java
+++ b/test/transform/resource/after-delombok/SetterAlreadyExists.java
@@ -50,4 +50,4 @@ class Setter9 {
boolean isFoo;
void setFoo(boolean foo) {
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SetterDeprecated.java b/test/transform/resource/after-delombok/SetterDeprecated.java
index 72a609ad..cc52413b 100644
--- a/test/transform/resource/after-delombok/SetterDeprecated.java
+++ b/test/transform/resource/after-delombok/SetterDeprecated.java
@@ -18,4 +18,4 @@ class SetterDeprecated {
public void setJavadoc(final int javadoc) {
this.javadoc = javadoc;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SetterOnClass.java b/test/transform/resource/after-delombok/SetterOnClass.java
index 7077c492..f2347bcb 100644
--- a/test/transform/resource/after-delombok/SetterOnClass.java
+++ b/test/transform/resource/after-delombok/SetterOnClass.java
@@ -58,4 +58,4 @@ class SetterOnClass6 {
}
this.nonNull = nonNull;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SetterPlain.java b/test/transform/resource/after-delombok/SetterPlain.java
index 39aa7b61..0ec9ca1b 100644
--- a/test/transform/resource/after-delombok/SetterPlain.java
+++ b/test/transform/resource/after-delombok/SetterPlain.java
@@ -9,4 +9,4 @@ class SetterPlain {
public void setFoo(final int foo) {
this.foo = foo;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SetterWithDollar.java b/test/transform/resource/after-delombok/SetterWithDollar.java
index 974efdcd..8d116e99 100644
--- a/test/transform/resource/after-delombok/SetterWithDollar.java
+++ b/test/transform/resource/after-delombok/SetterWithDollar.java
@@ -2,6 +2,8 @@ class SetterWithDollar1 {
int $i;
@java.lang.SuppressWarnings("all")
+
+
public void set$i(final int $i) {
this.$i = $i;
}
@@ -11,6 +13,8 @@ class SetterWithDollar2 {
int i;
@java.lang.SuppressWarnings("all")
+
+
public void set$i(final int $i) {
this.$i = $i;
}
@@ -18,4 +22,4 @@ class SetterWithDollar2 {
public void setI(final int i) {
this.i = i;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SneakyThrowsMultiple.java b/test/transform/resource/after-delombok/SneakyThrowsMultiple.java
index 42b275c6..5faca0a1 100644
--- a/test/transform/resource/after-delombok/SneakyThrowsMultiple.java
+++ b/test/transform/resource/after-delombok/SneakyThrowsMultiple.java
@@ -42,4 +42,4 @@ class SneakyThrowsMultiple {
throw lombok.Lombok.sneakyThrow($ex);
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SneakyThrowsPlain.java b/test/transform/resource/after-delombok/SneakyThrowsPlain.java
index f712ab55..86f7790c 100644
--- a/test/transform/resource/after-delombok/SneakyThrowsPlain.java
+++ b/test/transform/resource/after-delombok/SneakyThrowsPlain.java
@@ -28,4 +28,4 @@ class SneakyThrowsPlain {
throw lombok.Lombok.sneakyThrow($ex);
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SneakyThrowsSingle.java b/test/transform/resource/after-delombok/SneakyThrowsSingle.java
index 8901f827..24b4566a 100644
--- a/test/transform/resource/after-delombok/SneakyThrowsSingle.java
+++ b/test/transform/resource/after-delombok/SneakyThrowsSingle.java
@@ -23,4 +23,4 @@ class SneakyThrowsSingle {
throw lombok.Lombok.sneakyThrow($ex);
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SynchronizedName.java b/test/transform/resource/after-delombok/SynchronizedName.java
index ab3c0431..91fd7ea7 100644
--- a/test/transform/resource/after-delombok/SynchronizedName.java
+++ b/test/transform/resource/after-delombok/SynchronizedName.java
@@ -17,4 +17,4 @@ class SynchronizedName {
System.out.println("five");
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SynchronizedNameNoSuchField.java b/test/transform/resource/after-delombok/SynchronizedNameNoSuchField.java
index d252985f..73ce25ec 100644
--- a/test/transform/resource/after-delombok/SynchronizedNameNoSuchField.java
+++ b/test/transform/resource/after-delombok/SynchronizedNameNoSuchField.java
@@ -4,4 +4,4 @@ class SynchronizedNameNoSuchField {
void test2() {
System.out.println("two");
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SynchronizedNameStaticToInstanceRef.java b/test/transform/resource/after-delombok/SynchronizedNameStaticToInstanceRef.java
index 8441570b..effa036f 100644
--- a/test/transform/resource/after-delombok/SynchronizedNameStaticToInstanceRef.java
+++ b/test/transform/resource/after-delombok/SynchronizedNameStaticToInstanceRef.java
@@ -6,4 +6,4 @@ class SynchronizedNameStaticToInstanceRef {
System.out.println("three");
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/SynchronizedPlain.java b/test/transform/resource/after-delombok/SynchronizedPlain.java
index 1a065085..f178aa4e 100644
--- a/test/transform/resource/after-delombok/SynchronizedPlain.java
+++ b/test/transform/resource/after-delombok/SynchronizedPlain.java
@@ -25,4 +25,4 @@ class SynchronizedPlain2 {
System.out.println("four");
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ToStringConfiguration.java b/test/transform/resource/after-delombok/ToStringConfiguration.java
index 035ecdb2..6fa9111e 100644
--- a/test/transform/resource/after-delombok/ToStringConfiguration.java
+++ b/test/transform/resource/after-delombok/ToStringConfiguration.java
@@ -29,4 +29,4 @@ class ToStringConfiguration3 {
public int getX() {
return this.x;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ToStringInner.java b/test/transform/resource/after-delombok/ToStringInner.java
index 7b1d5e21..fe77fcfd 100644
--- a/test/transform/resource/after-delombok/ToStringInner.java
+++ b/test/transform/resource/after-delombok/ToStringInner.java
@@ -33,4 +33,4 @@ class ToStringOuter {
public java.lang.String toString() {
return "ToStringOuter(x=" + this.x + ", name=" + this.name + ")";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ToStringPlain.java b/test/transform/resource/after-delombok/ToStringPlain.java
index e6f3db7a..af9daf4f 100644
--- a/test/transform/resource/after-delombok/ToStringPlain.java
+++ b/test/transform/resource/after-delombok/ToStringPlain.java
@@ -15,4 +15,4 @@ class ToString2 {
public java.lang.String toString() {
return "ToString2(x=" + this.x + ", name=" + this.name + ")";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/Tolerate.java b/test/transform/resource/after-delombok/Tolerate.java
index fbb42f1b..c3e3d7fd 100644
--- a/test/transform/resource/after-delombok/Tolerate.java
+++ b/test/transform/resource/after-delombok/Tolerate.java
@@ -10,11 +10,15 @@ class Tolerate {
}
@java.lang.SuppressWarnings("all")
+
+
public void setPattern(final Pattern pattern) {
this.pattern = pattern;
}
@java.lang.SuppressWarnings("all")
+
+
public Pattern getPattern() {
return this.pattern;
}
@@ -32,16 +36,19 @@ class Tolerate2 {
}
@java.lang.SuppressWarnings("all")
+
+
public Pattern getPattern() {
return this.pattern;
}
@java.lang.SuppressWarnings("all")
+
+
public Tolerate2 withPattern(final Pattern pattern) {
return this.pattern == pattern ? this : new Tolerate2(pattern);
}
- @java.beans.ConstructorProperties({"pattern"})
@java.lang.SuppressWarnings("all")
public Tolerate2(final Pattern pattern) {
this.pattern = pattern;
diff --git a/test/transform/resource/after-delombok/UtilityClass.java b/test/transform/resource/after-delombok/UtilityClass.java
new file mode 100644
index 00000000..8d3f4c08
--- /dev/null
+++ b/test/transform/resource/after-delombok/UtilityClass.java
@@ -0,0 +1,43 @@
+final class UtilityClass {
+ private static long someField = System.currentTimeMillis();
+ static void someMethod() {
+ System.out.println();
+ }
+ protected static class InnerClass {
+ private String innerInnerMember;
+ }
+ @java.lang.SuppressWarnings("all")
+ private UtilityClass() {
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+}
+class UtilityInner {
+ static class InnerInner {
+ static final class InnerInnerInner {
+ static int member;
+ @java.lang.SuppressWarnings("all")
+ private InnerInnerInner() {
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+ }
+ }
+ enum UtilityInsideEnum {
+ FOO, BAR;
+ static final class InsideEnum {
+ static int member;
+ @java.lang.SuppressWarnings("all")
+ private InsideEnum() {
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+ }
+ }
+ interface UtilityInsideInterface {
+ final class InsideInterface {
+ static int member;
+ @java.lang.SuppressWarnings("all")
+ private InsideInterface() {
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/UtilityClassErrors.java b/test/transform/resource/after-delombok/UtilityClassErrors.java
new file mode 100644
index 00000000..5181b750
--- /dev/null
+++ b/test/transform/resource/after-delombok/UtilityClassErrors.java
@@ -0,0 +1,19 @@
+final class UtilityClassErrors1 {
+ private static String someField;
+ protected UtilityClassErrors1() {
+ }
+ static void method() {
+ class MethodLocalClass {
+ }
+ }
+}
+enum UtilityClassErrors2 {
+ ;
+}
+class UtilityClassErrors3 {
+ class NonStaticInner {
+ class ThisShouldFail {
+ private String member;
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java
new file mode 100644
index 00000000..07093e5a
--- /dev/null
+++ b/test/transform/resource/after-delombok/ValAnonymousSubclassWithGenerics.java
@@ -0,0 +1,18 @@
+import java.util.*;
+public class ValAnonymousSubclassWithGenerics {
+ Object object = new Object() {
+ void foo() {
+ final int j = 1;
+ }
+ };
+ void bar() {
+ final int k = super.hashCode();
+ int x = k;
+ }
+ java.util.List<String> names = new java.util.ArrayList<String>() {
+ public String get(int i) {
+ final java.lang.String result = super.get(i);
+ return result;
+ }
+ };
+}
diff --git a/test/transform/resource/after-delombok/ValComplex.java b/test/transform/resource/after-delombok/ValComplex.java
index 0df87fac..e0dfe1b7 100644
--- a/test/transform/resource/after-delombok/ValComplex.java
+++ b/test/transform/resource/after-delombok/ValComplex.java
@@ -17,4 +17,4 @@ public class ValComplex {
}
final java.lang.String shouldBeString = field; //Unshadowing
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValDefault.java b/test/transform/resource/after-delombok/ValDefault.java
index 8c85311b..74376dbb 100644
--- a/test/transform/resource/after-delombok/ValDefault.java
+++ b/test/transform/resource/after-delombok/ValDefault.java
@@ -5,4 +5,4 @@ interface ValDefault {
final int x = 1;
final int size = size();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValErrors.java b/test/transform/resource/after-delombok/ValErrors.java
index 770a7e95..f8365c2d 100644
--- a/test/transform/resource/after-delombok/ValErrors.java
+++ b/test/transform/resource/after-delombok/ValErrors.java
@@ -5,4 +5,4 @@ public class ValErrors {
public void arrayInitializer() {
val e = {"foo", "bar"};
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValFinal.java b/test/transform/resource/after-delombok/ValFinal.java
new file mode 100644
index 00000000..6be08565
--- /dev/null
+++ b/test/transform/resource/after-delombok/ValFinal.java
@@ -0,0 +1,5 @@
+public class ValFinal {
+ public void test() {
+ final int x = 10;
+ }
+}
diff --git a/test/transform/resource/after-delombok/ValInBasicFor.java b/test/transform/resource/after-delombok/ValInBasicFor.java
index e21450e1..a3746b23 100644
--- a/test/transform/resource/after-delombok/ValInBasicFor.java
+++ b/test/transform/resource/after-delombok/ValInBasicFor.java
@@ -6,4 +6,4 @@ public class ValInBasicFor {
System.out.println("");
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValInFor.java b/test/transform/resource/after-delombok/ValInFor.java
index de75803b..5cb15e1a 100644
--- a/test/transform/resource/after-delombok/ValInFor.java
+++ b/test/transform/resource/after-delombok/ValInFor.java
@@ -6,4 +6,4 @@ public class ValInFor {
final java.lang.String shouldBeString2 = shouldBeString;
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValInLambda.java b/test/transform/resource/after-delombok/ValInLambda.java
new file mode 100644
index 00000000..7ce1e1b4
--- /dev/null
+++ b/test/transform/resource/after-delombok/ValInLambda.java
@@ -0,0 +1,18 @@
+// version 8:
+class ValInLambda {
+ Runnable foo = (Runnable) () -> {
+ final int i = 1;
+ };
+
+ public void easyLambda() {
+ Runnable foo = (Runnable) () -> {
+ final int i = 1;
+ };
+ }
+
+ public void easyIntersectionLambda() {
+ Runnable foo = (Runnable) () -> {
+ final int i = 1;
+ };
+ }
+}
diff --git a/test/transform/resource/after-delombok/ValInMultiDeclaration.java b/test/transform/resource/after-delombok/ValInMultiDeclaration.java
index 32f689c7..d1074174 100644
--- a/test/transform/resource/after-delombok/ValInMultiDeclaration.java
+++ b/test/transform/resource/after-delombok/ValInMultiDeclaration.java
@@ -3,4 +3,4 @@ public class ValInMultiDeclaration {
final int x = 10;
final java.lang.String y = "";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValLambda.java b/test/transform/resource/after-delombok/ValLambda.java
index 0b13b5a1..9214b490 100644
--- a/test/transform/resource/after-delombok/ValLambda.java
+++ b/test/transform/resource/after-delombok/ValLambda.java
@@ -1,21 +1,21 @@
// version 8:
class ValLambda {
public void easyLambda() {
- final java.lang.Runnable foo = (Runnable)() -> {
+ final java.lang.Runnable foo = (Runnable) () -> {
};
}
public void easyIntersectionLambda() {
- final java.lang.Object foo = (Runnable & java.io.Serializable)() -> {
+ final java.lang.Object foo = (Runnable & java.io.Serializable) () -> {
};
- final java.lang.Object bar = (java.io.Serializable & Runnable)() -> {
+ final java.lang.Object bar = (java.io.Serializable & Runnable) () -> {
};
}
public void easyLubLambda() {
- final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable)() -> {
- } : (Runnable)System.out::println;
+ final java.lang.Runnable foo = (System.currentTimeMillis() > 0) ? (Runnable) () -> {
+ } : (Runnable) System.out::println;
}
// public void castLubLambda() {
-// Runnable foo = (Runnable)((System.currentTimeMillis() > 0) ? ()-> {} : System.out::println);
-// lombok.val foo = (Runnable)((System.currentTimeMillis() > 0) ? ()-> {} : System.out::println);
+// Runnable foo = (Runnable) ((System.currentTimeMillis() > 0) ? () -> {} : System.out::println);
+// lombok.val foo = (Runnable) ((System.currentTimeMillis() > 0) ? () -> {} : System.out::println);
// }
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValLessSimple.java b/test/transform/resource/after-delombok/ValLessSimple.java
index d06c66ec..5edd5056 100644
--- a/test/transform/resource/after-delombok/ValLessSimple.java
+++ b/test/transform/resource/after-delombok/ValLessSimple.java
@@ -30,4 +30,4 @@ public class ValLessSimple {
}
}
private String field = "field";
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValLub.java b/test/transform/resource/after-delombok/ValLub.java
index d7e8f944..e0847cec 100644
--- a/test/transform/resource/after-delombok/ValLub.java
+++ b/test/transform/resource/after-delombok/ValLub.java
@@ -15,4 +15,4 @@ class ValLub {
thisShouldBeCollection.add("");
String foo = thisShouldBeCollection.iterator().next();
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValNullInit.java b/test/transform/resource/after-delombok/ValNullInit.java
new file mode 100644
index 00000000..91818083
--- /dev/null
+++ b/test/transform/resource/after-delombok/ValNullInit.java
@@ -0,0 +1,5 @@
+class ValNullInit {
+ void method() {
+ final java.lang.Object x = null;
+ }
+}
diff --git a/test/transform/resource/after-delombok/ValRawType.java b/test/transform/resource/after-delombok/ValRawType.java
index dc297046..2e638f98 100644
--- a/test/transform/resource/after-delombok/ValRawType.java
+++ b/test/transform/resource/after-delombok/ValRawType.java
@@ -5,7 +5,7 @@ public class ValRawType {
public void test() {
Element propElement = new Element();
for (final java.lang.Object attribute : propElement.attributes()) {
- final ValRawType.Attribute attr = (Attribute)attribute;
+ final ValRawType.Attribute attr = (Attribute) attribute;
}
}
@@ -17,4 +17,4 @@ public class ValRawType {
static class Attribute {
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValWeirdTypes.java b/test/transform/resource/after-delombok/ValWeirdTypes.java
index 2c2905ed..cd6ba538 100644
--- a/test/transform/resource/after-delombok/ValWeirdTypes.java
+++ b/test/transform/resource/after-delombok/ValWeirdTypes.java
@@ -18,7 +18,7 @@ public class ValWeirdTypes<Z> {
final long y = 5 + 3L;
}
public void testAnonymousInnerClass() {
- final java.lang.Runnable y = new Runnable(){
+ final java.lang.Runnable y = new Runnable() {
public void run() {
}
};
@@ -48,10 +48,10 @@ public class ValWeirdTypes<Z> {
final java.lang.Object nully = null;
}
public void testArrays() {
- final int[] intArray = new int[]{1, 2, 3};
- final java.lang.Object[][] multiDimArray = new Object[][]{{}};
+ final int[] intArray = new int[] {1, 2, 3};
+ final java.lang.Object[][] multiDimArray = new Object[][] {{}};
final int[] copy = intArray;
final java.lang.Object[] single = multiDimArray[0];
final int singleInt = copy[0];
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValWithLabel.java b/test/transform/resource/after-delombok/ValWithLabel.java
index 4d8eabf2..2d046e93 100644
--- a/test/transform/resource/after-delombok/ValWithLabel.java
+++ b/test/transform/resource/after-delombok/ValWithLabel.java
@@ -7,4 +7,4 @@ public class ValWithLabel {
}
}
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/ValWithLocalClasses.java b/test/transform/resource/after-delombok/ValWithLocalClasses.java
new file mode 100644
index 00000000..6487eb82
--- /dev/null
+++ b/test/transform/resource/after-delombok/ValWithLocalClasses.java
@@ -0,0 +1,11 @@
+class ValWithLocalClasses1 {
+ {
+ final ValWithLocalClasses2 f2 = new ValWithLocalClasses2() {
+ };
+ }
+}
+class ValWithLocalClasses2 {
+ {
+ final int f3 = 0;
+ }
+}
diff --git a/test/transform/resource/after-delombok/ValueCallSuper.java b/test/transform/resource/after-delombok/ValueCallSuper.java
new file mode 100644
index 00000000..63a536cd
--- /dev/null
+++ b/test/transform/resource/after-delombok/ValueCallSuper.java
@@ -0,0 +1,32 @@
+class ValueParent {
+}
+final class ValueCallSuper extends ValueParent {
+ @java.lang.SuppressWarnings("all")
+ public ValueCallSuper() {
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public boolean equals(final java.lang.Object o) {
+ if (o == this) return true;
+ if (!(o instanceof ValueCallSuper)) return false;
+ final ValueCallSuper other = (ValueCallSuper) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
+ if (!super.equals(o)) return false;
+ return true;
+ }
+ @java.lang.SuppressWarnings("all")
+ protected boolean canEqual(final java.lang.Object other) {
+ return other instanceof ValueCallSuper;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public int hashCode() {
+ int result = super.hashCode();
+ return result;
+ }
+ @java.lang.Override
+ @java.lang.SuppressWarnings("all")
+ public java.lang.String toString() {
+ return "ValueCallSuper()";
+ }
+}
diff --git a/test/transform/resource/after-delombok/ValueExperimental.java b/test/transform/resource/after-delombok/ValueExperimental.java
deleted file mode 100644
index 77a48ec9..00000000
--- a/test/transform/resource/after-delombok/ValueExperimental.java
+++ /dev/null
@@ -1,46 +0,0 @@
-final class ValueExperimental1 {
- @java.lang.SuppressWarnings("all")
- public ValueExperimental1() {
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public boolean equals(final java.lang.Object o) {
- if (o == this) return true;
- if (!(o instanceof ValueExperimental1)) return false;
- return true;
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public int hashCode() {
- int result = 1;
- return result;
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public java.lang.String toString() {
- return "ValueExperimental1()";
- }
-}
-final class ValueExperimental2 {
- @java.lang.SuppressWarnings("all")
- public ValueExperimental2() {
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public boolean equals(final java.lang.Object o) {
- if (o == this) return true;
- if (!(o instanceof ValueExperimental2)) return false;
- return true;
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public int hashCode() {
- int result = 1;
- return result;
- }
- @java.lang.Override
- @java.lang.SuppressWarnings("all")
- public java.lang.String toString() {
- return "ValueExperimental2()";
- }
-} \ No newline at end of file
diff --git a/test/transform/resource/after-delombok/ValuePlain.java b/test/transform/resource/after-delombok/ValuePlain.java
index 64e5b9b9..cf2c1142 100644
--- a/test/transform/resource/after-delombok/ValuePlain.java
+++ b/test/transform/resource/after-delombok/ValuePlain.java
@@ -1,7 +1,6 @@
final class Value1 {
private final int x;
private final String name;
- @java.beans.ConstructorProperties({"x", "name"})
@java.lang.SuppressWarnings("all")
public Value1(final int x, final String name) {
this.x = x;
@@ -20,7 +19,7 @@ final class Value1 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Value1)) return false;
- final Value1 other = (Value1)o;
+ final Value1 other = (Value1) o;
if (this.getX() != other.getX()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
@@ -34,7 +33,7 @@ final class Value1 {
int result = 1;
result = result * PRIME + this.getX();
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -46,7 +45,6 @@ final class Value1 {
class Value2 {
public final int x;
private final String name;
- @java.beans.ConstructorProperties({"x", "name"})
@java.lang.SuppressWarnings("all")
public Value2(final int x, final String name) {
this.x = x;
@@ -65,8 +63,8 @@ class Value2 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Value2)) return false;
- final Value2 other = (Value2)o;
- if (!other.canEqual((java.lang.Object)this)) return false;
+ final Value2 other = (Value2) o;
+ if (!other.canEqual((java.lang.Object) this)) return false;
if (this.getX() != other.getX()) return false;
final java.lang.Object this$name = this.getName();
final java.lang.Object other$name = other.getName();
@@ -84,7 +82,7 @@ class Value2 {
int result = 1;
result = result * PRIME + this.getX();
final java.lang.Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
return result;
}
@java.lang.Override
@@ -96,7 +94,6 @@ class Value2 {
final class Value3 {
private int x;
private final int y;
- @java.beans.ConstructorProperties({"x", "y"})
@java.lang.SuppressWarnings("all")
public Value3(final int x, final int y) {
this.x = x;
@@ -115,7 +112,7 @@ final class Value3 {
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
if (!(o instanceof Value3)) return false;
- final Value3 other = (Value3)o;
+ final Value3 other = (Value3) o;
if (this.getX() != other.getX()) return false;
if (this.getY() != other.getY()) return false;
return true;
diff --git a/test/transform/resource/after-delombok/ValueExperimentalStarImport.java b/test/transform/resource/after-delombok/ValueStaticField.java
index 6911f260..2b489a1a 100644
--- a/test/transform/resource/after-delombok/ValueExperimentalStarImport.java
+++ b/test/transform/resource/after-delombok/ValueStaticField.java
@@ -1,14 +1,14 @@
-import lombok.experimental.*;
-final class ValueExperimentalStarImport {
+final class ValueStaticField {
+ static int x;
+ static String PASSWORD = "Ken sent me";
@java.lang.SuppressWarnings("all")
- public ValueExperimentalStarImport() {
-
+ public ValueStaticField() {
}
@java.lang.Override
@java.lang.SuppressWarnings("all")
public boolean equals(final java.lang.Object o) {
if (o == this) return true;
- if (!(o instanceof ValueExperimentalStarImport)) return false;
+ if (!(o instanceof ValueStaticField)) return false;
return true;
}
@java.lang.Override
@@ -20,6 +20,6 @@ final class ValueExperimentalStarImport {
@java.lang.Override
@java.lang.SuppressWarnings("all")
public java.lang.String toString() {
- return "ValueExperimentalStarImport()";
+ return "ValueStaticField()";
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/VarComplex.java b/test/transform/resource/after-delombok/VarComplex.java
new file mode 100644
index 00000000..b08ad115
--- /dev/null
+++ b/test/transform/resource/after-delombok/VarComplex.java
@@ -0,0 +1,20 @@
+public class VarComplex {
+ private String field = "";
+ private static final int CONSTANT = 20;
+ public void testComplex() {
+ char[] shouldBeCharArray = field.toCharArray();
+ int shouldBeInt = CONSTANT;
+ java.lang.Object lock = new Object();
+ synchronized (lock) {
+ int field = 20; //Shadowing
+ int inner = 10;
+ switch (field) {
+ case 5:
+ char[] shouldBeCharArray2 = shouldBeCharArray;
+ int innerInner = inner;
+
+ }
+ }
+ java.lang.String shouldBeString = field; //Unshadowing
+ }
+}
diff --git a/test/transform/resource/after-delombok/VarInFor.java b/test/transform/resource/after-delombok/VarInFor.java
new file mode 100644
index 00000000..f2e95b09
--- /dev/null
+++ b/test/transform/resource/after-delombok/VarInFor.java
@@ -0,0 +1,9 @@
+public class VarInFor {
+ public void enhancedFor() {
+ int[] list = new int[] {1, 2};
+ for (int shouldBeInt : list) {
+ System.out.println(shouldBeInt);
+ int shouldBeInt2 = shouldBeInt;
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/VarInForOld.java b/test/transform/resource/after-delombok/VarInForOld.java
new file mode 100644
index 00000000..ddb370ef
--- /dev/null
+++ b/test/transform/resource/after-delombok/VarInForOld.java
@@ -0,0 +1,7 @@
+public class VarInForOld {
+ public void oldFor() {
+ for (int i = 0; i < 100; ++i) {
+ System.out.println(i);
+ }
+ }
+}
diff --git a/test/transform/resource/after-delombok/VarModifier.java b/test/transform/resource/after-delombok/VarModifier.java
new file mode 100644
index 00000000..ba4d9362
--- /dev/null
+++ b/test/transform/resource/after-delombok/VarModifier.java
@@ -0,0 +1,7 @@
+public class VarModifier {
+ private String field = "";
+ public void testComplex() {
+ final char[] shouldBeFinalCharArray = field.toCharArray();
+ char[] shouldBeCharArray = field.toCharArray();
+ }
+}
diff --git a/test/transform/resource/after-delombok/VarNullInit.java b/test/transform/resource/after-delombok/VarNullInit.java
new file mode 100644
index 00000000..ed5f8e8d
--- /dev/null
+++ b/test/transform/resource/after-delombok/VarNullInit.java
@@ -0,0 +1,6 @@
+
+public class VarNullInit {
+ void method() {
+ java.lang.Object x = null;
+ }
+}
diff --git a/test/transform/resource/after-delombok/VarWarning.java b/test/transform/resource/after-delombok/VarWarning.java
new file mode 100644
index 00000000..a333c87c
--- /dev/null
+++ b/test/transform/resource/after-delombok/VarWarning.java
@@ -0,0 +1,6 @@
+public class VarWarning {
+ public void isOkay() {
+ java.lang.String x = "Warning";
+ x.toLowerCase();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-delombok/WithInnerAnnotation.java b/test/transform/resource/after-delombok/WithInnerAnnotation.java
index a8decfeb..1e88b226 100644
--- a/test/transform/resource/after-delombok/WithInnerAnnotation.java
+++ b/test/transform/resource/after-delombok/WithInnerAnnotation.java
@@ -2,4 +2,4 @@ class WithInnerAnnotation {
@interface Inner {
int bar() default 42;
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/WitherAccessLevel.java b/test/transform/resource/after-delombok/WitherAccessLevel.java
index 963f6972..c687d645 100644
--- a/test/transform/resource/after-delombok/WitherAccessLevel.java
+++ b/test/transform/resource/after-delombok/WitherAccessLevel.java
@@ -27,4 +27,4 @@ class WitherAccessLevel {
public WitherAccessLevel withValue(final boolean value) {
return this.value == value ? this : new WitherAccessLevel(this.isNone, this.isPrivate, this.isPackage, this.isProtected, this.isPublic, value);
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/WitherAlreadyExists.java b/test/transform/resource/after-delombok/WitherAlreadyExists.java
index be41f6bc..d609bc7b 100644
--- a/test/transform/resource/after-delombok/WitherAlreadyExists.java
+++ b/test/transform/resource/after-delombok/WitherAlreadyExists.java
@@ -68,4 +68,4 @@ class Wither9 {
}
Wither9(boolean foo) {
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/WitherAndAllArgsConstructor.java b/test/transform/resource/after-delombok/WitherAndAllArgsConstructor.java
index 7607dce4..ff4fe3e2 100644
--- a/test/transform/resource/after-delombok/WitherAndAllArgsConstructor.java
+++ b/test/transform/resource/after-delombok/WitherAndAllArgsConstructor.java
@@ -4,7 +4,6 @@ class WitherAndAllArgsConstructor<T, J extends T, L extends java.lang.Number> {
final int x = 10;
int y = 20;
final int z;
- @java.beans.ConstructorProperties({"test", "test2", "y", "z"})
@java.lang.SuppressWarnings("all")
public WitherAndAllArgsConstructor(final J test, final java.util.List<L> test2, final int y, final int z) {
this.test = test;
@@ -20,4 +19,4 @@ class WitherAndAllArgsConstructor<T, J extends T, L extends java.lang.Number> {
public WitherAndAllArgsConstructor<T, J, L> withTest2(final java.util.List<L> test2) {
return this.test2 == test2 ? this : new WitherAndAllArgsConstructor<T, J, L>(this.test, test2, this.y, this.z);
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/WitherDeprecated.java b/test/transform/resource/after-delombok/WitherDeprecated.java
index 29192012..b342a861 100644
--- a/test/transform/resource/after-delombok/WitherDeprecated.java
+++ b/test/transform/resource/after-delombok/WitherDeprecated.java
@@ -20,4 +20,4 @@ class WitherDeprecated {
public WitherDeprecated withJavadoc(final int javadoc) {
return this.javadoc == javadoc ? this : new WitherDeprecated(this.annotation, javadoc);
}
-} \ No newline at end of file
+}
diff --git a/test/transform/resource/after-delombok/WitherWithAbstract.java b/test/transform/resource/after-delombok/WitherWithAbstract.java
new file mode 100644
index 00000000..f9178e99
--- /dev/null
+++ b/test/transform/resource/after-delombok/WitherWithAbstract.java
@@ -0,0 +1,5 @@
+abstract class WitherWithAbstract {
+ String foo;
+ @java.lang.SuppressWarnings("all")
+ public abstract WitherWithAbstract withFoo(final String foo);
+}
diff --git a/test/transform/resource/after-ecj/Accessors.java b/test/transform/resource/after-ecj/Accessors.java
index 6b8976d0..8ac92e6e 100644
--- a/test/transform/resource/after-ecj/Accessors.java
+++ b/test/transform/resource/after-ecj/Accessors.java
@@ -77,7 +77,7 @@ class AccessorsChain {
return true;
if ((! (o instanceof AccessorsPrefix3)))
return false;
- final @java.lang.SuppressWarnings("all") AccessorsPrefix3 other = (AccessorsPrefix3) o;
+ final AccessorsPrefix3 other = (AccessorsPrefix3) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
final java.lang.Object this$fName = this.getName();
@@ -93,7 +93,7 @@ class AccessorsChain {
final int PRIME = 59;
int result = 1;
final java.lang.Object $fName = this.getName();
- result = ((result * PRIME) + (($fName == null) ? 0 : $fName.hashCode()));
+ result = ((result * PRIME) + (($fName == null) ? 43 : $fName.hashCode()));
return result;
}
}
diff --git a/test/transform/resource/after-ecj/BuilderChainAndFluent.java b/test/transform/resource/after-ecj/BuilderChainAndFluent.java
deleted file mode 100644
index 6a307105..00000000
--- a/test/transform/resource/after-ecj/BuilderChainAndFluent.java
+++ /dev/null
@@ -1,25 +0,0 @@
-@lombok.experimental.Builder(fluent = false,chain = false) class BuilderChainAndFluent {
- public static @java.lang.SuppressWarnings("all") class BuilderChainAndFluentBuilder {
- private int yes;
- @java.lang.SuppressWarnings("all") BuilderChainAndFluentBuilder() {
- super();
- }
- public @java.lang.SuppressWarnings("all") void setYes(final int yes) {
- this.yes = yes;
- }
- public @java.lang.SuppressWarnings("all") BuilderChainAndFluent build() {
- return new BuilderChainAndFluent(yes);
- }
- public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return (("BuilderChainAndFluent.BuilderChainAndFluentBuilder(yes=" + this.yes) + ")");
- }
- }
- private final int yes;
- @java.lang.SuppressWarnings("all") BuilderChainAndFluent(final int yes) {
- super();
- this.yes = yes;
- }
- public static @java.lang.SuppressWarnings("all") BuilderChainAndFluentBuilder builder() {
- return new BuilderChainAndFluentBuilder();
- }
-}
diff --git a/test/transform/resource/after-ecj/BuilderComplex.java b/test/transform/resource/after-ecj/BuilderComplex.java
index 19aeb043..93d70fe9 100644
--- a/test/transform/resource/after-ecj/BuilderComplex.java
+++ b/test/transform/resource/after-ecj/BuilderComplex.java
@@ -1,11 +1,11 @@
import java.util.List;
-import lombok.experimental.Builder;
+import lombok.Builder;
class BuilderComplex {
public static @java.lang.SuppressWarnings("all") class VoidBuilder<T extends Number> {
- private T number;
- private int arg2;
- private String arg3;
- private BuilderComplex selfRef;
+ private @java.lang.SuppressWarnings("all") T number;
+ private @java.lang.SuppressWarnings("all") int arg2;
+ private @java.lang.SuppressWarnings("all") String arg3;
+ private @java.lang.SuppressWarnings("all") BuilderComplex selfRef;
@java.lang.SuppressWarnings("all") VoidBuilder() {
super();
}
diff --git a/test/transform/resource/after-ecj/BuilderDefaults.java b/test/transform/resource/after-ecj/BuilderDefaults.java
new file mode 100644
index 00000000..1a0f1168
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderDefaults.java
@@ -0,0 +1,90 @@
+import lombok.Builder;
+import lombok.Value;
+public final @Value @Builder class BuilderDefaults {
+ public static @java.lang.SuppressWarnings("all") class BuilderDefaultsBuilder {
+ private @java.lang.SuppressWarnings("all") int x;
+ private @java.lang.SuppressWarnings("all") boolean x$set;
+ private @java.lang.SuppressWarnings("all") String name;
+ private @java.lang.SuppressWarnings("all") long z;
+ private @java.lang.SuppressWarnings("all") boolean z$set;
+ @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder x(final int x) {
+ this.x = x;
+ x$set = true;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder name(final String name) {
+ this.name = name;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder z(final long z) {
+ this.z = z;
+ z$set = true;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaults build() {
+ return new BuilderDefaults((x$set ? x : BuilderDefaults.$default$x()), name, (z$set ? z : BuilderDefaults.$default$z()));
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderDefaults.BuilderDefaultsBuilder(x=" + this.x) + ", name=") + this.name) + ", z=") + this.z) + ")");
+ }
+ }
+ private final @Builder.Default int x;
+ private final String name;
+ private final @Builder.Default long z;
+ private static @java.lang.SuppressWarnings("all") int $default$x() {
+ return 10;
+ }
+ private static @java.lang.SuppressWarnings("all") long $default$z() {
+ return System.currentTimeMillis();
+ }
+ @java.lang.SuppressWarnings("all") BuilderDefaults(final int x, final String name, final long z) {
+ super();
+ this.x = x;
+ this.name = name;
+ this.z = z;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderDefaultsBuilder builder() {
+ return new BuilderDefaultsBuilder();
+ }
+ public @java.lang.SuppressWarnings("all") int getX() {
+ return this.x;
+ }
+ public @java.lang.SuppressWarnings("all") String getName() {
+ return this.name;
+ }
+ public @java.lang.SuppressWarnings("all") long getZ() {
+ return this.z;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof BuilderDefaults)))
+ return false;
+ final BuilderDefaults other = (BuilderDefaults) o;
+ if ((this.getX() != other.getX()))
+ return false;
+ final java.lang.Object this$name = this.getName();
+ final java.lang.Object other$name = other.getName();
+ if (((this$name == null) ? (other$name != null) : (! this$name.equals(other$name))))
+ return false;
+ if ((this.getZ() != other.getZ()))
+ return false;
+ return true;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.getX());
+ final java.lang.Object $name = this.getName();
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
+ final long $z = this.getZ();
+ result = ((result * PRIME) + (int) ($z ^ ($z >>> 32)));
+ return result;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderDefaults(x=" + this.getX()) + ", name=") + this.getName()) + ", z=") + this.getZ()) + ")");
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java b/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java
new file mode 100644
index 00000000..a8f81afa
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderDefaultsGenerics.java
@@ -0,0 +1,57 @@
+import lombok.Builder;
+import java.util.*;
+public @Builder class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> {
+ public static @java.lang.SuppressWarnings("all") class BuilderDefaultsGenericsBuilder<N extends Number, T, R extends List<T>> {
+ private @java.lang.SuppressWarnings("all") java.util.concurrent.Callable<N> callable;
+ private @java.lang.SuppressWarnings("all") boolean callable$set;
+ private @java.lang.SuppressWarnings("all") T tee;
+ private @java.lang.SuppressWarnings("all") boolean tee$set;
+ private @java.lang.SuppressWarnings("all") R arrr;
+ private @java.lang.SuppressWarnings("all") boolean arrr$set;
+ @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> callable(final java.util.concurrent.Callable<N> callable) {
+ this.callable = callable;
+ callable$set = true;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> tee(final T tee) {
+ this.tee = tee;
+ tee$set = true;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsGenericsBuilder<N, T, R> arrr(final R arrr) {
+ this.arrr = arrr;
+ arrr$set = true;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsGenerics<N, T, R> build() {
+ return new BuilderDefaultsGenerics<N, T, R>((callable$set ? callable : BuilderDefaultsGenerics.<N, T, R>$default$callable()), (tee$set ? tee : BuilderDefaultsGenerics.<N, T, R>$default$tee()), (arrr$set ? arrr : BuilderDefaultsGenerics.<N, T, R>$default$arrr()));
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderDefaultsGenerics.BuilderDefaultsGenericsBuilder(callable=" + this.callable) + ", tee=") + this.tee) + ", arrr=") + this.arrr) + ")");
+ }
+ }
+ private @Builder.Default java.util.concurrent.Callable<N> callable;
+ private @Builder.Default T tee;
+ private @Builder.Default R arrr;
+ private static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>java.util.concurrent.Callable<N> $default$callable() {
+ return null;
+ }
+ private static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>T $default$tee() {
+ return null;
+ }
+ private static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>R $default$arrr() {
+ return null;
+ }
+ @java.lang.SuppressWarnings("all") BuilderDefaultsGenerics(final java.util.concurrent.Callable<N> callable, final T tee, final R arrr) {
+ super();
+ this.callable = callable;
+ this.tee = tee;
+ this.arrr = arrr;
+ }
+ public static @java.lang.SuppressWarnings("all") <N extends Number, T, R extends List<T>>BuilderDefaultsGenericsBuilder<N, T, R> builder() {
+ return new BuilderDefaultsGenericsBuilder<N, T, R>();
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderDefaultsWarnings.java b/test/transform/resource/after-ecj/BuilderDefaultsWarnings.java
new file mode 100644
index 00000000..236632d0
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderDefaultsWarnings.java
@@ -0,0 +1,87 @@
+import lombok.Builder;
+import lombok.Singular;
+public @Builder class BuilderDefaultsWarnings {
+ public static @java.lang.SuppressWarnings("all") class BuilderDefaultsWarningsBuilder {
+ private @java.lang.SuppressWarnings("all") long x;
+ private @java.lang.SuppressWarnings("all") int z;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> items;
+ @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder x(final long x) {
+ this.x = x;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder z(final int z) {
+ this.z = z;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder item(String item) {
+ if ((this.items == null))
+ this.items = new java.util.ArrayList<String>();
+ this.items.add(item);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder items(java.util.Collection<? extends String> items) {
+ if ((this.items == null))
+ this.items = new java.util.ArrayList<String>();
+ this.items.addAll(items);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder clearItems() {
+ if ((this.items != null))
+ this.items.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderDefaultsWarnings build() {
+ java.util.List<String> items;
+ switch (((this.items == null) ? 0 : this.items.size())) {
+ case 0 :
+ items = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ items = java.util.Collections.singletonList(this.items.get(0));
+ break;
+ default :
+ items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.items));
+ }
+ return new BuilderDefaultsWarnings(x, z, items);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderDefaultsWarnings.BuilderDefaultsWarningsBuilder(x=" + this.x) + ", z=") + this.z) + ", items=") + this.items) + ")");
+ }
+ }
+ long x = System.currentTimeMillis();
+ final int y = 5;
+ @Builder.Default int z;
+ @Builder.Default @Singular java.util.List<String> items;
+ @java.lang.SuppressWarnings("all") BuilderDefaultsWarnings(final long x, final int z, final java.util.List<String> items) {
+ super();
+ this.x = x;
+ this.z = z;
+ this.items = items;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderDefaultsWarningsBuilder builder() {
+ return new BuilderDefaultsWarningsBuilder();
+ }
+}
+class NoBuilderButHasDefaults {
+ public static @java.lang.SuppressWarnings("all") class NoBuilderButHasDefaultsBuilder {
+ @java.lang.SuppressWarnings("all") NoBuilderButHasDefaultsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") NoBuilderButHasDefaults build() {
+ return new NoBuilderButHasDefaults();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return "NoBuilderButHasDefaults.NoBuilderButHasDefaultsBuilder()";
+ }
+ }
+ private final @Builder.Default long z = 5;
+ public @Builder NoBuilderButHasDefaults() {
+ super();
+ }
+ public static @java.lang.SuppressWarnings("all") NoBuilderButHasDefaultsBuilder builder() {
+ return new NoBuilderButHasDefaultsBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderGenericMethod.java b/test/transform/resource/after-ecj/BuilderGenericMethod.java
new file mode 100644
index 00000000..1b770654
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderGenericMethod.java
@@ -0,0 +1,35 @@
+import java.util.List;
+import lombok.Builder;
+import java.util.*;
+class BuilderGenericMethod<T> {
+ public @java.lang.SuppressWarnings("all") class MapBuilder<N extends Number> {
+ private @java.lang.SuppressWarnings("all") int a;
+ private @java.lang.SuppressWarnings("all") long b;
+ @java.lang.SuppressWarnings("all") MapBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") MapBuilder<N> a(final int a) {
+ this.a = a;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") MapBuilder<N> b(final long b) {
+ this.b = b;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") Map<N, T> build() {
+ return BuilderGenericMethod.this.<N>foo(a, b);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((("BuilderGenericMethod.MapBuilder(a=" + this.a) + ", b=") + this.b) + ")");
+ }
+ }
+ BuilderGenericMethod() {
+ super();
+ }
+ public @Builder <N extends Number>Map<N, T> foo(int a, long b) {
+ return null;
+ }
+ public @java.lang.SuppressWarnings("all") <N extends Number>MapBuilder<N> builder() {
+ return new MapBuilder<N>();
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderInstanceMethod.java b/test/transform/resource/after-ecj/BuilderInstanceMethod.java
new file mode 100644
index 00000000..5f57aef7
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderInstanceMethod.java
@@ -0,0 +1,43 @@
+import java.util.List;
+class BuilderInstanceMethod<T> {
+ public @java.lang.SuppressWarnings("all") class StringBuilder {
+ private @java.lang.SuppressWarnings("all") int show;
+ private @java.lang.SuppressWarnings("all") int yes;
+ private @java.lang.SuppressWarnings("all") List<T> also;
+ private @java.lang.SuppressWarnings("all") int $andMe;
+ @java.lang.SuppressWarnings("all") StringBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") StringBuilder show(final int show) {
+ this.show = show;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") StringBuilder yes(final int yes) {
+ this.yes = yes;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") StringBuilder also(final List<T> also) {
+ this.also = also;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") StringBuilder $andMe(final int $andMe) {
+ this.$andMe = $andMe;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") String build() {
+ return BuilderInstanceMethod.this.create(show, yes, also, $andMe);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((("BuilderInstanceMethod.StringBuilder(show=" + this.show) + ", yes=") + this.yes) + ", also=") + this.also) + ", $andMe=") + this.$andMe) + ")");
+ }
+ }
+ BuilderInstanceMethod() {
+ super();
+ }
+ public @lombok.Builder String create(int show, final int yes, List<T> also, int $andMe) {
+ return (((("" + show) + yes) + also) + $andMe);
+ }
+ public @java.lang.SuppressWarnings("all") StringBuilder builder() {
+ return new StringBuilder();
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderSimple.java b/test/transform/resource/after-ecj/BuilderSimple.java
index 85db360d..bc0ff186 100644
--- a/test/transform/resource/after-ecj/BuilderSimple.java
+++ b/test/transform/resource/after-ecj/BuilderSimple.java
@@ -1,8 +1,8 @@
import java.util.List;
-@lombok.experimental.Builder class BuilderSimple<T> {
+@lombok.Builder class BuilderSimple<T> {
public static @java.lang.SuppressWarnings("all") class BuilderSimpleBuilder<T> {
- private int yes;
- private List<T> also;
+ private @java.lang.SuppressWarnings("all") int yes;
+ private @java.lang.SuppressWarnings("all") List<T> also;
@java.lang.SuppressWarnings("all") BuilderSimpleBuilder() {
super();
}
diff --git a/test/transform/resource/after-ecj/BuilderSingularGuavaListsSets.java b/test/transform/resource/after-ecj/BuilderSingularGuavaListsSets.java
new file mode 100644
index 00000000..12c2b293
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularGuavaListsSets.java
@@ -0,0 +1,125 @@
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableTable;
+import lombok.Singular;
+@lombok.Builder class BuilderSingularGuavaListsSets<T> {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularGuavaListsSetsBuilder<T> {
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder<T> cards;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder<Number> frogs;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableSet.Builder<java.lang.Object> rawSet;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableSortedSet.Builder<String> passes;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableTable.Builder<Number, Number, String> users;
+ @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> card(T card) {
+ if ((this.cards == null))
+ this.cards = com.google.common.collect.ImmutableList.builder();
+ this.cards.add(card);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> cards(java.lang.Iterable<? extends T> cards) {
+ if ((this.cards == null))
+ this.cards = com.google.common.collect.ImmutableList.builder();
+ this.cards.addAll(cards);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> clearCards() {
+ this.cards = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> frog(Number frog) {
+ if ((this.frogs == null))
+ this.frogs = com.google.common.collect.ImmutableList.builder();
+ this.frogs.add(frog);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> frogs(java.lang.Iterable<? extends Number> frogs) {
+ if ((this.frogs == null))
+ this.frogs = com.google.common.collect.ImmutableList.builder();
+ this.frogs.addAll(frogs);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> clearFrogs() {
+ this.frogs = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> rawSet(java.lang.Object rawSet) {
+ if ((this.rawSet == null))
+ this.rawSet = com.google.common.collect.ImmutableSet.builder();
+ this.rawSet.add(rawSet);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> rawSet(java.lang.Iterable<?> rawSet) {
+ if ((this.rawSet == null))
+ this.rawSet = com.google.common.collect.ImmutableSet.builder();
+ this.rawSet.addAll(rawSet);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> clearRawSet() {
+ this.rawSet = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> pass(String pass) {
+ if ((this.passes == null))
+ this.passes = com.google.common.collect.ImmutableSortedSet.naturalOrder();
+ this.passes.add(pass);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> passes(java.lang.Iterable<? extends String> passes) {
+ if ((this.passes == null))
+ this.passes = com.google.common.collect.ImmutableSortedSet.naturalOrder();
+ this.passes.addAll(passes);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> clearPasses() {
+ this.passes = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> user(Number rowKey, Number columnKey, String value) {
+ if ((this.users == null))
+ this.users = com.google.common.collect.ImmutableTable.builder();
+ this.users.put(rowKey, columnKey, value);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> users(com.google.common.collect.Table<? extends Number, ? extends Number, ? extends String> users) {
+ if ((this.users == null))
+ this.users = com.google.common.collect.ImmutableTable.builder();
+ this.users.putAll(users);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSetsBuilder<T> clearUsers() {
+ this.users = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSets<T> build() {
+ com.google.common.collect.ImmutableList<T> cards = ((this.cards == null) ? com.google.common.collect.ImmutableList.<T>of() : this.cards.build());
+ com.google.common.collect.ImmutableCollection<Number> frogs = ((this.frogs == null) ? com.google.common.collect.ImmutableList.<Number>of() : this.frogs.build());
+ com.google.common.collect.ImmutableSet<java.lang.Object> rawSet = ((this.rawSet == null) ? com.google.common.collect.ImmutableSet.<java.lang.Object>of() : this.rawSet.build());
+ com.google.common.collect.ImmutableSortedSet<String> passes = ((this.passes == null) ? com.google.common.collect.ImmutableSortedSet.<String>of() : this.passes.build());
+ com.google.common.collect.ImmutableTable<Number, Number, String> users = ((this.users == null) ? com.google.common.collect.ImmutableTable.<Number, Number, String>of() : this.users.build());
+ return new BuilderSingularGuavaListsSets<T>(cards, frogs, rawSet, passes, users);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((((("BuilderSingularGuavaListsSets.BuilderSingularGuavaListsSetsBuilder(cards=" + this.cards) + ", frogs=") + this.frogs) + ", rawSet=") + this.rawSet) + ", passes=") + this.passes) + ", users=") + this.users) + ")");
+ }
+ }
+ private @Singular ImmutableList<T> cards;
+ private @Singular ImmutableCollection<? extends Number> frogs;
+ private @SuppressWarnings("all") @Singular("rawSet") ImmutableSet rawSet;
+ private @Singular ImmutableSortedSet<String> passes;
+ private @Singular ImmutableTable<? extends Number, ? extends Number, String> users;
+ @java.lang.SuppressWarnings("all") BuilderSingularGuavaListsSets(final ImmutableList<T> cards, final ImmutableCollection<? extends Number> frogs, final ImmutableSet rawSet, final ImmutableSortedSet<String> passes, final ImmutableTable<? extends Number, ? extends Number, String> users) {
+ super();
+ this.cards = cards;
+ this.frogs = frogs;
+ this.rawSet = rawSet;
+ this.passes = passes;
+ this.users = users;
+ }
+ public static @java.lang.SuppressWarnings("all") <T>BuilderSingularGuavaListsSetsBuilder<T> builder() {
+ return new BuilderSingularGuavaListsSetsBuilder<T>();
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderSingularGuavaMaps.java b/test/transform/resource/after-ecj/BuilderSingularGuavaMaps.java
new file mode 100644
index 00000000..44533ac1
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularGuavaMaps.java
@@ -0,0 +1,83 @@
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableSortedMap;
+import lombok.Singular;
+@lombok.Builder class BuilderSingularGuavaMaps<K, V> {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularGuavaMapsBuilder<K, V> {
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableMap.Builder<K, V> battleaxes;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableSortedMap.Builder<Integer, V> vertices;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableBiMap.Builder<java.lang.Object, java.lang.Object> rawMap;
+ @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> battleaxe(K key, V value) {
+ if ((this.battleaxes == null))
+ this.battleaxes = com.google.common.collect.ImmutableMap.builder();
+ this.battleaxes.put(key, value);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> battleaxes(java.util.Map<? extends K, ? extends V> battleaxes) {
+ if ((this.battleaxes == null))
+ this.battleaxes = com.google.common.collect.ImmutableMap.builder();
+ this.battleaxes.putAll(battleaxes);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> clearBattleaxes() {
+ this.battleaxes = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> vertex(Integer key, V value) {
+ if ((this.vertices == null))
+ this.vertices = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.vertices.put(key, value);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> vertices(java.util.Map<? extends Integer, ? extends V> vertices) {
+ if ((this.vertices == null))
+ this.vertices = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.vertices.putAll(vertices);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> clearVertices() {
+ this.vertices = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> rawMap(java.lang.Object key, java.lang.Object value) {
+ if ((this.rawMap == null))
+ this.rawMap = com.google.common.collect.ImmutableBiMap.builder();
+ this.rawMap.put(key, value);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> rawMap(java.util.Map<?, ?> rawMap) {
+ if ((this.rawMap == null))
+ this.rawMap = com.google.common.collect.ImmutableBiMap.builder();
+ this.rawMap.putAll(rawMap);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMapsBuilder<K, V> clearRawMap() {
+ this.rawMap = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularGuavaMaps<K, V> build() {
+ com.google.common.collect.ImmutableMap<K, V> battleaxes = ((this.battleaxes == null) ? com.google.common.collect.ImmutableMap.<K, V>of() : this.battleaxes.build());
+ com.google.common.collect.ImmutableSortedMap<Integer, V> vertices = ((this.vertices == null) ? com.google.common.collect.ImmutableSortedMap.<Integer, V>of() : this.vertices.build());
+ com.google.common.collect.ImmutableBiMap<java.lang.Object, java.lang.Object> rawMap = ((this.rawMap == null) ? com.google.common.collect.ImmutableBiMap.<java.lang.Object, java.lang.Object>of() : this.rawMap.build());
+ return new BuilderSingularGuavaMaps<K, V>(battleaxes, vertices, rawMap);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderSingularGuavaMaps.BuilderSingularGuavaMapsBuilder(battleaxes=" + this.battleaxes) + ", vertices=") + this.vertices) + ", rawMap=") + this.rawMap) + ")");
+ }
+ }
+ private @Singular ImmutableMap<K, V> battleaxes;
+ private @Singular ImmutableSortedMap<Integer, ? extends V> vertices;
+ private @SuppressWarnings("all") @Singular("rawMap") ImmutableBiMap rawMap;
+ @java.lang.SuppressWarnings("all") BuilderSingularGuavaMaps(final ImmutableMap<K, V> battleaxes, final ImmutableSortedMap<Integer, ? extends V> vertices, final ImmutableBiMap rawMap) {
+ super();
+ this.battleaxes = battleaxes;
+ this.vertices = vertices;
+ this.rawMap = rawMap;
+ }
+ public static @java.lang.SuppressWarnings("all") <K, V>BuilderSingularGuavaMapsBuilder<K, V> builder() {
+ return new BuilderSingularGuavaMapsBuilder<K, V>();
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderSingularLists.java b/test/transform/resource/after-ecj/BuilderSingularLists.java
new file mode 100644
index 00000000..3e093e1a
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularLists.java
@@ -0,0 +1,116 @@
+import java.util.List;
+import java.util.Collection;
+
+import lombok.Singular;
+@lombok.Builder class BuilderSingularLists<T> {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularListsBuilder<T> {
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<T> children;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<Number> scarves;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<java.lang.Object> rawList;
+ @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> child(T child) {
+ if ((this.children == null))
+ this.children = new java.util.ArrayList<T>();
+ this.children.add(child);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> children(java.util.Collection<? extends T> children) {
+ if ((this.children == null))
+ this.children = new java.util.ArrayList<T>();
+ this.children.addAll(children);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> clearChildren() {
+ if ((this.children != null))
+ this.children.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> scarf(Number scarf) {
+ if ((this.scarves == null))
+ this.scarves = new java.util.ArrayList<Number>();
+ this.scarves.add(scarf);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> scarves(java.util.Collection<? extends Number> scarves) {
+ if ((this.scarves == null))
+ this.scarves = new java.util.ArrayList<Number>();
+ this.scarves.addAll(scarves);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> clearScarves() {
+ if ((this.scarves != null))
+ this.scarves.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> rawList(java.lang.Object rawList) {
+ if ((this.rawList == null))
+ this.rawList = new java.util.ArrayList<java.lang.Object>();
+ this.rawList.add(rawList);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> rawList(java.util.Collection<?> rawList) {
+ if ((this.rawList == null))
+ this.rawList = new java.util.ArrayList<java.lang.Object>();
+ this.rawList.addAll(rawList);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularListsBuilder<T> clearRawList() {
+ if ((this.rawList != null))
+ this.rawList.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularLists<T> build() {
+ java.util.List<T> children;
+ switch (((this.children == null) ? 0 : this.children.size())) {
+ case 0 :
+ children = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ children = java.util.Collections.singletonList(this.children.get(0));
+ break;
+ default :
+ children = java.util.Collections.unmodifiableList(new java.util.ArrayList<T>(this.children));
+ }
+ java.util.Collection<Number> scarves;
+ switch (((this.scarves == null) ? 0 : this.scarves.size())) {
+ case 0 :
+ scarves = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ scarves = java.util.Collections.singletonList(this.scarves.get(0));
+ break;
+ default :
+ scarves = java.util.Collections.unmodifiableList(new java.util.ArrayList<Number>(this.scarves));
+ }
+ java.util.List<java.lang.Object> rawList;
+ switch (((this.rawList == null) ? 0 : this.rawList.size())) {
+ case 0 :
+ rawList = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ rawList = java.util.Collections.singletonList(this.rawList.get(0));
+ break;
+ default :
+ rawList = java.util.Collections.unmodifiableList(new java.util.ArrayList<java.lang.Object>(this.rawList));
+ }
+ return new BuilderSingularLists<T>(children, scarves, rawList);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderSingularLists.BuilderSingularListsBuilder(children=" + this.children) + ", scarves=") + this.scarves) + ", rawList=") + this.rawList) + ")");
+ }
+ }
+ private @Singular List<T> children;
+ private @Singular Collection<? extends Number> scarves;
+ private @SuppressWarnings("all") @Singular("rawList") List rawList;
+ @java.lang.SuppressWarnings("all") BuilderSingularLists(final List<T> children, final Collection<? extends Number> scarves, final List rawList) {
+ super();
+ this.children = children;
+ this.scarves = scarves;
+ this.rawList = rawList;
+ }
+ public static @java.lang.SuppressWarnings("all") <T>BuilderSingularListsBuilder<T> builder() {
+ return new BuilderSingularListsBuilder<T>();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderSingularMaps.java b/test/transform/resource/after-ecj/BuilderSingularMaps.java
new file mode 100644
index 00000000..efcf5ef5
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularMaps.java
@@ -0,0 +1,209 @@
+import java.util.Map;
+import java.util.SortedMap;
+import lombok.Singular;
+@lombok.Builder class BuilderSingularMaps<K, V> {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularMapsBuilder<K, V> {
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<K> women$key;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<V> women$value;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<K> men$key;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<Number> men$value;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<java.lang.Object> rawMap$key;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<java.lang.Object> rawMap$value;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> stringMap$key;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<V> stringMap$value;
+ @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> woman(K womanKey, V womanValue) {
+ if ((this.women$key == null))
+ {
+ this.women$key = new java.util.ArrayList<K>();
+ this.women$value = new java.util.ArrayList<V>();
+ }
+ this.women$key.add(womanKey);
+ this.women$value.add(womanValue);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> women(java.util.Map<? extends K, ? extends V> women) {
+ if ((this.women$key == null))
+ {
+ this.women$key = new java.util.ArrayList<K>();
+ this.women$value = new java.util.ArrayList<V>();
+ }
+ for (java.util.Map.Entry<? extends K, ? extends V> $lombokEntry : women.entrySet())
+ {
+ this.women$key.add($lombokEntry.getKey());
+ this.women$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> clearWomen() {
+ if ((this.women$key != null))
+ {
+ this.women$key.clear();
+ this.women$value.clear();
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> man(K manKey, Number manValue) {
+ if ((this.men$key == null))
+ {
+ this.men$key = new java.util.ArrayList<K>();
+ this.men$value = new java.util.ArrayList<Number>();
+ }
+ this.men$key.add(manKey);
+ this.men$value.add(manValue);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> men(java.util.Map<? extends K, ? extends Number> men) {
+ if ((this.men$key == null))
+ {
+ this.men$key = new java.util.ArrayList<K>();
+ this.men$value = new java.util.ArrayList<Number>();
+ }
+ for (java.util.Map.Entry<? extends K, ? extends Number> $lombokEntry : men.entrySet())
+ {
+ this.men$key.add($lombokEntry.getKey());
+ this.men$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> clearMen() {
+ if ((this.men$key != null))
+ {
+ this.men$key.clear();
+ this.men$value.clear();
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> rawMap(java.lang.Object rawMapKey, java.lang.Object rawMapValue) {
+ if ((this.rawMap$key == null))
+ {
+ this.rawMap$key = new java.util.ArrayList<java.lang.Object>();
+ this.rawMap$value = new java.util.ArrayList<java.lang.Object>();
+ }
+ this.rawMap$key.add(rawMapKey);
+ this.rawMap$value.add(rawMapValue);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> rawMap(java.util.Map<?, ?> rawMap) {
+ if ((this.rawMap$key == null))
+ {
+ this.rawMap$key = new java.util.ArrayList<java.lang.Object>();
+ this.rawMap$value = new java.util.ArrayList<java.lang.Object>();
+ }
+ for (java.util.Map.Entry<?, ?> $lombokEntry : rawMap.entrySet())
+ {
+ this.rawMap$key.add($lombokEntry.getKey());
+ this.rawMap$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> clearRawMap() {
+ if ((this.rawMap$key != null))
+ {
+ this.rawMap$key.clear();
+ this.rawMap$value.clear();
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> stringMap(String stringMapKey, V stringMapValue) {
+ if ((this.stringMap$key == null))
+ {
+ this.stringMap$key = new java.util.ArrayList<String>();
+ this.stringMap$value = new java.util.ArrayList<V>();
+ }
+ this.stringMap$key.add(stringMapKey);
+ this.stringMap$value.add(stringMapValue);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> stringMap(java.util.Map<? extends String, ? extends V> stringMap) {
+ if ((this.stringMap$key == null))
+ {
+ this.stringMap$key = new java.util.ArrayList<String>();
+ this.stringMap$value = new java.util.ArrayList<V>();
+ }
+ for (java.util.Map.Entry<? extends String, ? extends V> $lombokEntry : stringMap.entrySet())
+ {
+ this.stringMap$key.add($lombokEntry.getKey());
+ this.stringMap$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMapsBuilder<K, V> clearStringMap() {
+ if ((this.stringMap$key != null))
+ {
+ this.stringMap$key.clear();
+ this.stringMap$value.clear();
+ }
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularMaps<K, V> build() {
+ java.util.Map<K, V> women;
+ switch (((this.women$key == null) ? 0 : this.women$key.size())) {
+ case 0 :
+ women = java.util.Collections.emptyMap();
+ break;
+ case 1 :
+ women = java.util.Collections.singletonMap(this.women$key.get(0), this.women$value.get(0));
+ break;
+ default :
+ women = new java.util.LinkedHashMap<K, V>(((this.women$key.size() < 0x40000000) ? ((1 + this.women$key.size()) + ((this.women$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ for (int $i = 0;; ($i < this.women$key.size()); $i ++)
+ women.put(this.women$key.get($i), this.women$value.get($i));
+ women = java.util.Collections.unmodifiableMap(women);
+ }
+ java.util.SortedMap<K, Number> men = new java.util.TreeMap<K, Number>();
+ if ((this.men$key != null))
+ for (int $i = 0;; ($i < ((this.men$key == null) ? 0 : this.men$key.size())); $i ++)
+ men.put(this.men$key.get($i), this.men$value.get($i));
+ men = java.util.Collections.unmodifiableSortedMap(men);
+ java.util.Map<java.lang.Object, java.lang.Object> rawMap;
+ switch (((this.rawMap$key == null) ? 0 : this.rawMap$key.size())) {
+ case 0 :
+ rawMap = java.util.Collections.emptyMap();
+ break;
+ case 1 :
+ rawMap = java.util.Collections.singletonMap(this.rawMap$key.get(0), this.rawMap$value.get(0));
+ break;
+ default :
+ rawMap = new java.util.LinkedHashMap<java.lang.Object, java.lang.Object>(((this.rawMap$key.size() < 0x40000000) ? ((1 + this.rawMap$key.size()) + ((this.rawMap$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ for (int $i = 0;; ($i < this.rawMap$key.size()); $i ++)
+ rawMap.put(this.rawMap$key.get($i), this.rawMap$value.get($i));
+ rawMap = java.util.Collections.unmodifiableMap(rawMap);
+ }
+ java.util.Map<String, V> stringMap;
+ switch (((this.stringMap$key == null) ? 0 : this.stringMap$key.size())) {
+ case 0 :
+ stringMap = java.util.Collections.emptyMap();
+ break;
+ case 1 :
+ stringMap = java.util.Collections.singletonMap(this.stringMap$key.get(0), this.stringMap$value.get(0));
+ break;
+ default :
+ stringMap = new java.util.LinkedHashMap<String, V>(((this.stringMap$key.size() < 0x40000000) ? ((1 + this.stringMap$key.size()) + ((this.stringMap$key.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ for (int $i = 0;; ($i < this.stringMap$key.size()); $i ++)
+ stringMap.put(this.stringMap$key.get($i), this.stringMap$value.get($i));
+ stringMap = java.util.Collections.unmodifiableMap(stringMap);
+ }
+ return new BuilderSingularMaps<K, V>(women, men, rawMap, stringMap);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((((((((((("BuilderSingularMaps.BuilderSingularMapsBuilder(women$key=" + this.women$key) + ", women$value=") + this.women$value) + ", men$key=") + this.men$key) + ", men$value=") + this.men$value) + ", rawMap$key=") + this.rawMap$key) + ", rawMap$value=") + this.rawMap$value) + ", stringMap$key=") + this.stringMap$key) + ", stringMap$value=") + this.stringMap$value) + ")");
+ }
+ }
+ private @Singular Map<K, V> women;
+ private @Singular SortedMap<K, ? extends Number> men;
+ private @SuppressWarnings("all") @Singular("rawMap") Map rawMap;
+ private @Singular("stringMap") Map<String, V> stringMap;
+ @java.lang.SuppressWarnings("all") BuilderSingularMaps(final Map<K, V> women, final SortedMap<K, ? extends Number> men, final Map rawMap, final Map<String, V> stringMap) {
+ super();
+ this.women = women;
+ this.men = men;
+ this.rawMap = rawMap;
+ this.stringMap = stringMap;
+ }
+ public static @java.lang.SuppressWarnings("all") <K, V>BuilderSingularMapsBuilder<K, V> builder() {
+ return new BuilderSingularMapsBuilder<K, V>();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderSingularNoAuto.java b/test/transform/resource/after-ecj/BuilderSingularNoAuto.java
new file mode 100644
index 00000000..fa38efc3
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularNoAuto.java
@@ -0,0 +1,114 @@
+import java.util.List;
+import lombok.Singular;
+@lombok.Builder class BuilderSingularNoAuto {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularNoAutoBuilder {
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> things;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> widgets;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> items;
+ @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder things(String things) {
+ if ((this.things == null))
+ this.things = new java.util.ArrayList<String>();
+ this.things.add(things);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder things(java.util.Collection<? extends String> things) {
+ if ((this.things == null))
+ this.things = new java.util.ArrayList<String>();
+ this.things.addAll(things);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder clearThings() {
+ if ((this.things != null))
+ this.things.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder widget(String widget) {
+ if ((this.widgets == null))
+ this.widgets = new java.util.ArrayList<String>();
+ this.widgets.add(widget);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder widgets(java.util.Collection<? extends String> widgets) {
+ if ((this.widgets == null))
+ this.widgets = new java.util.ArrayList<String>();
+ this.widgets.addAll(widgets);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder clearWidgets() {
+ if ((this.widgets != null))
+ this.widgets.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder items(String items) {
+ if ((this.items == null))
+ this.items = new java.util.ArrayList<String>();
+ this.items.add(items);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder items(java.util.Collection<? extends String> items) {
+ if ((this.items == null))
+ this.items = new java.util.ArrayList<String>();
+ this.items.addAll(items);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder clearItems() {
+ if ((this.items != null))
+ this.items.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularNoAuto build() {
+ java.util.List<String> things;
+ switch (((this.things == null) ? 0 : this.things.size())) {
+ case 0 :
+ things = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ things = java.util.Collections.singletonList(this.things.get(0));
+ break;
+ default :
+ things = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.things));
+ }
+ java.util.List<String> widgets;
+ switch (((this.widgets == null) ? 0 : this.widgets.size())) {
+ case 0 :
+ widgets = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ widgets = java.util.Collections.singletonList(this.widgets.get(0));
+ break;
+ default :
+ widgets = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.widgets));
+ }
+ java.util.List<String> items;
+ switch (((this.items == null) ? 0 : this.items.size())) {
+ case 0 :
+ items = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ items = java.util.Collections.singletonList(this.items.get(0));
+ break;
+ default :
+ items = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.items));
+ }
+ return new BuilderSingularNoAuto(things, widgets, items);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderSingularNoAuto.BuilderSingularNoAutoBuilder(things=" + this.things) + ", widgets=") + this.widgets) + ", items=") + this.items) + ")");
+ }
+ }
+ private @Singular List<String> things;
+ private @Singular("widget") List<String> widgets;
+ private @Singular List<String> items;
+ @java.lang.SuppressWarnings("all") BuilderSingularNoAuto(final List<String> things, final List<String> widgets, final List<String> items) {
+ super();
+ this.things = things;
+ this.widgets = widgets;
+ this.items = items;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderSingularNoAutoBuilder builder() {
+ return new BuilderSingularNoAutoBuilder();
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderSingularRedirectToGuava.java b/test/transform/resource/after-ecj/BuilderSingularRedirectToGuava.java
new file mode 100644
index 00000000..4823e46e
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularRedirectToGuava.java
@@ -0,0 +1,83 @@
+import java.util.Set;
+import java.util.NavigableMap;
+import java.util.Collection;
+import lombok.Singular;
+@lombok.Builder class BuilderSingularRedirectToGuava {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularRedirectToGuavaBuilder {
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableSet.Builder<String> dangerMice;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableSortedMap.Builder<Integer, Number> things;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder<Class<?>> doohickeys;
+ @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder dangerMouse(String dangerMouse) {
+ if ((this.dangerMice == null))
+ this.dangerMice = com.google.common.collect.ImmutableSet.builder();
+ this.dangerMice.add(dangerMouse);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder dangerMice(java.lang.Iterable<? extends String> dangerMice) {
+ if ((this.dangerMice == null))
+ this.dangerMice = com.google.common.collect.ImmutableSet.builder();
+ this.dangerMice.addAll(dangerMice);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder clearDangerMice() {
+ this.dangerMice = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder thing(Integer key, Number value) {
+ if ((this.things == null))
+ this.things = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.things.put(key, value);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder things(java.util.Map<? extends Integer, ? extends Number> things) {
+ if ((this.things == null))
+ this.things = com.google.common.collect.ImmutableSortedMap.naturalOrder();
+ this.things.putAll(things);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder clearThings() {
+ this.things = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder doohickey(Class<?> doohickey) {
+ if ((this.doohickeys == null))
+ this.doohickeys = com.google.common.collect.ImmutableList.builder();
+ this.doohickeys.add(doohickey);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder doohickeys(java.lang.Iterable<? extends Class<?>> doohickeys) {
+ if ((this.doohickeys == null))
+ this.doohickeys = com.google.common.collect.ImmutableList.builder();
+ this.doohickeys.addAll(doohickeys);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder clearDoohickeys() {
+ this.doohickeys = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuava build() {
+ java.util.Set<String> dangerMice = ((this.dangerMice == null) ? com.google.common.collect.ImmutableSet.<String>of() : this.dangerMice.build());
+ java.util.NavigableMap<Integer, Number> things = ((this.things == null) ? com.google.common.collect.ImmutableSortedMap.<Integer, Number>of() : this.things.build());
+ java.util.Collection<Class<?>> doohickeys = ((this.doohickeys == null) ? com.google.common.collect.ImmutableList.<Class<?>>of() : this.doohickeys.build());
+ return new BuilderSingularRedirectToGuava(dangerMice, things, doohickeys);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((("BuilderSingularRedirectToGuava.BuilderSingularRedirectToGuavaBuilder(dangerMice=" + this.dangerMice) + ", things=") + this.things) + ", doohickeys=") + this.doohickeys) + ")");
+ }
+ }
+ private @Singular Set<String> dangerMice;
+ private @Singular NavigableMap<Integer, Number> things;
+ private @Singular Collection<Class<?>> doohickeys;
+ @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuava(final Set<String> dangerMice, final NavigableMap<Integer, Number> things, final Collection<Class<?>> doohickeys) {
+ super();
+ this.dangerMice = dangerMice;
+ this.things = things;
+ this.doohickeys = doohickeys;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderSingularRedirectToGuavaBuilder builder() {
+ return new BuilderSingularRedirectToGuavaBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderSingularSets.java b/test/transform/resource/after-ecj/BuilderSingularSets.java
new file mode 100644
index 00000000..bf403831
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularSets.java
@@ -0,0 +1,145 @@
+import java.util.Set;
+import java.util.SortedSet;
+import lombok.Singular;
+@lombok.Builder class BuilderSingularSets<T> {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularSetsBuilder<T> {
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<T> dangerMice;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<Number> octopodes;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<java.lang.Object> rawSet;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> stringSet;
+ @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> dangerMouse(T dangerMouse) {
+ if ((this.dangerMice == null))
+ this.dangerMice = new java.util.ArrayList<T>();
+ this.dangerMice.add(dangerMouse);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> dangerMice(java.util.Collection<? extends T> dangerMice) {
+ if ((this.dangerMice == null))
+ this.dangerMice = new java.util.ArrayList<T>();
+ this.dangerMice.addAll(dangerMice);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> clearDangerMice() {
+ if ((this.dangerMice != null))
+ this.dangerMice.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> octopus(Number octopus) {
+ if ((this.octopodes == null))
+ this.octopodes = new java.util.ArrayList<Number>();
+ this.octopodes.add(octopus);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> octopodes(java.util.Collection<? extends Number> octopodes) {
+ if ((this.octopodes == null))
+ this.octopodes = new java.util.ArrayList<Number>();
+ this.octopodes.addAll(octopodes);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> clearOctopodes() {
+ if ((this.octopodes != null))
+ this.octopodes.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> rawSet(java.lang.Object rawSet) {
+ if ((this.rawSet == null))
+ this.rawSet = new java.util.ArrayList<java.lang.Object>();
+ this.rawSet.add(rawSet);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> rawSet(java.util.Collection<?> rawSet) {
+ if ((this.rawSet == null))
+ this.rawSet = new java.util.ArrayList<java.lang.Object>();
+ this.rawSet.addAll(rawSet);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> clearRawSet() {
+ if ((this.rawSet != null))
+ this.rawSet.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> stringSet(String stringSet) {
+ if ((this.stringSet == null))
+ this.stringSet = new java.util.ArrayList<String>();
+ this.stringSet.add(stringSet);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> stringSet(java.util.Collection<? extends String> stringSet) {
+ if ((this.stringSet == null))
+ this.stringSet = new java.util.ArrayList<String>();
+ this.stringSet.addAll(stringSet);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSetsBuilder<T> clearStringSet() {
+ if ((this.stringSet != null))
+ this.stringSet.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularSets<T> build() {
+ java.util.Set<T> dangerMice;
+ switch (((this.dangerMice == null) ? 0 : this.dangerMice.size())) {
+ case 0 :
+ dangerMice = java.util.Collections.emptySet();
+ break;
+ case 1 :
+ dangerMice = java.util.Collections.singleton(this.dangerMice.get(0));
+ break;
+ default :
+ dangerMice = new java.util.LinkedHashSet<T>(((this.dangerMice.size() < 0x40000000) ? ((1 + this.dangerMice.size()) + ((this.dangerMice.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ dangerMice.addAll(this.dangerMice);
+ dangerMice = java.util.Collections.unmodifiableSet(dangerMice);
+ }
+ java.util.SortedSet<Number> octopodes = new java.util.TreeSet<Number>();
+ if ((this.octopodes != null))
+ octopodes.addAll(this.octopodes);
+ octopodes = java.util.Collections.unmodifiableSortedSet(octopodes);
+ java.util.Set<java.lang.Object> rawSet;
+ switch (((this.rawSet == null) ? 0 : this.rawSet.size())) {
+ case 0 :
+ rawSet = java.util.Collections.emptySet();
+ break;
+ case 1 :
+ rawSet = java.util.Collections.singleton(this.rawSet.get(0));
+ break;
+ default :
+ rawSet = new java.util.LinkedHashSet<java.lang.Object>(((this.rawSet.size() < 0x40000000) ? ((1 + this.rawSet.size()) + ((this.rawSet.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ rawSet.addAll(this.rawSet);
+ rawSet = java.util.Collections.unmodifiableSet(rawSet);
+ }
+ java.util.Set<String> stringSet;
+ switch (((this.stringSet == null) ? 0 : this.stringSet.size())) {
+ case 0 :
+ stringSet = java.util.Collections.emptySet();
+ break;
+ case 1 :
+ stringSet = java.util.Collections.singleton(this.stringSet.get(0));
+ break;
+ default :
+ stringSet = new java.util.LinkedHashSet<String>(((this.stringSet.size() < 0x40000000) ? ((1 + this.stringSet.size()) + ((this.stringSet.size() - 3) / 3)) : java.lang.Integer.MAX_VALUE));
+ stringSet.addAll(this.stringSet);
+ stringSet = java.util.Collections.unmodifiableSet(stringSet);
+ }
+ return new BuilderSingularSets<T>(dangerMice, octopodes, rawSet, stringSet);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((("BuilderSingularSets.BuilderSingularSetsBuilder(dangerMice=" + this.dangerMice) + ", octopodes=") + this.octopodes) + ", rawSet=") + this.rawSet) + ", stringSet=") + this.stringSet) + ")");
+ }
+ }
+ private @Singular Set<T> dangerMice;
+ private @Singular SortedSet<? extends Number> octopodes;
+ private @SuppressWarnings("all") @Singular("rawSet") Set rawSet;
+ private @Singular("stringSet") Set<String> stringSet;
+ @java.lang.SuppressWarnings("all") BuilderSingularSets(final Set<T> dangerMice, final SortedSet<? extends Number> octopodes, final Set rawSet, final Set<String> stringSet) {
+ super();
+ this.dangerMice = dangerMice;
+ this.octopodes = octopodes;
+ this.rawSet = rawSet;
+ this.stringSet = stringSet;
+ }
+ public static @java.lang.SuppressWarnings("all") <T>BuilderSingularSetsBuilder<T> builder() {
+ return new BuilderSingularSetsBuilder<T>();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderSingularWithPrefixes.java b/test/transform/resource/after-ecj/BuilderSingularWithPrefixes.java
new file mode 100644
index 00000000..12c299c6
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderSingularWithPrefixes.java
@@ -0,0 +1,51 @@
+import lombok.Singular;
+@lombok.Builder @lombok.experimental.Accessors(prefix = "_") class BuilderSingularWithPrefixes {
+ public static @java.lang.SuppressWarnings("all") class BuilderSingularWithPrefixesBuilder {
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> elems;
+ @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixesBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixesBuilder elem(String elem) {
+ if ((this.elems == null))
+ this.elems = new java.util.ArrayList<String>();
+ this.elems.add(elem);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixesBuilder elems(java.util.Collection<? extends String> elems) {
+ if ((this.elems == null))
+ this.elems = new java.util.ArrayList<String>();
+ this.elems.addAll(elems);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixesBuilder clearElems() {
+ if ((this.elems != null))
+ this.elems.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixes build() {
+ java.util.List<String> elems;
+ switch (((this.elems == null) ? 0 : this.elems.size())) {
+ case 0 :
+ elems = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ elems = java.util.Collections.singletonList(this.elems.get(0));
+ break;
+ default :
+ elems = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.elems));
+ }
+ return new BuilderSingularWithPrefixes(elems);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (("BuilderSingularWithPrefixes.BuilderSingularWithPrefixesBuilder(elems=" + this.elems) + ")");
+ }
+ }
+ private @Singular java.util.List<String> _elems;
+ @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixes(final java.util.List<String> elems) {
+ super();
+ this._elems = elems;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderSingularWithPrefixesBuilder builder() {
+ return new BuilderSingularWithPrefixesBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderValueData.java b/test/transform/resource/after-ecj/BuilderValueData.java
new file mode 100644
index 00000000..06456e86
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderValueData.java
@@ -0,0 +1,90 @@
+import java.util.List;
+final @lombok.Builder @lombok.Value class BuilderAndValue {
+ public static @java.lang.SuppressWarnings("all") class BuilderAndValueBuilder {
+ @java.lang.SuppressWarnings("all") BuilderAndValueBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderAndValue build() {
+ return new BuilderAndValue();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return "BuilderAndValue.BuilderAndValueBuilder()";
+ }
+ }
+ private final int zero = 0;
+ @java.lang.SuppressWarnings("all") BuilderAndValue() {
+ super();
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderAndValueBuilder builder() {
+ return new BuilderAndValueBuilder();
+ }
+ public @java.lang.SuppressWarnings("all") int getZero() {
+ return this.zero;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof BuilderAndValue)))
+ return false;
+ final BuilderAndValue other = (BuilderAndValue) o;
+ if ((this.getZero() != other.getZero()))
+ return false;
+ return true;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.getZero());
+ return result;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (("BuilderAndValue(zero=" + this.getZero()) + ")");
+ }
+}
+@lombok.Builder @lombok.Data class BuilderAndData {
+ public static @java.lang.SuppressWarnings("all") class BuilderAndDataBuilder {
+ @java.lang.SuppressWarnings("all") BuilderAndDataBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderAndData build() {
+ return new BuilderAndData();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return "BuilderAndData.BuilderAndDataBuilder()";
+ }
+ }
+ private final int zero = 0;
+ @java.lang.SuppressWarnings("all") BuilderAndData() {
+ super();
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderAndDataBuilder builder() {
+ return new BuilderAndDataBuilder();
+ }
+ public @java.lang.SuppressWarnings("all") int getZero() {
+ return this.zero;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof BuilderAndData)))
+ return false;
+ final BuilderAndData other = (BuilderAndData) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ if ((this.getZero() != other.getZero()))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof BuilderAndData);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.getZero());
+ return result;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (("BuilderAndData(zero=" + this.getZero()) + ")");
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderWithAccessors.java b/test/transform/resource/after-ecj/BuilderWithAccessors.java
index 79776dc4..a7bee291 100644
--- a/test/transform/resource/after-ecj/BuilderWithAccessors.java
+++ b/test/transform/resource/after-ecj/BuilderWithAccessors.java
@@ -1,9 +1,9 @@
-@lombok.experimental.Builder @lombok.experimental.Accessors(prefix = {"p", "_"}) class BuilderWithAccessors {
+@lombok.Builder @lombok.experimental.Accessors(prefix = {"p", "_"}) class BuilderWithAccessors {
public static @java.lang.SuppressWarnings("all") class BuilderWithAccessorsBuilder {
- private int plower;
- private int upper;
- private int foo;
- private int _bar;
+ private @java.lang.SuppressWarnings("all") int plower;
+ private @java.lang.SuppressWarnings("all") int upper;
+ private @java.lang.SuppressWarnings("all") int foo;
+ private @java.lang.SuppressWarnings("all") int _bar;
@java.lang.SuppressWarnings("all") BuilderWithAccessorsBuilder() {
super();
}
diff --git a/test/transform/resource/after-ecj/BuilderWithDeprecated.java b/test/transform/resource/after-ecj/BuilderWithDeprecated.java
new file mode 100644
index 00000000..09a0b786
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderWithDeprecated.java
@@ -0,0 +1,87 @@
+import com.google.common.collect.ImmutableList;
+import lombok.Builder;
+import lombok.Singular;
+public @Builder class BuilderWithDeprecated {
+ public static @java.lang.SuppressWarnings("all") class BuilderWithDeprecatedBuilder {
+ private @java.lang.SuppressWarnings("all") String dep1;
+ private @java.lang.SuppressWarnings("all") int dep2;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<String> strings;
+ private @java.lang.SuppressWarnings("all") com.google.common.collect.ImmutableList.Builder<Integer> numbers;
+ @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder() {
+ super();
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder dep1(final String dep1) {
+ this.dep1 = dep1;
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder dep2(final int dep2) {
+ this.dep2 = dep2;
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder string(String string) {
+ if ((this.strings == null))
+ this.strings = new java.util.ArrayList<String>();
+ this.strings.add(string);
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder strings(java.util.Collection<? extends String> strings) {
+ if ((this.strings == null))
+ this.strings = new java.util.ArrayList<String>();
+ this.strings.addAll(strings);
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder clearStrings() {
+ if ((this.strings != null))
+ this.strings.clear();
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder number(Integer number) {
+ if ((this.numbers == null))
+ this.numbers = com.google.common.collect.ImmutableList.builder();
+ this.numbers.add(number);
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder numbers(java.lang.Iterable<? extends Integer> numbers) {
+ if ((this.numbers == null))
+ this.numbers = com.google.common.collect.ImmutableList.builder();
+ this.numbers.addAll(numbers);
+ return this;
+ }
+ public @java.lang.Deprecated @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder clearNumbers() {
+ this.numbers = null;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithDeprecated build() {
+ java.util.List<String> strings;
+ switch (((this.strings == null) ? 0 : this.strings.size())) {
+ case 0 :
+ strings = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ strings = java.util.Collections.singletonList(this.strings.get(0));
+ break;
+ default :
+ strings = java.util.Collections.unmodifiableList(new java.util.ArrayList<String>(this.strings));
+ }
+ com.google.common.collect.ImmutableList<Integer> numbers = ((this.numbers == null) ? com.google.common.collect.ImmutableList.<Integer>of() : this.numbers.build());
+ return new BuilderWithDeprecated(dep1, dep2, strings, numbers);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((("BuilderWithDeprecated.BuilderWithDeprecatedBuilder(dep1=" + this.dep1) + ", dep2=") + this.dep2) + ", strings=") + this.strings) + ", numbers=") + this.numbers) + ")");
+ }
+ }
+ String dep1;
+ @Deprecated int dep2;
+ @Singular @Deprecated java.util.List<String> strings;
+ @Singular @Deprecated ImmutableList<Integer> numbers;
+ @java.lang.SuppressWarnings("all") BuilderWithDeprecated(final String dep1, final int dep2, final java.util.List<String> strings, final ImmutableList<Integer> numbers) {
+ super();
+ this.dep1 = dep1;
+ this.dep2 = dep2;
+ this.strings = strings;
+ this.numbers = numbers;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderWithDeprecatedBuilder builder() {
+ return new BuilderWithDeprecatedBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/BuilderWithExistingBuilderClass.java b/test/transform/resource/after-ecj/BuilderWithExistingBuilderClass.java
index 38cb0038..0e6ba335 100644
--- a/test/transform/resource/after-ecj/BuilderWithExistingBuilderClass.java
+++ b/test/transform/resource/after-ecj/BuilderWithExistingBuilderClass.java
@@ -1,8 +1,8 @@
-import lombok.experimental.Builder;
+import lombok.Builder;
class BuilderWithExistingBuilderClass<T, K extends Number> {
public static class BuilderWithExistingBuilderClassBuilder<Z extends Number> {
- private boolean arg2;
- private String arg3;
+ private @java.lang.SuppressWarnings("all") boolean arg2;
+ private @java.lang.SuppressWarnings("all") String arg3;
private Z arg1;
public void arg2(boolean arg) {
}
diff --git a/test/transform/resource/after-ecj/BuilderWithRecursiveGenerics.java b/test/transform/resource/after-ecj/BuilderWithRecursiveGenerics.java
new file mode 100644
index 00000000..8246ca2c
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderWithRecursiveGenerics.java
@@ -0,0 +1,78 @@
+import java.util.Set;
+import lombok.Builder;
+import lombok.Value;
+public class BuilderWithRecursiveGenerics {
+ interface Inter<T, U extends Inter<T, U>> {
+ }
+ public static final @Builder @Value class Test<Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>> {
+ public static @java.lang.SuppressWarnings("all") class TestBuilder<Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>> {
+ private @java.lang.SuppressWarnings("all") Foo foo;
+ private @java.lang.SuppressWarnings("all") Bar bar;
+ @java.lang.SuppressWarnings("all") TestBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") TestBuilder<Foo, Bar, Quz> foo(final Foo foo) {
+ this.foo = foo;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") TestBuilder<Foo, Bar, Quz> bar(final Bar bar) {
+ this.bar = bar;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") Test<Foo, Bar, Quz> build() {
+ return new Test<Foo, Bar, Quz>(foo, bar);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((("BuilderWithRecursiveGenerics.Test.TestBuilder(foo=" + this.foo) + ", bar=") + this.bar) + ")");
+ }
+ }
+ private final Foo foo;
+ private final Bar bar;
+ @java.lang.SuppressWarnings("all") Test(final Foo foo, final Bar bar) {
+ super();
+ this.foo = foo;
+ this.bar = bar;
+ }
+ public static @java.lang.SuppressWarnings("all") <Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>>TestBuilder<Foo, Bar, Quz> builder() {
+ return new TestBuilder<Foo, Bar, Quz>();
+ }
+ public @java.lang.SuppressWarnings("all") Foo getFoo() {
+ return this.foo;
+ }
+ public @java.lang.SuppressWarnings("all") Bar getBar() {
+ return this.bar;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof BuilderWithRecursiveGenerics.Test)))
+ return false;
+ final BuilderWithRecursiveGenerics.Test<?, ?, ?> other = (BuilderWithRecursiveGenerics.Test<?, ?, ?>) o;
+ final java.lang.Object this$foo = this.getFoo();
+ final java.lang.Object other$foo = other.getFoo();
+ if (((this$foo == null) ? (other$foo != null) : (! this$foo.equals(other$foo))))
+ return false;
+ final java.lang.Object this$bar = this.getBar();
+ final java.lang.Object other$bar = other.getBar();
+ if (((this$bar == null) ? (other$bar != null) : (! this$bar.equals(other$bar))))
+ return false;
+ return true;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final java.lang.Object $foo = this.getFoo();
+ result = ((result * PRIME) + (($foo == null) ? 43 : $foo.hashCode()));
+ final java.lang.Object $bar = this.getBar();
+ result = ((result * PRIME) + (($bar == null) ? 43 : $bar.hashCode()));
+ return result;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((("BuilderWithRecursiveGenerics.Test(foo=" + this.getFoo()) + ", bar=") + this.getBar()) + ")");
+ }
+ }
+ public BuilderWithRecursiveGenerics() {
+ super();
+ }
+}
+
diff --git a/test/transform/resource/after-ecj/BuilderWithToBuilder.java b/test/transform/resource/after-ecj/BuilderWithToBuilder.java
new file mode 100644
index 00000000..d304293c
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderWithToBuilder.java
@@ -0,0 +1,155 @@
+import java.util.List;
+import lombok.Builder;
+@Builder(toBuilder = true) @lombok.experimental.Accessors(prefix = "m") class BuilderWithToBuilder<T> {
+ public static @java.lang.SuppressWarnings("all") class BuilderWithToBuilderBuilder<T> {
+ private @java.lang.SuppressWarnings("all") String one;
+ private @java.lang.SuppressWarnings("all") String two;
+ private @java.lang.SuppressWarnings("all") T foo;
+ private @java.lang.SuppressWarnings("all") java.util.ArrayList<T> bars;
+ @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> one(final String one) {
+ this.one = one;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> two(final String two) {
+ this.two = two;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> foo(final T foo) {
+ this.foo = foo;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> bar(T bar) {
+ if ((this.bars == null))
+ this.bars = new java.util.ArrayList<T>();
+ this.bars.add(bar);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> bars(java.util.Collection<? extends T> bars) {
+ if ((this.bars == null))
+ this.bars = new java.util.ArrayList<T>();
+ this.bars.addAll(bars);
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> clearBars() {
+ if ((this.bars != null))
+ this.bars.clear();
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilder<T> build() {
+ java.util.List<T> bars;
+ switch (((this.bars == null) ? 0 : this.bars.size())) {
+ case 0 :
+ bars = java.util.Collections.emptyList();
+ break;
+ case 1 :
+ bars = java.util.Collections.singletonList(this.bars.get(0));
+ break;
+ default :
+ bars = java.util.Collections.unmodifiableList(new java.util.ArrayList<T>(this.bars));
+ }
+ return new BuilderWithToBuilder<T>(one, two, foo, bars);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((((((("BuilderWithToBuilder.BuilderWithToBuilderBuilder(one=" + this.one) + ", two=") + this.two) + ", foo=") + this.foo) + ", bars=") + this.bars) + ")");
+ }
+ }
+ private String mOne;
+ private String mTwo;
+ private @Builder.ObtainVia(method = "rrr",isStatic = true) T foo;
+ private @lombok.Singular List<T> bars;
+ public static <K>K rrr(BuilderWithToBuilder<K> x) {
+ return x.foo;
+ }
+ @java.lang.SuppressWarnings("all") BuilderWithToBuilder(final String one, final String two, final T foo, final List<T> bars) {
+ super();
+ this.mOne = one;
+ this.mTwo = two;
+ this.foo = foo;
+ this.bars = bars;
+ }
+ public static @java.lang.SuppressWarnings("all") <T>BuilderWithToBuilderBuilder<T> builder() {
+ return new BuilderWithToBuilderBuilder<T>();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithToBuilderBuilder<T> toBuilder() {
+ return new BuilderWithToBuilderBuilder<T>().one(this.mOne).two(this.mTwo).foo(BuilderWithToBuilder.rrr(this)).bars(this.bars);
+ }
+}
+@lombok.experimental.Accessors(prefix = "m") class ConstructorWithToBuilder<T> {
+ public static @java.lang.SuppressWarnings("all") class ConstructorWithToBuilderBuilder<T> {
+ private @java.lang.SuppressWarnings("all") String mOne;
+ private @java.lang.SuppressWarnings("all") T bar;
+ @java.lang.SuppressWarnings("all") ConstructorWithToBuilderBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") ConstructorWithToBuilderBuilder<T> mOne(final String mOne) {
+ this.mOne = mOne;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") ConstructorWithToBuilderBuilder<T> bar(final T bar) {
+ this.bar = bar;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") ConstructorWithToBuilder<T> build() {
+ return new ConstructorWithToBuilder<T>(mOne, bar);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((("ConstructorWithToBuilder.ConstructorWithToBuilderBuilder(mOne=" + this.mOne) + ", bar=") + this.bar) + ")");
+ }
+ }
+ private String mOne;
+ private String mTwo;
+ private T foo;
+ private @lombok.Singular List<T> bars;
+ public @Builder(toBuilder = true) ConstructorWithToBuilder(String mOne, @Builder.ObtainVia(field = "foo") T bar) {
+ super();
+ }
+ public static @java.lang.SuppressWarnings("all") <T>ConstructorWithToBuilderBuilder<T> builder() {
+ return new ConstructorWithToBuilderBuilder<T>();
+ }
+ public @java.lang.SuppressWarnings("all") ConstructorWithToBuilderBuilder<T> toBuilder() {
+ return new ConstructorWithToBuilderBuilder<T>().mOne(this.mOne).bar(this.foo);
+ }
+}
+@lombok.experimental.Accessors(prefix = "m") class StaticWithToBuilder<T, K> {
+ public static @java.lang.SuppressWarnings("all") class StaticWithToBuilderBuilder<Z> {
+ private @java.lang.SuppressWarnings("all") String mOne;
+ private @java.lang.SuppressWarnings("all") Z bar;
+ @java.lang.SuppressWarnings("all") StaticWithToBuilderBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") StaticWithToBuilderBuilder<Z> mOne(final String mOne) {
+ this.mOne = mOne;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") StaticWithToBuilderBuilder<Z> bar(final Z bar) {
+ this.bar = bar;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") StaticWithToBuilder<Z, String> build() {
+ return StaticWithToBuilder.<Z>test(mOne, bar);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (((("StaticWithToBuilder.StaticWithToBuilderBuilder(mOne=" + this.mOne) + ", bar=") + this.bar) + ")");
+ }
+ }
+ private String mOne;
+ private String mTwo;
+ private T foo;
+ private K bar;
+ private @lombok.Singular List<T> bars;
+ StaticWithToBuilder() {
+ super();
+ }
+ public static @Builder(toBuilder = true) <Z>StaticWithToBuilder<Z, String> test(String mOne, @Builder.ObtainVia(field = "foo") Z bar) {
+ return new StaticWithToBuilder<Z, String>();
+ }
+ public static @java.lang.SuppressWarnings("all") <Z>StaticWithToBuilderBuilder<Z> builder() {
+ return new StaticWithToBuilderBuilder<Z>();
+ }
+ public @java.lang.SuppressWarnings("all") StaticWithToBuilderBuilder<T> toBuilder() {
+ return new StaticWithToBuilderBuilder<T>().mOne(this.mOne).bar(this.foo);
+ }
+}
diff --git a/test/transform/resource/after-ecj/BuilderWithTolerate.java b/test/transform/resource/after-ecj/BuilderWithTolerate.java
new file mode 100644
index 00000000..b64fd49a
--- /dev/null
+++ b/test/transform/resource/after-ecj/BuilderWithTolerate.java
@@ -0,0 +1,34 @@
+import lombok.Builder;
+import lombok.experimental.Tolerate;
+public @Builder class BuilderWithTolerate {
+ public static class BuilderWithTolerateBuilder {
+ private @java.lang.SuppressWarnings("all") int value;
+ public @Tolerate BuilderWithTolerateBuilder value(String s) {
+ return this.value(Integer.parseInt(s));
+ }
+ @java.lang.SuppressWarnings("all") BuilderWithTolerateBuilder() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithTolerateBuilder value(final int value) {
+ this.value = value;
+ return this;
+ }
+ public @java.lang.SuppressWarnings("all") BuilderWithTolerate build() {
+ return new BuilderWithTolerate(value);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (("BuilderWithTolerate.BuilderWithTolerateBuilder(value=" + this.value) + ")");
+ }
+ }
+ private final int value;
+ public static void main(String[] args) {
+ BuilderWithTolerate.builder().value("42").build();
+ }
+ @java.lang.SuppressWarnings("all") BuilderWithTolerate(final int value) {
+ super();
+ this.value = value;
+ }
+ public static @java.lang.SuppressWarnings("all") BuilderWithTolerateBuilder builder() {
+ return new BuilderWithTolerateBuilder();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/ConflictingStaticConstructorNames.java b/test/transform/resource/after-ecj/ConflictingStaticConstructorNames.java
index f8aff69c..0d234d36 100644
--- a/test/transform/resource/after-ecj/ConflictingStaticConstructorNames.java
+++ b/test/transform/resource/after-ecj/ConflictingStaticConstructorNames.java
@@ -4,7 +4,7 @@
return true;
if ((! (o instanceof ConflictingStaticConstructorNames)))
return false;
- final @java.lang.SuppressWarnings("all") ConflictingStaticConstructorNames other = (ConflictingStaticConstructorNames) o;
+ final ConflictingStaticConstructorNames other = (ConflictingStaticConstructorNames) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
return true;
diff --git a/test/transform/resource/after-ecj/Constructors.java b/test/transform/resource/after-ecj/Constructors.java
index a4597ce6..8f8ee129 100644
--- a/test/transform/resource/after-ecj/Constructors.java
+++ b/test/transform/resource/after-ecj/Constructors.java
@@ -1,7 +1,7 @@
@lombok.RequiredArgsConstructor class RequiredArgsConstructor1 {
final int x;
String name;
- public @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") RequiredArgsConstructor1(final int x) {
+ public @java.lang.SuppressWarnings("all") RequiredArgsConstructor1(final int x) {
super();
this.x = x;
}
@@ -9,7 +9,7 @@
@lombok.RequiredArgsConstructor(access = lombok.AccessLevel.PROTECTED) class RequiredArgsConstructorAccess {
final int x;
String name;
- protected @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") RequiredArgsConstructorAccess(final int x) {
+ protected @java.lang.SuppressWarnings("all") RequiredArgsConstructorAccess(final int x) {
super();
this.x = x;
}
@@ -28,7 +28,7 @@
@lombok.RequiredArgsConstructor() class RequiredArgsConstructorWithAnnotations {
final int x;
String name;
- public @Deprecated @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") RequiredArgsConstructorWithAnnotations(final int x) {
+ public @Deprecated @java.lang.SuppressWarnings("all") RequiredArgsConstructorWithAnnotations(final int x) {
super();
this.x = x;
}
@@ -36,7 +36,7 @@
@lombok.AllArgsConstructor class AllArgsConstructor1 {
final int x;
String name;
- public @java.beans.ConstructorProperties({"x", "name"}) @java.lang.SuppressWarnings("all") AllArgsConstructor1(final int x, final String name) {
+ public @java.lang.SuppressWarnings("all") AllArgsConstructor1(final int x, final String name) {
super();
this.x = x;
this.name = name;
@@ -77,4 +77,22 @@
super();
this.x = x;
}
+}
+@lombok.NoArgsConstructor(force = true) class NoArgsConstructor2 {
+ final int x;
+ final double y;
+ final char c;
+ final boolean b;
+ final float f;
+ final String s;
+ byte z;
+ public @java.lang.SuppressWarnings("all") NoArgsConstructor2() {
+ super();
+ this.x = 0;
+ this.y = 0D;
+ this.c = '\0';
+ this.b = false;
+ this.f = 0F;
+ this.s = null;
+ }
} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/ConstructorsConfiguration.java b/test/transform/resource/after-ecj/ConstructorsConfiguration.java
index b55d3e03..2e88a59f 100644
--- a/test/transform/resource/after-ecj/ConstructorsConfiguration.java
+++ b/test/transform/resource/after-ecj/ConstructorsConfiguration.java
@@ -5,10 +5,3 @@
this.x = x;
}
}
-@lombok.AllArgsConstructor(suppressConstructorProperties = false) class ConstructorsConfigurationExplicit {
- int x;
- public @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") ConstructorsConfigurationExplicit(final int x) {
- super();
- this.x = x;
- }
-}
diff --git a/test/transform/resource/after-ecj/ConstructorsWithAccessors.java b/test/transform/resource/after-ecj/ConstructorsWithAccessors.java
index 0df8fbe1..301e6132 100644
--- a/test/transform/resource/after-ecj/ConstructorsWithAccessors.java
+++ b/test/transform/resource/after-ecj/ConstructorsWithAccessors.java
@@ -3,7 +3,7 @@
int pUpper;
int _huh;
int __huh2;
- public @java.beans.ConstructorProperties({"plower", "upper", "huh", "_huh2"}) @java.lang.SuppressWarnings("all") ConstructorsWithAccessors(final int plower, final int upper, final int huh, final int _huh2) {
+ public @java.lang.SuppressWarnings("all") ConstructorsWithAccessors(final int plower, final int upper, final int huh, final int _huh2) {
super();
this.plower = plower;
this.pUpper = upper;
@@ -11,3 +11,32 @@
this.__huh2 = _huh2;
}
}
+@lombok.AllArgsConstructor @lombok.experimental.Accessors(prefix = {"p", "_"}) class ConstructorsWithAccessorsNonNull {
+ @lombok.NonNull Integer plower;
+ @lombok.NonNull Integer pUpper;
+ @lombok.NonNull Integer _huh;
+ final @lombok.NonNull Integer __huh2;
+ public @java.lang.SuppressWarnings("all") ConstructorsWithAccessorsNonNull(final @lombok.NonNull Integer plower, final @lombok.NonNull Integer upper, final @lombok.NonNull Integer huh, final @lombok.NonNull Integer _huh2) {
+ super();
+ if ((plower == null))
+ {
+ throw new java.lang.NullPointerException("plower");
+ }
+ if ((upper == null))
+ {
+ throw new java.lang.NullPointerException("upper");
+ }
+ if ((huh == null))
+ {
+ throw new java.lang.NullPointerException("huh");
+ }
+ if ((_huh2 == null))
+ {
+ throw new java.lang.NullPointerException("_huh2");
+ }
+ this.plower = plower;
+ this.pUpper = upper;
+ this._huh = huh;
+ this.__huh2 = _huh2;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/DataConfiguration.java b/test/transform/resource/after-ecj/DataConfiguration.java
index f2733a88..1e7adfbf 100644
--- a/test/transform/resource/after-ecj/DataConfiguration.java
+++ b/test/transform/resource/after-ecj/DataConfiguration.java
@@ -8,10 +8,10 @@
return true;
if ((! (o instanceof DataConfiguration)))
return false;
- final @java.lang.SuppressWarnings("all") DataConfiguration other = (DataConfiguration) o;
+ final DataConfiguration other = (DataConfiguration) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
- if ((this.getX() != other.getX()))
+ if ((this.x != other.x))
return false;
return true;
}
@@ -21,11 +21,11 @@
public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
final int PRIME = 59;
int result = 1;
- result = ((result * PRIME) + this.getX());
+ result = ((result * PRIME) + this.x);
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return (("DataConfiguration(x=" + this.getX()) + ")");
+ return (("DataConfiguration(x=" + this.x) + ")");
}
public @java.lang.SuppressWarnings("all") DataConfiguration(final int x) {
super();
diff --git a/test/transform/resource/after-ecj/DataExtended.java b/test/transform/resource/after-ecj/DataExtended.java
index c2652ba4..3250421f 100644
--- a/test/transform/resource/after-ecj/DataExtended.java
+++ b/test/transform/resource/after-ecj/DataExtended.java
@@ -11,7 +11,7 @@
return true;
if ((! (o instanceof DataExtended)))
return false;
- final @java.lang.SuppressWarnings("all") DataExtended other = (DataExtended) o;
+ final DataExtended other = (DataExtended) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
diff --git a/test/transform/resource/after-ecj/DataIgnore.java b/test/transform/resource/after-ecj/DataIgnore.java
index d077a5db..d3ac8aa3 100644
--- a/test/transform/resource/after-ecj/DataIgnore.java
+++ b/test/transform/resource/after-ecj/DataIgnore.java
@@ -9,7 +9,7 @@
return true;
if ((! (o instanceof DataIgnore)))
return false;
- final @java.lang.SuppressWarnings("all") DataIgnore other = (DataIgnore) o;
+ final DataIgnore other = (DataIgnore) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
@@ -28,7 +28,7 @@
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (("DataIgnore(x=" + this.getX()) + ")");
}
- public @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") DataIgnore(final int x) {
+ public @java.lang.SuppressWarnings("all") DataIgnore(final int x) {
super();
this.x = x;
}
diff --git a/test/transform/resource/after-ecj/DataOnLocalClass.java b/test/transform/resource/after-ecj/DataOnLocalClass.java
index 3f4832ff..341df49b 100644
--- a/test/transform/resource/after-ecj/DataOnLocalClass.java
+++ b/test/transform/resource/after-ecj/DataOnLocalClass.java
@@ -21,7 +21,7 @@ class DataOnLocalClass1 {
return true;
if ((! (o instanceof Local)))
return false;
- final @java.lang.SuppressWarnings("all") Local other = (Local) o;
+ final Local other = (Local) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
@@ -40,7 +40,7 @@ class DataOnLocalClass1 {
int result = 1;
result = ((result * PRIME) + this.getX());
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
@@ -73,7 +73,7 @@ class DataOnLocalClass2 {
return true;
if ((! (o instanceof Local.InnerLocal)))
return false;
- final @java.lang.SuppressWarnings("all") InnerLocal other = (InnerLocal) o;
+ final Local.InnerLocal other = (Local.InnerLocal) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
final java.lang.Object this$name = this.getName();
@@ -89,7 +89,7 @@ class DataOnLocalClass2 {
final int PRIME = 59;
int result = 1;
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
@@ -113,7 +113,7 @@ class DataOnLocalClass2 {
return true;
if ((! (o instanceof Local)))
return false;
- final @java.lang.SuppressWarnings("all") Local other = (Local) o;
+ final Local other = (Local) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
diff --git a/test/transform/resource/after-ecj/DataPlain.java b/test/transform/resource/after-ecj/DataPlain.java
index 858f46dd..eaeef509 100644
--- a/test/transform/resource/after-ecj/DataPlain.java
+++ b/test/transform/resource/after-ecj/DataPlain.java
@@ -16,7 +16,7 @@ import lombok.Data;
return true;
if ((! (o instanceof Data1)))
return false;
- final @java.lang.SuppressWarnings("all") Data1 other = (Data1) o;
+ final Data1 other = (Data1) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
@@ -35,13 +35,13 @@ import lombok.Data;
int result = 1;
result = ((result * PRIME) + this.getX());
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((("Data1(x=" + this.getX()) + ", name=") + this.getName()) + ")");
}
- public @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") Data1(final int x) {
+ public @java.lang.SuppressWarnings("all") Data1(final int x) {
super();
this.x = x;
}
@@ -63,7 +63,7 @@ import lombok.Data;
return true;
if ((! (o instanceof Data2)))
return false;
- final @java.lang.SuppressWarnings("all") Data2 other = (Data2) o;
+ final Data2 other = (Data2) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
@@ -82,13 +82,13 @@ import lombok.Data;
int result = 1;
result = ((result * PRIME) + this.getX());
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((("Data2(x=" + this.getX()) + ", name=") + this.getName()) + ")");
}
- public @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") Data2(final int x) {
+ public @java.lang.SuppressWarnings("all") Data2(final int x) {
super();
this.x = x;
}
@@ -110,7 +110,7 @@ final @Data class Data3 {
return true;
if ((! (o instanceof Data3)))
return false;
- final @java.lang.SuppressWarnings("all") Data3 other = (Data3) o;
+ final Data3 other = (Data3) o;
if ((this.getX() != other.getX()))
return false;
final java.lang.Object this$name = this.getName();
@@ -124,13 +124,13 @@ final @Data class Data3 {
int result = 1;
result = ((result * PRIME) + this.getX());
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((("Data3(x=" + this.getX()) + ", name=") + this.getName()) + ")");
}
- public @java.beans.ConstructorProperties({"x"}) @java.lang.SuppressWarnings("all") Data3(final int x) {
+ public @java.lang.SuppressWarnings("all") Data3(final int x) {
super();
this.x = x;
}
@@ -154,7 +154,7 @@ final @Data @lombok.EqualsAndHashCode(callSuper = true) class Data4 extends java
return true;
if ((! (o instanceof Data4)))
return false;
- final @java.lang.SuppressWarnings("all") Data4 other = (Data4) o;
+ final Data4 other = (Data4) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((! super.equals(o)))
@@ -168,8 +168,7 @@ final @Data @lombok.EqualsAndHashCode(callSuper = true) class Data4 extends java
}
public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
final int PRIME = 59;
- int result = 1;
- result = ((result * PRIME) + super.hashCode());
+ int result = super.hashCode();
result = ((result * PRIME) + this.getX());
return result;
}
@@ -180,7 +179,7 @@ final @Data @lombok.EqualsAndHashCode(callSuper = true) class Data4 extends java
return true;
if ((! (o instanceof Data5)))
return false;
- final @java.lang.SuppressWarnings("all") Data5 other = (Data5) o;
+ final Data5 other = (Data5) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
return true;
diff --git a/test/transform/resource/after-ecj/DataWithGetter.java b/test/transform/resource/after-ecj/DataWithGetter.java
index ee74ed4e..fa291eca 100644
--- a/test/transform/resource/after-ecj/DataWithGetter.java
+++ b/test/transform/resource/after-ecj/DataWithGetter.java
@@ -13,7 +13,7 @@
return true;
if ((! (o instanceof DataWithGetter)))
return false;
- final @java.lang.SuppressWarnings("all") DataWithGetter other = (DataWithGetter) o;
+ final DataWithGetter other = (DataWithGetter) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
@@ -35,13 +35,13 @@
result = ((result * PRIME) + this.getX());
result = ((result * PRIME) + this.getY());
final java.lang.Object $z = this.getZ();
- result = ((result * PRIME) + (($z == null) ? 0 : $z.hashCode()));
+ result = ((result * PRIME) + (($z == null) ? 43 : $z.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((((("DataWithGetter(x=" + this.getX()) + ", y=") + this.getY()) + ", z=") + this.getZ()) + ")");
}
- public @java.beans.ConstructorProperties({"z"}) @java.lang.SuppressWarnings("all") DataWithGetter(final String z) {
+ public @java.lang.SuppressWarnings("all") DataWithGetter(final String z) {
super();
this.z = z;
}
diff --git a/test/transform/resource/after-ecj/DataWithGetterNone.java b/test/transform/resource/after-ecj/DataWithGetterNone.java
index 056e071d..4545dc46 100644
--- a/test/transform/resource/after-ecj/DataWithGetterNone.java
+++ b/test/transform/resource/after-ecj/DataWithGetterNone.java
@@ -13,7 +13,7 @@
return true;
if ((! (o instanceof DataWithGetterNone)))
return false;
- final @java.lang.SuppressWarnings("all") DataWithGetterNone other = (DataWithGetterNone) o;
+ final DataWithGetterNone other = (DataWithGetterNone) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.x != other.x))
@@ -35,13 +35,13 @@
result = ((result * PRIME) + this.x);
result = ((result * PRIME) + this.y);
final java.lang.Object $z = this.z;
- result = ((result * PRIME) + (($z == null) ? 0 : $z.hashCode()));
+ result = ((result * PRIME) + (($z == null) ? 43 : $z.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((((("DataWithGetterNone(x=" + this.x) + ", y=") + this.y) + ", z=") + this.z) + ")");
}
- public @java.beans.ConstructorProperties({"z"}) @java.lang.SuppressWarnings("all") DataWithGetterNone(final String z) {
+ public @java.lang.SuppressWarnings("all") DataWithGetterNone(final String z) {
super();
this.z = z;
}
diff --git a/test/transform/resource/after-ecj/DelegateWithVarargs.java b/test/transform/resource/after-ecj/DelegateWithVarargs.java
new file mode 100644
index 00000000..71a0ca5a
--- /dev/null
+++ b/test/transform/resource/after-ecj/DelegateWithVarargs.java
@@ -0,0 +1,25 @@
+import lombok.experimental.Delegate;
+class DelegateWithVarargs {
+ private interface Bar {
+ void justOneParameter(int... varargs);
+ void multipleParameters(String first, int... varargs);
+ void array(int[] array);
+ void arrayVarargs(int[]... arrayVarargs);
+ }
+ private @Delegate Bar bar;
+ DelegateWithVarargs() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") void array(final int[] array) {
+ this.bar.array(array);
+ }
+ public @java.lang.SuppressWarnings("all") void arrayVarargs(final int[]... arrayVarargs) {
+ this.bar.arrayVarargs(arrayVarargs);
+ }
+ public @java.lang.SuppressWarnings("all") void justOneParameter(final int... varargs) {
+ this.bar.justOneParameter(varargs);
+ }
+ public @java.lang.SuppressWarnings("all") void multipleParameters(final java.lang.String first, final int... varargs) {
+ this.bar.multipleParameters(first, varargs);
+ }
+}
diff --git a/test/transform/resource/after-ecj/EncodingUsAscii.java b/test/transform/resource/after-ecj/EncodingUsAscii.java
new file mode 100644
index 00000000..b66feb0c
--- /dev/null
+++ b/test/transform/resource/after-ecj/EncodingUsAscii.java
@@ -0,0 +1 @@
+//ignore: This test serves to check what happens with 'weird' characters when you use delombok. It's just not relevant for ecj.
diff --git a/test/transform/resource/after-ecj/EncodingUtf8.java b/test/transform/resource/after-ecj/EncodingUtf8.java
new file mode 100644
index 00000000..b66feb0c
--- /dev/null
+++ b/test/transform/resource/after-ecj/EncodingUtf8.java
@@ -0,0 +1 @@
+//ignore: This test serves to check what happens with 'weird' characters when you use delombok. It's just not relevant for ecj.
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCode.java b/test/transform/resource/after-ecj/EqualsAndHashCode.java
index 05cbf2a3..8baa61f2 100644
--- a/test/transform/resource/after-ecj/EqualsAndHashCode.java
+++ b/test/transform/resource/after-ecj/EqualsAndHashCode.java
@@ -12,7 +12,7 @@
return true;
if ((! (o instanceof EqualsAndHashCode)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCode other = (EqualsAndHashCode) o;
+ final EqualsAndHashCode other = (EqualsAndHashCode) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.x != other.x))
@@ -41,9 +41,9 @@
result = ((result * PRIME) + java.util.Arrays.hashCode(this.y));
result = ((result * PRIME) + java.util.Arrays.deepHashCode(this.z));
final java.lang.Object $a = this.a;
- result = ((result * PRIME) + (($a == null) ? 0 : $a.hashCode()));
+ result = ((result * PRIME) + (($a == null) ? 43 : $a.hashCode()));
final java.lang.Object $b = this.b;
- result = ((result * PRIME) + (($b == null) ? 0 : $b.hashCode()));
+ result = ((result * PRIME) + (($b == null) ? 43 : $b.hashCode()));
return result;
}
}
@@ -61,7 +61,7 @@ final @lombok.EqualsAndHashCode class EqualsAndHashCode2 {
return true;
if ((! (o instanceof EqualsAndHashCode2)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCode2 other = (EqualsAndHashCode2) o;
+ final EqualsAndHashCode2 other = (EqualsAndHashCode2) o;
if ((this.x != other.x))
return false;
if ((this.y != other.y))
@@ -96,7 +96,7 @@ final @lombok.EqualsAndHashCode(callSuper = false) class EqualsAndHashCode3 exte
return true;
if ((! (o instanceof EqualsAndHashCode3)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCode3 other = (EqualsAndHashCode3) o;
+ final EqualsAndHashCode3 other = (EqualsAndHashCode3) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
return true;
@@ -118,7 +118,7 @@ final @lombok.EqualsAndHashCode(callSuper = false) class EqualsAndHashCode3 exte
return true;
if ((! (o instanceof EqualsAndHashCode4)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCode4 other = (EqualsAndHashCode4) o;
+ final EqualsAndHashCode4 other = (EqualsAndHashCode4) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((! super.equals(o)))
@@ -129,9 +129,7 @@ final @lombok.EqualsAndHashCode(callSuper = false) class EqualsAndHashCode3 exte
return (other instanceof EqualsAndHashCode4);
}
public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
- final int PRIME = 59;
- int result = 1;
- result = ((result * PRIME) + super.hashCode());
+ int result = super.hashCode();
return result;
}
}
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys1.java b/test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys1.java
new file mode 100644
index 00000000..1561962c
--- /dev/null
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys1.java
@@ -0,0 +1,49 @@
+@lombok.EqualsAndHashCode class EqualsAndHashCodeConfigKeys1Parent {
+ EqualsAndHashCodeConfigKeys1Parent() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeConfigKeys1Parent)))
+ return false;
+ final EqualsAndHashCodeConfigKeys1Parent other = (EqualsAndHashCodeConfigKeys1Parent) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeConfigKeys1Parent);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ int result = 1;
+ return result;
+ }
+}
+@lombok.EqualsAndHashCode class EqualsAndHashCodeConfigKeys1 extends EqualsAndHashCodeConfigKeys1Parent {
+ int x;
+ EqualsAndHashCodeConfigKeys1() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeConfigKeys1)))
+ return false;
+ final EqualsAndHashCodeConfigKeys1 other = (EqualsAndHashCodeConfigKeys1) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ if ((this.x != other.x))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeConfigKeys1);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.x);
+ return result;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys2.java b/test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys2.java
new file mode 100644
index 00000000..0245eae0
--- /dev/null
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeConfigKeys2.java
@@ -0,0 +1,73 @@
+@lombok.EqualsAndHashCode class EqualsAndHashCodeConfigKeys2Object extends Object {
+ EqualsAndHashCodeConfigKeys2Object() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeConfigKeys2Object)))
+ return false;
+ final EqualsAndHashCodeConfigKeys2Object other = (EqualsAndHashCodeConfigKeys2Object) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeConfigKeys2Object);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ int result = 1;
+ return result;
+ }
+}
+@lombok.EqualsAndHashCode class EqualsAndHashCodeConfigKeys2Parent {
+ EqualsAndHashCodeConfigKeys2Parent() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeConfigKeys2Parent)))
+ return false;
+ final EqualsAndHashCodeConfigKeys2Parent other = (EqualsAndHashCodeConfigKeys2Parent) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeConfigKeys2Parent);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ int result = 1;
+ return result;
+ }
+}
+@lombok.EqualsAndHashCode class EqualsAndHashCodeConfigKeys2 extends EqualsAndHashCodeConfigKeys2Parent {
+ int x;
+ EqualsAndHashCodeConfigKeys2() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeConfigKeys2)))
+ return false;
+ final EqualsAndHashCodeConfigKeys2 other = (EqualsAndHashCodeConfigKeys2) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ if ((! super.equals(o)))
+ return false;
+ if ((this.x != other.x))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeConfigKeys2);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = super.hashCode();
+ result = ((result * PRIME) + this.x);
+ return result;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeNestedShadow.java b/test/transform/resource/after-ecj/EqualsAndHashCodeNestedShadow.java
new file mode 100644
index 00000000..e08f523d
--- /dev/null
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeNestedShadow.java
@@ -0,0 +1,58 @@
+interface EqualsAndHashCodeNestedShadow {
+ interface Foo {
+ }
+ class Bar {
+ public static @lombok.EqualsAndHashCode(callSuper = false) class Foo extends Bar implements EqualsAndHashCodeNestedShadow.Foo {
+ public Foo() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeNestedShadow.Bar.Foo)))
+ return false;
+ final EqualsAndHashCodeNestedShadow.Bar.Foo other = (EqualsAndHashCodeNestedShadow.Bar.Foo) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeNestedShadow.Bar.Foo);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ int result = 1;
+ return result;
+ }
+ }
+ Bar() {
+ super();
+ }
+ }
+ class Baz {
+ public static @lombok.EqualsAndHashCode(callSuper = false) class Foo<T> extends Bar implements EqualsAndHashCodeNestedShadow.Foo {
+ public Foo() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeNestedShadow.Baz.Foo)))
+ return false;
+ final EqualsAndHashCodeNestedShadow.Baz.Foo<?> other = (EqualsAndHashCodeNestedShadow.Baz.Foo<?>) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeNestedShadow.Baz.Foo);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ int result = 1;
+ return result;
+ }
+ }
+ Baz() {
+ super();
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeOfAndExclude.java b/test/transform/resource/after-ecj/EqualsAndHashCodeOfAndExclude.java
new file mode 100644
index 00000000..8e93963a
--- /dev/null
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeOfAndExclude.java
@@ -0,0 +1,46 @@
+final @lombok.EqualsAndHashCode(of = {"x"}) class EqualsAndHashCodeOf {
+ int x;
+ int y;
+ EqualsAndHashCodeOf() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeOf)))
+ return false;
+ final EqualsAndHashCodeOf other = (EqualsAndHashCodeOf) o;
+ if ((this.x != other.x))
+ return false;
+ return true;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.x);
+ return result;
+ }
+}
+final @lombok.EqualsAndHashCode(exclude = {"y"}) class EqualsAndHashCodeExclude {
+ int x;
+ int y;
+ EqualsAndHashCodeExclude() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeExclude)))
+ return false;
+ final EqualsAndHashCodeExclude other = (EqualsAndHashCodeExclude) o;
+ if ((this.x != other.x))
+ return false;
+ return true;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.x);
+ return result;
+ }
+}
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeWithExistingMethods.java b/test/transform/resource/after-ecj/EqualsAndHashCodeWithExistingMethods.java
index feda33ce..cc0d6544 100644
--- a/test/transform/resource/after-ecj/EqualsAndHashCodeWithExistingMethods.java
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeWithExistingMethods.java
@@ -29,7 +29,7 @@ final @lombok.EqualsAndHashCode(callSuper = true) class EqualsAndHashCodeWithExi
return true;
if ((! (o instanceof EqualsAndHashCodeWithExistingMethods3)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCodeWithExistingMethods3 other = (EqualsAndHashCodeWithExistingMethods3) o;
+ final EqualsAndHashCodeWithExistingMethods3 other = (EqualsAndHashCodeWithExistingMethods3) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((! super.equals(o)))
@@ -40,8 +40,7 @@ final @lombok.EqualsAndHashCode(callSuper = true) class EqualsAndHashCodeWithExi
}
public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
final int PRIME = 59;
- int result = 1;
- result = ((result * PRIME) + super.hashCode());
+ int result = super.hashCode();
result = ((result * PRIME) + this.x);
return result;
}
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java
new file mode 100644
index 00000000..164d0f15
--- /dev/null
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeWithGenericsOnInners.java
@@ -0,0 +1,32 @@
+public class EqualsAndHashCodeWithGenericsOnInners<A> {
+ @lombok.EqualsAndHashCode class Inner<B> {
+ int x;
+ Inner() {
+ super();
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof EqualsAndHashCodeWithGenericsOnInners.Inner)))
+ return false;
+ final EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?> other = (EqualsAndHashCodeWithGenericsOnInners<?>.Inner<?>) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ if ((this.x != other.x))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof EqualsAndHashCodeWithGenericsOnInners.Inner);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = ((result * PRIME) + this.x);
+ return result;
+ }
+ }
+ public EqualsAndHashCodeWithGenericsOnInners() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeWithOnParam.java b/test/transform/resource/after-ecj/EqualsAndHashCodeWithOnParam.java
index fc226f06..d8af4c77 100644
--- a/test/transform/resource/after-ecj/EqualsAndHashCodeWithOnParam.java
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeWithOnParam.java
@@ -15,7 +15,7 @@
return true;
if ((! (o instanceof EqualsAndHashCodeWithOnParam)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCodeWithOnParam other = (EqualsAndHashCodeWithOnParam) o;
+ final EqualsAndHashCodeWithOnParam other = (EqualsAndHashCodeWithOnParam) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.x != other.x))
@@ -44,9 +44,9 @@
result = ((result * PRIME) + java.util.Arrays.hashCode(this.y));
result = ((result * PRIME) + java.util.Arrays.deepHashCode(this.z));
final java.lang.Object $a = this.a;
- result = ((result * PRIME) + (($a == null) ? 0 : $a.hashCode()));
+ result = ((result * PRIME) + (($a == null) ? 43 : $a.hashCode()));
final java.lang.Object $b = this.b;
- result = ((result * PRIME) + (($b == null) ? 0 : $b.hashCode()));
+ result = ((result * PRIME) + (($b == null) ? 43 : $b.hashCode()));
return result;
}
} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/EqualsAndHashCodeWithSomeExistingMethods.java b/test/transform/resource/after-ecj/EqualsAndHashCodeWithSomeExistingMethods.java
index ee846c64..781faccb 100644
--- a/test/transform/resource/after-ecj/EqualsAndHashCodeWithSomeExistingMethods.java
+++ b/test/transform/resource/after-ecj/EqualsAndHashCodeWithSomeExistingMethods.java
@@ -22,7 +22,7 @@ import static lombok.AccessLevel.NONE;
return true;
if ((! (o instanceof EqualsAndHashCodeWithSomeExistingMethods2)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCodeWithSomeExistingMethods2 other = (EqualsAndHashCodeWithSomeExistingMethods2) o;
+ final EqualsAndHashCodeWithSomeExistingMethods2 other = (EqualsAndHashCodeWithSomeExistingMethods2) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.x != other.x))
@@ -64,7 +64,7 @@ import static lombok.AccessLevel.NONE;
return true;
if ((! (o instanceof EqualsAndHashCodeWithNoExistingMethods)))
return false;
- final @java.lang.SuppressWarnings("all") EqualsAndHashCodeWithNoExistingMethods other = (EqualsAndHashCodeWithNoExistingMethods) o;
+ final EqualsAndHashCodeWithNoExistingMethods other = (EqualsAndHashCodeWithNoExistingMethods) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.x != other.x))
diff --git a/test/transform/resource/after-ecj/FieldDefaults.java b/test/transform/resource/after-ecj/FieldDefaults.java
index e76c1251..a6941b7b 100644
--- a/test/transform/resource/after-ecj/FieldDefaults.java
+++ b/test/transform/resource/after-ecj/FieldDefaults.java
@@ -1,14 +1,20 @@
@lombok.experimental.FieldDefaults(makeFinal = true) class FieldDefaults1 {
+ static int STATIC = 3;
final int x;
@lombok.experimental.NonFinal int y;
+ <clinit>() {
+ }
FieldDefaults1(int x) {
super();
this.x = x;
}
}
@lombok.experimental.FieldDefaults(level = lombok.AccessLevel.PRIVATE) class FieldDefaults2 {
+ static int STATIC = 3;
@lombok.experimental.PackagePrivate int x;
private int y;
+ <clinit>() {
+ }
FieldDefaults2() {
super();
}
diff --git a/test/transform/resource/after-ecj/FieldDefaultsViaConfig.java b/test/transform/resource/after-ecj/FieldDefaultsViaConfig.java
new file mode 100644
index 00000000..689d2601
--- /dev/null
+++ b/test/transform/resource/after-ecj/FieldDefaultsViaConfig.java
@@ -0,0 +1,15 @@
+class FieldDefaultsViaConfig1 {
+ private final int x;
+ private @lombok.experimental.NonFinal int y;
+ FieldDefaultsViaConfig1(int x) {
+ super();
+ this.x = x;
+ }
+}
+@lombok.experimental.FieldDefaults(level = lombok.AccessLevel.PROTECTED) class FieldDefaultsViaConfig2 {
+ final @lombok.experimental.PackagePrivate int x = 2;
+ protected final int y = 0;
+ FieldDefaultsViaConfig2() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/FieldDefaultsViaConfigAndRequiredArgsConstructor.java b/test/transform/resource/after-ecj/FieldDefaultsViaConfigAndRequiredArgsConstructor.java
new file mode 100644
index 00000000..02def41a
--- /dev/null
+++ b/test/transform/resource/after-ecj/FieldDefaultsViaConfigAndRequiredArgsConstructor.java
@@ -0,0 +1,7 @@
+@lombok.RequiredArgsConstructor class FieldDefaultsViaConfigAndRequiredArgsConstructor {
+ final int x;
+ public @java.lang.SuppressWarnings("all") FieldDefaultsViaConfigAndRequiredArgsConstructor(final int x) {
+ super();
+ this.x = x;
+ }
+}
diff --git a/test/transform/resource/after-ecj/GenerateSuppressFBWarnings.java b/test/transform/resource/after-ecj/GenerateSuppressFBWarnings.java
new file mode 100644
index 00000000..9cd996d5
--- /dev/null
+++ b/test/transform/resource/after-ecj/GenerateSuppressFBWarnings.java
@@ -0,0 +1,9 @@
+class GenerateSuppressFBWarnings {
+ @lombok.Getter int y;
+ GenerateSuppressFBWarnings() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") @edu.umd.cs.findbugs.annotations.SuppressFBWarnings(justification = "generated code") int getY() {
+ return this.y;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/GeneratedJavaxOff.java b/test/transform/resource/after-ecj/GeneratedJavaxOff.java
new file mode 100644
index 00000000..481e0ba9
--- /dev/null
+++ b/test/transform/resource/after-ecj/GeneratedJavaxOff.java
@@ -0,0 +1,9 @@
+class GeneratedJavaxOff {
+ @lombok.Getter int x;
+ GeneratedJavaxOff() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-ecj/GeneratedJavaxOnLombokOn.java b/test/transform/resource/after-ecj/GeneratedJavaxOnLombokOn.java
new file mode 100644
index 00000000..dc4537b9
--- /dev/null
+++ b/test/transform/resource/after-ecj/GeneratedJavaxOnLombokOn.java
@@ -0,0 +1,9 @@
+class GeneratedJavaxOnLombokOn {
+ @lombok.Getter int x;
+ GeneratedJavaxOnLombokOn() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") @lombok.Generated int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-ecj/GeneratedOff.java b/test/transform/resource/after-ecj/GeneratedOff.java
new file mode 100644
index 00000000..2644e42c
--- /dev/null
+++ b/test/transform/resource/after-ecj/GeneratedOff.java
@@ -0,0 +1,9 @@
+class GeneratedOff {
+ @lombok.Getter int x;
+ GeneratedOff() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-ecj/GeneratedOffJavaxOn.java b/test/transform/resource/after-ecj/GeneratedOffJavaxOn.java
new file mode 100644
index 00000000..c21b5379
--- /dev/null
+++ b/test/transform/resource/after-ecj/GeneratedOffJavaxOn.java
@@ -0,0 +1,9 @@
+class GeneratedOffJavaxOn {
+ @lombok.Getter int x;
+ GeneratedOffJavaxOn() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") @javax.annotation.Generated("lombok") int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-ecj/GeneratedOffLombokOn.java b/test/transform/resource/after-ecj/GeneratedOffLombokOn.java
new file mode 100644
index 00000000..4d215593
--- /dev/null
+++ b/test/transform/resource/after-ecj/GeneratedOffLombokOn.java
@@ -0,0 +1,9 @@
+class GeneratedOffLombokOn {
+ @lombok.Getter int x;
+ GeneratedOffLombokOn() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") @lombok.Generated int getX() {
+ return this.x;
+ }
+}
diff --git a/test/transform/resource/after-ecj/GetterLazyBoolean.java b/test/transform/resource/after-ecj/GetterLazyBoolean.java
index cd5bac20..174389e8 100644
--- a/test/transform/resource/after-ecj/GetterLazyBoolean.java
+++ b/test/transform/resource/after-ecj/GetterLazyBoolean.java
@@ -46,7 +46,7 @@
return true;
if ((! (o instanceof GetterLazyBoolean)))
return false;
- final @java.lang.SuppressWarnings("all") GetterLazyBoolean other = (GetterLazyBoolean) o;
+ final GetterLazyBoolean other = (GetterLazyBoolean) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.isBooleanValue() != other.isBooleanValue()))
diff --git a/test/transform/resource/after-ecj/GetterLazyEahcToString.java b/test/transform/resource/after-ecj/GetterLazyEahcToString.java
index df26f912..e66a9c2e 100644
--- a/test/transform/resource/after-ecj/GetterLazyEahcToString.java
+++ b/test/transform/resource/after-ecj/GetterLazyEahcToString.java
@@ -29,7 +29,7 @@
return true;
if ((! (o instanceof GetterLazyEahcToString)))
return false;
- final @java.lang.SuppressWarnings("all") GetterLazyEahcToString other = (GetterLazyEahcToString) o;
+ final GetterLazyEahcToString other = (GetterLazyEahcToString) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
final java.lang.Object this$value = this.getValue();
@@ -49,9 +49,9 @@
final int PRIME = 59;
int result = 1;
final java.lang.Object $value = this.getValue();
- result = ((result * PRIME) + (($value == null) ? 0 : $value.hashCode()));
+ result = ((result * PRIME) + (($value == null) ? 43 : $value.hashCode()));
final java.lang.Object $value2 = this.value2;
- result = ((result * PRIME) + (($value2 == null) ? 0 : $value2.hashCode()));
+ result = ((result * PRIME) + (($value2 == null) ? 43 : $value2.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
diff --git a/test/transform/resource/after-ecj/GetterLazyTransient.java b/test/transform/resource/after-ecj/GetterLazyTransient.java
new file mode 100644
index 00000000..3ffd9b69
--- /dev/null
+++ b/test/transform/resource/after-ecj/GetterLazyTransient.java
@@ -0,0 +1,28 @@
+class GetterLazyTransient {
+ private final @lombok.Getter(lazy = true) java.util.concurrent.atomic.AtomicReference<java.lang.Object> nonTransientField = new java.util.concurrent.atomic.AtomicReference<java.lang.Object>();
+ private final transient @lombok.Getter(lazy = true) int transientField = 2;
+ private final transient @lombok.Getter int nonLazyTransientField = 3;
+ GetterLazyTransient() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") int getNonTransientField() {
+ java.lang.Object value = this.nonTransientField.get();
+ if ((value == null))
+ {
+ synchronized (this.nonTransientField)
+ {
+ value = this.nonTransientField.get();
+ if ((value == null))
+ {
+ final int actualValue = 1;
+ value = actualValue;
+ this.nonTransientField.set(value);
+ }
+ }
+ }
+ return (java.lang.Integer) value;
+ }
+ public @java.lang.SuppressWarnings("all") int getNonLazyTransientField() {
+ return this.nonLazyTransientField;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/GetterSetterJavadoc.java b/test/transform/resource/after-ecj/GetterSetterJavadoc.java
index 9f3bb9bd..4923fd02 100644
--- a/test/transform/resource/after-ecj/GetterSetterJavadoc.java
+++ b/test/transform/resource/after-ecj/GetterSetterJavadoc.java
@@ -11,7 +11,7 @@
return true;
if ((! (o instanceof GetterSetterJavadoc1)))
return false;
- final @java.lang.SuppressWarnings("all") GetterSetterJavadoc1 other = (GetterSetterJavadoc1) o;
+ final GetterSetterJavadoc1 other = (GetterSetterJavadoc1) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getFieldName() != other.getFieldName()))
@@ -57,4 +57,30 @@ class GetterSetterJavadoc3 {
public @java.lang.SuppressWarnings("all") void setFieldName(final int fieldName) {
this.fieldName = fieldName;
}
+}
+@lombok.experimental.Accessors(chain = true,fluent = true) class GetterSetterJavadoc4 {
+ private @lombok.Getter @lombok.Setter int fieldName;
+ GetterSetterJavadoc4() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") int fieldName() {
+ return this.fieldName;
+ }
+ public @java.lang.SuppressWarnings("all") GetterSetterJavadoc4 fieldName(final int fieldName) {
+ this.fieldName = fieldName;
+ return this;
+ }
+}
+@lombok.experimental.Accessors(chain = true,fluent = true) class GetterSetterJavadoc5 {
+ private @lombok.Getter @lombok.Setter int fieldName;
+ GetterSetterJavadoc5() {
+ super();
+ }
+ public @java.lang.SuppressWarnings("all") int fieldName() {
+ return this.fieldName;
+ }
+ public @java.lang.SuppressWarnings("all") GetterSetterJavadoc5 fieldName(final int fieldName) {
+ this.fieldName = fieldName;
+ return this;
+ }
} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/Helper.java b/test/transform/resource/after-ecj/Helper.java
new file mode 100644
index 00000000..44c2a171
--- /dev/null
+++ b/test/transform/resource/after-ecj/Helper.java
@@ -0,0 +1,30 @@
+import lombok.experimental.Helper;
+class HelperTest {
+ {
+ final int z = 5;
+ if (Boolean.TRUE)
+ {
+ @Helper class H1 {
+ H1() {
+ super();
+ }
+ void foo(int x) {
+ System.out.println(("Hello, " + (x + z)));
+ }
+ }
+ final H1 $H1 = new H1();
+ $H1.foo(10);
+ @Helper class H2 {
+ H2() {
+ super();
+ }
+ void bar() {
+ $H1.foo(12);
+ }
+ }
+ }
+ }
+ HelperTest() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/InnerClass.java b/test/transform/resource/after-ecj/InnerClass.java
new file mode 100644
index 00000000..32004225
--- /dev/null
+++ b/test/transform/resource/after-ecj/InnerClass.java
@@ -0,0 +1,56 @@
+class A {
+ @lombok.AllArgsConstructor class B {
+ String s;
+ public @java.lang.SuppressWarnings("all") B(final String s) {
+ super();
+ this.s = s;
+ }
+ }
+ A() {
+ super();
+ }
+}
+class C {
+ final @lombok.Value class D {
+ private final A a;
+ A.B test(String s) {
+ return a.new B(s) {
+ x(<no type> $anonymous0) {
+ super($anonymous0);
+ }
+};
+ }
+ public @java.lang.SuppressWarnings("all") A getA() {
+ return this.a;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof C.D)))
+ return false;
+ final C.D other = (C.D) o;
+ final java.lang.Object this$a = this.getA();
+ final java.lang.Object other$a = other.getA();
+ if (((this$a == null) ? (other$a != null) : (! this$a.equals(other$a))))
+ return false;
+ return true;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final java.lang.Object $a = this.getA();
+ result = ((result * PRIME) + (($a == null) ? 43 : $a.hashCode()));
+ return result;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return (("C.D(a=" + this.getA()) + ")");
+ }
+ public @java.lang.SuppressWarnings("all") D(final A a) {
+ super();
+ this.a = a;
+ }
+ }
+ C() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/LoggerJBossLog.java b/test/transform/resource/after-ecj/LoggerJBossLog.java
new file mode 100644
index 00000000..e5c35708
--- /dev/null
+++ b/test/transform/resource/after-ecj/LoggerJBossLog.java
@@ -0,0 +1,38 @@
+import lombok.extern.jbosslog.JBossLog;
+@lombok.extern.jbosslog.JBossLog class LoggerJBossLog {
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLog.class);
+ <clinit>() {
+ }
+ LoggerJBossLog() {
+ super();
+ }
+}
+@JBossLog class LoggerJBossLogWithImport {
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(LoggerJBossLogWithImport.class);
+ <clinit>() {
+ }
+ LoggerJBossLogWithImport() {
+ super();
+ }
+}
+class LoggerJBossLogOuter {
+ static @lombok.extern.jbosslog.JBossLog class Inner {
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger(Inner.class);
+ <clinit>() {
+ }
+ Inner() {
+ super();
+ }
+ }
+ LoggerJBossLogOuter() {
+ super();
+ }
+}
+@JBossLog(topic = "DifferentLogger") class LoggerJBossLogWithDifferentLoggerName {
+ private static final org.jboss.logging.Logger log = org.jboss.logging.Logger.getLogger("DifferentLogger");
+ <clinit>() {
+ }
+ LoggerJBossLogWithDifferentLoggerName() {
+ super();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/LoggerSlf4jOnNonType.java b/test/transform/resource/after-ecj/LoggerSlf4jOnNonType.java
deleted file mode 100644
index f0c2ee58..00000000
--- a/test/transform/resource/after-ecj/LoggerSlf4jOnNonType.java
+++ /dev/null
@@ -1,7 +0,0 @@
-class LoggerSlf4jOnNonType {
- LoggerSlf4jOnNonType() {
- super();
- }
- @lombok.extern.slf4j.Slf4j void foo() {
- }
-} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/NoArgsConstructorForce.java b/test/transform/resource/after-ecj/NoArgsConstructorForce.java
new file mode 100644
index 00000000..850aa8a5
--- /dev/null
+++ b/test/transform/resource/after-ecj/NoArgsConstructorForce.java
@@ -0,0 +1,12 @@
+import lombok.NoArgsConstructor;
+public @NoArgsConstructor(force = true) class NoArgsConstructorForce {
+ private final int[] i;
+ private final Object[] o;
+ private final java.util.List<?>[] fullQualifiedList;
+ public @java.lang.SuppressWarnings("all") NoArgsConstructorForce() {
+ super();
+ this.i = null;
+ this.o = null;
+ this.fullQualifiedList = null;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/NonNullOnParameterOfDefaultMethod.java b/test/transform/resource/after-ecj/NonNullOnParameterOfDefaultMethod.java
new file mode 100644
index 00000000..85e99702
--- /dev/null
+++ b/test/transform/resource/after-ecj/NonNullOnParameterOfDefaultMethod.java
@@ -0,0 +1,10 @@
+interface NonNullOnParameterOfDefaultMethod {
+ void test(@lombok.NonNull String arg);
+ default void test2(@lombok.NonNull String arg) {
+ if ((arg == null))
+ {
+ throw new java.lang.NullPointerException("arg");
+ }
+ System.out.println(arg);
+ }
+}
diff --git a/test/transform/resource/after-ecj/NonNullPlain.java b/test/transform/resource/after-ecj/NonNullPlain.java
index 6e937f6a..9edb576b 100644
--- a/test/transform/resource/after-ecj/NonNullPlain.java
+++ b/test/transform/resource/after-ecj/NonNullPlain.java
@@ -5,7 +5,7 @@ import java.lang.annotation.*;
@lombok.NonNull int i;
@lombok.NonNull String s;
@NotNull Object o;
- public @java.beans.ConstructorProperties({"i", "s"}) @java.lang.SuppressWarnings("all") NonNullPlain(final @lombok.NonNull int i, final @lombok.NonNull String s) {
+ public @java.lang.SuppressWarnings("all") NonNullPlain(final @lombok.NonNull int i, final @lombok.NonNull String s) {
super();
if ((s == null))
{
diff --git a/test/transform/resource/after-ecj/OnXJava7Style.java b/test/transform/resource/after-ecj/OnXJava7Style.java
new file mode 100644
index 00000000..67f6e686
--- /dev/null
+++ b/test/transform/resource/after-ecj/OnXJava7Style.java
@@ -0,0 +1,31 @@
+public class OnXJava7Style {
+ @interface Foo {
+ String value() default "";
+ }
+ @interface Bar {
+ String stuff() default "";
+ }
+ @lombok.Getter() String a;
+ @lombok.Setter() String b;
+ @lombok.Setter() String c;
+ @lombok.Setter() String d;
+ @lombok.Getter() String e;
+ public OnXJava7Style() {
+ super();
+ }
+ public @Foo @java.lang.SuppressWarnings("all") String getA() {
+ return this.a;
+ }
+ public @Foo() @java.lang.SuppressWarnings("all") void setB(final String b) {
+ this.b = b;
+ }
+ public @java.lang.SuppressWarnings("all") void setC(final @Foo("a") String c) {
+ this.c = c;
+ }
+ public @java.lang.SuppressWarnings("all") void setD(final @Bar(stuff = "b") String d) {
+ this.d = d;
+ }
+ public @Foo(value = "c") @Bar(stuff = "d") @java.lang.SuppressWarnings("all") String getE() {
+ return this.e;
+ }
+}
diff --git a/test/transform/resource/after-ecj/OnXJava7StyleOn8.java b/test/transform/resource/after-ecj/OnXJava7StyleOn8.java
new file mode 100644
index 00000000..d3adca1c
--- /dev/null
+++ b/test/transform/resource/after-ecj/OnXJava7StyleOn8.java
@@ -0,0 +1,31 @@
+public class OnXJava7StyleOn8 {
+ @interface Foo {
+ String value() default "";
+ }
+ @interface Bar {
+ String stuff() default "";
+ }
+ @lombok.Getter() String a;
+ @lombok.Setter() String b;
+ @lombok.Setter() String c;
+ @lombok.Setter() String d;
+ @lombok.Getter() String e;
+ public OnXJava7StyleOn8() {
+ super();
+ }
+ public @Foo @java.lang.SuppressWarnings("all") String getA() {
+ return this.a;
+ }
+ public @Foo() @java.lang.SuppressWarnings("all") void setB(final String b) {
+ this.b = b;
+ }
+ public @java.lang.SuppressWarnings("all") void setC(final @Foo("a") String c) {
+ this.c = c;
+ }
+ public @java.lang.SuppressWarnings("all") void setD(final @Bar(stuff = "b") String d) {
+ this.d = d;
+ }
+ public @Foo(value = "c") @Bar(stuff = "d") @java.lang.SuppressWarnings("all") String getE() {
+ return this.e;
+ }
+}
diff --git a/test/transform/resource/after-ecj/OnXJava8Style.java b/test/transform/resource/after-ecj/OnXJava8Style.java
new file mode 100644
index 00000000..4e39460e
--- /dev/null
+++ b/test/transform/resource/after-ecj/OnXJava8Style.java
@@ -0,0 +1,31 @@
+public class OnXJava8Style {
+ @interface Foo {
+ String value() default "";
+ }
+ @interface Bar {
+ String stuff() default "";
+ }
+ @lombok.Getter() String a;
+ @lombok.Setter() String b;
+ @lombok.Setter() String c;
+ @lombok.Setter() String d;
+ @lombok.Getter() String e;
+ public OnXJava8Style() {
+ super();
+ }
+ public @Foo @java.lang.SuppressWarnings("all") String getA() {
+ return this.a;
+ }
+ public @Foo() @java.lang.SuppressWarnings("all") void setB(final String b) {
+ this.b = b;
+ }
+ public @java.lang.SuppressWarnings("all") void setC(final @Foo("a") String c) {
+ this.c = c;
+ }
+ public @java.lang.SuppressWarnings("all") void setD(final @Bar(stuff = "b") String d) {
+ this.d = d;
+ }
+ public @Foo(value = "c") @Bar(stuff = "d") @java.lang.SuppressWarnings("all") String getE() {
+ return this.e;
+ }
+}
diff --git a/test/transform/resource/after-ecj/OnXJava8StyleOn7.java b/test/transform/resource/after-ecj/OnXJava8StyleOn7.java
new file mode 100644
index 00000000..fca90ad7
--- /dev/null
+++ b/test/transform/resource/after-ecj/OnXJava8StyleOn7.java
@@ -0,0 +1,31 @@
+public class OnXJava8StyleOn7 {
+ @interface Foo {
+ String value() default "";
+ }
+ @interface Bar {
+ String stuff() default "";
+ }
+ @lombok.Getter() String a;
+ @lombok.Setter() String b;
+ @lombok.Setter() String c;
+ @lombok.Setter() String d;
+ @lombok.Getter() String e;
+ public OnXJava8StyleOn7() {
+ super();
+ }
+ public @Foo @java.lang.SuppressWarnings("all") String getA() {
+ return this.a;
+ }
+ public @Foo() @java.lang.SuppressWarnings("all") void setB(final String b) {
+ this.b = b;
+ }
+ public @java.lang.SuppressWarnings("all") void setC(final @Foo("a") String c) {
+ this.c = c;
+ }
+ public @java.lang.SuppressWarnings("all") void setD(final @Bar(stuff = "b") String d) {
+ this.d = d;
+ }
+ public @Foo(value = "c") @Bar(stuff = "d") @java.lang.SuppressWarnings("all") String getE() {
+ return this.e;
+ }
+}
diff --git a/test/transform/resource/after-ecj/Tolerate.java b/test/transform/resource/after-ecj/Tolerate.java
index b5039a98..1fe5fe4c 100644
--- a/test/transform/resource/after-ecj/Tolerate.java
+++ b/test/transform/resource/after-ecj/Tolerate.java
@@ -28,7 +28,7 @@ import java.util.regex.Pattern;
public @java.lang.SuppressWarnings("all") Tolerate2 withPattern(final Pattern pattern) {
return ((this.pattern == pattern) ? this : new Tolerate2(pattern));
}
- public @java.beans.ConstructorProperties({"pattern"}) @java.lang.SuppressWarnings("all") Tolerate2(final Pattern pattern) {
+ public @java.lang.SuppressWarnings("all") Tolerate2(final Pattern pattern) {
super();
this.pattern = pattern;
}
diff --git a/test/transform/resource/after-ecj/UtilityClass.java b/test/transform/resource/after-ecj/UtilityClass.java
new file mode 100644
index 00000000..656c0184
--- /dev/null
+++ b/test/transform/resource/after-ecj/UtilityClass.java
@@ -0,0 +1,66 @@
+final @lombok.experimental.UtilityClass class UtilityClass {
+ protected static class InnerClass {
+ private String innerInnerMember;
+ protected InnerClass() {
+ super();
+ }
+ }
+ private static long someField = System.currentTimeMillis();
+ <clinit>() {
+ }
+ static void someMethod() {
+ System.out.println();
+ }
+ private @java.lang.SuppressWarnings("all") UtilityClass() {
+ super();
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+}
+class UtilityInner {
+ static class InnerInner {
+ static final @lombok.experimental.UtilityClass class InnerInnerInner {
+ static int member;
+ <clinit>() {
+ }
+ private @java.lang.SuppressWarnings("all") InnerInnerInner() {
+ super();
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+ }
+ InnerInner() {
+ super();
+ }
+ }
+ enum UtilityInsideEnum {
+ static final @lombok.experimental.UtilityClass class InsideEnum {
+ static int member;
+ <clinit>() {
+ }
+ private @java.lang.SuppressWarnings("all") InsideEnum() {
+ super();
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+ }
+ FOO(),
+ BAR(),
+ <clinit>() {
+ }
+ UtilityInsideEnum() {
+ super();
+ }
+ }
+ interface UtilityInsideInterface {
+ final @lombok.experimental.UtilityClass class InsideInterface {
+ static int member;
+ <clinit>() {
+ }
+ private @java.lang.SuppressWarnings("all") InsideInterface() {
+ super();
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+ }
+ }
+ UtilityInner() {
+ super();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/UtilityClassErrors.java b/test/transform/resource/after-ecj/UtilityClassErrors.java
new file mode 100644
index 00000000..b5a51313
--- /dev/null
+++ b/test/transform/resource/after-ecj/UtilityClassErrors.java
@@ -0,0 +1,38 @@
+final @lombok.experimental.UtilityClass class UtilityClassErrors1 {
+ private static String someField;
+ <clinit>() {
+ }
+ protected UtilityClassErrors1() {
+ super();
+ }
+ static void method() {
+ @lombok.experimental.UtilityClass class MethodLocalClass {
+ MethodLocalClass() {
+ super();
+ }
+ }
+ }
+}
+@lombok.experimental.UtilityClass enum UtilityClassErrors2 {
+ <clinit>() {
+ }
+ UtilityClassErrors2() {
+ super();
+ }
+}
+class UtilityClassErrors3 {
+ class NonStaticInner {
+ @lombok.experimental.UtilityClass class ThisShouldFail {
+ private String member;
+ ThisShouldFail() {
+ super();
+ }
+ }
+ NonStaticInner() {
+ super();
+ }
+ }
+ UtilityClassErrors3() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java
new file mode 100644
index 00000000..989555fc
--- /dev/null
+++ b/test/transform/resource/after-ecj/ValAnonymousSubclassWithGenerics.java
@@ -0,0 +1,28 @@
+import java.util.*;
+import lombok.val;
+public class ValAnonymousSubclassWithGenerics {
+ Object object = new Object() {
+ x() {
+ super();
+ }
+ void foo() {
+ final @val int j = 1;
+ }
+ };
+ java.util.List<String> names = new java.util.ArrayList<String>() {
+ x() {
+ super();
+ }
+ public String get(int i) {
+ final @val java.lang.String result = super.get(i);
+ return result;
+ }
+ };
+ public ValAnonymousSubclassWithGenerics() {
+ super();
+ }
+ void bar() {
+ final @val int k = super.hashCode();
+ int x = k;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/ValFinal.java b/test/transform/resource/after-ecj/ValFinal.java
new file mode 100644
index 00000000..d7cf9cb7
--- /dev/null
+++ b/test/transform/resource/after-ecj/ValFinal.java
@@ -0,0 +1,9 @@
+import lombok.val;
+public class ValFinal {
+ public ValFinal() {
+ super();
+ }
+ public void test() {
+ final @val int x = 10;
+ }
+}
diff --git a/test/transform/resource/after-ecj/ValInLambda.java b/test/transform/resource/after-ecj/ValInLambda.java
new file mode 100644
index 00000000..7669789b
--- /dev/null
+++ b/test/transform/resource/after-ecj/ValInLambda.java
@@ -0,0 +1,21 @@
+// version 8:
+
+import lombok.val;
+class ValInLambda {
+ Runnable foo = (Runnable) () -> {
+ final @val int i = 1;
+};
+ ValInLambda() {
+ super();
+ }
+ public void easyLambda() {
+ Runnable foo = (Runnable) () -> {
+ final @val int i = 1;
+};
+ }
+ public void easyIntersectionLambda() {
+ Runnable foo = (Runnable) () -> {
+ final @val int i = 1;
+};
+ }
+}
diff --git a/test/transform/resource/after-ecj/ValNullInit.java b/test/transform/resource/after-ecj/ValNullInit.java
new file mode 100644
index 00000000..bd89c023
--- /dev/null
+++ b/test/transform/resource/after-ecj/ValNullInit.java
@@ -0,0 +1,10 @@
+import lombok.val;
+
+class ValNullInit {
+ ValNullInit() {
+ super();
+ }
+ void method() {
+ final @val java.lang.Object x = null;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/ValWithLocalClasses.java b/test/transform/resource/after-ecj/ValWithLocalClasses.java
new file mode 100644
index 00000000..59880acf
--- /dev/null
+++ b/test/transform/resource/after-ecj/ValWithLocalClasses.java
@@ -0,0 +1,20 @@
+class ValWithLocalClasses1 {
+ {
+ final @lombok.val ValWithLocalClasses2 f2 = new ValWithLocalClasses2() {
+ x() {
+ super();
+ }
+ };
+ }
+ ValWithLocalClasses1() {
+ super();
+ }
+}
+class ValWithLocalClasses2 {
+ {
+ final @lombok.val int f3 = 0;
+ }
+ ValWithLocalClasses2() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/ValueCallSuper.java b/test/transform/resource/after-ecj/ValueCallSuper.java
new file mode 100644
index 00000000..0c28b9b6
--- /dev/null
+++ b/test/transform/resource/after-ecj/ValueCallSuper.java
@@ -0,0 +1,32 @@
+class ValueParent {
+ ValueParent() {
+ super();
+ }
+}
+final @lombok.Value class ValueCallSuper extends ValueParent {
+ public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
+ if ((o == this))
+ return true;
+ if ((! (o instanceof ValueCallSuper)))
+ return false;
+ final ValueCallSuper other = (ValueCallSuper) o;
+ if ((! other.canEqual((java.lang.Object) this)))
+ return false;
+ if ((! super.equals(o)))
+ return false;
+ return true;
+ }
+ protected @java.lang.SuppressWarnings("all") boolean canEqual(final java.lang.Object other) {
+ return (other instanceof ValueCallSuper);
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
+ int result = super.hashCode();
+ return result;
+ }
+ public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
+ return "ValueCallSuper()";
+ }
+ public @java.lang.SuppressWarnings("all") ValueCallSuper() {
+ super();
+ }
+}
diff --git a/test/transform/resource/after-ecj/ValueExperimental.java b/test/transform/resource/after-ecj/ValueExperimental.java
deleted file mode 100644
index dd13574a..00000000
--- a/test/transform/resource/after-ecj/ValueExperimental.java
+++ /dev/null
@@ -1,39 +0,0 @@
-import lombok.experimental.Value;
-final @Value class ValueExperimental1 {
- public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
- if ((o == this))
- return true;
- if ((! (o instanceof ValueExperimental1)))
- return false;
- return true;
- }
- public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
- int result = 1;
- return result;
- }
- public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return "ValueExperimental1()";
- }
- public @java.lang.SuppressWarnings("all") ValueExperimental1() {
- super();
- }
-}
-final @lombok.experimental.Value class ValueExperimental2 {
- public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
- if ((o == this))
- return true;
- if ((! (o instanceof ValueExperimental2)))
- return false;
- return true;
- }
- public @java.lang.Override @java.lang.SuppressWarnings("all") int hashCode() {
- int result = 1;
- return result;
- }
- public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return "ValueExperimental2()";
- }
- public @java.lang.SuppressWarnings("all") ValueExperimental2() {
- super();
- }
-} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/ValuePlain.java b/test/transform/resource/after-ecj/ValuePlain.java
index 8162ab93..442a63ac 100644
--- a/test/transform/resource/after-ecj/ValuePlain.java
+++ b/test/transform/resource/after-ecj/ValuePlain.java
@@ -13,7 +13,7 @@ final @lombok.Value class Value1 {
return true;
if ((! (o instanceof Value1)))
return false;
- final @java.lang.SuppressWarnings("all") Value1 other = (Value1) o;
+ final Value1 other = (Value1) o;
if ((this.getX() != other.getX()))
return false;
final java.lang.Object this$name = this.getName();
@@ -27,13 +27,13 @@ final @lombok.Value class Value1 {
int result = 1;
result = ((result * PRIME) + this.getX());
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((("Value1(x=" + this.getX()) + ", name=") + this.getName()) + ")");
}
- public @java.beans.ConstructorProperties({"x", "name"}) @java.lang.SuppressWarnings("all") Value1(final int x, final String name) {
+ public @java.lang.SuppressWarnings("all") Value1(final int x, final String name) {
super();
this.x = x;
this.name = name;
@@ -53,7 +53,7 @@ final @lombok.Value class Value1 {
return true;
if ((! (o instanceof Value2)))
return false;
- final @java.lang.SuppressWarnings("all") Value2 other = (Value2) o;
+ final Value2 other = (Value2) o;
if ((! other.canEqual((java.lang.Object) this)))
return false;
if ((this.getX() != other.getX()))
@@ -72,13 +72,13 @@ final @lombok.Value class Value1 {
int result = 1;
result = ((result * PRIME) + this.getX());
final java.lang.Object $name = this.getName();
- result = ((result * PRIME) + (($name == null) ? 0 : $name.hashCode()));
+ result = ((result * PRIME) + (($name == null) ? 43 : $name.hashCode()));
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((("Value2(x=" + this.getX()) + ", name=") + this.getName()) + ")");
}
- public @java.beans.ConstructorProperties({"x", "name"}) @java.lang.SuppressWarnings("all") Value2(final int x, final String name) {
+ public @java.lang.SuppressWarnings("all") Value2(final int x, final String name) {
super();
this.x = x;
this.name = name;
@@ -98,7 +98,7 @@ final @Value class Value3 {
return true;
if ((! (o instanceof Value3)))
return false;
- final @java.lang.SuppressWarnings("all") Value3 other = (Value3) o;
+ final Value3 other = (Value3) o;
if ((this.getX() != other.getX()))
return false;
if ((this.getY() != other.getY()))
@@ -115,7 +115,7 @@ final @Value class Value3 {
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
return (((("Value3(x=" + this.getX()) + ", y=") + this.getY()) + ")");
}
- public @java.beans.ConstructorProperties({"x", "y"}) @java.lang.SuppressWarnings("all") Value3(final int x, final int y) {
+ public @java.lang.SuppressWarnings("all") Value3(final int x, final int y) {
super();
this.x = x;
this.y = y;
diff --git a/test/transform/resource/after-ecj/ValueExperimentalStarImport.java b/test/transform/resource/after-ecj/ValueStaticField.java
index b69e85d9..dd116fc7 100644
--- a/test/transform/resource/after-ecj/ValueExperimentalStarImport.java
+++ b/test/transform/resource/after-ecj/ValueStaticField.java
@@ -1,9 +1,13 @@
-import lombok.experimental.*;
-final @Value class ValueExperimentalStarImport {
+import lombok.Value;
+final @Value class ValueStaticField {
+ static int x;
+ static String PASSWORD = "Ken sent me";
+ <clinit>() {
+ }
public @java.lang.Override @java.lang.SuppressWarnings("all") boolean equals(final java.lang.Object o) {
if ((o == this))
return true;
- if ((! (o instanceof ValueExperimentalStarImport)))
+ if ((! (o instanceof ValueStaticField)))
return false;
return true;
}
@@ -12,9 +16,9 @@ final @Value class ValueExperimentalStarImport {
return result;
}
public @java.lang.Override @java.lang.SuppressWarnings("all") java.lang.String toString() {
- return "ValueExperimentalStarImport()";
+ return "ValueStaticField()";
}
- public @java.lang.SuppressWarnings("all") ValueExperimentalStarImport() {
+ public @java.lang.SuppressWarnings("all") ValueStaticField() {
super();
}
-}
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/VarComplex.java b/test/transform/resource/after-ecj/VarComplex.java
new file mode 100644
index 00000000..97a0a177
--- /dev/null
+++ b/test/transform/resource/after-ecj/VarComplex.java
@@ -0,0 +1,26 @@
+import lombok.var;
+public class VarComplex {
+ private String field = "";
+ private static final int CONSTANT = 20;
+ <clinit>() {
+ }
+ public VarComplex() {
+ super();
+ }
+ public void testComplex() {
+ @var char[] shouldBeCharArray = field.toCharArray();
+ @var int shouldBeInt = CONSTANT;
+ @var java.lang.Object lock = new Object();
+ synchronized (lock)
+ {
+ @var int field = 20;
+ @var int inner = 10;
+ switch (field) {
+ case 5 :
+ @var char[] shouldBeCharArray2 = shouldBeCharArray;
+ @var int innerInner = inner;
+ }
+ }
+ @var java.lang.String shouldBeString = field;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/VarInFor.java b/test/transform/resource/after-ecj/VarInFor.java
new file mode 100644
index 00000000..1799d9b7
--- /dev/null
+++ b/test/transform/resource/after-ecj/VarInFor.java
@@ -0,0 +1,14 @@
+import lombok.var;
+public class VarInFor {
+ public VarInFor() {
+ super();
+ }
+ public void enhancedFor() {
+ int[] list = new int[]{1, 2};
+ for (@var int shouldBeInt : list)
+ {
+ System.out.println(shouldBeInt);
+ @var int shouldBeInt2 = shouldBeInt;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/VarInForOld.java b/test/transform/resource/after-ecj/VarInForOld.java
new file mode 100644
index 00000000..065ea94d
--- /dev/null
+++ b/test/transform/resource/after-ecj/VarInForOld.java
@@ -0,0 +1,12 @@
+import lombok.var;
+public class VarInForOld {
+ public VarInForOld() {
+ super();
+ }
+ public void oldFor() {
+ for (@var int i = 0;; (i < 100); ++ i)
+ {
+ System.out.println(i);
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/VarModifier.java b/test/transform/resource/after-ecj/VarModifier.java
new file mode 100644
index 00000000..d11142ca
--- /dev/null
+++ b/test/transform/resource/after-ecj/VarModifier.java
@@ -0,0 +1,12 @@
+import lombok.experimental.var;
+public class VarModifier {
+ private String field = "";
+ public VarModifier() {
+ super();
+ }
+ public void testComplex() {
+ final @var char[] shouldBeFinalCharArray = field.toCharArray();
+ @var char[] shouldBeCharArray = field.toCharArray();
+
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/VarNullInit.java b/test/transform/resource/after-ecj/VarNullInit.java
new file mode 100644
index 00000000..848744cc
--- /dev/null
+++ b/test/transform/resource/after-ecj/VarNullInit.java
@@ -0,0 +1,9 @@
+import lombok.var;
+public class VarNullInit {
+ public VarNullInit() {
+ super();
+ }
+ void method() {
+ @var java.lang.Object x = null;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/VarWarning.java b/test/transform/resource/after-ecj/VarWarning.java
new file mode 100644
index 00000000..4caf90f8
--- /dev/null
+++ b/test/transform/resource/after-ecj/VarWarning.java
@@ -0,0 +1,10 @@
+import lombok.var;
+public class VarWarning {
+ public VarWarning() {
+ super();
+ }
+ public void isOkay() {
+ @var java.lang.String x = "Warning";
+ x.toLowerCase();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/after-ecj/WitherAndAllArgsConstructor.java b/test/transform/resource/after-ecj/WitherAndAllArgsConstructor.java
index 091024e2..10e993e1 100644
--- a/test/transform/resource/after-ecj/WitherAndAllArgsConstructor.java
+++ b/test/transform/resource/after-ecj/WitherAndAllArgsConstructor.java
@@ -10,7 +10,7 @@
public @java.lang.SuppressWarnings("all") WitherAndAllArgsConstructor<T, J, L> withTest2(final java.util.List<L> test2) {
return ((this.test2 == test2) ? this : new WitherAndAllArgsConstructor<T, J, L>(this.test, test2, this.y, this.z));
}
- public @java.beans.ConstructorProperties({"test", "test2", "y", "z"}) @java.lang.SuppressWarnings("all") WitherAndAllArgsConstructor(final J test, final java.util.List<L> test2, final int y, final int z) {
+ public @java.lang.SuppressWarnings("all") WitherAndAllArgsConstructor(final J test, final java.util.List<L> test2, final int y, final int z) {
super();
this.test = test;
this.test2 = test2;
diff --git a/test/transform/resource/after-ecj/WitherWithAbstract.java b/test/transform/resource/after-ecj/WitherWithAbstract.java
new file mode 100644
index 00000000..ed71347e
--- /dev/null
+++ b/test/transform/resource/after-ecj/WitherWithAbstract.java
@@ -0,0 +1,7 @@
+abstract class WitherWithAbstract {
+ @lombok.experimental.Wither String foo;
+ WitherWithAbstract() {
+ super();
+ }
+ public abstract @java.lang.SuppressWarnings("all") WitherWithAbstract withFoo(final String foo);
+}
diff --git a/test/transform/resource/before/BuilderChainAndFluent.java b/test/transform/resource/before/BuilderChainAndFluent.java
deleted file mode 100644
index 4d08741b..00000000
--- a/test/transform/resource/before/BuilderChainAndFluent.java
+++ /dev/null
@@ -1,4 +0,0 @@
-@lombok.experimental.Builder(fluent = false, chain = false)
-class BuilderChainAndFluent {
- private final int yes;
-}
diff --git a/test/transform/resource/before/BuilderComplex.java b/test/transform/resource/before/BuilderComplex.java
index 590a2723..c13f5877 100644
--- a/test/transform/resource/before/BuilderComplex.java
+++ b/test/transform/resource/before/BuilderComplex.java
@@ -1,5 +1,5 @@
import java.util.List;
-import lombok.experimental.Builder;
+import lombok.Builder;
class BuilderComplex {
@Builder(buildMethodName = "execute")
diff --git a/test/transform/resource/before/BuilderDefaults.java b/test/transform/resource/before/BuilderDefaults.java
new file mode 100644
index 00000000..a1ce14a5
--- /dev/null
+++ b/test/transform/resource/before/BuilderDefaults.java
@@ -0,0 +1,9 @@
+import lombok.Builder;
+import lombok.Value;
+
+@Value @Builder
+public class BuilderDefaults {
+ @Builder.Default int x = 10;
+ String name;
+ @Builder.Default long z = System.currentTimeMillis();
+}
diff --git a/test/transform/resource/before/BuilderDefaultsGenerics.java b/test/transform/resource/before/BuilderDefaultsGenerics.java
new file mode 100644
index 00000000..fffc9739
--- /dev/null
+++ b/test/transform/resource/before/BuilderDefaultsGenerics.java
@@ -0,0 +1,9 @@
+import lombok.Builder;
+import java.util.*;
+
+@Builder
+public class BuilderDefaultsGenerics<N extends Number, T, R extends List<T>> {
+ @Builder.Default private java.util.concurrent.Callable<N> callable = null;
+ @Builder.Default private T tee = null;
+ @Builder.Default private R arrr = null;
+}
diff --git a/test/transform/resource/before/BuilderDefaultsWarnings.java b/test/transform/resource/before/BuilderDefaultsWarnings.java
new file mode 100644
index 00000000..8ef3dc59
--- /dev/null
+++ b/test/transform/resource/before/BuilderDefaultsWarnings.java
@@ -0,0 +1,18 @@
+import lombok.Builder;
+import lombok.Singular;
+
+@Builder
+public class BuilderDefaultsWarnings {
+ long x = System.currentTimeMillis();
+ final int y = 5;
+ @Builder.Default int z;
+ @Builder.Default @Singular java.util.List<String> items;
+}
+
+class NoBuilderButHasDefaults {
+ @Builder.Default private final long z = 5;
+
+ @Builder
+ public NoBuilderButHasDefaults() {
+ }
+}
diff --git a/test/transform/resource/before/BuilderGenericMethod.java b/test/transform/resource/before/BuilderGenericMethod.java
new file mode 100644
index 00000000..63dcb4db
--- /dev/null
+++ b/test/transform/resource/before/BuilderGenericMethod.java
@@ -0,0 +1,11 @@
+import java.util.List;
+
+import lombok.Builder;
+import java.util.*;
+
+class BuilderGenericMethod<T> {
+ @Builder
+ public <N extends Number> Map<N,T> foo(int a, long b) {
+ return null;
+ }
+}
diff --git a/test/transform/resource/before/BuilderInstanceMethod.java b/test/transform/resource/before/BuilderInstanceMethod.java
new file mode 100644
index 00000000..666664a2
--- /dev/null
+++ b/test/transform/resource/before/BuilderInstanceMethod.java
@@ -0,0 +1,8 @@
+import java.util.List;
+
+class BuilderInstanceMethod<T> {
+ @lombok.Builder
+ public String create(int show, final int yes, List<T> also, int $andMe) {
+ return "" + show + yes + also + $andMe;
+ }
+}
diff --git a/test/transform/resource/before/BuilderInvalidUse.java b/test/transform/resource/before/BuilderInvalidUse.java
index d7052e1e..1a5f2950 100644
--- a/test/transform/resource/before/BuilderInvalidUse.java
+++ b/test/transform/resource/before/BuilderInvalidUse.java
@@ -1,5 +1,5 @@
//skip compare content
-@lombok.experimental.Builder
+@lombok.Builder
class BuilderInvalidUse {
private int something;
@@ -10,7 +10,7 @@ class BuilderInvalidUse {
}
}
-@lombok.experimental.Builder
+@lombok.Builder
class AlsoInvalid {
@lombok.Value
public static class AlsoInvalidBuilder {
diff --git a/test/transform/resource/before/BuilderSimple.java b/test/transform/resource/before/BuilderSimple.java
index c749bb6c..83c89713 100644
--- a/test/transform/resource/before/BuilderSimple.java
+++ b/test/transform/resource/before/BuilderSimple.java
@@ -1,6 +1,6 @@
import java.util.List;
-@lombok.experimental.Builder
+@lombok.Builder
class BuilderSimple<T> {
private final int noshow = 0;
private final int yes;
diff --git a/test/transform/resource/before/BuilderSingularGuavaListsSets.java b/test/transform/resource/before/BuilderSingularGuavaListsSets.java
new file mode 100644
index 00000000..73e8018c
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularGuavaListsSets.java
@@ -0,0 +1,16 @@
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableCollection;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+import com.google.common.collect.ImmutableTable;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularGuavaListsSets<T> {
+ @Singular private ImmutableList<T> cards;
+ @Singular private ImmutableCollection<? extends Number> frogs;
+ @SuppressWarnings("all") @Singular("rawSet") private ImmutableSet rawSet;
+ @Singular private ImmutableSortedSet<String> passes;
+ @Singular private ImmutableTable<? extends Number, ? extends Number, String> users;
+}
diff --git a/test/transform/resource/before/BuilderSingularGuavaMaps.java b/test/transform/resource/before/BuilderSingularGuavaMaps.java
new file mode 100644
index 00000000..64a53570
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularGuavaMaps.java
@@ -0,0 +1,12 @@
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableBiMap;
+import com.google.common.collect.ImmutableSortedMap;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularGuavaMaps<K, V> {
+ @Singular private ImmutableMap<K, V> battleaxes;
+ @Singular private ImmutableSortedMap<Integer, ? extends V> vertices;
+ @SuppressWarnings("all") @Singular("rawMap") private ImmutableBiMap rawMap;
+}
diff --git a/test/transform/resource/before/BuilderSingularLists.java b/test/transform/resource/before/BuilderSingularLists.java
new file mode 100644
index 00000000..93fced8e
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularLists.java
@@ -0,0 +1,11 @@
+import java.util.List;
+import java.util.Collection;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularLists<T> {
+ @Singular private List<T> children;
+ @Singular private Collection<? extends Number> scarves;
+ @SuppressWarnings("all") @Singular("rawList") private List rawList;
+}
diff --git a/test/transform/resource/before/BuilderSingularMaps.java b/test/transform/resource/before/BuilderSingularMaps.java
new file mode 100644
index 00000000..7fe1a149
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularMaps.java
@@ -0,0 +1,15 @@
+//FORMAT: javaLangAsFQN = skip
+//FORMAT: generated = skip
+//FORMAT: finalParams = skip
+import java.util.Map;
+import java.util.SortedMap;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularMaps<K, V> {
+ @Singular private Map<K, V> women;
+ @Singular private SortedMap<K, ? extends Number> men;
+ @SuppressWarnings("all") @Singular("rawMap") private Map rawMap;
+ @Singular("stringMap") private Map<String, V> stringMap;
+}
diff --git a/test/transform/resource/before/BuilderSingularNoAuto.java b/test/transform/resource/before/BuilderSingularNoAuto.java
new file mode 100644
index 00000000..f58c4075
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularNoAuto.java
@@ -0,0 +1,11 @@
+//CONF: lombok.singular.auto = false
+import java.util.List;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularNoAuto {
+ @Singular private List<String> things;
+ @Singular("widget") private List<String> widgets;
+ @Singular private List<String> items;
+}
diff --git a/test/transform/resource/before/BuilderSingularRedirectToGuava.java b/test/transform/resource/before/BuilderSingularRedirectToGuava.java
new file mode 100644
index 00000000..2dfa7684
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularRedirectToGuava.java
@@ -0,0 +1,13 @@
+//CONF: lombok.singular.useGuava = true
+import java.util.Set;
+import java.util.NavigableMap;
+import java.util.Collection;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularRedirectToGuava {
+ @Singular private Set<String> dangerMice;
+ @Singular private NavigableMap<Integer, Number> things;
+ @Singular private Collection<Class<?>> doohickeys;
+}
diff --git a/test/transform/resource/before/BuilderSingularSets.java b/test/transform/resource/before/BuilderSingularSets.java
new file mode 100644
index 00000000..68c4510a
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularSets.java
@@ -0,0 +1,12 @@
+import java.util.Set;
+import java.util.SortedSet;
+
+import lombok.Singular;
+
+@lombok.Builder
+class BuilderSingularSets<T> {
+ @Singular private Set<T> dangerMice;
+ @Singular private SortedSet<? extends Number> octopodes;
+ @SuppressWarnings("all") @Singular("rawSet") private Set rawSet;
+ @Singular("stringSet") private Set<String> stringSet;
+}
diff --git a/test/transform/resource/before/BuilderSingularWithPrefixes.java b/test/transform/resource/before/BuilderSingularWithPrefixes.java
new file mode 100644
index 00000000..32d3e438
--- /dev/null
+++ b/test/transform/resource/before/BuilderSingularWithPrefixes.java
@@ -0,0 +1,7 @@
+import lombok.Singular;
+
+@lombok.Builder
+@lombok.experimental.Accessors(prefix = "_")
+class BuilderSingularWithPrefixes {
+ @Singular private java.util.List<String> _elems;
+}
diff --git a/test/transform/resource/before/BuilderValueData.java b/test/transform/resource/before/BuilderValueData.java
new file mode 100644
index 00000000..da4da99a
--- /dev/null
+++ b/test/transform/resource/before/BuilderValueData.java
@@ -0,0 +1,11 @@
+import java.util.List;
+
+@lombok.Builder @lombok.Value
+class BuilderAndValue {
+ private final int zero = 0;
+}
+
+@lombok.Builder @lombok.Data
+class BuilderAndData {
+ private final int zero = 0;
+}
diff --git a/test/transform/resource/before/BuilderWithAccessors.java b/test/transform/resource/before/BuilderWithAccessors.java
index 4f5660a1..79546885 100644
--- a/test/transform/resource/before/BuilderWithAccessors.java
+++ b/test/transform/resource/before/BuilderWithAccessors.java
@@ -1,4 +1,4 @@
-@lombok.experimental.Builder @lombok.experimental.Accessors(prefix={"p", "_"})
+@lombok.Builder @lombok.experimental.Accessors(prefix={"p", "_"})
class BuilderWithAccessors {
private final int plower;
private final int pUpper;
diff --git a/test/transform/resource/before/BuilderWithDeprecated.java b/test/transform/resource/before/BuilderWithDeprecated.java
new file mode 100644
index 00000000..cd8ffad9
--- /dev/null
+++ b/test/transform/resource/before/BuilderWithDeprecated.java
@@ -0,0 +1,11 @@
+import com.google.common.collect.ImmutableList;
+import lombok.Builder;
+import lombok.Singular;
+
+@Builder
+public class BuilderWithDeprecated {
+ /** @deprecated */ String dep1;
+ @Deprecated int dep2;
+ @Singular @Deprecated java.util.List<String> strings;
+ @Singular @Deprecated ImmutableList<Integer> numbers;
+}
diff --git a/test/transform/resource/before/BuilderWithExistingBuilderClass.java b/test/transform/resource/before/BuilderWithExistingBuilderClass.java
index 262e3b85..c8e0a24b 100644
--- a/test/transform/resource/before/BuilderWithExistingBuilderClass.java
+++ b/test/transform/resource/before/BuilderWithExistingBuilderClass.java
@@ -1,4 +1,4 @@
-import lombok.experimental.Builder;
+import lombok.Builder;
class BuilderWithExistingBuilderClass<T, K extends Number> {
@Builder
diff --git a/test/transform/resource/before/BuilderWithRecursiveGenerics.java b/test/transform/resource/before/BuilderWithRecursiveGenerics.java
new file mode 100644
index 00000000..041da414
--- /dev/null
+++ b/test/transform/resource/before/BuilderWithRecursiveGenerics.java
@@ -0,0 +1,13 @@
+//issue #1298
+import java.util.Set;
+import lombok.Builder;
+import lombok.Value;
+
+public class BuilderWithRecursiveGenerics {
+ interface Inter<T, U extends Inter<T, U>> {}
+
+ @Builder @Value public static class Test<Foo, Bar extends Set<Foo>, Quz extends Inter<Bar, Quz>> {
+ Foo foo;
+ Bar bar;
+ }
+}
diff --git a/test/transform/resource/before/BuilderWithToBuilder.java b/test/transform/resource/before/BuilderWithToBuilder.java
new file mode 100644
index 00000000..63e16ae8
--- /dev/null
+++ b/test/transform/resource/before/BuilderWithToBuilder.java
@@ -0,0 +1,31 @@
+import java.util.List;
+import lombok.Builder;
+@Builder(toBuilder = true) @lombok.experimental.Accessors(prefix = "m")
+class BuilderWithToBuilder<T> {
+ private String mOne, mTwo;
+ @Builder.ObtainVia(method = "rrr", isStatic = true) private T foo;
+ @lombok.Singular private List<T> bars;
+ public static <K> K rrr(BuilderWithToBuilder<K> x) {
+ return x.foo;
+ }
+}
+@lombok.experimental.Accessors(prefix = "m")
+class ConstructorWithToBuilder<T> {
+ private String mOne, mTwo;
+ private T foo;
+ @lombok.Singular private List<T> bars;
+ @Builder(toBuilder = true)
+ public ConstructorWithToBuilder(String mOne, @Builder.ObtainVia(field = "foo") T bar) {
+ }
+}
+@lombok.experimental.Accessors(prefix = "m")
+class StaticWithToBuilder<T, K> {
+ private String mOne, mTwo;
+ private T foo;
+ private K bar;
+ @lombok.Singular private List<T> bars;
+ @Builder(toBuilder = true)
+ public static <Z> StaticWithToBuilder<Z, String> test(String mOne, @Builder.ObtainVia(field = "foo") Z bar) {
+ return new StaticWithToBuilder<Z, String>();
+ }
+}
diff --git a/test/transform/resource/before/BuilderWithTolerate.java b/test/transform/resource/before/BuilderWithTolerate.java
new file mode 100644
index 00000000..48fefce5
--- /dev/null
+++ b/test/transform/resource/before/BuilderWithTolerate.java
@@ -0,0 +1,18 @@
+import lombok.Builder;
+import lombok.experimental.Tolerate;
+
+@Builder
+public class BuilderWithTolerate {
+ private final int value;
+
+ public static void main(String[] args) {
+ BuilderWithTolerate.builder().value("42").build();
+ }
+
+ public static class BuilderWithTolerateBuilder {
+ @Tolerate
+ public BuilderWithTolerateBuilder value(String s) {
+ return this.value(Integer.parseInt(s));
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/Constructors.java b/test/transform/resource/before/Constructors.java
index c80acf2b..3569986f 100644
--- a/test/transform/resource/before/Constructors.java
+++ b/test/transform/resource/before/Constructors.java
@@ -32,4 +32,13 @@
}
@lombok.AllArgsConstructor(access=lombok.AccessLevel.PACKAGE) class AllArgsConstructorPackageAccess {
final String x;
-} \ No newline at end of file
+}
+@lombok.NoArgsConstructor(force = true) class NoArgsConstructor2 {
+ final int x;
+ final double y;
+ final char c;
+ final boolean b;
+ final float f;
+ final String s;
+ byte z;
+}
diff --git a/test/transform/resource/before/ConstructorsConfiguration.java b/test/transform/resource/before/ConstructorsConfiguration.java
index 8fae10fc..4d0e8bd9 100644
--- a/test/transform/resource/before/ConstructorsConfiguration.java
+++ b/test/transform/resource/before/ConstructorsConfiguration.java
@@ -3,7 +3,3 @@
class ConstructorsConfiguration {
int x;
}
-@lombok.AllArgsConstructor(suppressConstructorProperties=false)
-class ConstructorsConfigurationExplicit {
- int x;
-}
diff --git a/test/transform/resource/before/ConstructorsWithAccessors.java b/test/transform/resource/before/ConstructorsWithAccessors.java
index e5d2939f..e67a47ce 100644
--- a/test/transform/resource/before/ConstructorsWithAccessors.java
+++ b/test/transform/resource/before/ConstructorsWithAccessors.java
@@ -4,3 +4,11 @@
int _huh;
int __huh2;
}
+
+@lombok.AllArgsConstructor @lombok.experimental.Accessors(prefix={"p", "_"}) class ConstructorsWithAccessorsNonNull {
+ @lombok.NonNull Integer plower;
+ @lombok.NonNull Integer pUpper;
+ @lombok.NonNull Integer _huh;
+ @lombok.NonNull final Integer __huh2;
+}
+
diff --git a/test/transform/resource/before/DataConfiguration.java b/test/transform/resource/before/DataConfiguration.java
index 660d6d18..8b9657f9 100644
--- a/test/transform/resource/before/DataConfiguration.java
+++ b/test/transform/resource/before/DataConfiguration.java
@@ -1,4 +1,6 @@
//CONF: lombok.anyConstructor.suppressConstructorProperties = true
+//CONF: lombok.toString.doNotUseGetters = true
+//CONF: lombok.equalsAndHashCode.doNotUseGetters = true
@lombok.Data
class DataConfiguration {
final int x;
diff --git a/test/transform/resource/before/DelegateWithVarargs.java b/test/transform/resource/before/DelegateWithVarargs.java
new file mode 100644
index 00000000..0c266620
--- /dev/null
+++ b/test/transform/resource/before/DelegateWithVarargs.java
@@ -0,0 +1,12 @@
+import lombok.experimental.Delegate;
+
+class DelegateWithVarargs {
+ @Delegate private Bar bar;
+
+ private interface Bar {
+ void justOneParameter(int... varargs);
+ void multipleParameters(String first, int... varargs);
+ void array(int[] array);
+ void arrayVarargs(int[]... arrayVarargs);
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/EncodingUsAscii.java b/test/transform/resource/before/EncodingUsAscii.java
new file mode 100644
index 00000000..dbcd150b
--- /dev/null
+++ b/test/transform/resource/before/EncodingUsAscii.java
@@ -0,0 +1,5 @@
+//ENCODING: US-ASCII
+@lombok.ToString
+class EncodingUsAscii {
+ String foo\u0e51\u0e51 = "\u000e \10 ";
+} \ No newline at end of file
diff --git a/test/transform/resource/before/EncodingUtf8.java b/test/transform/resource/before/EncodingUtf8.java
new file mode 100644
index 00000000..75b0ee00
--- /dev/null
+++ b/test/transform/resource/before/EncodingUtf8.java
@@ -0,0 +1,5 @@
+//ENCODING: UTF-8
+@lombok.ToString
+class EncodingUtf8 {
+ String foo\u0e51๑ = "\u000e \10 ";
+} \ No newline at end of file
diff --git a/test/transform/resource/before/EqualsAndHashCodeConfigKeys1.java b/test/transform/resource/before/EqualsAndHashCodeConfigKeys1.java
new file mode 100644
index 00000000..38520d8f
--- /dev/null
+++ b/test/transform/resource/before/EqualsAndHashCodeConfigKeys1.java
@@ -0,0 +1,9 @@
+//CONF: lombok.equalsAndHashCode.callSuper = skip
+
+@lombok.EqualsAndHashCode
+class EqualsAndHashCodeConfigKeys1Parent {
+}
+@lombok.EqualsAndHashCode
+class EqualsAndHashCodeConfigKeys1 extends EqualsAndHashCodeConfigKeys1Parent {
+ int x;
+}
diff --git a/test/transform/resource/before/EqualsAndHashCodeConfigKeys2.java b/test/transform/resource/before/EqualsAndHashCodeConfigKeys2.java
new file mode 100644
index 00000000..08698184
--- /dev/null
+++ b/test/transform/resource/before/EqualsAndHashCodeConfigKeys2.java
@@ -0,0 +1,11 @@
+//CONF: lombok.equalsAndHashCode.callSuper = call
+@lombok.EqualsAndHashCode
+class EqualsAndHashCodeConfigKeys2Object extends Object {
+}
+@lombok.EqualsAndHashCode
+class EqualsAndHashCodeConfigKeys2Parent {
+}
+@lombok.EqualsAndHashCode
+class EqualsAndHashCodeConfigKeys2 extends EqualsAndHashCodeConfigKeys2Parent {
+ int x;
+}
diff --git a/test/transform/resource/before/EqualsAndHashCodeNestedShadow.java b/test/transform/resource/before/EqualsAndHashCodeNestedShadow.java
new file mode 100644
index 00000000..2b0c4fa3
--- /dev/null
+++ b/test/transform/resource/before/EqualsAndHashCodeNestedShadow.java
@@ -0,0 +1,15 @@
+interface EqualsAndHashCodeNestedShadow {
+ interface Foo {
+ }
+ class Bar {
+ @lombok.EqualsAndHashCode(callSuper=false)
+ public static class Foo extends Bar implements EqualsAndHashCodeNestedShadow.Foo {
+ }
+ }
+
+ class Baz {
+ @lombok.EqualsAndHashCode(callSuper=false)
+ public static class Foo<T> extends Bar implements EqualsAndHashCodeNestedShadow.Foo {
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/EqualsAndHashCodeOfAndExclude.java b/test/transform/resource/before/EqualsAndHashCodeOfAndExclude.java
new file mode 100644
index 00000000..b8ba21fb
--- /dev/null
+++ b/test/transform/resource/before/EqualsAndHashCodeOfAndExclude.java
@@ -0,0 +1,11 @@
+@lombok.EqualsAndHashCode(of={"x"})
+final class EqualsAndHashCodeOf {
+ int x;
+ int y;
+}
+
+@lombok.EqualsAndHashCode(exclude={"y"})
+final class EqualsAndHashCodeExclude {
+ int x;
+ int y;
+}
diff --git a/test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java b/test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java
new file mode 100644
index 00000000..7af1d054
--- /dev/null
+++ b/test/transform/resource/before/EqualsAndHashCodeWithGenericsOnInners.java
@@ -0,0 +1,6 @@
+public class EqualsAndHashCodeWithGenericsOnInners<A> {
+ @lombok.EqualsAndHashCode class Inner<B> {
+ int x;
+ }
+}
+
diff --git a/test/transform/resource/before/EqualsAndHashCodeWithSomeExistingMethods.java b/test/transform/resource/before/EqualsAndHashCodeWithSomeExistingMethods.java
index debe75b9..ec5ef7ad 100644
--- a/test/transform/resource/before/EqualsAndHashCodeWithSomeExistingMethods.java
+++ b/test/transform/resource/before/EqualsAndHashCodeWithSomeExistingMethods.java
@@ -1,3 +1,4 @@
+//CONF: lombok.addGeneratedAnnotation = false
import lombok.*;
import static lombok.AccessLevel.NONE;
diff --git a/test/transform/resource/before/FieldDefaults.java b/test/transform/resource/before/FieldDefaults.java
index ffe89734..97389411 100644
--- a/test/transform/resource/before/FieldDefaults.java
+++ b/test/transform/resource/before/FieldDefaults.java
@@ -1,5 +1,6 @@
@lombok.experimental.FieldDefaults(makeFinal = true)
class FieldDefaults1 {
+ static int STATIC = 3;
int x;
@lombok.experimental.NonFinal int y;
@@ -10,6 +11,7 @@ class FieldDefaults1 {
@lombok.experimental.FieldDefaults(level = lombok.AccessLevel.PRIVATE)
class FieldDefaults2 {
+ static int STATIC = 3;
@lombok.experimental.PackagePrivate int x;
int y;
} \ No newline at end of file
diff --git a/test/transform/resource/before/FieldDefaultsViaConfig.java b/test/transform/resource/before/FieldDefaultsViaConfig.java
new file mode 100644
index 00000000..61f6daca
--- /dev/null
+++ b/test/transform/resource/before/FieldDefaultsViaConfig.java
@@ -0,0 +1,16 @@
+//CONF: lombok.fieldDefaults.defaultFinal = true
+//CONF: lombok.fieldDefaults.defaultPrivate = true
+class FieldDefaultsViaConfig1 {
+ int x;
+ @lombok.experimental.NonFinal int y;
+
+ FieldDefaultsViaConfig1(int x) {
+ this.x = x;
+ }
+}
+
+@lombok.experimental.FieldDefaults(level = lombok.AccessLevel.PROTECTED)
+class FieldDefaultsViaConfig2 {
+ @lombok.experimental.PackagePrivate int x = 2;
+ int y = 0;
+}
diff --git a/test/transform/resource/before/FieldDefaultsViaConfigAndRequiredArgsConstructor.java b/test/transform/resource/before/FieldDefaultsViaConfigAndRequiredArgsConstructor.java
new file mode 100644
index 00000000..8c0607d7
--- /dev/null
+++ b/test/transform/resource/before/FieldDefaultsViaConfigAndRequiredArgsConstructor.java
@@ -0,0 +1,5 @@
+//CONF: lombok.fieldDefaults.defaultFinal = true
+@lombok.RequiredArgsConstructor
+class FieldDefaultsViaConfigAndRequiredArgsConstructor {
+ int x;
+}
diff --git a/test/transform/resource/before/GenerateSuppressFBWarnings.java b/test/transform/resource/before/GenerateSuppressFBWarnings.java
new file mode 100644
index 00000000..2ab9c744
--- /dev/null
+++ b/test/transform/resource/before/GenerateSuppressFBWarnings.java
@@ -0,0 +1,5 @@
+//VERSION 7:
+//CONF: lombok.extern.findbugs.addSuppressFBWarnings = true
+class GenerateSuppressFBWarnings {
+ @lombok.Getter int y;
+}
diff --git a/test/transform/resource/before/GeneratedJavaxOff.java b/test/transform/resource/before/GeneratedJavaxOff.java
new file mode 100644
index 00000000..db7ee0d1
--- /dev/null
+++ b/test/transform/resource/before/GeneratedJavaxOff.java
@@ -0,0 +1,5 @@
+//CONF: lombok.addJavaxGeneratedAnnotation = false
+class GeneratedJavaxOff {
+ @lombok.Getter
+ int x;
+}
diff --git a/test/transform/resource/before/GeneratedJavaxOnLombokOn.java b/test/transform/resource/before/GeneratedJavaxOnLombokOn.java
new file mode 100644
index 00000000..4eb86de1
--- /dev/null
+++ b/test/transform/resource/before/GeneratedJavaxOnLombokOn.java
@@ -0,0 +1,7 @@
+//CONF: lombok.addJavaxGeneratedAnnotation = true
+//CONF: lombok.addLombokGeneratedAnnotation = true
+//version :8
+class GeneratedJavaxOnLombokOn {
+ @lombok.Getter
+ int x;
+}
diff --git a/test/transform/resource/before/GeneratedOff.java b/test/transform/resource/before/GeneratedOff.java
new file mode 100644
index 00000000..7d62991b
--- /dev/null
+++ b/test/transform/resource/before/GeneratedOff.java
@@ -0,0 +1,5 @@
+//CONF: lombok.addGeneratedAnnotation = false
+class GeneratedOff {
+ @lombok.Getter
+ int x;
+}
diff --git a/test/transform/resource/before/GeneratedOffJavaxOn.java b/test/transform/resource/before/GeneratedOffJavaxOn.java
new file mode 100644
index 00000000..83c03eac
--- /dev/null
+++ b/test/transform/resource/before/GeneratedOffJavaxOn.java
@@ -0,0 +1,7 @@
+//CONF: lombok.addGeneratedAnnotation = false
+//CONF: lombok.addJavaxGeneratedAnnotation = true
+//version :8
+class GeneratedOffJavaxOn {
+ @lombok.Getter
+ int x;
+}
diff --git a/test/transform/resource/before/GeneratedOffLombokOn.java b/test/transform/resource/before/GeneratedOffLombokOn.java
new file mode 100644
index 00000000..9d122306
--- /dev/null
+++ b/test/transform/resource/before/GeneratedOffLombokOn.java
@@ -0,0 +1,6 @@
+//CONF: lombok.addGeneratedAnnotation = false
+//CONF: lombok.addLombokGeneratedAnnotation = true
+class GeneratedOffLombokOn {
+ @lombok.Getter
+ int x;
+}
diff --git a/test/transform/resource/before/GetterLazyTransient.java b/test/transform/resource/before/GetterLazyTransient.java
new file mode 100644
index 00000000..1a913669
--- /dev/null
+++ b/test/transform/resource/before/GetterLazyTransient.java
@@ -0,0 +1,10 @@
+class GetterLazyTransient {
+ @lombok.Getter(lazy=true)
+ private final int nonTransientField = 1;
+
+ @lombok.Getter(lazy=true)
+ private final transient int transientField = 2;
+
+ @lombok.Getter
+ private final transient int nonLazyTransientField = 3;
+}
diff --git a/test/transform/resource/before/GetterOnMethodErrors2.java b/test/transform/resource/before/GetterOnMethodErrors2.java
index 2fd98c83..08ef13c6 100644
--- a/test/transform/resource/before/GetterOnMethodErrors2.java
+++ b/test/transform/resource/before/GetterOnMethodErrors2.java
@@ -1,3 +1,4 @@
+//version 8:
class GetterOnMethodErrors2 {
@lombok.Getter(onMethod=@_A_(@Deprecated)) private int bad1;
@lombok.Getter(onMethod=@__(5)) private int bad2;
diff --git a/test/transform/resource/before/GetterSetterJavadoc.java b/test/transform/resource/before/GetterSetterJavadoc.java
index 0dc64092..2ad46f8d 100644
--- a/test/transform/resource/before/GetterSetterJavadoc.java
+++ b/test/transform/resource/before/GetterSetterJavadoc.java
@@ -35,3 +35,30 @@ class GetterSetterJavadoc3 {
*/
@lombok.Getter @lombok.Setter private int fieldName;
}
+
+@lombok.experimental.Accessors(chain = true, fluent = true)
+class GetterSetterJavadoc4 {
+ /**
+ * Some text
+ *
+ * @param fieldName Hello, World4
+ * @return Sky is blue4
+ */
+ @lombok.Getter @lombok.Setter private int fieldName;
+}
+
+@lombok.experimental.Accessors(chain = true, fluent = true)
+class GetterSetterJavadoc5 {
+ /**
+ * Some text
+ *
+ * **SETTER**
+ * Setter section
+ * @param fieldName Hello, World5
+ * @return Sky is blue5
+ * **GETTER**
+ * Getter section
+ * @return Sky is blue5
+ */
+ @lombok.Getter @lombok.Setter private int fieldName;
+}
diff --git a/test/transform/resource/before/Helper.java b/test/transform/resource/before/Helper.java
new file mode 100644
index 00000000..cec9c7ce
--- /dev/null
+++ b/test/transform/resource/before/Helper.java
@@ -0,0 +1,22 @@
+import lombok.experimental.Helper;
+
+class HelperTest {
+ {
+ final int z = 5;
+ if (Boolean.TRUE) {
+ @Helper class H1 {
+ void foo(int x) {
+ System.out.println("Hello, " + (x + z));
+ }
+ }
+
+ foo(10);
+
+ @Helper class H2 {
+ void bar() {
+ foo(12);
+ }
+ }
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/InnerClass.java b/test/transform/resource/before/InnerClass.java
new file mode 100644
index 00000000..ba020686
--- /dev/null
+++ b/test/transform/resource/before/InnerClass.java
@@ -0,0 +1,17 @@
+class A {
+ @lombok.AllArgsConstructor
+ class B {
+ String s;
+ }
+}
+
+class C {
+ @lombok.Value
+ class D {
+ A a;
+
+ A.B test(String s) {
+ return a.new B(s) {};
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/JavadocGenerally.java b/test/transform/resource/before/JavadocGenerally.java
index ee015acf..1df93385 100644
--- a/test/transform/resource/before/JavadocGenerally.java
+++ b/test/transform/resource/before/JavadocGenerally.java
@@ -1,3 +1,4 @@
+// unchanged
/**
* Doc on package
*/
@@ -10,6 +11,9 @@ package testPackage;
class JavadocGenerally {
/**
* Doc on field
+ * <pre>
+ * // code
+ * </pre>
*/
private int someField;
diff --git a/test/transform/resource/before/LoggerJBossLog.java b/test/transform/resource/before/LoggerJBossLog.java
new file mode 100644
index 00000000..fbd88177
--- /dev/null
+++ b/test/transform/resource/before/LoggerJBossLog.java
@@ -0,0 +1,20 @@
+import lombok.extern.jbosslog.JBossLog;
+
+@lombok.extern.jbosslog.JBossLog
+class LoggerJBossLog {
+}
+
+@JBossLog
+class LoggerJBossLogWithImport {
+}
+
+class LoggerJBossLogOuter {
+ @lombok.extern.jbosslog.JBossLog
+ static class Inner {
+
+ }
+}
+
+@JBossLog(topic="DifferentLogger")
+class LoggerJBossLogWithDifferentLoggerName {
+} \ No newline at end of file
diff --git a/test/transform/resource/before/NoArgsConstructorForce.java b/test/transform/resource/before/NoArgsConstructorForce.java
new file mode 100644
index 00000000..48df1a37
--- /dev/null
+++ b/test/transform/resource/before/NoArgsConstructorForce.java
@@ -0,0 +1,8 @@
+import lombok.NoArgsConstructor;
+
+@NoArgsConstructor(force = true)
+public class NoArgsConstructorForce {
+ private final int[] i;
+ private final Object[] o;
+ private final java.util.List<?>[] fullQualifiedList;
+} \ No newline at end of file
diff --git a/test/transform/resource/before/NonNullOnParameterOfDefaultMethod.java b/test/transform/resource/before/NonNullOnParameterOfDefaultMethod.java
new file mode 100644
index 00000000..ab343ef0
--- /dev/null
+++ b/test/transform/resource/before/NonNullOnParameterOfDefaultMethod.java
@@ -0,0 +1,7 @@
+// version 8:
+interface NonNullOnParameterOfDefaultMethod {
+ void test(@lombok.NonNull String arg);
+ default void test2(@lombok.NonNull String arg) {
+ System.out.println(arg);
+ }
+}
diff --git a/test/transform/resource/before/OnXJava7Style.java b/test/transform/resource/before/OnXJava7Style.java
new file mode 100644
index 00000000..6a3c35ff
--- /dev/null
+++ b/test/transform/resource/before/OnXJava7Style.java
@@ -0,0 +1,16 @@
+//version :7
+public class OnXJava7Style {
+ @interface Foo {
+ String value() default "";
+ }
+
+ @interface Bar {
+ String stuff() default "";
+ }
+
+ @lombok.Getter(onMethod=@__(@Foo)) String a;
+ @lombok.Setter(onMethod=@__(@Foo())) String b;
+ @lombok.Setter(onParam=@__(@Foo("a"))) String c;
+ @lombok.Setter(onParam=@__(@Bar(stuff="b"))) String d;
+ @lombok.Getter(onMethod=@__({@Foo(value="c"), @Bar(stuff="d")})) String e;
+}
diff --git a/test/transform/resource/before/OnXJava7StyleOn8.java b/test/transform/resource/before/OnXJava7StyleOn8.java
new file mode 100644
index 00000000..582fe6ce
--- /dev/null
+++ b/test/transform/resource/before/OnXJava7StyleOn8.java
@@ -0,0 +1,18 @@
+//platform ecj
+//version 8:
+
+public class OnXJava7StyleOn8 {
+ @interface Foo {
+ String value() default "";
+ }
+
+ @interface Bar {
+ String stuff() default "";
+ }
+
+ @lombok.Getter(onMethod=@__(@Foo)) String a;
+ @lombok.Setter(onMethod=@__(@Foo())) String b;
+ @lombok.Setter(onParam=@__(@Foo("a"))) String c;
+ @lombok.Setter(onParam=@__(@Bar(stuff="b"))) String d;
+ @lombok.Getter(onMethod=@__({@Foo(value="c"), @Bar(stuff="d")})) String e;
+}
diff --git a/test/transform/resource/before/OnXJava8Style.java b/test/transform/resource/before/OnXJava8Style.java
new file mode 100644
index 00000000..ffb91727
--- /dev/null
+++ b/test/transform/resource/before/OnXJava8Style.java
@@ -0,0 +1,16 @@
+//version 8:
+public class OnXJava8Style {
+ @interface Foo {
+ String value() default "";
+ }
+
+ @interface Bar {
+ String stuff() default "";
+ }
+
+ @lombok.Getter(onMethod_=@Foo) String a;
+ @lombok.Setter(onMethod_=@Foo()) String b;
+ @lombok.Setter(onParam_=@Foo("a")) String c;
+ @lombok.Setter(onParam_=@Bar(stuff="b")) String d;
+ @lombok.Getter(onMethod_={@Foo(value="c"), @Bar(stuff="d")}) String e;
+}
diff --git a/test/transform/resource/before/OnXJava8StyleOn7.java b/test/transform/resource/before/OnXJava8StyleOn7.java
new file mode 100644
index 00000000..c006e468
--- /dev/null
+++ b/test/transform/resource/before/OnXJava8StyleOn7.java
@@ -0,0 +1,18 @@
+//platform ecj
+//version :7
+
+public class OnXJava8StyleOn7 {
+ @interface Foo {
+ String value() default "";
+ }
+
+ @interface Bar {
+ String stuff() default "";
+ }
+
+ @lombok.Getter(onMethod_=@Foo) String a;
+ @lombok.Setter(onMethod_=@Foo()) String b;
+ @lombok.Setter(onParam_=@Foo("a")) String c;
+ @lombok.Setter(onParam_=@Bar(stuff="b")) String d;
+ @lombok.Getter(onMethod_={@Foo(value="c"), @Bar(stuff="d")}) String e;
+}
diff --git a/test/transform/resource/before/TestOperators.java b/test/transform/resource/before/TestOperators.java
index 566bedfc..de384122 100644
--- a/test/transform/resource/before/TestOperators.java
+++ b/test/transform/resource/before/TestOperators.java
@@ -1,3 +1,4 @@
+// unchanged
class TestOperators {
int x = 10;
public void test() {
diff --git a/test/transform/resource/before/TrickyTypeResolution2.java b/test/transform/resource/before/TrickyTypeResolution2.java
index 00f2ac39..6dfddee0 100644
--- a/test/transform/resource/before/TrickyTypeResolution2.java
+++ b/test/transform/resource/before/TrickyTypeResolution2.java
@@ -1,3 +1,4 @@
+// unchanged
import lombok.*;
class DoNothingDueToTopLevel {
void test() {
diff --git a/test/transform/resource/before/UtilityClass.java b/test/transform/resource/before/UtilityClass.java
new file mode 100644
index 00000000..016a166e
--- /dev/null
+++ b/test/transform/resource/before/UtilityClass.java
@@ -0,0 +1,37 @@
+@lombok.experimental.UtilityClass
+class UtilityClass {
+ private long someField = System.currentTimeMillis();
+
+ void someMethod() {
+ System.out.println();
+ }
+
+ protected class InnerClass {
+ private String innerInnerMember;
+ }
+}
+
+class UtilityInner {
+ static class InnerInner {
+ @lombok.experimental.UtilityClass
+ class InnerInnerInner {
+ int member;
+ }
+ }
+
+ enum UtilityInsideEnum {
+ FOO, BAR;
+
+ @lombok.experimental.UtilityClass
+ class InsideEnum {
+ int member;
+ }
+ }
+
+ interface UtilityInsideInterface {
+ @lombok.experimental.UtilityClass
+ class InsideInterface {
+ int member;
+ }
+ }
+}
diff --git a/test/transform/resource/before/UtilityClassErrors.java b/test/transform/resource/before/UtilityClassErrors.java
new file mode 100644
index 00000000..d750e2bd
--- /dev/null
+++ b/test/transform/resource/before/UtilityClassErrors.java
@@ -0,0 +1,22 @@
+@lombok.experimental.UtilityClass
+class UtilityClassErrors1 {
+ private String someField;
+ protected UtilityClassErrors1() {
+ }
+ void method() {
+ @lombok.experimental.UtilityClass
+ class MethodLocalClass {
+ }
+ }
+}
+@lombok.experimental.UtilityClass
+enum UtilityClassErrors2 {
+}
+class UtilityClassErrors3 {
+ class NonStaticInner {
+ @lombok.experimental.UtilityClass
+ class ThisShouldFail {
+ private String member;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java
index 49fc86e0..c0f8157a 100644
--- a/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java
+++ b/test/transform/resource/before/ValAnonymousSubclassWithGenerics.java
@@ -1,4 +1,4 @@
-// ignore
+// issue 205: val inside anonymous inner classes is a bit tricky in javac, this test ensures we don't break it.
import java.util.*;
import lombok.val;
diff --git a/test/transform/resource/before/ValErrors.java b/test/transform/resource/before/ValErrors.java
index 96181638..87383719 100644
--- a/test/transform/resource/before/ValErrors.java
+++ b/test/transform/resource/before/ValErrors.java
@@ -1,3 +1,4 @@
+// unchanged
import lombok.val;
public class ValErrors {
diff --git a/test/transform/resource/before/ValFinal.java b/test/transform/resource/before/ValFinal.java
new file mode 100644
index 00000000..3c5af366
--- /dev/null
+++ b/test/transform/resource/before/ValFinal.java
@@ -0,0 +1,6 @@
+import lombok.val;
+public class ValFinal {
+ public void test() {
+ final val x = 10;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/ValInBasicFor.java b/test/transform/resource/before/ValInBasicFor.java
index 1f132b8f..a109bcd3 100644
--- a/test/transform/resource/before/ValInBasicFor.java
+++ b/test/transform/resource/before/ValInBasicFor.java
@@ -1,3 +1,4 @@
+// unchanged
import lombok.val;
public class ValInBasicFor {
diff --git a/test/transform/resource/before/ValInLambda.java b/test/transform/resource/before/ValInLambda.java
new file mode 100644
index 00000000..2c2a5942
--- /dev/null
+++ b/test/transform/resource/before/ValInLambda.java
@@ -0,0 +1,21 @@
+// version 8:
+
+import lombok.val;
+
+class ValInLambda {
+ Runnable foo = (Runnable) () -> {
+ val i = 1;
+ };
+
+ public void easyLambda() {
+ Runnable foo = (Runnable) () -> {
+ val i = 1;
+ };
+ }
+
+ public void easyIntersectionLambda() {
+ Runnable foo = (Runnable) () -> {
+ val i = 1;
+ };
+ }
+}
diff --git a/test/transform/resource/before/ValLambda.java b/test/transform/resource/before/ValLambda.java
index ed843ed7..51c4fba1 100644
--- a/test/transform/resource/before/ValLambda.java
+++ b/test/transform/resource/before/ValLambda.java
@@ -14,7 +14,7 @@ class ValLambda {
}
// public void castLubLambda() {
-// Runnable foo = (Runnable)((System.currentTimeMillis() > 0) ? ()-> {} : System.out::println);
-// lombok.val foo = (Runnable)((System.currentTimeMillis() > 0) ? ()-> {} : System.out::println);
+// Runnable foo = (Runnable) ((System.currentTimeMillis() > 0) ? () -> {} : System.out::println);
+// lombok.val foo = (Runnable) ((System.currentTimeMillis() > 0) ? () -> {} : System.out::println);
// }
}
diff --git a/test/transform/resource/before/ValNullInit.java b/test/transform/resource/before/ValNullInit.java
new file mode 100644
index 00000000..649bc0cd
--- /dev/null
+++ b/test/transform/resource/before/ValNullInit.java
@@ -0,0 +1,7 @@
+import lombok.val;
+
+class ValNullInit {
+ void method() {
+ val x = null;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/ValWithLocalClasses.java b/test/transform/resource/before/ValWithLocalClasses.java
new file mode 100644
index 00000000..572a1e7d
--- /dev/null
+++ b/test/transform/resource/before/ValWithLocalClasses.java
@@ -0,0 +1,12 @@
+//issue 694: In javac, resolving the RHS (which is what val does) can cause an entire class to be resolved, breaking all usage of val inside that class. This tests that we handle that better.
+class ValWithLocalClasses1 {
+ {
+ lombok.val f2 = new ValWithLocalClasses2() {};
+ }
+}
+
+class ValWithLocalClasses2 {
+ {
+ lombok.val f3 = 0;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/ValueCallSuper.java b/test/transform/resource/before/ValueCallSuper.java
new file mode 100644
index 00000000..e236b404
--- /dev/null
+++ b/test/transform/resource/before/ValueCallSuper.java
@@ -0,0 +1,7 @@
+//CONF: lombok.equalsAndHashCode.callSuper = call
+
+class ValueParent {
+}
+@lombok.Value
+class ValueCallSuper extends ValueParent {
+}
diff --git a/test/transform/resource/before/ValueExperimental.java b/test/transform/resource/before/ValueExperimental.java
deleted file mode 100644
index 6bae26a0..00000000
--- a/test/transform/resource/before/ValueExperimental.java
+++ /dev/null
@@ -1,9 +0,0 @@
-import lombok.experimental.Value;
-
-@Value
-class ValueExperimental1 {
-}
-
-@lombok.experimental.Value
-class ValueExperimental2 {
-} \ No newline at end of file
diff --git a/test/transform/resource/before/ValueExperimentalStarImport.java b/test/transform/resource/before/ValueExperimentalStarImport.java
deleted file mode 100644
index 5f18cffe..00000000
--- a/test/transform/resource/before/ValueExperimentalStarImport.java
+++ /dev/null
@@ -1,5 +0,0 @@
-import lombok.experimental.*;
-
-@Value
-class ValueExperimentalStarImport {
-} \ No newline at end of file
diff --git a/test/transform/resource/before/ValueStaticField.java b/test/transform/resource/before/ValueStaticField.java
new file mode 100644
index 00000000..f731758a
--- /dev/null
+++ b/test/transform/resource/before/ValueStaticField.java
@@ -0,0 +1,5 @@
+import lombok.Value;
+@Value class ValueStaticField {
+ static int x;
+ static String PASSWORD = "Ken sent me";
+}
diff --git a/test/transform/resource/before/VarComplex.java b/test/transform/resource/before/VarComplex.java
new file mode 100644
index 00000000..c93e177a
--- /dev/null
+++ b/test/transform/resource/before/VarComplex.java
@@ -0,0 +1,22 @@
+import lombok.var;
+
+public class VarComplex {
+ private String field = "";
+ private static final int CONSTANT = 20;
+
+ public void testComplex() {
+ var shouldBeCharArray = field.toCharArray();
+ var shouldBeInt = CONSTANT;
+ var lock = new Object();
+ synchronized (lock) {
+ var field = 20; //Shadowing
+ var inner = 10;
+ switch (field) {
+ case 5:
+ var shouldBeCharArray2 = shouldBeCharArray;
+ var innerInner = inner;
+ }
+ }
+ var shouldBeString = field; //Unshadowing
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/VarInFor.java b/test/transform/resource/before/VarInFor.java
new file mode 100644
index 00000000..7f7bb7a7
--- /dev/null
+++ b/test/transform/resource/before/VarInFor.java
@@ -0,0 +1,11 @@
+import lombok.var;
+
+public class VarInFor {
+ public void enhancedFor() {
+ int[] list = new int[] {1, 2};
+ for (var shouldBeInt : list) {
+ System.out.println(shouldBeInt);
+ var shouldBeInt2 = shouldBeInt;
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/VarInForOld.java b/test/transform/resource/before/VarInForOld.java
new file mode 100644
index 00000000..99e83b57
--- /dev/null
+++ b/test/transform/resource/before/VarInForOld.java
@@ -0,0 +1,9 @@
+import lombok.var;
+
+public class VarInForOld {
+ public void oldFor() {
+ for (var i = 0; i < 100; ++i) {
+ System.out.println(i);
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/VarInForOldMulti.java b/test/transform/resource/before/VarInForOldMulti.java
new file mode 100644
index 00000000..e2ea9682
--- /dev/null
+++ b/test/transform/resource/before/VarInForOldMulti.java
@@ -0,0 +1,10 @@
+//skip compare contents
+import lombok.var;
+
+public class VarInForOldMulti {
+ public void oldForMulti() {
+ for (var i = 0, j = "Hey"; i < 100; ++i) {
+ System.out.println(i);
+ }
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/VarModifier.java b/test/transform/resource/before/VarModifier.java
new file mode 100644
index 00000000..5c68caa7
--- /dev/null
+++ b/test/transform/resource/before/VarModifier.java
@@ -0,0 +1,10 @@
+import lombok.experimental.var;
+
+public class VarModifier {
+ private String field = "";
+
+ public void testComplex() {
+ final var shouldBeFinalCharArray = field.toCharArray();
+ var shouldBeCharArray = field.toCharArray();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/VarNullInit.java b/test/transform/resource/before/VarNullInit.java
new file mode 100644
index 00000000..f9bb53a3
--- /dev/null
+++ b/test/transform/resource/before/VarNullInit.java
@@ -0,0 +1,7 @@
+import lombok.var;
+
+public class VarNullInit {
+ void method() {
+ var x = null;
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/VarWarning.java b/test/transform/resource/before/VarWarning.java
new file mode 100644
index 00000000..90464d30
--- /dev/null
+++ b/test/transform/resource/before/VarWarning.java
@@ -0,0 +1,9 @@
+//CONF: lombok.var.flagUsage = WARNING
+import lombok.var;
+
+public class VarWarning {
+ public void isOkay() {
+ var x = "Warning";
+ x.toLowerCase();
+ }
+} \ No newline at end of file
diff --git a/test/transform/resource/before/WithInnerAnnotation.java b/test/transform/resource/before/WithInnerAnnotation.java
index a8decfeb..dca1f269 100644
--- a/test/transform/resource/before/WithInnerAnnotation.java
+++ b/test/transform/resource/before/WithInnerAnnotation.java
@@ -1,3 +1,4 @@
+// unchanged
class WithInnerAnnotation {
@interface Inner {
int bar() default 42;
diff --git a/test/transform/resource/before/WitherWithAbstract.java b/test/transform/resource/before/WitherWithAbstract.java
new file mode 100644
index 00000000..acc9094b
--- /dev/null
+++ b/test/transform/resource/before/WitherWithAbstract.java
@@ -0,0 +1,3 @@
+abstract class WitherWithAbstract {
+ @lombok.experimental.Wither String foo;
+} \ No newline at end of file
diff --git a/test/transform/resource/messages-delombok/BuilderDefaultsWarnings.java.messages b/test/transform/resource/messages-delombok/BuilderDefaultsWarnings.java.messages
new file mode 100644
index 00000000..694511f8
--- /dev/null
+++ b/test/transform/resource/messages-delombok/BuilderDefaultsWarnings.java.messages
@@ -0,0 +1,4 @@
+13 @Builder.Default requires @Builder on the class for it to mean anything.
+6 @Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.
+8 @Builder.Default requires an initializing expression (' = something;').
+9 @Builder.Default and @Singular cannot be mixed.
diff --git a/test/transform/resource/messages-delombok/BuilderSingularNoAuto.java.messages b/test/transform/resource/messages-delombok/BuilderSingularNoAuto.java.messages
new file mode 100644
index 00000000..8719789b
--- /dev/null
+++ b/test/transform/resource/messages-delombok/BuilderSingularNoAuto.java.messages
@@ -0,0 +1,2 @@
+8 The singular must be specified explicitly (e.g. @Singular("task")) because auto singularization is disabled.
+10 The singular must be specified explicitly (e.g. @Singular("task")) because auto singularization is disabled.
diff --git a/test/transform/resource/messages-delombok/EqualsAndHashCodeWithSomeExistingMethods.java.messages b/test/transform/resource/messages-delombok/EqualsAndHashCodeWithSomeExistingMethods.java.messages
index d3119bd6..d8c064a0 100644
--- a/test/transform/resource/messages-delombok/EqualsAndHashCodeWithSomeExistingMethods.java.messages
+++ b/test/transform/resource/messages-delombok/EqualsAndHashCodeWithSomeExistingMethods.java.messages
@@ -1 +1 @@
-4 Not generating equals: One of equals or hashCode exists. You should either write both of these or none of these (in the latter case, lombok generates them).
+5 Not generating equals: One of equals or hashCode exists. You should either write both of these or none of these (in the latter case, lombok generates them).
diff --git a/test/transform/resource/messages-delombok/GetterLazyTransient.java.messages b/test/transform/resource/messages-delombok/GetterLazyTransient.java.messages
new file mode 100644
index 00000000..8c1873eb
--- /dev/null
+++ b/test/transform/resource/messages-delombok/GetterLazyTransient.java.messages
@@ -0,0 +1 @@
+5 'lazy' is not supported on transient fields. \ No newline at end of file
diff --git a/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages b/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages
index 53a9b9ad..3386b565 100644
--- a/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages
+++ b/test/transform/resource/messages-delombok/GetterOnMethodErrors2.java.messages
@@ -1,4 +1,4 @@
-2 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
-3 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
-4 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
-5 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
+3 The correct format is
+4 The correct format is
+5 The correct format is
+6 The correct format is
diff --git a/test/transform/resource/messages-delombok/Helper.java.messages b/test/transform/resource/messages-delombok/Helper.java.messages
new file mode 100644
index 00000000..bf780b03
--- /dev/null
+++ b/test/transform/resource/messages-delombok/Helper.java.messages
@@ -0,0 +1 @@
+15 No methods of this helper class are ever used. \ No newline at end of file
diff --git a/test/transform/resource/messages-delombok/NonNullOnParameterAbstract.java.messages b/test/transform/resource/messages-delombok/NonNullOnParameterAbstract.java.messages
deleted file mode 100644
index fd5bffd5..00000000
--- a/test/transform/resource/messages-delombok/NonNullOnParameterAbstract.java.messages
+++ /dev/null
@@ -1 +0,0 @@
-6 @NonNull is meaningless on a parameter of an abstract method.
diff --git a/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages b/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages
new file mode 100644
index 00000000..4afa12ec
--- /dev/null
+++ b/test/transform/resource/messages-delombok/UtilityClassErrors.java.messages
@@ -0,0 +1,4 @@
+4 @UtilityClasses cannot have declared constructors.
+7 @UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class.
+12 @UtilityClass is only supported on a class (can't be an interface, enum, or annotation).
+17 @UtilityClass automatically makes the class static, however, this class cannot be made static. \ No newline at end of file
diff --git a/test/transform/resource/messages-delombok/ValErrors.java.messages b/test/transform/resource/messages-delombok/ValErrors.java.messages
index bb33c6de..0777143b 100644
--- a/test/transform/resource/messages-delombok/ValErrors.java.messages
+++ b/test/transform/resource/messages-delombok/ValErrors.java.messages
@@ -1,2 +1,2 @@
-5 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved
-9 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })
+6 Cannot use 'val' here because initializer expression does not have a representable type: Type cannot be resolved
+10 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })
diff --git a/test/transform/resource/messages-delombok/ValInBasicFor.java.messages b/test/transform/resource/messages-delombok/ValInBasicFor.java.messages
index 7166b550..60f8f70c 100644
--- a/test/transform/resource/messages-delombok/ValInBasicFor.java.messages
+++ b/test/transform/resource/messages-delombok/ValInBasicFor.java.messages
@@ -1 +1 @@
-6 'val' is not allowed in old-style for loops
+7 'val' is not allowed in old-style for loops
diff --git a/test/transform/resource/messages-delombok/VarInForOldMulti.java.messages b/test/transform/resource/messages-delombok/VarInForOldMulti.java.messages
new file mode 100644
index 00000000..f65fe823
--- /dev/null
+++ b/test/transform/resource/messages-delombok/VarInForOldMulti.java.messages
@@ -0,0 +1 @@
+6 'var' is not allowed in old-style for loops if there is more than 1 initializer
diff --git a/test/transform/resource/messages-delombok/VarNullInit.java.messages b/test/transform/resource/messages-delombok/VarNullInit.java.messages
new file mode 100644
index 00000000..5a2a6ae1
--- /dev/null
+++ b/test/transform/resource/messages-delombok/VarNullInit.java.messages
@@ -0,0 +1 @@
+5 variable initializer is 'null' \ No newline at end of file
diff --git a/test/transform/resource/messages-delombok/VarWarning.java.messages b/test/transform/resource/messages-delombok/VarWarning.java.messages
new file mode 100644
index 00000000..886e98f4
--- /dev/null
+++ b/test/transform/resource/messages-delombok/VarWarning.java.messages
@@ -0,0 +1 @@
+6 Use of var is flagged according to lombok configuration \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/BuilderDefaultsWarnings.java.messages b/test/transform/resource/messages-ecj/BuilderDefaultsWarnings.java.messages
new file mode 100644
index 00000000..f64aa5d5
--- /dev/null
+++ b/test/transform/resource/messages-ecj/BuilderDefaultsWarnings.java.messages
@@ -0,0 +1,5 @@
+6 @Builder will ignore the initializing expression entirely. If you want the initializing expression to serve as default, add @Builder.Default. If it is not supposed to be settable during building, make the field final.
+8 @Builder.Default requires an initializing expression (' = something;').
+9 @Builder.Default and @Singular cannot be mixed.
+13 @Builder.Default requires @Builder on the class for it to mean anything.
+
diff --git a/test/transform/resource/messages-ecj/BuilderSingularNoAuto.java.messages b/test/transform/resource/messages-ecj/BuilderSingularNoAuto.java.messages
new file mode 100644
index 00000000..8719789b
--- /dev/null
+++ b/test/transform/resource/messages-ecj/BuilderSingularNoAuto.java.messages
@@ -0,0 +1,2 @@
+8 The singular must be specified explicitly (e.g. @Singular("task")) because auto singularization is disabled.
+10 The singular must be specified explicitly (e.g. @Singular("task")) because auto singularization is disabled.
diff --git a/test/transform/resource/messages-ecj/EqualsAndHashCodeWithSomeExistingMethods.java.messages b/test/transform/resource/messages-ecj/EqualsAndHashCodeWithSomeExistingMethods.java.messages
index d3119bd6..d8c064a0 100644
--- a/test/transform/resource/messages-ecj/EqualsAndHashCodeWithSomeExistingMethods.java.messages
+++ b/test/transform/resource/messages-ecj/EqualsAndHashCodeWithSomeExistingMethods.java.messages
@@ -1 +1 @@
-4 Not generating equals: One of equals or hashCode exists. You should either write both of these or none of these (in the latter case, lombok generates them).
+5 Not generating equals: One of equals or hashCode exists. You should either write both of these or none of these (in the latter case, lombok generates them).
diff --git a/test/transform/resource/messages-ecj/GetterLazyTransient.java.messages b/test/transform/resource/messages-ecj/GetterLazyTransient.java.messages
new file mode 100644
index 00000000..8c1873eb
--- /dev/null
+++ b/test/transform/resource/messages-ecj/GetterLazyTransient.java.messages
@@ -0,0 +1 @@
+5 'lazy' is not supported on transient fields. \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages b/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages
index 53a9b9ad..3386b565 100644
--- a/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages
+++ b/test/transform/resource/messages-ecj/GetterOnMethodErrors2.java.messages
@@ -1,4 +1,4 @@
-2 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
-3 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
-4 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
-5 The correct format is @Getter(onMethod=@__({@SomeAnnotation, @SomeOtherAnnotation}))
+3 The correct format is
+4 The correct format is
+5 The correct format is
+6 The correct format is
diff --git a/test/transform/resource/messages-ecj/Helper.java.messages b/test/transform/resource/messages-ecj/Helper.java.messages
new file mode 100644
index 00000000..4193dfe2
--- /dev/null
+++ b/test/transform/resource/messages-ecj/Helper.java.messages
@@ -0,0 +1 @@
+15 No methods of this helper class are ever used.
diff --git a/test/transform/resource/messages-ecj/NonNullOnParameterAbstract.java.messages b/test/transform/resource/messages-ecj/NonNullOnParameterAbstract.java.messages
deleted file mode 100644
index 8eb312ef..00000000
--- a/test/transform/resource/messages-ecj/NonNullOnParameterAbstract.java.messages
+++ /dev/null
@@ -1 +0,0 @@
-6 @NonNull is meaningless on a parameter of an abstract method. \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages b/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages
new file mode 100644
index 00000000..15c9b10f
--- /dev/null
+++ b/test/transform/resource/messages-ecj/UtilityClassErrors.java.messages
@@ -0,0 +1,4 @@
+4 @UtilityClasses cannot have declared constructors.
+7 @UtilityClass cannot be placed on a method local or anonymous inner class, or any class nested in such a class.
+12 @UtilityClass is only supported on a class (can't be an interface, enum, or annotation)
+17 @UtilityClass automatically makes the class static, however, this class cannot be made static. \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages b/test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages
new file mode 100644
index 00000000..37f87639
--- /dev/null
+++ b/test/transform/resource/messages-ecj/ValAnonymousSubclassWithGenerics.java.messages
@@ -0,0 +1 @@
+17 The serializable class does not declare a static final serialVersionUID field of type long \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/ValErrors.java.messages b/test/transform/resource/messages-ecj/ValErrors.java.messages
index 6d53ddd6..c4c76901 100644
--- a/test/transform/resource/messages-ecj/ValErrors.java.messages
+++ b/test/transform/resource/messages-ecj/ValErrors.java.messages
@@ -1,2 +1,2 @@
-5 d cannot be resolved to a variable
-9 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })
+6 d cannot be resolved to a variable
+10 'val' is not compatible with array initializer expressions. Use the full form (new int[] { ... } instead of just { ... })
diff --git a/test/transform/resource/messages-ecj/ValInBasicFor.java.messages b/test/transform/resource/messages-ecj/ValInBasicFor.java.messages
index c75e20f2..b32eabe4 100644
--- a/test/transform/resource/messages-ecj/ValInBasicFor.java.messages
+++ b/test/transform/resource/messages-ecj/ValInBasicFor.java.messages
@@ -1,2 +1,2 @@
-6 'val' is not allowed in old-style for loops
-6 Type mismatch: cannot convert from int to val
+7 'val' is not allowed in old-style for loops
+7 Type mismatch: cannot convert from int to val
diff --git a/test/transform/resource/messages-ecj/ValInTryWithResources.java.messages b/test/transform/resource/messages-ecj/ValInTryWithResources.java.messages
new file mode 100644
index 00000000..9d0d7a6e
--- /dev/null
+++ b/test/transform/resource/messages-ecj/ValInTryWithResources.java.messages
@@ -0,0 +1 @@
+OPTIONAL 8 Resource leak: 'i' is never closed
diff --git a/test/transform/resource/messages-ecj/ValueExperimental.java.messages b/test/transform/resource/messages-ecj/ValueExperimental.java.messages
deleted file mode 100644
index e454a878..00000000
--- a/test/transform/resource/messages-ecj/ValueExperimental.java.messages
+++ /dev/null
@@ -1 +0,0 @@
-1 The type Value is deprecated \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/VarInForOldMulti.java.messages b/test/transform/resource/messages-ecj/VarInForOldMulti.java.messages
new file mode 100644
index 00000000..0bfd6e65
--- /dev/null
+++ b/test/transform/resource/messages-ecj/VarInForOldMulti.java.messages
@@ -0,0 +1 @@
+6 'var' is not allowed in old-style for loops if there is more than 1 initializer \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/VarModifier.java.messages b/test/transform/resource/messages-ecj/VarModifier.java.messages
new file mode 100644
index 00000000..051d1ad7
--- /dev/null
+++ b/test/transform/resource/messages-ecj/VarModifier.java.messages
@@ -0,0 +1,3 @@
+1 The type var is deprecated
+7 The type var is deprecated
+8 The type var is deprecated
diff --git a/test/transform/resource/messages-ecj/VarNullInit.java.messages b/test/transform/resource/messages-ecj/VarNullInit.java.messages
new file mode 100644
index 00000000..5a2a6ae1
--- /dev/null
+++ b/test/transform/resource/messages-ecj/VarNullInit.java.messages
@@ -0,0 +1 @@
+5 variable initializer is 'null' \ No newline at end of file
diff --git a/test/transform/resource/messages-ecj/VarWarning.java.messages b/test/transform/resource/messages-ecj/VarWarning.java.messages
new file mode 100644
index 00000000..25096b84
--- /dev/null
+++ b/test/transform/resource/messages-ecj/VarWarning.java.messages
@@ -0,0 +1 @@
+6 Use of var is flagged according to lombok configuration. \ No newline at end of file
diff --git a/test/transform/resource/messages-idempotent/NonNullOnParameterAbstract.java.messages b/test/transform/resource/messages-idempotent/NonNullOnParameterAbstract.java.messages
deleted file mode 100644
index 0d9fcfdc..00000000
--- a/test/transform/resource/messages-idempotent/NonNullOnParameterAbstract.java.messages
+++ /dev/null
@@ -1 +0,0 @@
-9 @NonNull is meaningless on a parameter of an abstract method. \ No newline at end of file
diff --git a/test/transform/resource/messages-idempotent/NonNullPlain.java.messages b/test/transform/resource/messages-idempotent/NonNullPlain.java.messages
index 1d8c4d9c..3a3a052d 100644
--- a/test/transform/resource/messages-idempotent/NonNullPlain.java.messages
+++ b/test/transform/resource/messages-idempotent/NonNullPlain.java.messages
@@ -1,3 +1,3 @@
3 @NonNull is meaningless on a primitive.
-15 @NonNull is meaningless on a primitive.
-37 @NonNull is meaningless on a primitive. \ No newline at end of file
+14 @NonNull is meaningless on a primitive.
+36 @NonNull is meaningless on a primitive.
diff --git a/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java b/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java
index d2909943..754a4237 100644
--- a/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java
+++ b/test/transform/src/lombok/transform/TestLombokFilesIdempotent.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -53,4 +53,9 @@ public class TestLombokFilesIdempotent extends DirectoryRunner.TestParams {
public boolean printErrors() {
return true;
}
+
+ @Override
+ public boolean expectChanges() {
+ return false;
+ }
}
diff --git a/test/transform/src/lombok/transform/TestSourceFiles.java b/test/transform/src/lombok/transform/TestSourceFiles.java
index c3ac0a68..17be133e 100644
--- a/test/transform/src/lombok/transform/TestSourceFiles.java
+++ b/test/transform/src/lombok/transform/TestSourceFiles.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -53,4 +53,9 @@ public class TestSourceFiles extends DirectoryRunner.TestParams {
public File getMessagesDirectory() {
return null;
}
+
+ @Override
+ public boolean expectChanges() {
+ return false;
+ }
}
diff --git a/test/transform/src/lombok/transform/TestWithDelombok.java b/test/transform/src/lombok/transform/TestWithDelombok.java
index bd8d9d09..9f4cf94a 100644
--- a/test/transform/src/lombok/transform/TestWithDelombok.java
+++ b/test/transform/src/lombok/transform/TestWithDelombok.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2010 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -53,4 +53,9 @@ public class TestWithDelombok extends DirectoryRunner.TestParams {
public File getMessagesDirectory() {
return new File("test/transform/resource/messages-delombok");
}
+
+ @Override
+ public boolean expectChanges() {
+ return true;
+ }
}
diff --git a/test/transform/src/lombok/transform/TestWithEcj.java b/test/transform/src/lombok/transform/TestWithEcj.java
index 0a4057dd..3df8dc8b 100644
--- a/test/transform/src/lombok/transform/TestWithEcj.java
+++ b/test/transform/src/lombok/transform/TestWithEcj.java
@@ -1,5 +1,5 @@
/*
- * Copyright (C) 2009-2012 The Project Lombok Authors.
+ * Copyright (C) 2009-2015 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
@@ -57,4 +57,9 @@ public class TestWithEcj extends DirectoryRunner.TestParams {
public File getMessagesDirectory() {
return new File("test/transform/resource/messages-ecj");
}
+
+ @Override
+ public boolean expectChanges() {
+ return true;
+ }
}
diff --git a/usage_examples/BuilderExample_post.jpage b/usage_examples/BuilderExample_post.jpage
new file mode 100644
index 00000000..0b64703c
--- /dev/null
+++ b/usage_examples/BuilderExample_post.jpage
@@ -0,0 +1,87 @@
+import java.util.Set;
+
+public class BuilderExample {
+ private long created;
+ private String name;
+ private int age;
+ private Set<String> occupations;
+
+ BuilderExample(String name, int age, Set<String> occupations) {
+ this.name = name;
+ this.age = age;
+ this.occupations = occupations;
+ }
+
+ private static long $default$created() {
+ return System.currentTimeMillis();
+ }
+
+ public static BuilderExampleBuilder builder() {
+ return new BuilderExampleBuilder();
+ }
+
+ public static class BuilderExampleBuilder {
+ private long created;
+ private boolean created$set;
+ private String name;
+ private int age;
+ private java.util.ArrayList<String> occupations;
+
+ BuilderExampleBuilder() {
+ }
+
+ public BuilderExampleBuilder created(long created) {
+ this.created = created;
+ this.created$set = true;
+ return this;
+ }
+
+ public BuilderExampleBuilder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public BuilderExampleBuilder age(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public BuilderExampleBuilder occupation(String occupation) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.add(occupation);
+ return this;
+ }
+
+ public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.addAll(occupations);
+ return this;
+ }
+
+ public BuilderExampleBuilder clearOccupations() {
+ if (this.occupations != null) {
+ this.occupations.clear();
+ }
+
+ return this;
+ }
+
+ public BuilderExample build() {
+ // complicated switch statement to produce a compact properly sized immutable set omitted.
+ // go to https://projectlombok.org/features/Singular-snippet.html to see it.
+ Set<String> occupations = ...;
+ return new BuilderExample(created$set ? created : BuilderExample.$default$created(), name, age, occupations);
+ }
+
+ @java.lang.Override
+ public String toString() {
+ return "BuilderExample.BuilderExampleBuilder(created = " + this.created + ", name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
+ }
+ }
+} \ No newline at end of file
diff --git a/usage_examples/BuilderExample_pre.jpage b/usage_examples/BuilderExample_pre.jpage
new file mode 100644
index 00000000..3b1b0df2
--- /dev/null
+++ b/usage_examples/BuilderExample_pre.jpage
@@ -0,0 +1,11 @@
+import lombok.Builder;
+import lombok.Singular;
+import java.util.Set;
+
+@Builder
+public class BuilderExample {
+ @Builder.Default private long created = System.currentTimeMillis();
+ private String name;
+ private int age;
+ @Singular private Set<String> occupations;
+}
diff --git a/usage_examples/DataExample_post.jpage b/usage_examples/DataExample_post.jpage
index e53e999c..bef0a0f1 100644
--- a/usage_examples/DataExample_post.jpage
+++ b/usage_examples/DataExample_post.jpage
@@ -62,7 +62,7 @@ public class DataExample {
final int PRIME = 59;
int result = 1;
final long temp1 = Double.doubleToLongBits(this.getScore());
- result = (result*PRIME) + (this.getName() == null ? 0 : this.getName().hashCode());
+ result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
result = (result*PRIME) + this.getAge();
result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
@@ -111,8 +111,8 @@ public class DataExample {
@Override public int hashCode() {
final int PRIME = 59;
int result = 1;
- result = (result*PRIME) + (this.getName() == null ? 0 : this.getName().hashCode());
- result = (result*PRIME) + (this.getValue() == null ? 0 : this.getValue().hashCode());
+ result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
+ result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
return result;
}
}
diff --git a/usage_examples/EqualsAndHashCodeExample_post.jpage b/usage_examples/EqualsAndHashCodeExample_post.jpage
index f58e045b..91e78250 100644
--- a/usage_examples/EqualsAndHashCodeExample_post.jpage
+++ b/usage_examples/EqualsAndHashCodeExample_post.jpage
@@ -27,7 +27,7 @@ public class EqualsAndHashCodeExample {
final int PRIME = 59;
int result = 1;
final long temp1 = Double.doubleToLongBits(this.score);
- result = (result*PRIME) + (this.name == null ? 0 : this.name.hashCode());
+ result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
result = (result*PRIME) + Arrays.deepHashCode(this.tags);
return result;
diff --git a/usage_examples/Singular-snippetExample_post.jpage b/usage_examples/Singular-snippetExample_post.jpage
new file mode 100644
index 00000000..4e2b0460
--- /dev/null
+++ b/usage_examples/Singular-snippetExample_post.jpage
@@ -0,0 +1,160 @@
+import java.util.Collection;
+import java.util.Set;
+import java.util.SortedMap;
+import com.google.common.collect.ImmutableList;
+
+public class SingularExample<T extends Number> {
+ private Set<String> occupations;
+ private ImmutableList<String> axes;
+ private SortedMap<Integer, T> elves;
+ private Collection<?> minutiae;
+
+ SingularExample(Set<String> occupations, ImmutableList<String> axes, SortedMap<Integer, T> elves, Collection<?> minutiae) {
+ this.occupations = occupations;
+ this.axes = axes;
+ this.elves = elves;
+ this.minutiae = minutiae;
+ }
+
+ public static class SingularExampleBuilder<T extends Number> {
+ private java.util.ArrayList<String> occupations;
+ private com.google.common.collect.ImmutableList.Builder<String> axes;
+ private java.util.ArrayList<Integer> elves$key;
+ private java.util.ArrayList<T> elves$value;
+ private java.util.ArrayList<java.lang.Object> minutiae;
+
+ SingularExampleBuilder() {
+ }
+
+ public SingularExampleBuilder<T> occupation(String occupation) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.add(occupation);
+ return this;
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public SingularExampleBuilder<T> occupations(java.util.Collection<? extends String> occupations) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.addAll(occupations);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> axis(String axis) {
+ if (this.axes == null) {
+ this.axes = com.google.common.collect.ImmutableList.builder();
+ }
+
+ this.axes.add(axis);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> axes(java.lang.Iterable<? extends String> axes) {
+ if (this.axes == null) {
+ this.axes = com.google.common.collect.ImmutableList.builder();
+ }
+
+ this.axes.addAll(axes);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> elf(Integer elfKey, T elfValue) {
+ if (this.elves$key == null) {
+ this.elves$key = new java.util.ArrayList<Integer>();
+ this.elves$value = new java.util.ArrayList<T>();
+ }
+
+ this.elves$key.add(elfKey);
+ this.elves$value.add(elfValue);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> elves(java.util.Map<? extends Integer, ? extends T> elves) {
+ if (this.elves$key == null) {
+ this.elves$key = new java.util.ArrayList<Integer>();
+ this.elves$value = new java.util.ArrayList<T>();
+ }
+
+ for (java.util.Map.Entry<? extends Integer, ? extends T> $lombokEntry : elves.entrySet()) {
+ this.elves$key.add($lombokEntry.getKey());
+ this.elves$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+
+ public SingularExampleBuilder<T> minutia(java.lang.Object minutia) {
+ if (this.minutiae == null) {
+ this.minutiae = new java.util.ArrayList<java.lang.Object>();
+ }
+
+ this.minutiae.add(minutia);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> minutiae(java.util.Collection<?> minutiae) {
+ if (this.minutiae == null) {
+ this.minutiae = new java.util.ArrayList<java.lang.Object>();
+ }
+
+ this.minutiae.addAll(minutiae);
+ return this;
+ }
+
+ public SingularExample<T> build() {
+ java.util.Set<String> occupations;
+ switch (this.occupations == null ? 0 : this.occupations.size()) {
+ case 0:
+ occupations = java.util.Collections.emptySet();
+ break;
+
+ case 1:
+ occupations = java.util.Collections.singleton(this.occupations.get(0));
+ break;
+
+ default:
+ occupations = new java.util.LinkedHashSet<String>(this.occupations.size() < 1073741824 ? 1 + this.occupations.size() + (this.occupations.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
+ occupations.addAll(this.occupations);
+ occupations = java.util.Collections.unmodifiableSet(occupations);
+
+ }
+
+ com.google.common.collect.ImmutableList<String> axes = this.axes == null ? com.google.common.collect.ImmutableList.<String>of() : this.axes.build();
+
+ java.util.SortedMap<Integer, T> elves = new java.util.TreeMap<Integer, T>();
+ if (this.elves$key != null) for (int $i = 0; $i < (this.elves$key == null ? 0 : this.elves$key.size()); $i++) elves.put(this.elves$key.get($i), this.elves$value.get($i));
+ elves = java.util.Collections.unmodifiableSortedMap(elves);
+
+ java.util.Collection<java.lang.Object> minutiae;
+ switch (this.minutiae == null ? 0 : this.minutiae.size()) {
+ case 0:
+ minutiae = java.util.Collections.emptyList();
+ break;
+
+ case 1:
+ minutiae = java.util.Collections.singletonList(this.minutiae.get(0));
+ break;
+
+ default:
+ minutiae = java.util.Collections.unmodifiableList(new java.util.ArrayList<java.lang.Object>(this.minutiae));
+
+ }
+
+ return new SingularExample<T>(occupations, axes, elves, minutiae);
+ }
+
+ @java.lang.Override
+ public java.lang.String toString() {
+ return "SingularExample.SingularExampleBuilder(occupations=" + this.occupations + ", axes=" + this.axes + ", elves$key=" + this.elves$key + ", elves$value=" + this.elves$value + ", minutiae=" + this.minutiae + ")";
+ }
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public static <T extends Number> SingularExampleBuilder<T> builder() {
+ return new SingularExampleBuilder<T>();
+ }
+}
diff --git a/usage_examples/Singular-snippetExample_pre.jpage b/usage_examples/Singular-snippetExample_pre.jpage
new file mode 100644
index 00000000..65f6bbc8
--- /dev/null
+++ b/usage_examples/Singular-snippetExample_pre.jpage
@@ -0,0 +1,14 @@
+import lombok.Builder;
+import lombok.Singular;
+import java.util.Collection;
+import java.util.Set;
+import java.util.SortedMap;
+import com.google.common.collect.ImmutableList;
+
+@Builder
+public class SingularExample<T extends Number> {
+ private @Singular Set<String> occupations;
+ private @Singular("axis") ImmutableList<String> axes;
+ private @Singular SortedMap<Integer, T> elves;
+ private @Singular Collection<?> minutiae;
+}
diff --git a/usage_examples/ToStringExample_pre.jpage b/usage_examples/ToStringExample_pre.jpage
index a15fb944..39b25892 100644
--- a/usage_examples/ToStringExample_pre.jpage
+++ b/usage_examples/ToStringExample_pre.jpage
@@ -9,7 +9,7 @@ public class ToStringExample {
private int id;
public String getName() {
- return this.getName();
+ return this.name;
}
@ToString(callSuper=true, includeFieldNames=true)
diff --git a/usage_examples/ValueExample_post.jpage b/usage_examples/ValueExample_post.jpage
index 4ac8654e..8a5d4836 100644
--- a/usage_examples/ValueExample_post.jpage
+++ b/usage_examples/ValueExample_post.jpage
@@ -49,7 +49,7 @@ public final class ValueExample {
final int PRIME = 59;
int result = 1;
final Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
result = result * PRIME + this.getAge();
final long $score = Double.doubleToLongBits(this.getScore());
result = result * PRIME + (int)($score >>> 32 ^ $score);
@@ -106,9 +106,9 @@ public final class ValueExample {
final int PRIME = 59;
int result = 1;
final Object $name = this.getName();
- result = result * PRIME + ($name == null ? 0 : $name.hashCode());
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
final Object $value = this.getValue();
- result = result * PRIME + ($value == null ? 0 : $value.hashCode());
+ result = result * PRIME + ($value == null ? 43 : $value.hashCode());
return result;
}
diff --git a/usage_examples/experimental/BuilderExample_post.jpage b/usage_examples/experimental/BuilderExample_post.jpage
deleted file mode 100644
index 624b236b..00000000
--- a/usage_examples/experimental/BuilderExample_post.jpage
+++ /dev/null
@@ -1,40 +0,0 @@
-public class BuilderExample {
- private String name;
- private int age;
-
- BuilderExample(String name, int age) {
- this.name = name;
- this.age = age;
- }
-
- public static BuilderExampleBuilder builder() {
- return new BuilderExampleBuilder();
- }
-
- public static class BuilderExampleBuilder {
- private String name;
- private int age;
-
- BuilderExampleBuilder() {
- }
-
- public BuilderExampleBuilder name(String name) {
- this.name = name;
- return this;
- }
-
- public BuilderExampleBuilder age(int age) {
- this.age = age;
- return this;
- }
-
- public BuilderExample build() {
- return new BuilderExample(name, age);
- }
-
- @java.lang.Override
- public String toString() {
- return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ")";
- }
- }
-} \ No newline at end of file
diff --git a/usage_examples/experimental/BuilderExample_pre.jpage b/usage_examples/experimental/BuilderExample_pre.jpage
deleted file mode 100644
index 9c754352..00000000
--- a/usage_examples/experimental/BuilderExample_pre.jpage
+++ /dev/null
@@ -1,7 +0,0 @@
-import lombok.experimental.Builder;
-
-@Builder
-public class BuilderExample {
- private String name;
- private int age;
-}
diff --git a/usage_examples/experimental/HelperExample_post.jpage b/usage_examples/experimental/HelperExample_post.jpage
new file mode 100644
index 00000000..04a97b9f
--- /dev/null
+++ b/usage_examples/experimental/HelperExample_post.jpage
@@ -0,0 +1,14 @@
+public class HelperExample {
+ int someMethod(int arg1) {
+ int localVar = 5;
+
+ class Helpers {
+ int helperMethod(int arg) {
+ return arg + localVar;
+ }
+ }
+ Helpers $Helpers = new Helpers();
+
+ return $Helpers.helperMethod(10);
+ }
+}
diff --git a/usage_examples/experimental/HelperExample_pre.jpage b/usage_examples/experimental/HelperExample_pre.jpage
new file mode 100644
index 00000000..cd86ef3c
--- /dev/null
+++ b/usage_examples/experimental/HelperExample_pre.jpage
@@ -0,0 +1,15 @@
+import lombok.experimental.Helper;
+
+public class HelperExample {
+ int someMethod(int arg1) {
+ int localVar = 5;
+
+ @Helper class Helpers {
+ int helperMethod(int arg) {
+ return arg + localVar;
+ }
+ }
+
+ return helperMethod(10);
+ }
+}
diff --git a/usage_examples/experimental/UtilityClassExample_post.jpage b/usage_examples/experimental/UtilityClassExample_post.jpage
new file mode 100644
index 00000000..70810230
--- /dev/null
+++ b/usage_examples/experimental/UtilityClassExample_post.jpage
@@ -0,0 +1,11 @@
+public final class UtilityClassExample {
+ private static final int CONSTANT = 5;
+
+ private UtilityClassExample() {
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
+ public static void addSomething(int in) {
+ return in + CONSTANT;
+ }
+}
diff --git a/usage_examples/experimental/UtilityClassExample_pre.jpage b/usage_examples/experimental/UtilityClassExample_pre.jpage
new file mode 100644
index 00000000..85731b81
--- /dev/null
+++ b/usage_examples/experimental/UtilityClassExample_pre.jpage
@@ -0,0 +1,10 @@
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class UtilityClassExample {
+ private final int CONSTANT = 5;
+
+ public void addSomething(int in) {
+ return in + CONSTANT;
+ }
+}
diff --git a/usage_examples/experimental/WitherExample_post.jpage b/usage_examples/experimental/WitherExample_post.jpage
index bb5952af..3447192a 100644
--- a/usage_examples/experimental/WitherExample_post.jpage
+++ b/usage_examples/experimental/WitherExample_post.jpage
@@ -3,19 +3,19 @@ import lombok.NonNull;
public class WitherExample {
private final int age;
private @NonNull final String name;
-
+
public WitherExample(String name, int age) {
if (name == null) throw new NullPointerException();
this.name = name;
this.age = age;
}
-
+
public WitherExample withAge(int age) {
- return this.age == age ? this : new WitherExample(age, name);
+ return this.age == age ? this : new WitherExample(name, age);
}
-
+
protected WitherExample withName(@NonNull String name) {
if (name == null) throw new java.lang.NullPointerException("name");
- return this.name == name ? this : new WitherExample(age, name);
+ return this.name == name ? this : new WitherExample(name, age);
}
} \ No newline at end of file
diff --git a/usage_examples/experimental/onXExample_pre.jpage b/usage_examples/experimental/onXExample_pre.jpage
index f8fcb435..e54371ae 100644
--- a/usage_examples/experimental/onXExample_pre.jpage
+++ b/usage_examples/experimental/onXExample_pre.jpage
@@ -9,7 +9,9 @@ import javax.validation.constraints.Max;
@AllArgsConstructor(onConstructor=@__(@Inject))
public class OnXExample {
- @Getter(onMethod=@__({@Id, @Column(name="unique-id")}))
- @Setter(onParam=@__(@Max(10000)))
+// @Getter(onMethod=@__({@Id, @Column(name="unique-id")})) //JDK7
+// @Setter(onParam=@__(@Max(10000))) //JDK7
+ @Getter(onMethod_={@Id, @Column(name="unique-id")}) //JDK8
+ @Setter(onParam_=@Max(10000)) //JDK8
private long unid;
}
diff --git a/usage_examples/experimental/varExample_post.jpage b/usage_examples/experimental/varExample_post.jpage
new file mode 100644
index 00000000..d0a7c124
--- /dev/null
+++ b/usage_examples/experimental/varExample_post.jpage
@@ -0,0 +1,21 @@
+import java.util.ArrayList;
+import lombok.var;
+
+public class VarExample {
+ public String example() {
+ ArrayList<String> example = new ArrayList<String>();
+ example.add("Hello, World!");
+ final String foo = example.get(0);
+ return foo.toLowerCase();
+ }
+
+ public void example2() {
+ ArrayList<String> list = new ArrayList<String>();
+ list.add("zero");
+ list.add("one");
+ list.add("two");
+ for(int i = 0; i < list.size(); ++i) {
+ System.out.printf("%d: %s\n", i, list.get(i));
+ }
+ }
+}
diff --git a/usage_examples/experimental/varExample_pre.jpage b/usage_examples/experimental/varExample_pre.jpage
new file mode 100644
index 00000000..e58c4c0d
--- /dev/null
+++ b/usage_examples/experimental/varExample_pre.jpage
@@ -0,0 +1,21 @@
+import java.util.ArrayList;
+import lombok.var;
+
+public class VarExample {
+ public String example() {
+ var example = new ArrayList<String>();
+ example.add("Hello, World!");
+ final var foo = example.get(0);
+ return foo.toLowerCase();
+ }
+
+ public void example2() {
+ var list = new ArrayList<String>();
+ list.add("zero");
+ list.add("one");
+ list.add("two");
+ for(var i = 0; i < list.size(); ++i) {
+ System.out.printf("%d: %s\n", i, list.get(i));
+ }
+ }
+}
diff --git a/website/buttonbar.jpg b/website/buttonbar.jpg
deleted file mode 100644
index 6eb10e71..00000000
--- a/website/buttonbar.jpg
+++ /dev/null
Binary files differ
diff --git a/website/buttonbar.psd b/website/buttonbar.psd
deleted file mode 100644
index b8335cbb..00000000
--- a/website/buttonbar.psd
+++ /dev/null
Binary files differ
diff --git a/website/buttonbar_unmodified.png b/website/buttonbar_unmodified.png
deleted file mode 100644
index 6a3121af..00000000
--- a/website/buttonbar_unmodified.png
+++ /dev/null
Binary files differ
diff --git a/website/changelog.html b/website/changelog.html
deleted file mode 100644
index df09e661..00000000
--- a/website/changelog.html
+++ /dev/null
@@ -1,15 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok - Changelog</title>
- <style type="text/css">
- body {
- margin: 8px;
- }
- </style>
-</head><body>
- @CHANGELOG@
-</body></html>
diff --git a/website/clear.gif b/website/clear.gif
deleted file mode 100644
index 35d42e80..00000000
--- a/website/clear.gif
+++ /dev/null
Binary files differ
diff --git a/website/credits.html b/website/credits.html
deleted file mode 100644
index 36c9895c..00000000
--- a/website/credits.html
+++ /dev/null
@@ -1,133 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok - Credits</title>
- <style type="text/css">
- h1 {
- font-size: 14px;
- text-align: center;
- width: 100%;
- }
-
- .meat {
- margin: 16px auto 0 auto;
- width: 800px;
- }
-
- .personList {
- clear: both;
- padding-top: 16px;
- }
-
- .personList h3 {
- font-size: 1em;
- }
-
- .person {
- width: 128px;
- float: left;
- margin-right: 32px;
- }
-
- .person .imgCt {
- width: 128px;
- }
-
- .person img {
- text-align: center;
- margin: 0 auto;
- display: block;
- }
-
- .person .name {
- margin: 0 auto 0 auto;
- width: 100%;
- text-align: center;
- display: block;
- }
-
- .thanks {
- clear: both;
- padding-top: 32px;
- }
-
- .back {
- margin-top: 32px;
- }
-
- ul {
- list-style-image: url(lombokBullet.png);
- list-style-position: inside;
- }
- </style>
-</head><body>
- <div class="meat">
- <h1>Project Lombok - About the authors and everyone that's helped us create Project Lombok.</h1>
- <div class="credits">
- <div class="committers personList">
- <h3>Regular contributors to Project Lombok:</h3>
- <div class="person">
- <div class="imgCt"><img class="jappeImg" src="unknown_person.gif" /></div>
- <span class="name">Jappe van der Hel</span>
- </div>
- <div class="person">
- <div class="imgCt"><img class="philippImg" src="unknown_person.gif" /></div>
- <span class="name">Philipp Eichhorn</span>
- </div>
- <div class="person">
- <div class="imgCt"><img class="reinierImg" src="reinier.jpg" /></div>
- <span class="name">Reinier Zwitserloot</span>
- </div>
- <div class="person">
- <div class="imgCt"><img class="rjImg" src="robbertjan.jpg" /></div>
- <span class="name">Robbert Jan Grootjans</span>
- </div>
- <div class="person">
- <div class="imgCt"><img class="roelImg" src="roel.jpg" /></div>
- <span class="name">Roel Spilker</span>
- </div>
- <div class="person">
- <div class="imgCt"><img class="sanderImg" src="sander.jpg" /></div>
- <span class="name">Sander Koning</span>
- </div>
- </div>
- <div class="thanks">
- We'd like to thank:<ul>
- <li>Perry Nguyen (pfn on ##java on freenode) for creating the inspiration for project lombok.</li>
- <li>Tor Norbye, Jan Lahoda, and Petr Jiricka for helping out with Netbeans internals and/or javac.</li>
- <li><a href="http://javaposse.com/">The Java Posse</a> for making the java community <em>awesome</em>. Listen to their podcast!</li>
- <li>all contributors who submitted patches or helped answering questions!</li>
- </ul>
- as well as the authors of the following tools that we use:<ul>
- <li><a href="http://code.google.com/">Google Code Hosting</a> for hosting our issue tracker as well as the lombok releases.</a></li>
- <li><a href="http://github.com/">Github</a> for hosting lombok's repository.</li>
- <li>The <a href="http://asm.ow2.org/index.html">ASM team</a> at ObjectWeb for creating an excellent class file editing tool.
- Lombok uses ASM to interact with Eclipse.</li>
- <li>Markus Gebhard for creating <a href="http://java2html.de/">java2html</a> which we use for the example code snippets on the
- features pages.</li>
- <li><a href="http://camendesign.com/code/video_for_everybody">Kroc Camen</a>'s video for everbody. The lombok demo video
- runs on just about every system imaginable because of it.</a></li>
- <li>Longtail Video's <a href="http://www.longtailvideo.com/players/jw-flv-player/">JWPlayer</a>, which is bringing the video to
- those of you who have an aging browser.</li>
- <li>The <a href="http://code.google.com/p/spi/">spi project</a>, which makes it very easy to extend lombok with your own transformations.</li>
- <li><a href="http://ant.apache.org/ivy/">Apache Ivy</a> - Dependency management</li>
- <li><a href="http://cobertura.sourceforge.net/">Cobertura</a> which we use to ensure our tests cover as much as possible.</li>
- </ul>
- </div>
- </div>
- <div class="back"><a href="index.html">Back to the home page</a>.
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/disableCheckedExceptions.html b/website/disableCheckedExceptions.html
deleted file mode 100644
index 8bd54171..00000000
--- a/website/disableCheckedExceptions.html
+++ /dev/null
@@ -1,61 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok side projects - Disable checked Exceptions</title>
- <style type="text/css">
- code {
- font-size: 12px;
- font-family: monospaced;
- }
-
- .meat {
- margin: 16px auto 0 auto;
- width: 800px;
- }
-
- .backLink {
- padding-top: 100px;
- width: 100%;
- text-align: right;
- }
- </style>
-</head><body>
- <div class="meat">
- <h1>Tired of checked exceptions?</h1>
- <p>
- This lombok spinoff project consists of a hack that only works in javac - not eclipse or any other IDE.<br />
- It will completely disable the notion of checked exceptions. You may throw any exception anywhere, and you may
- also catch any exception anywhere. In standard javac, you may not catch a checked exception that is not declared
- as thrown by at least 1 statement in your try block, unless it is <code>Exception</code> or <code>Throwable</code>.<br />
- This restriction is lifted as well.
- </p>
- <h3>Usage</h3>
- <p>
- Just make sure <code>disableCheckedExceptions-alpha.jar</code> is on the classpath as you compile. For example:<br />
- <code>javac -cp disableCheckedExceptions-alpha.jar MySource.java</code>
- </p>
- <p>
- Ready to try it out? download it here: <a href="downloads/disableCheckedExceptions-alpha.jar">disableCheckedExceptions-alpha.jar</a>
- </p>
- <p>
- Want to know how its done? Grab the lombok repository <a href="http://github.com/rzwitserloot/lombok/tree/disableCheckedExceptions">here on github</a>,
- and look in the <code>experimental</code> directory.
- </p>
- <div class="backLink">
- <a href="index.html">back to the project homepage</a>
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/download-edge-none.html b/website/download-edge-none.html
deleted file mode 100644
index 07091b90..00000000
--- a/website/download-edge-none.html
+++ /dev/null
@@ -1,54 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok - Cutting Edge build</title>
- <style type="text/css">
- code {
- font-size: 12px;
- font-family: monospaced;
- }
-
- #downloadLink {
- font-size: 14px;
- }
-
- .meat {
- margin: 16px auto 0 auto;
- width: 800px;
- }
-
- .backLink {
- padding-top: 100px;
- width: 100%;
- text-align: right;
- }
-
- h1 {
- padding-bottom: 0;
- margin-bottom: 4px;
- }
- </style>
-</head><body>
- <div class="meat download edge">
- <h1>Download Lombok Cutting Edge build</h1>
- <div class="versionInfo">
- No edge build as been released since the last <a href="download.html">stable release</a> of lombok.
- </div>
- <div class="backLink">
- <a href="index.html">back to the project homepage</a>
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/download-edge.html b/website/download-edge.html
deleted file mode 100644
index 4cf794a6..00000000
--- a/website/download-edge.html
+++ /dev/null
@@ -1,63 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok - Cutting Edge build</title>
- <style type="text/css">
- code {
- font-size: 12px;
- font-family: monospaced;
- }
-
- #downloadLink {
- font-size: 14px;
- }
-
- .meat {
- margin: 16px auto 0 auto;
- width: 800px;
- }
-
- .backLink {
- padding-top: 100px;
- width: 100%;
- text-align: right;
- }
-
- h1 {
- padding-bottom: 0;
- margin-bottom: 4px;
- }
- </style>
-</head><body>
- <div class="meat download edge">
- <h1>Download Lombok Cutting Edge build</h1>
- <div class="versionInfo">
- version: @VERSION-EDGE@
- </div>
- <p id="changelog">
- @CHANGELOG-EDGE@
- </p>
- <a href="lombok-edge.jar" id="downloadLink">
- Download now!
- </a>
- <p>
- Cutting edge a bit too gutsy for you? You can grab the <a href="download.html">stable release</a> instead.
- </p>
- <div class="backLink">
- <a href="index.html">back to the project homepage</a>
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/download.html b/website/download.html
deleted file mode 100644
index afacde2b..00000000
--- a/website/download.html
+++ /dev/null
@@ -1,97 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script src="logi/jQuery-all.js" type="text/javascript"></script>
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="index.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <!--[if lt IE 7]><script type="text/javascript" src="logi/iepngfix_tilebg.js"></script><![endif]-->
-</head><body>
- <a id="forkMe" href="http://github.com/rzwitserloot/lombok"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
- <div class="meat">
- <h1><a href="/">Project Lombok</a> - Download</h1>
- <div id="buttonBar" class="buttonBar">
- <a class="button" href="features/index.html">
- <img src="icon_overview.png" />
- <span>Feature Overview</span>
- </a>
- <a class="button" href="http://groups.google.com/group/project-lombok">
- <img src="icon_discussion.png" />
- <span>Discuss / Help</span>
- </a>
- <a class="button" href="http://wiki.github.com/rzwitserloot/lombok/contributing">
- <img src="icon_contribute.png" />
- <span>Contribute</span>
- </a>
- <a class="button" href="http://code.google.com/p/projectlombok/issues/list">
- <img src="icon_bugs.png" />
- <span>Report an issue</span>
- </a>
- <div class="downloadContainer">
- <a class="downloadLink" id="downloadLink" href="download.html">
- <img src="icon_download.png" />
- <span>Download!</span>
- </a>
- <div class="versionInfo">
- Version: @VERSION@ | <a href="changelog.html">changelog</a>
- </div>
- </div>
- </div>
- <div class="downloadHelp">
- <div class="stableLink">Download <a href="http://projectlombok.org/downloads/lombok.jar">lombok.jar</a> @VERSION@.</div>
- <div class="edgeLink">Feeling adventurous? Download the latest <a href="download-edge.html">snapshot</a> release.</div>
-
- <table cellspacing="0" cellpadding="0">
- <tr><td class="platform">Maven,&nbsp;Ivy&nbsp;or&nbsp;Gradle</td>
- <td class="instruction">Lombok is in maven central. <a href="mavenrepo/index.html">More&hellip;</a></td></tr>
-
- <tr><td class="platform">Javac</td>
- <td class="instruction">Just put <code>lombok.jar</code> on the classpath.</td></tr>
-
- <tr><td class="platform">NetBeans</td>
- <td class="instruction">Just put <code>lombok.jar</code> on the classpath and enable annotation processing. <a href="setup/netbeans.html">More&hellip;</a></td></tr>
-
- <tr><td class="platform">Eclipse&nbsp;and&nbsp;variants</td>
- <td class="instruction">Run <code>lombok.jar</code> as a java app (i.e. doubleclick it, usually) to install. Also add lombok.jar to your project. <span style="font-size: 0.8em;"><em>Supported variants: Springsource Tool Suite, JBoss Developer Studio</em></span></td></tr>
-
- <tr><td class="platform">IDEA&nbsp;IntelliJ</td>
- <td class="instruction"><a href="https://code.google.com/p/lombok-intellij-plugin/">A plugin developed by Michael Plushnikov</a> adds support for most features.</td></tr>
-
- <tr><td class="platform">Javadoc</td>
- <td class="instruction">First delombok your code then run javadoc on the result. <a href="features/delombok.html">More&hellip;</a></td></tr>
-
- <tr><td class="platform">Android</td>
- <td class="instruction">The proper way to use lombok with android is somewhat complicated but possible. <a href="setup/android.html">More&hellip;</a></td></tr>
-
- <tr><td class="platform">GWT</td>
- <td class="instruction">Lombok works with GWT. <a href="setup/gwt.html">More&hellip;</a></td></tr>
-
- <tr><td class="platform">Play!&nbsp;Framework</td>
- <td class="instruction">Use Aaron Freeman's <a href="https://github.com/aaronfreeman/play-lombok#readme">lombok play plugin</a>.</td></tr>
-
- <tr><td class="platform">ecj</td>
- <td class="instruction">Lombok works on ecj and ecj-based tools. <a href="setup/ecj.html">More&hellip;</a></td></tr>
- </table>
- <p style="font-size: 0.9em">
- Or, <a href="http://code.google.com/p/projectlombok/downloads/list">download</a> a previous version of lombok.
- </p>
- </div>
- <div class="endBar">
- </div>
- <div class="footer">
- <a href="credits.html" class="creditsLink">credits</a> | Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/downloadButton.png b/website/downloadButton.png
deleted file mode 100644
index 8a0c73b8..00000000
--- a/website/downloadButton.png
+++ /dev/null
Binary files differ
diff --git a/website/downloadButton.svg b/website/downloadButton.svg
deleted file mode 100644
index ce5e33a8..00000000
--- a/website/downloadButton.svg
+++ /dev/null
@@ -1,16 +0,0 @@
-<?xml version="1.0" encoding="UTF-8" standalone="no"?>
-<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
-<!-- Created with Inkscape (http://www.inkscape.org/) -->
-<svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="800" height="200" version="1.1">
- <defs id="defs4">
- <linearGradient id="lg1">
- <stop id="s1" offset="0" style="stop-color:white;stop-opacity:0;" />
- <stop id="s2" offset="1" style="stop-color:white;stop-opacity: .3" />
- </linearGradient>
- <linearGradient xlink:href="#lg1" id="lg3" x1="191" y1="156" x2="148" y2="10" gradientUnits="userSpaceOnUse" />
- </defs>
- <g id="layer1">
- <rect x="1%" y="1%" width="98%" height="98%" rx="18px" ry="18px" style="stroke:#d40000;fill:#ff5050;stroke-width: 2;" />
- <rect x="1%" y="1%" width="98%" height="98%" rx="18px" ry="18px" style="fill:url(#lg3);" />
- </g>
-</svg> \ No newline at end of file
diff --git a/website/extra/htaccess b/website/extra/htaccess
new file mode 100644
index 00000000..db3393af
--- /dev/null
+++ b/website/extra/htaccess
@@ -0,0 +1,59 @@
+RewriteEngine On
+
+RewriteRule ^$ /main.html [L,END]
+RewriteRule ^(index|home)(\.html)?$ / [NC,R=301]
+
+RewriteRule ^setup/overview$ /setup/main.html [L,END]
+RewriteRule ^setup/main(\.html)?$ /setup/overview [NC,R=301]
+RewriteRule ^setup/index(\.html)?$ /setup/overview [NC,R=301]
+RewriteRule ^setup(/(overview)?)?$ /setup/overview [NC,R=301]
+
+RewriteRule ^changelog$ /changelog.html [L,END]
+RewriteRule ^changelog(\.html)?$ /changelog [NC,R=301]
+RewriteRule ^credits$ /credits.html [L,END]
+RewriteRule ^credits(\.html)?$ /credits [NC,R=301]
+RewriteRule ^download$ /download.html [L,END]
+RewriteRule ^download(\.html)?$ /download [NC,R=301]
+RewriteRule ^download-edge$ /download-edge.html [L,END]
+RewriteRule ^download-edge(\.html)?$ /download-edge [NC,R=301]
+RewriteRule ^all-versions$ /all-versions.html [L,END]
+RewriteRule ^all-versions(\.html)?$ /all-versions [NC,R=301]
+RewriteRule ^all-versions$ /all-versions.html [L,END]
+RewriteRule ^all-versions(\.html)?$ /all-versions [NC,R=301]
+RewriteRule ^disable-checked-exceptions$ /disable-checked-exceptions.html [L,END]
+RewriteRule ^disable-checked-exceptions(\.html)?$ /disable-checked-exceptions [NC,R=301]
+RewriteRule ^contributing$ /contributing.html [L,END]
+RewriteRule ^contributing(\.html)?$ /contributing [NC,R=301]
+RewriteRule ^supporters$ /supporters.html [L,END]
+RewriteRule ^supporters(.html)?$ /supporters [NC,R=301]
+RewriteRule ^order-license-info$ /order-license-info.html [L,END]
+RewriteRule ^order-?license-?info(.html)?$ /order-license-info [NC,R=301]
+RewriteRule ^order-license$ /order-license.html [L,END]
+RewriteRule ^order-?license(.html)?$ /order-license [NC,R=301]
+
+<#list setupPages as pg>
+RewriteRule ^setup/${pg?no_esc}$ /setup/${pg?no_esc}.html [L,END]
+RewriteRule ^setup/${pg?no_esc}(\.html)?$ /setup/${pg?no_esc} [NC,R=301]
+</#list>
+
+RewriteRule ^features/all$ /features/index.html [L,END]
+RewriteRule ^features(/all)?$ /features/all [NC,R=301]
+RewriteRule ^features/index(\.html)?$ /features/all [NC,R=301]
+
+<#list featurePages as pg>
+RewriteRule ^features/${pg?no_esc}$ /features/${pg?no_esc}.html [L,END]
+RewriteRule ^features/${pg?no_esc}(\.html)?$ /features/${pg?no_esc} [NC,R=301]
+</#list>
+
+RewriteRule ^features/experimental/Builder(\.html)?$ /features/Builder [NC,R=301]
+RewriteRule ^features/experimental/Value(\.html)?$ /features/Value [NC,R=301]
+RewriteRule ^features/experimental/var(\.html)?$ /features/var [NC,R=301]
+
+RewriteRule ^features/experimental/all$ /features/experimental/index.html [L,END]
+RewriteRule ^features/experimental(/all)?$ /features/experimental/all [NC,R=301]
+RewriteRule ^features/experimental/index(\.html)?$ /features/experimental/all [NC,R=301]
+
+<#list experimentalPages as pg>
+RewriteRule ^features/experimental/${pg?no_esc}$ /features/experimental/${pg?no_esc}.html [L,END]
+RewriteRule ^features/experimental/${pg?no_esc}(\.html)?$ /features/experimental/${pg?no_esc} [NC,R=301]
+</#list>
diff --git a/website/favicon.ico b/website/favicon.ico
deleted file mode 100644
index bf83a474..00000000
--- a/website/favicon.ico
+++ /dev/null
Binary files differ
diff --git a/website/features/Cleanup.html b/website/features/Cleanup.html
deleted file mode 100644
index f4b16946..00000000
--- a/website/features/Cleanup.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Cleanup</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Cleanup</h1>
- <div class="byline">Automatic resource management: Call your <code>close()</code> methods safely with no hassle.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- You can use <code>@Cleanup</code> to ensure a given resource is automatically cleaned up before the code execution path exits your
- current scope. You do this by annotating any local variable declaration with the <code>@Cleanup</code> annotation like so:<br />
- <code>@Cleanup InputStream in = new FileInputStream("some/file");</code><br />
- As a result, at the end of the scope you're in, <code>in.close()</code> is called. This call is guaranteed to run by way of a
- try/finally construct. Look at the example below to see how this works.
- </p><p>
- If the type of object you'd like to cleanup does not have a <code>close()</code> method, but some other no-argument method, you can
- specify the name of this method like so:<br />
- <code>@Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);</code><br />
- By default, the cleanup method is presumed to be <code>close()</code>. A cleanup method that takes 1 or more arguments cannot be called via
- <code>@Cleanup</code>.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.cleanup.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Cleanup</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- In the finally block, the cleanup method is only called if the given resource is not <code>null</code>. However, if you use <code>delombok</code>
- on the code, a call to <code>lombok.Lombok.preventNullAnalysis(Object o)</code> is inserted to prevent warnings if static code analysis could
- determine that a null-check would not be needed. Compilation with <code>lombok.jar</code> on the classpath removes that method call,
- so there is no runtime dependency.
- </p>
- <p>
- If your code throws an exception, and the cleanup method call that is then triggered also throws an exception, then the original exception
- is hidden by the exception thrown by the cleanup call. You should <em>not</em> rely on this 'feature'. Preferably, lombok would like to generate
- code so that, if the main body has thrown an exception, any exception thrown by the close call is silently swallowed (but if the main body
- exited in any other way, exceptions by the close call will not be swallowed). The authors of lombok do not currently know of a feasible way
- to implement this scheme, but if java updates allow it, or we find a way, we'll fix it.
- </p><p>
- You do still need to handle any exception that the cleanup method can generate!
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="NonNull.html">Previous feature (@NonNull)</a> | <a href="GetterSetter.html">Next feature (@Getter / @Setter)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/Constructor.html b/website/features/Constructor.html
deleted file mode 100644
index 6dbbc0de..00000000
--- a/website/features/Constructor.html
+++ /dev/null
@@ -1,111 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@XArgsConstructor</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor</h1>
- <div class="byline">Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- This set of 3 annotations generate a constructor that will accept 1 parameter for certain fields, and simply assigns this parameter to the field.
- </p><p>
- <code>@NoArgsConstructor</code> will generate a constructor with no parameters. If this is not possible (because of final fields), a compiler error will result instead.
- For fields with constraints, such as <code>@NonNull</code> fields, <em>no</em> check or assignment is generated, so be aware that these constraints may then not be
- fulfilled until those fields are properly initialized later. Certain java constructs, such as hibernate and the Service Provider Interface require a no-args constructor.
- This annotation is useful primarily in combination with either <code>@Data</code> or one of the other constructor generating annotations.
- </p><p>
- <code>@RequiredArgsConstructor</code> generates a constructor with 1 parameter for each field that requires special handling. All non-initialized <code>final</code> fields get a parameter,
- as well as any fields that are marked as <code>@NonNull</code> that aren't initialized where they are declared. For those fields marked with <code>@NonNull</code>, an explicit
- null check is also generated. The constructor will throw a <code>NullPointerException</code> if any of the parameters intended for the fields marked with <code>@NonNull</code>
- contain <code>null</code>. The order of the parameters match the order in which the fields appear in your class.
- </p><p>
- <code>@AllArgsConstructor</code> generates a constructor with 1 parameter for each field in your class. Fields marked with <code>@NonNull</code> result in null checks on
- those parameters.
- </p><p>
- Each of these annotations allows an alternate form, where the generated constructor is always private, and an additional static factory method that wraps around the
- private constructor is generated. This mode is enabled by supplying the <code>staticName</code> value for the annotation, like so: <code>@RequiredArgsConstructor(staticName="of")</code>.
- Such a static factory method will infer generics, unlike a normal constructor. This means your API users get write <code>MapEntry.of("foo", 5)</code> instead of the much longer
- <code>new MapEntry&lt;String, Integer&gt;("foo", 5)</code>.
- </p><p>
- To put annotations on the generated constructor, you can use <code>onConstructor=@__({@AnnotationsHere})</code>, but be careful; this is an experimental feature. For more details see the documentation on the <a href="experimental/onX.html">onX</a> feature.
- </p><p>
- Static fields are skipped by these annotations. Also, a <code>@java.beans.ConstructorProperties</code> annotation is added for all constructors with at least 1 argument,
- which allows bean editor tools to call the generated constructors. <code>@ConstructorProperties</code> is now in Java 1.6, which means that if your code is intended for
- compilation on Java 1.5, a compiler error will occur. <em>Running</em> on a JVM 1.5 should be no problem (the annotation will be ignored). To suppress the generation of
- the <code>@ConstructorProperties</code> annotation, add a parameter to your annotation: <code>@AllArgsConstructor(suppressConstructorProperties=true)</code>. However,
- as java 1.5, which has already been end-of-lifed, fades into obscurity, this parameter will eventually be removed. It has also been marked deprecated for this reason.
- </p><p>
- Unlike most other lombok annotations, the existence of an explicit constructor does not stop these annotations from generating their own constructor. This means you can write your own specialized constructor, and let lombok generate the boilerplate ones as well. If a conflict arises (one of your constructors ends up with the same signature as one that lombok generates), a compiler error will occur.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.anyConstructor.suppressConstructorProperties</code> = [<code>true</code> | <code>false</code>] (default: <code>false</code>)</dt>
- <dd>If set to <code>true</code>, then lombok will skip adding a <code>@java.beans.ConstructorProperties</code> to generated constructors. This is useful in android and GWT development where that annotation is not usually available.</dd>
- <dt><code>lombok.</code>[<code>allArgsConstructor</code>|<code>requiredArgsConstructor</code>|<code>noArgsConstructor</code>]<code>.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of the relevant annotation (<code>@AllArgsConstructor</code>, <code>@RequiredArgsConstructor</code> or <code>@NoArgsConstructor</code>) as a warning or error if configured.</dd>
- <dt><code>lombok.anyConstructor.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of any of the 3 constructor-generating annotations as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Even if a field is explicitly initialized with <code>null</code>, lombok will consider the requirement to avoid null as fulfilled, and will <em>NOT</em> consider
- the field as a 'required' argument. The assumption is that if you explicitly assign <code>null</code> to a field that you've also marked as <code>@NonNull</code>
- signals you must know what you're doing.
- </p><p>
- The <code>@java.beans.ConstructorProperties</code> annotation is never generated for a constructor with no arguments. This also explains why <code>@NoArgsConstructor</code>
- lacks the <code>suppressConstructorProperties</code> annotation method. The <code>@ConstructorProperties</code> annotation is also omitted for private constructors. The
- generated static factory methods also do not get <code>@ConstructorProperties</code>, as this annotation can only be added to real constructors.
- </p><p>
- <code>@XArgsConstructor</code> can also be used on an enum definition. The generated constructor will always be
- private, because non-private constructors aren't legal in enums. You don't have to specify <code>AccessLevel.PRIVATE</code>.
- </p><p>
- While <code>suppressConstructorProperties</code> has been marked deprecated in anticipation of a world where all java environments have the
- <code>@ConstructorProperties</code> annotation available, first GWT 2.2 and Android 2.3.3, which do not (yet) have this annotation, will have
- to be ancient history before this annotation parameter will be removed.
- </p><p>
- The <code>flagUsage</code> configuration keys do not trigger when a constructor is generated by <code>@Data</code>, <code>@Value</code> or any other lombok annotation.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="EqualsAndHashCode.html">Previous feature (@EqualsAndHashCode)</a> | <a href="Data.html">Next feature (@Data)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/Data.html b/website/features/Data.html
deleted file mode 100644
index c3d0a644..00000000
--- a/website/features/Data.html
+++ /dev/null
@@ -1,84 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Data</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Data</h1>
- <div class="byline">All together now: A shortcut for <code>@ToString</code>, <code>@EqualsAndHashCode</code>,
- <code>@Getter</code> on all fields, <code>@Setter</code> on all non-final fields, and <code>@RequiredArgsConstructor</code>!</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <code>@Data</code> is a convenient shortcut annotation that bundles the features of <a href="ToString.html"><code>@ToString</code></a>, <a href="EqualsAndHashCode.html"><code>@EqualsAndHashCode</code></a>, <a href="GetterSetter.html"><code>@Getter</code> / <code>@Setter</code></a> and <a href="Constructor.html"><code>@RequiredArgsConstructor</code></a> together: In other words, <code>@Data</code> generates <em>all</em> the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate <code>toString</code>, <code>equals</code> and <code>hashCode</code> implementations that involve the fields of the class, and a constructor that initializes all final fields, as well as all non-final fields with no initializer that have been marked with <code>@NonNull</code>, in order to ensure the field is never null.
- </p><p>
- <code>@Data</code> is like having implicit <code>@Getter</code>, <code>@Setter</code>, <code>@ToString</code>, <code>@EqualsAndHashCode</code> and <code>@RequiredArgsConstructor</code> annotations on the class. However, the parameters of these annotations (such as <code>callSuper</code>, <code>includeFieldNames</code> and <code>exclude</code>) cannot be set with <code>@Data</code>. If you need to set non-default values for any of these parameters, just add those annotations explicitly; <code>@Data</code> is smart enough to defer to those annotations.
- </p><p>
- All generated getters and setters will be <code>public</code>. To override the access level, annotate the field or class with an explicit <code>@Setter</code> and/or <code>@Getter</code> annotation. You can also use this annotation (by combining it with <code>AccessLevel.NONE</code>) to suppress generating a getter and/or setter altogether.
- </p><p>
- All fields marked as <code>transient</code> will not be considered for <code>hashCode</code> and <code>equals</code>. All static fields will be skipped entirely (not considered for any of the generated methods, and no setter/getter will be made for them).
- </p><p>
- If the class already contains a method with the same name and parameter count as any method that would normally be generated, that method is not generated, and no warning or error is emitted. For example, if you already have a method with signature <code>equals(AnyType param)</code>, no <code>equals</code> method will be generated, even though technically it might be an entirely different method due to having different parameter types. The same rule applies to the constructor (any explicit constructor will prevent <code>@Data</code> from generating one), as well as <code>toString</code>, <code>equals</code>, and all getters and setters. You can mark any constructor or method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
- </p><p>
- <code>@Data</code> can handle generics parameters for fields just fine. In order to reduce the boilerplate when constructing objects for classes with
- generics, you can use the <code>staticConstructor</code> parameter to generate a private constructor, as well as a static method that returns a new instance. This way, javac will infer the variable name. Thus, by declaring like so: <code>@Data(staticConstructor="of") class Foo&lt;T&gt; { private T x;}</code> you can create new instances of <code>Foo</code> by writing: <code>Foo.of(5);</code> instead of having to write: <code>new Foo&lt;Integer&gt;(5);</code>.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.data.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Data</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>See the small print of <a href="ToString.html"><code>@ToString</code></a>, <a href="EqualsAndHashCode.html"><code>@EqualsAndHashCode</code></a>,
- <a href="GetterSetter.html"><code>@Getter / @Setter</code></a> and <a href="Constructor.html">@RequiredArgsConstructor</a>.
- </p><p>
- Any annotations named <code>@NonNull</code> (case insensitive) on a field are interpreted as: This field must not ever hold
- <em>null</em>. Therefore, these annotations result in an explicit null check in the generated constructor for the provided field. Also, these
- annotations (as well as any annotation named <code>@Nullable</code>) are copied to the constructor parameter, in both the true constructor and
- any static constructor. The same principle applies to generated getters and setters (see the documentation for <a href="GetterSetter.html">@Getter / @Setter</a>)
- </p><p>
- By default, any variables that start with a $ symbol are excluded automatically.
- You can include them by specifying an explicit annotation (<code>@Getter</code> or <code>@ToString</code>, for example) and using the 'of' parameter.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="Constructor.html">Previous feature (@<em>X</em>Constructor)</a> | <a href="Value.html">Next feature (@Value)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/EqualsAndHashCode.html b/website/features/EqualsAndHashCode.html
deleted file mode 100644
index 32dcb6c3..00000000
--- a/website/features/EqualsAndHashCode.html
+++ /dev/null
@@ -1,94 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@EqualsAndHashCode</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@EqualsAndHashCode</h1>
- <div class="byline">Equality made easy: Generates <code>hashCode</code> and <code>equals</code> implementations from the fields of your object.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- Any class definition may be annotated with <code>@EqualsAndHashCode</code> to let lombok generate implementations of the <code>equals(Object other)</code> and <code>hashCode()</code> methods. By default, it'll use all non-static, non-transient fields, but you can exclude more fields by naming them in the optional <code>exclude</code> parameter to the annotation. Alternatively, you can specify exactly which fields you wish to be used by naming them in the <code>of</code> parameter.
- </p><p>
- By setting <code>callSuper</code> to <em>true</em>, you can include the <code>equals</code> and <code>hashCode</code> methods of your superclass in the generated methods. For <code>hashCode</code>, the result of <code>super.hashCode()</code> is included in the hash algorithm, and for <code>equals</code>, the generated method will return false if the super implementation thinks it is not equal to the passed in object. Be aware that not all <code>equals</code> implementations handle this situation properly. However, lombok-generated <code>equals</code> implementations <strong>do</strong> handle this situation properly, so you can safely call your superclass equals if it, too, has a lombok-generated <code>equals</code> method.<br />
- </p><p>
- Setting <code>callSuper</code> to <em>true</em> when you don't extend anything (you extend <code>java.lang.Object</code>) is a compile-time error, because it would turn the generated <code>equals()</code> and <code>hashCode()</code> implementations into having the same behaviour as simply inheriting these methods from <code>java.lang.Object</code>: only the same object will be equal to each other and will have the same hashCode. Not setting <code>callSuper</code> to <em>true</em> when you extend another class generates a warning, because unless the superclass has no (equality-important) fields, lombok cannot generate an implementation for you that takes into account the fields declared by your superclasses. You'll need to write your own implementations, or rely on the
- <code>callSuper</code> chaining facility.
- </p><p>
- <em>NEW in Lombok 0.10: </em>Unless your class is <code>final</code> and extends <code>java.lang.Object</code>, lombok generates a <code>canEqual</code> method
- which means JPA proxies can still be equal to their base class, but subclasses that add new state don't break the equals contract. The complicated reasons for
- why such a method is necessary are explained in this paper: <a href="http://www.artima.com/lejava/articles/equality.html">How to Write an Equality Method in Java</a>.
- If all classes in a hierarchy are a mix of scala case classes and classes with lombok-generated equals methods, all equality will 'just work'.
- If you need to write your own equals methods, you should always override <code>canEqual</code> if you change <code>equals</code> and <code>hashCode</code>.
- </p><p>
- <em>NEW in Lombok 1.14.0: </em>To put annotations on the <code>other</code> parameter of the <code>equals</code> (and, if relevant, <code>canEqual</code>) method, you can use <code>onParam=@__({@AnnotationsHere})</code>. Be careful though! This is an experimental feature. For more details see the documentation on the <a href="experimental/onX.html">onX</a> feature.
-
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.equalsAndHashCode.doNotUseGetters</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, lombok will access fields directly instead of using getters (if available) when generating <code>equals</code> and <code>hashCode</code> methods. The annotation parameter '<code>doNotUseGetters</code>', if explicitly specified, takes precedence over this setting.</dd>
- <dt><code>lombok.equalsAndHashCode.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@EqualsAndHashCode</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Arrays are 'deep' compared/hashCoded, which means that arrays that contain themselves will result in <code>StackOverflowError</code>s. However, this behaviour is no different from e.g. <code>ArrayList</code>.
- </p><p>
- You may safely presume that the hashCode implementation used will not change between versions of lombok, however this guarantee is not set in stone; if there's a significant performance improvement to be gained from using an alternate hash algorithm, that will be substituted in a future version.
- </p><p>
- For the purposes of equality, 2 <code>NaN</code> (not a number) values for floats and doubles are considered equal, eventhough 'NaN == NaN' would return false. This is analogous to <code>java.lang.Double</code>'s equals method, and is in fact required to ensure that comparing an object to an exact copy of itself returns <code>true</code> for equality.
- </p><p>
- If there is <em>any</em> method named either <code>hashCode</code> or <code>equals</code>, regardless of return type, no methods will be generated, and a warning is emitted instead. These 2 methods need to be in sync with each other, which lombok cannot guarantee unless it generates all the methods, hence you always get a warning if one <em>or</em> both of the methods already exist. You can mark any method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
- </p><p>
- Attempting to exclude fields that don't exist or would have been excluded anyway (because they are static or transient) results in warnings on the named fields. You therefore don't have to worry about typos.
- </p><p>
- Having both <code>exclude</code> and <code>of</code> generates a warning; the <code>exclude</code> parameter will be ignored in that case.
- </p><p>
- By default, any variables that start with a $ symbol are excluded automatically. You can only include them by using the 'of' parameter.
- </p><p>
- If a getter exists for a field to be included, it is called instead of using a direct field reference. This behaviour can be suppressed:<br />
- <code>@EqualsAndHashCode(doNotUseGetters = true)</code>
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="ToString.html">Previous feature (@ToString)</a> | <a href="Constructor.html">Next feature (@<em>X</em>Constructor)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/GetterLazy.html b/website/features/GetterLazy.html
deleted file mode 100644
index a438f08a..00000000
--- a/website/features/GetterLazy.html
+++ /dev/null
@@ -1,66 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Getter(lazy=true)</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Getter(lazy=true)</h1>
- <div class="byline">Laziness is a virtue!</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <em>NEW IN Lombok 0.10: </em>You can let lombok generate a getter which will calculate a value once, the first time this getter is called, and cache it from then on. This can be useful if calculating the value takes a lot of CPU, or the value takes a lot of memory. To use this feature, create a <code>private final</code> variable, initialize it with the expression that's expensive to run, and annotate your field with <code>@Getter(lazy=true)</code>. The field will be hidden from the rest of your code, and the expression will be evaluated no more than once, when the getter is first called. There are no magic marker values (i.e. even if the result of your expensive calculation is <code>null</code>, the result is cached) and your expensive calculation need not be thread-safe, as lombok takes care of locking.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys (in addition to those listed on <a href="GetterSetter.html"><code>@Getter</code>'s main page</a>):</h3>
- <dl>
- <dt><code>lombok.getter.lazy.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Getter(lazy=true)</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- You should never refer to the field directly, always use the getter generated by lombok, because the type of the field will be mangled into an <code>AtomicReference</code>. Do not try to directly access this <code>AtomicReference</code>; if it points to itself, the value has been calculated, and it is <code>null</code>. If the reference points to <code>null</code>, then the value has not been calculated. This behaviour may change in future versions. Therefore, <em>always</em> use the generated getter to access your field!
- </p><p>
- Other Lombok annotations such as <code>@ToString</code> always call the getter even if you use <code>doNotUseGetters=true</code>.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="Synchronized.html">Previous feature (@Synchronized)</a> | <a href="Log.html">Next feature (@Log)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/GetterSetter.html b/website/features/GetterSetter.html
deleted file mode 100644
index ad83f86a..00000000
--- a/website/features/GetterSetter.html
+++ /dev/null
@@ -1,105 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Getter and @Setter</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Getter and @Setter</h1>
- <div class="byline">Never write <code>public int getFoo() {return foo;}</code> again.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- You can annotate any field with <code>@Getter</code> and/or <code>@Setter</code>, to let lombok generate the default getter/setter automatically.<br />
- A default getter simply returns the field, and is named <code>getFoo</code> if the field is called <code>foo</code> (or <code>isFoo</code> if the field's type is <code>boolean</code>). A default setter is named <code>setFoo</code> if the field is called <code>foo</code>, returns <code>void</code>, and takes 1 parameter of the same type as the field. It simply sets the field to this value.
- </p><p>
- The generated getter/setter method will be <code>public</code> unless you explicitly specify an <code>AccessLevel</code>, as shown in the example below. Legal access levels are <code>PUBLIC</code>, <code>PROTECTED</code>, <code>PACKAGE</code>, and <code>PRIVATE</code>.
- </p><p>
- You can also put a <code>@Getter</code> and/or <code>@Setter</code> annotation on a class. In that case, it's as if you annotate all the non-static fields in that class with the annotation.
- </p><p>
- You can always manually disable getter/setter generation for any field by using the special <code>AccessLevel.NONE</code> access level. This lets you override the behaviour of a <code>@Getter</code>, <code>@Setter</code> or <code>@Data</code> annotation on a class.
- </p><p>
- To put annotations on the generated method, you can use <code>onMethod=@__({@AnnotationsHere})</code>; to put annotations on the only parameter of a generated setter method, you can use <code>onParam=@__({@AnnotationsHere})</code>. Be careful though! This is an experimental feature. For more details see the documentation on the <a href="experimental/onX.html">onX</a> feature.
- </p><p>
- <em>NEW in lombok v1.12.0:</em> javadoc on the field will now be copied to generated getters and setters. Normally, all text is copied, and <code>@return</code> is <em>moved</em> to the getter, whilst <code>@param</code> lines are <em>moved</em> to the setter. Moved means: Deleted from the field's javadoc. It is also possible to define unique text for each getter/setter. To do that, you create a 'section' named <code>GETTER</code> and/or <code>SETTER</code>. A section is a line in your javadoc containing 2 or more dashes, then the text 'GETTER' or 'SETTER', followed by 2 or more dashes, and nothing else on the line. If you use sections, <code>@return</code> and <code>@param</code> stripping for that section is no longer done (move the <code>@return</code> or <code>@param</code> line into the section).
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.accessors.chain</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, generated setters will return <code>this</code> (instead of <code>void</code>). An explicitly configured <code>chain</code> parameter of an <a href="experimental/Accessors.html"><code>@Accessors</code></a> annotation takes precedence over this setting.</dd>
- <dt><code>lombok.accessors.fluent</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, generated getters and setters will not be prefixed with the bean-standard '<code>get</code>, <code>is</code> or <code>set</code>; instead, the methods will use the same name as the field (minus prefixes). An explicitly configured <code>chain</code> parameter of an <a href="experimental/Accessors.html"><code>@Accessors</code></a> annotation takes precedence over this setting.</dd>
- <dt><code>lombok.accessors.prefix</code> += <em>a field prefix</em> (default: empty list)</dt>
- <dd>This is a list property; entries can be added with the <code>+=</code> operator. Inherited prefixes from parent config files can be removed with the <code>-=</code> operator. Lombok will strip any matching field prefix from the name of a field in order to determine the name of the getter/setter to generate. For example, if <code>m</code> is one of the prefixes listed in this setting, then a field named <code>mFoobar</code> will result in a getter named <code>getFoobar()</code>, not <code>getMFoobar()</code>. An explicitly configured <code>prefix</code> parameter of an <a href="experimental/Accessors.html"><code>@Accessors</code></a> annotation takes precedence over this setting.</dd>
- <dt><code>lombok.getter.noIsPrefix</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, getters generated for <code>boolean</code> fields will use the <code>get</code> prefix instead of the default<code>is</code> prefix, and any generated code that calls getters, such as <code>@ToString</code>, will also use <code>get</code> instead of <code>is</code>
- <dt><code>lombok.setter.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Setter</code> as a warning or error if configured.</dd>
- <dt><code>lombok.getter.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Getter</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- For generating the method names, the first character of the field, if it is a lowercase character, is title-cased, otherwise, it is left unmodified. Then, get/set/is is prefixed.
- </p><p>
- No method is generated if any method already exists with the same name (case insensitive) and same parameter count. For example, <code>getFoo()</code> will not be generated if there's already a method <code>getFoo(String... x)</code> even though it is technically possible to make the method. This caveat exists to prevent confusion. If the generation of a method is skipped for this reason, a warning is emitted instead. Varargs count as 0 to N parameters. You can mark any method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
- </p><p>
- For <code>boolean</code> fields that start with <code>is</code> immediately followed by a title-case letter, nothing is prefixed to generate the getter name.
- </p><p>
- Any variation on <code>boolean</code> will <em>not</em> result in using the <code>is</code> prefix instead of the <code>get</code> prefix; for example,
- returning <code>java.lang.Boolean</code> results in a <code>get</code> prefix, not an <code>is</code> prefix.
- </p><p>
- Any annotations named <code>@NonNull</code> (case insensitive) on the field are interpreted as: This field must not ever hold
- <em>null</em>. Therefore, these annotations result in an explicit null check in the generated setter. Also, these
- annotations (as well as any annotation named <code>@Nullable</code> or <code>@CheckForNull</code>) are copied to setter parameter and getter method.
- </p><p>
- You can annotate a class with a <code>@Getter</code> or <code>@Setter</code> annotation. Doing so is equivalent to annotating all non-static fields
- in that class with that annotation. <code>@Getter</code>/<code>@Setter</code> annotations on fields take precedence over the ones on classes.
- </p><p>
- Using the <code>AccessLevel.NONE</code> access level simply generates nothing. It's useful only in combination with
- <a href="Data.html"><code>@Data</code></a> or a class-wide <code>@Getter</code> or <code>@Setter</code>.
- </p><p>
- <code>@Getter</code> can also be used on enums. <code>@Setter</code> can't, not for a technical reason, but
- for a pragmatic one: Setters on enums are an extremely bad idea.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="Cleanup.html">Previous feature (@Cleanup)</a> | <a href="ToString.html">Next feature (@ToString)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/Log.html b/website/features/Log.html
deleted file mode 100644
index 8b635280..00000000
--- a/website/features/Log.html
+++ /dev/null
@@ -1,101 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Log (and friends)</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Log (and friends)</h1>
- <div class="byline">Captain's Log, stardate 24435.7: &quot;What was that line again?&quot;</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <em>NEW in lombok 0.10: </em>You can annotate any class with a log annotation to let lombok generate a logger field.<br />
- The logger is named <code>log</code> and the field's type depends on which logger you have selected.
- </p><p>
- There are six choices available:<br />
- <dl>
- <dt><code>@CommonsLog</code></dt>
- <dd>Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://commons.apache.org/logging/apidocs/org/apache/commons/logging/Log.html">org.apache.commons.logging.Log</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://commons.apache.org/logging/apidocs/org/apache/commons/logging/LogFactory.html#getLog(java.lang.Class)">org.apache.commons.logging.LogFactory.getLog</a>(LogExample.<span class="keyword">class</span>);</code></dd>
- <dt><code>@Log</code></dt>
- <dd>Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://download.oracle.com/javase/6/docs/api/java/util/logging/Logger.html">java.util.logging.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://download.oracle.com/javase/6/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)">java.util.logging.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>.getName());</code></dd>
- <dt><code>@Log4j</code></dt>
- <dd>Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html">org.apache.log4j.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.Class)">org.apache.log4j.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>);</code></dd>
- <dt><code>@Log4j2</code></dt>
- <dd>Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/Logger.html">org.apache.logging.log4j.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.Class)">org.apache.logging.log4j.LogManager.getLogger</a>(LogExample.<span class="keyword">class</span>);</code></dd>
- <dt><code>@Slf4j</code></dt>
- <dd>Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://www.slf4j.org/api/org/slf4j/Logger.html">org.slf4j.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html#getLogger(java.lang.Class)">org.slf4j.LoggerFactory.getLogger</a>(LogExample.<span class="keyword">class</span>);</code></dd>
- <dt><code>@XSlf4j</code></dt>
- <dd>Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://www.slf4j.org/api/org/slf4j/ext/XLogger.html">org.slf4j.ext.XLogger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://www.slf4j.org/apidocs/org/slf4j/ext/XLoggerFactory.html#getXLogger(java.lang.Class)">org.slf4j.ext.XLoggerFactory.getXLogger</a>(LogExample.<span class="keyword">class</span>);</code></dd>
- </dl>
- </p><p>
- By default, the topic (or name) of the logger will be the class name of the class annotated with the <code>@Log</code> annotation. This can be customised by specifying the <code>topic</code> parameter. For example: <code>@XSlf4j(topic="reporting")</code>.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.log.fieldName</code> = <em>an identifier</em> (default: <code>log</code>)</dt>
- <dd>The generated logger fieldname is by default '<code>log</code>', but you can change it to a different name with this setting.</dd>
- <dt><code>lombok.log.fieldIsStatic</code> = [<code>true</code> | <code>false</code>] (default: true)</dt>
- <dd>Normally the generated logger is a <code>static</code> field. By setting this key to <code>false</code>, the generated field will be an instance field instead.</dd>
- <dt><code>lombok.log.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of any of the various log annotations as a warning or error if configured.</dd>
- <dt><code>lombok.log.apacheCommons.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@lombok.extern.apachecommons.CommonsLog</code> as a warning or error if configured.</dd>
- <dt><code>lombok.log.javaUtilLogging.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@lombok.extern.java.Log</code> as a warning or error if configured.</dd>
- <dt><code>lombok.log.log4j.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@lombok.extern.log4j.Log4j</code> as a warning or error if configured.</dd>
- <dt><code>lombok.log.log4j2.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@lombok.extern.log4j.Log4j2</code> as a warning or error if configured.</dd>
- <dt><code>lombok.log.slf4j.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@lombok.extern.slf4j.Slf4j</code> as a warning or error if configured.</dd>
- <dt><code>lombok.log.xslf4j.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@lombok.extern.slf4j.XSlf4j</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- If a field called <code>log</code> already exists, a warning will be emitted and no code will be generated.
- </p><p>
- A future feature of lombok's diverse log annotations is to find calls to the logger field and, if the chosen logging framework supports it and the log level can be compile-time determined from the log call, guard it with an <code>if</code> statement. This way if the log statement ends up being ignored, the potentially expensive calculation of the log string is avoided entirely. This does mean that you should <em>NOT</em> put any side-effects in the expression that you log.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="GetterLazy.html">Previous feature (@Getter(lazy=true))</a> | <a href="configuration.html">Next feature (configuration)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/NonNull.html b/website/features/NonNull.html
deleted file mode 100644
index aa788dbd..00000000
--- a/website/features/NonNull.html
+++ /dev/null
@@ -1,83 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@NonNull</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@NonNull</h1>
- <div class="byline">or: How I learned to stop worrying and love the NullPointerException.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <em>NEW in Lombok 0.11.10: </em>You can use <code>@NonNull</code> on the parameter of a method or constructor to have lombok generate a null-check statement for you.
- </p><p>
- Lombok has always treated any annotation named <code>@NonNull</code> on a field as a signal to generate a null-check if lombok generates an entire method or constructor for you, via
- for example <a href="Data.html"><code>@Data</code></a>. Now, however, using lombok's own <code>@lombok.NonNull</code> on a parameter results in the insertion of just the null-check
- statement inside your own method or constructor.
- </p><p>
- The null-check looks like <code>if (param == null) throw new NullPointerException("param");</code> and will be inserted at the very top of your method. For constructors, the null-check
- will be inserted immediately following any explicit <code>this()</code> or <code>super()</code> calls.
- </p><p>
- If a null-check is already present at the top, no additional null-check will be generated.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.nonNull.exceptionType</code> = [<code>NullPointerException</code> | <code>IllegalArgumentException</code>] (default: <code>NullPointerException</code>).
- <dd>When lombok generates a null-check <code>if</code> statement, by default, a <code>java.lang.NullPointerException</code> will be thrown with the field name as the exception message.
- However, you can use <code>IllegalArgumentException</code> in this configuration key to have lombok throw that exception, with '<em>fieldName</em> is null' as exception message.</dd>
- <dt><code>lombok.nonNull.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@NonNull</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Lombok's detection scheme for already existing null-checks consists of scanning for if statements that look just like lombok's own. Any 'throws' statement as
- the 'then' part of the if statement, whether in braces or not, counts. The conditional of the if statement <em>must</em> look exactly like <code>PARAMNAME == null</code>.
- The first statement in your method that is not such a null-check stops the process of inspecting for null-checks.
- </p><p>
- While <code>@Data</code> and other method-generating lombok annotations will trigger on any annotation named <code>@NonNull</code> regardless of casing or package name,
- this feature only triggers on lombok's own <code>@NonNull</code> annotation from the <code>lombok</code> package.
- </p><p>
- A <code>@NonNull</code> on a primitive parameter results in a warning. No null-check will be generated.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="val.html">Previous feature (val)</a> | <a href="Cleanup.html">Next feature (@Cleanup)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/SneakyThrows.html b/website/features/SneakyThrows.html
deleted file mode 100644
index e1cd6685..00000000
--- a/website/features/SneakyThrows.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@SneakyThrows</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@SneakyThrows</h1>
- <div class="byline">To boldly throw checked exceptions where no one has thrown them before!</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <code>@SneakyThrows</code> can be used to sneakily throw checked exceptions without actually declaring this in your method's <code>throws</code>
- clause. This somewhat contentious ability should be used carefully, of course. The code generated by lombok will not ignore, wrap, replace,
- or otherwise modify the thrown checked exception; it simply fakes out the compiler. On the JVM (class file) level, all exceptions, checked or not,
- can be thrown regardless of the <code>throws</code> clause of your methods, which is why this works.
- </p><p>
- Common use cases for when you want to opt out of the checked exception mechanism center around 2 situations:<br /><ul>
- <li>A needlessly strict interface, such as <code>Runnable</code> - whatever exception propagates out of your <code>run()</code> method,
- checked or not, it will be passed to the <code>Thread</code>'s unhandled exception handler. Catching a checked exception and wrapping it
- in some sort of <code>RuntimeException</code> is only obscuring the real cause of the issue.</li>
- <li>An 'impossible' exception. For example, <code>new String(someByteArray, "UTF-8");</code> declares that it can throw an
- <code>UnsupportedEncodingException</code> but according to the JVM specification, UTF-8 <em>must</em> always be available. An
- <code>UnsupportedEncodingException</code> here is about as likely as a <code>ClassNotFoundError</code> when you use a String object,
- and you don't catch those either!</li></ul>
- </p><p>
- Be aware that it is <em>impossible</em> to catch sneakily thrown checked types directly, as javac will not let you write a catch block
- for an exception type that no method call in the try body declares as thrown. This problem is not relevant in either of the use cases listed
- above, so let this serve as a warning that you should not use the <code>@SneakyThrows</code> mechanism without some deliberation!
- </p><p>
- You can pass any number of exceptions to the <code>@SneakyThrows</code> annotation. If you pass no exceptions, you may throw any
- exception sneakily.
- </p><p>
- <em>NOTE: </em> with lombok versions older than 0.10, unlike other lombok transformations, you need to put <strong>lombok.jar</strong> on your
- classpath when you run your program.
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.sneakyThrows.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@SneakyThrows</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Because <code>@SneakyThrows</code> is an implementation detail and not part of your method signature, it is an error if you try to
- declare a checked exception as sneakily thrown when you don't call any methods that throw this exception. (Doing so is perfectly legal
- for <code>throws</code> statements to accommodate subclasses). Similarly, <code>@SneakyThrows</code> does not inherit.
- </p><p>
- For the nay-sayers in the crowd: Out of the box, Eclipse will offer a 'quick-fix' for uncaught exceptions that wraps the offending
- statement in a try/catch block with just <code>e.printStackTrace()</code> in the catch block. This is so spectacularly non-productive
- compared to just sneakily throwing the exception onwards, that Roel and Reinier feel more than justified in claiming that the
- checked exception system is far from perfect, and thus an opt-out mechanism is warranted.
- </p><p>
- If you put <code>@SneakyThrows</code> on a constructor, any call to a sibling or super constructor is <em>excluded</em> from the <code>@SneakyThrows</code> treatment. This is a
- java restriction we cannot work around: Calls to sibling/super constructors MUST be the first statement in the constructor; they cannot be placed inside try/catch blocks.
- </p><p>
- <code>@SneakyThrows</code> on an empty method, or a constructor that is empty or only has a call to a sibling / super constructor results in no try/catch block and a warning.
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="Value.html">Previous feature (@Value)</a> | <a href="Synchronized.html">Next feature (@Synchronized)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/Synchronized.html b/website/features/Synchronized.html
deleted file mode 100644
index 85c161c3..00000000
--- a/website/features/Synchronized.html
+++ /dev/null
@@ -1,85 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Synchronized</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Synchronized</h1>
- <div class="byline"><code>synchronized</code> done right: Don't expose your locks.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <code>@Synchronized</code> is a safer variant of the <code>synchronized</code> method modifier. Like <code>synchronized</code>, the
- annotation can be used on static and instance methods only. It operates similarly to the <code>synchronized</code> keyword, but it locks
- on different objects. The keyword locks on <code>this</code>, but the annotation locks on a field named <code>$lock</code>, which is private.<br />
- If the field does not exist, it is created for you. If you annotate a <code>static</code> method, the annotation locks on a static field
- named <code>$LOCK</code> instead.
- </p><p>
- If you want, you can create these locks yourself. The <code>$lock</code> and <code>$LOCK</code> fields will of course not be generated if you
- already created them yourself. You can also choose to lock on another field, by specifying it as parameter to the <code>@Synchronized</code>
- annotation. In this usage variant, the fields will not be created automatically, and you must explicitly create them yourself, or an error will be emitted.
- </p><p>
- Locking on <code>this</code> or your own class object can have unfortunate side-effects, as other code not under your control can lock on these
- objects as well, which can cause race conditions and other nasty threading-related bugs.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.synchronized.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Synchronized</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- If <code>$lock</code> and/or <code>$LOCK</code> are auto-generated, the fields are initialized with an empty <code>Object[]</code> array, and not
- just a <code>new Object()</code> as most snippets showing this pattern in action use. Lombok does this because a new object is <em>NOT</em>
- serializable, but 0-size array is. Therefore, using <code>@Synchronized</code> will not prevent your object from being serialized.
- </p><p>
- Having at least one <code>@Synchronized</code> method in your class means there will be a lock field, but if you later remove all such methods,
- there will no longer be a lock field. That means your predetermined <code>serialVersionUID</code> changes. We suggest you <em>always</em> add
- a <code>serialVersionUID</code> to your classes if you intend to store them long-term via java's serialization mechanism. If you do so, removing
- all <code>@Synchronized</code> annotations from your method will not break serialization.
- </p><p>
- If you'd like to know why a field is not automatically generated when you choose your own name for the lock object: Because otherwise making a typo
- in the field name will result in a <em>very</em> hard to find bug!
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="SneakyThrows.html">Previous feature (@SneakyThrows)</a> | <a href="GetterLazy.html">Next feature (@Getter(lazy=true))</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/ToString.html b/website/features/ToString.html
deleted file mode 100644
index 57bbd0f0..00000000
--- a/website/features/ToString.html
+++ /dev/null
@@ -1,92 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@ToString</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@ToString</h1>
- <div class="byline">No need to start a debugger to see your fields: Just let lombok generate a <code>toString</code> for you!</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- Any class definition may be annotated with <code>@ToString</code> to let lombok generate an implementation of the <code>toString()</code> method. By default, it'll print your class name, along with each field, in order, separated by commas.
- </p><p>
- By setting the <code>includeFieldNames</code> parameter to <em>true</em> you can add some clarity (but also quite some length) to the output of the <code>toString()</code> method.
- </p><p>
- By default, all non-static fields will be printed. If you want to skip some fields, you can name them in the <code>exclude</code> parameter; each named field will not be printed at all. Alternatively, you can specify exactly which fields you wish to be used by naming them in the <code>of</code> parameter.
- </p><p>
- By setting <code>callSuper</code> to <em>true</em>, you can include the output of the superclass implementation of <code>toString</code> to the output. Be aware that the default implementation of <code>toString()</code> in <code>java.lang.Object</code> is pretty much meaningless, so you probably don't want to do this unless you are extending another class.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.toString.includeFieldNames</code> = [<code>true</code> | <code>false</code>] (default: true)</dt>
- <dd>Normally lombok generates a fragment of the toString response for each field in the form of <code>fieldName = fieldValue</code>. If this setting is set to <code>false</code>, lombok will omit the name of the field and simply deploy a comma-separated list of all the field values. The annotation parameter '<code>includeFieldNames</code>', if explicitly specified, takes precedence over this setting.</dd>
- <dt><code>lombok.toString.doNotUseGetters</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, lombok will access fields directly instead of using getters (if available) when generating <code>toString</code> methods. The annotation parameter '<code>doNotUseGetters</code>', if explicitly specified, takes precedence over this setting.</dd>
- <dt><code>lombok.toString.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@ToString</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- If there is <em>any</em> method named <code>toString</code> with no arguments, regardless of return type, no method will be generated, and instead a warning is emitted explaining that your <code>@ToString</code> annotation is doing nothing. You can mark any method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
- </p><p>
- Arrays are printed via <code>Arrays.deepToString</code>, which means that arrays that contain themselves will result in <code>StackOverflowError</code>s. However,
- this behaviour is no different from e.g. <code>ArrayList</code>.
- </p><p>
- Attempting to exclude fields that don't exist or would have been excluded anyway (because they are static) results in warnings on the named fields.
- You therefore don't have to worry about typos.
- </p><p>
- Having both <code>exclude</code> and <code>of</code> generates a warning; the <code>exclude</code> parameter will be ignored in that case.
- </p><p>
- We don't promise to keep the output of the generated <code>toString()</code> methods the same between lombok versions. You should never design your API so that
- other code is forced to parse your <code>toString()</code> output anyway!
- </p><p>
- By default, any variables that start with a $ symbol are excluded automatically. You can only include them by using the 'of' parameter.
- </p><p>
- If a getter exists for a field to be included, it is called instead of using a direct field reference. This behaviour can be suppressed:<br />
- <code>@ToString(doNotUseGetters = true)</code>
- </p><p>
- <code>@ToString</code> can also be used on an enum definition.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="GetterSetter.html">Previous feature (@Getter / @Setter)</a> | <a href="EqualsAndHashCode.html">Next feature (@EqualsAndHashCode)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/Value.html b/website/features/Value.html
deleted file mode 100644
index 0e221b63..00000000
--- a/website/features/Value.html
+++ /dev/null
@@ -1,86 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Value</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>@Value</h1>
- <div class="byline">Immutable classes made very easy.</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- <code>@Value</code> was introduced as experimental feature in lombok v0.11.4.
- </p><p>
- <code>@Value</code> no longer implies <code>@Wither</code> since lombok v0.11.8.
- </p><p>
- <code>@Value</code> promoted to the main <code>lombok</code> package since lombok v0.12.0.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <code>@Value</code> is the immutable variant of <a href="Data.html"><code>@Data</code></a>; all fields are made <code>private</code> and <code>final</code> by default, and setters are not generated. The class itself is also made <code>final</code> by default, because immutability is not something that can be forced onto a subclass. Like <code>@Data</code>, useful <code>toString()</code>, <code>equals()</code> and <code>hashCode()</code> methods are also generated, each field gets a getter method, and a constructor that covers every
- argument (except <code>final</code> fields that are initialized in the field declaration) is also generated.
- </p><p>
- In practice, <code>@Value</code> is shorthand for: <code>final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter</code>, except that explicitly including an implementation of any of the relevant methods simply means that part won't be generated and no warning will be emitted. For example, if you write your own <code>toString</code>, no error occurs, and lombok will not generate a <code>toString</code>. Also, <em>any</em> explicit constructor, no matter the arguments list, implies lombok will not generate a constructor. If you do want lombok to generate the all-args constructor, add <code>@AllArgsConstructor</code> to the class. You can mark any constructor or method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
- </p><p>
- It is possible to override the final-by-default and private-by-default behaviour using either an explicit access level on a field, or by using the <code>@NonFinal</code> or <code>@PackagePrivate</code> annotations.<br />
- It is possible to override any default behaviour for any of the 'parts' that make up <code>@Value</code> by explicitly using that annotation.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.value.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Value</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Look for the documentation on the 'parts' of <code>@Value</code>: <a href="ToString.html"><code>@ToString</code></a>, <a href="EqualsAndHashCode.html"><code>@EqualsAndHashCode</code></a>, <a href="Constructor.html"><code>@AllArgsConstructor</code></a>, <a href="experimental/FieldDefaults.html"><code>@FieldDefaults</code></a>, and <a href="GetterSetter.html"><code>@Getter</code></a>.
- </p><p>
- For classes with generics, it's useful to have a static method which serves as a constructor, because inference of generic parameters via static methods works in java6 and avoids having to use the diamond operator. While you can force this by applying an explicit <code>@AllArgsConstructor(staticConstructor="of")</code> annotation, there's also the <code>@Value(staticConstructor="of")</code> feature, which will make the generated all-arguments constructor private, and generates a public static method named <code>of</code> which is a wrapper around this private constructor.
- </p><p>
- <code>@Value</code> was an experimental feature from v0.11.4 to v0.11.9 (as <code>@lombok.experimental.Value</code>). It has since been moved into the core package. The old annotation is still
- around (and is an alias). It will eventually be removed in a future version, though.
- </p><p>
- It is not possible to use <code>@FieldDefaults</code> to 'undo' the private-by-default and final-by-default aspect of fields in the annotated class. Use <code>@NonFinal</code> and <code>@PackagePrivate</code> on the fields in the class to override this behaviour.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="Data.html">Previous feature (@Data)</a> | <a href="SneakyThrows.html">Next feature (@SneakyThrows)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/clear.gif b/website/features/clear.gif
deleted file mode 100644
index 35d42e80..00000000
--- a/website/features/clear.gif
+++ /dev/null
Binary files differ
diff --git a/website/features/configuration.html b/website/features/configuration.html
deleted file mode 100644
index acf874e7..00000000
--- a/website/features/configuration.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Configuration system</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>Configuration system</h1>
- <div class="byline">Lombok, made to order: Configure lombok features in one place for your entire project or even your workspace.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <em>NEW in lombok 1.14: </em>You can create <code>lombok.config</code> files in any directory and put configuration directives in it. These apply to all source files in this directory and all child directories.<br />
- The configuration system is particularly useful for configurable aspects of lombok which tend to be the same across an entire project, such as the name of your log variable. The configuration system can also be used to tell lombok to flag any usage of some lombok feature you don't like as a warning or even an error.
- </p><p>
- Usually, a user of lombok puts a <code>lombok.config</code> file with their preferences in a workspace or project root directory, with the special <code>config.stopBubbling = true</code> key to tell lombok this is your root directory. You can then create <code>lombok.config</code> files in any subdirectories (generally representing projects or source packages) with different settings.
- </p><p>
- An up to date list of all configuration keys supported by your version of lombok can be generated by running:
- <div class="snippet example"><code>java -jar lombok.jar config -g --verbose</code></div>
- The output of the <em>config</em> tool is itself a valid <code>lombok.config</code> file.<br />
- The <em>config</em> tool can also be used to display the complete lombok configuration used for any given directory or source file by supplying these as arguments.
- </p><p>
- A sample of available configuration options (see the feature pages of the lombok features for their related config keys, as well as <code>java -jar lombok.jar config -g</code> for the complete list):
- <dl>
- <dt><code>lombok.accessors.chain</code></dt>
- <dd>If set to <code>true</code>, generated setters will 'chain' by default (They will return <code>this</code> instead of having a <code>void</code> return type).</dd>
- <dt><code>lombok.accessors.fluent</code></dt>
- <dd>If set to <code>true</code>, generated setters and getters will simply be named the same as the field name, without a <code>get</code> or <code>set</code> prefix.</dd>
- <dt><code>lombok.anyConstructor.suppressConstructorProperties</code></dt>
- <dd>If <code>true</code>, lombok will not generate a <code>@java.beans.ConstructorProperties</code> annotation when generating constructors. This is particularly useful for GWT and Android development.</dd>
- <dt><code>lombok.log.fieldName</code></dt>
- <dd>The name of the generated log field (default: <code>log</code>).</dd>
- <dt><code>lombok.<em>(featureName)</em>.flagUsage</code></dt>
- <dd>Allows you to forcibly stop or discourage use of a lombok feature. Legal values for this key are <code>warning</code> or <code>error</code>. Some examples of values for <em>(featureName)</em> are: "<code>experimental</code>" (flags use of any of the <a href="experimental/index.html">experimental</a> features)</li>, "<a href="experimental/Builder.html"><code>builder</code></a>", "<a href="SneakyThrows.html"><code>sneakyThrows</code></a>", or "<a href="experimental/ExtensionMethod.html"><code>extensionMethod</code></a>".</dd>
- </dl>
- </p><p>
- Configuration files are hierarchical: Any configuration setting applies to all source files in that directory, and all source files in subdirectories, but configuration settings closer to the source file take precedence. For example, if you have in <code>/Users/me/projects/lombok.config</code> the following:
- <div class="snippet example">
- <code>lombok.log.fieldName = foobar</code>
- </div></div>
- and in <code>/Users/me/projects/MyProject/lombok.config</code> you have:
- <div class="snippet example">
- <code>lombok.log.fieldName = xyzzy</code>
- </div>
-
- Then the various <a href="Log.html"><code>@Log</code></a> annotations will use <code>foobar</code> instead of the default <code>log</code> as a field name to generate in all your projects,
- except for your project in <code>/Users/me/projects/MyProject</code>, where <code>xyzzy</code> is used instead.
- </p><p>
- To restore a configuration key set by a parent config file back to the default, the <code>clear</code> option can be used. For example, if a parent configuration file has configured all use of <code>val</code> to emit a warning, you can turn off the warnings for a subdirectory by including in it a <code>lombok.config</code> file with:
- <div class="snippet example">
- <code>clear lombok.val.flagUsage</code>
- </div>
- </p><p>
- Some configuration keys take lists. For lists, use <code>+=</code> to add an entry. You can remove a single item from the list (useful to undo a parent configuration file's setting) with <code>-=</code>. For example:
- <div class="snippet example">
- <code>lombok.accessors.prefix += m_</code>
- </div>
- </p><p>
- To stop lombok from looking at parent directories for more configuration files, the special key:
- <div class="snippet example">
- <code>config.stopBubbling = true</code>
- </div>
- can be included.
- </p><p>
- Comments can be included in <code>lombok.config</code> files; any line that starts with <code>#</code> is considered a comment.
- </p>
- </div>
- <div style="clear: left;"></div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <a href="Log.html">Previous feature (@Log)</a> | <span class="disabled">Next feature</span><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/delombok.html b/website/features/delombok.html
deleted file mode 100644
index 30f21c04..00000000
--- a/website/features/delombok.html
+++ /dev/null
@@ -1,80 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>delombok</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>delombok</h1>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- Normally, lombok adds support for all the lombok features directly to your IDE and compiler by plugging into them.<br />
- However, lombok doesn't cover all tools. For example, lombok cannot plug into javadoc, nor can it plug into the Google Widget Toolkit, both of which
- run on java sources. Delombok still allows you to use lombok with these tools by preprocessing your java code into java code with all of lombok's
- transformations already applied.
- </p><p>
- Delombok can of course also help understand what's happening with your source by letting you look at exactly what lombok is doing 'under the hood'.
- </p><p>
- Delombok's standard mode of operation is that it copies an entire directory into another directory, recursively, skipping class files, and applying
- lombok transformations to any java source files it encounters.
- </p><p>
- Delombok's output format can be configured with command line options (use <code>--format-help</code> for a complete list). A few such options are automatically scanned from input if possible (such as indent). If delombok's formatting is not conforming to your preferred code style, have a look!
- </p>
- <h3>Running delombok on the command line</h3>
- <p>
- Delombok is included in <code>lombok.jar</code>. To use it, all you need to run on the command line is:
- <div class="snippet"><pre>java -jar lombok.jar delombok src -d src-delomboked</pre></div>
- <br />
- Which will duplicate the contents of the <code>src</code> directory into the <code>src-delomboked</code> directory, which will be created if it
- doesn't already exist, but delomboked of course. Delombok on the command line has a few more options; use the <code>--help</code> parameter to see more options.
- </p><p>
- To let delombok print the transformation result of a single java file directly to standard output, you can use:
- <div class="snippet"><pre>java -jar lombok.jar delombok -p MyJavaFile.java</pre></div>
- </p>
- <h3>Running delombok in ant</h3>
- <code>lombok.jar</code> includes an ant task which can apply delombok for you. For example, to create javadoc for your project, your <code>build.xml</code> file
- would look something like:
- <div class="snippet"><pre>&lt;target name="javadoc"&gt;
- &lt;taskdef classname="lombok.delombok.ant.DelombokTask" classpath="lib/lombok.jar" name="delombok" /&gt;
- &lt;mkdir dir="build/src-delomboked" /&gt;
- <strong>&lt;delombok verbose="true" encoding="UTF-8" to="build/src-delomboked" from="src"&gt;</strong>
- <strong>&lt;format value="suppressWarnings:skip" /&gt;</strong>
- <strong>&lt;/delombok&gt;</strong>
- &lt;mkdir dir="build/api" /&gt;
- &lt;javadoc sourcepath="build/src-delomboked" defaultexcludes="yes" destdir="build/api" /&gt;
-&lt;/target&gt;</pre></div>
- <br />
- Instead of a <code>from</code> attribute, you can also nest <code>&lt;fileset&gt;</code> nodes.
- <h3>Running delombok in maven</h3>
- Anthony Whitford has written a <a href="https://github.com/awhitford/lombok.maven">maven plugin</a> for delomboking your source code.
- <h3>Limitations</h3>
- Delombok tries to preserve your code as much as it can, but comments may move around a little bit, especially comments that are in the middle of
- a syntax node. For example, any comments appearing in the middle of a list of method modifiers, such as <code>public /*comment*/ static ...</code> will
- move towards the front of the list of modifiers. In practice, any java source parsing tool will not be affected.<br />
- To keep any changes to your code style to a minimum, delombok just copies a source file directly without changing any of it if the source file contains
- no lombok transformations.
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/Accessors.html b/website/features/experimental/Accessors.html
deleted file mode 100644
index 20590a07..00000000
--- a/website/features/experimental/Accessors.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>EXPERIMENTAL - @Accessors</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>@Accessors</h1>
- <div class="byline">A more fluent API for getters and setters.</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- @Accessors was introduced as experimental feature in lombok v0.11.0.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>We may want to roll these features into a more complete property support concept.</li>
- <li>New feature - community feedback requested.</li>
- </ul>
- Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- The <code>@Accessors</code> annotation is used to configure how lombok generates and looks for getters and setters.
- </p><p>
- By default, lombok follows the <em>bean specification</em> for getters and setters: The getter for a field named <code>pepper</code>
- is <code>getPepper</code> for example. However, some might like to break with the <em>bean specification</em> in order to end up with
- nicer looking APIs. <code>@Accessors</code> lets you do this.
- </p><p>
- Some programmers like to use a prefix for their fields, i.e. they write <code>fPepper</code> instead of <code>pepper</code>.
- We <em>strongly</em> discourage doing this, as you can't unit test the validity of your prefixes, and refactor scripts may turn fields
- into local variables or method names. Furthermore, your tools (such as your editor) can take care of rendering the identifier in a
- certain way if you want this information to be instantly visible. Nevertheless, you can list the prefixes that your project uses via
- <code>@Accessors</code> as well.
- </p><p>
- <code>@Accessors</code> therefore has 3 options:<ul>
- <li><code>fluent</code> - A boolean. If <em>true</em>, the getter for <code>pepper</code> is just <code>pepper()</code>, and the
- setter is <code>pepper(T newValue)</code>. Furthermore, unless specified, <code>chain</code> defaults to <em>true</em>.<br />
- Default: <em>false</em>.</li>
- <li><code>chain</code> - A boolean. If <em>true</em>, generated setters return <code>this</code> instead of <code>void</code>.<br />
- Default: <em>false</em>, unless <code>fluent=true</code>, then Default: <em>true</em>.</li>
- <li><code>prefix</code> - A list of strings. If present, fields must be prefixed with any of these prefixes. Each field name is
- compared to each prefix in the list in turn, and if a match is found, the prefix is stripped out to create the base name for
- the field. It is legal to include an empty string in the list, which will always match. For characters which are letters, the
- character following the prefix must not be a lowercase letter, i.e. <code>pepper</code> is not a match even to prefix <code>p</code>,
- but <code>pEpper</code> would be (and would mean the base name of this field is <code>epper</code>).</li>
- </p><p>
- The <code>@Accessors</code> annotation is legal on types and fields; the annotation that applies is the one on the field if present,
- otherwise the one on the class. When a <code>@Accessors</code> annotation on a field is present, any <code>@Accessors</code> annotation
- also present on that field's type is ignored.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.accessors.chain</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, any class that either doesn't have an <code>@Accessors</code> annotation, or it does, but that annotation does not have an explicit value for the <code>chain</code> parameter, will act as if <code>@Accessors(chain = true)</code> is present.</dd>
- <dt><code>lombok.accessors.fluent</code> = [<code>true</code> | <code>false</code>] (default: false)</dt>
- <dd>If set to <code>true</code>, any class that either doesn't have an <code>@Accessors</code> annotation, or it does, but that annotation does not have an explicit value for the <code>fluent</code> parameter, will act as if <code>@Accessors(fluent = true)</code> is present.</dd>
- <dt><code>lombok.accessors.prefix</code> += <em>a field prefix</em> (default: empty list)</dt>
- <dd>This is a list property; entries can be added with the <code>+=</code> operator. Inherited prefixes from parent config files can be removed with the <code>-=</code> operator. Any class that either doesn't have an <code>@Accessors</code> annotation, or it does, but that annotation does not have an explicit value for the <code>prefix</code> parameter, will act as if <code>@Accessors(prefix = {<em>prefixes listed in configuration</em>})</code> is present.</dd>
- <dt><code>lombok.accessors.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Accessors</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- The nearest <code>@Accessors</code> annotation is also used for the various methods in lombok that look for getters, such as
- <code>@EqualsAndHashCode</code>.
- </p><p>
- If a prefix list is provided and a field does not start with one of them, that field is skipped entirely by lombok, and
- a warning will be generated.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <a href="Builder.html">Previous feature (@Builder)</a> | <a href="ExtensionMethod.html">Next feature (@ExtensionMethod)</a><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/Builder.html b/website/features/experimental/Builder.html
deleted file mode 100644
index a8e21b9a..00000000
--- a/website/features/experimental/Builder.html
+++ /dev/null
@@ -1,141 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>EXPERIMENTAL - @Builder</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>@Builder</h1>
- <div class="byline">... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- @Builder was introduced as experimental feature in lombok v0.12.0.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>New feature - community feedback requested.</li>
- </ul>
- Current status: <em>sure thing</em> - This feature will move to the core package soon.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- The <code>@Builder</code> annotation produces complex builder APIs for your classes.
- </p><p>
- <code>@Builder</code> lets you automatically produce the code required to have your class be instantiable with code such as:<br />
- <code>Person.builder().name("Adam Savage").city("San Francisco").worksAt("Mythbusters").build();</code>
- </p><p>
- <code>@Builder</code> can be placed on a class, or on a constructor, or on a static method. While the "on a class" and "on a constructor"
- mode are the most common use-case, <code>@Builder</code> is most easily explained with the "static method" use-case.
- </p><p>
- A static method annotated with <code>@Builder</code> (from now on called the <em>target</em>) causes the following 7 things to be generated:<ul>
- <li>An inner static class named <code><em>Foo</em>Builder</code>, with the same type arguments as the static method (called the <em>builder</em>).</li>
- <li>In the <em>builder</em>: One private non-static non-final field for each parameter of the <em>target</em>.</li>
- <li>In the <em>builder</em>: A package private no-args empty constructor.</li>
- <li>In the <em>builder</em>: A 'setter'-like method for each parameter of the <em>target</em>: It has the same type as that parameter and the same name.
- It returns the builder itself, so that the setter calls can be chained, as in the above example.</li>
- <li>In the <em>builder</em>: A <code>build()</code> method which calls the static method, passing in each field. It returns the same type that the
- <em>target</em> returns.</li>
- <li>In the <em>builder</em>: A sensible <code>toString()</code> implementation.</li>
- <li>In the class containing the <em>target</em>: A <code>builder()</code> method, which creates a new instance of the <em>builder</em>.</li>
- </ul>
- Each listed generated element will be silently skipped if that element already exists (disregarding parameter counts and looking only at names). This
- includes the <em>builder</em> itself: If that class already exists, lombok will simply start injecting fields and methods inside this already existing
- class, unless of course the fields / methods to be injected already exist. You may not put any other method (or constructor) generating lombok annotation
- on a builder class though; for example, you can not put <code>@EqualsAndHashCode</code> on the builder class.
- </p><p>
- Now that the "static method" mode is clear, putting a <code>@Builder</code> annotation on a constructor functions similarly; effectively,
- constructors are just static methods that have a special syntax to invoke them: Their 'return type' is the class they construct, and their
- type parameters are the same as the type parameters of the class itself.
- </p><p>
- Finally, applying <code>@Builder</code> to a class is as if you added <code>@AllArgsConstructor(access = AccessLevel.PACKAGE)</code> to the class and applied the
- <code>@Builder</code> annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself. If you do have an
- explicit constructor, put the <code>@Builder</code> annotation on the constructor instead of on the class.
- </p><p>
- The name of the builder class is <code><em>Foobar</em>Builder</code>, where <em>Foobar</em> is the simplified, title-cased form of the return type of the
- <em>target</em> - that is, the name of your type for <code>@Builder</code> on constructors and types, and the name of the return type for <code>@Builder</code>
- on static methods. For example, if <code>@Builder</code> is applied to a class named <code>com.yoyodyne.FancyList&lt;T&gt;</code>, then the builder name will be
- <code>FancyListBuilder&lt;T&gt;</code>. If <code>@Builder</code> is applied to a static method that returns <code>void</code>, the builder will be named
- <code>VoidBuilder</code>.
- </p><p>
- The configurable aspects of builder are:<ul>
- <li>The <em>builder's class name</em> (default: return type + 'Builder')</li>
- <li>The <em>build()</em> method's name (default: <code>"build"</code>)</li>
- <li>The <em>builder()</em> method's name (default: <code>"builder"</code>)</li>
- <li>The 'fluent' nature of the generated 'setter'-like methods. A fluent 'setter' is named just <code>fieldName()</code>, a non-fluent one is named <code>setFieldName()</code>. (default: <code>true</code>)</li>
- <li>The 'chain' nature of the generated 'setter'-like methods. A chainable 'setter' returns the builder object itself, letting you chain 'set' calls. A non-chainable setter returns <code>void</code>. (default: <code>true</code>)</li>
- </ul>
- Example usage where all options are changed from their defaults:<br />
- <code>@Builder(builderClassName = "HelloWorldBuilder", buildMethodName = "execute", builderMethodName = "helloWorld", fluent = false, chain = false)</code><br />
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.builder.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Builder</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Another strategy for fluent APIs is that the programmer using your library statically imports your 'builder' method. In this case, you might want to name your builder
- method equal to your type's name. So, the builder method for a class called <code>Person</code> would become <code>person()</code>. This is nicer if the builder method
- is statically imported.
- </p><p>
- If the return type of your target static method is a type parameter (such as <code>T</code>), lombok will enforce an explicit builder class name.
- </p><p>
- You don't HAVE to use <code>@Builder</code> to build anything; you can for example put it on a static method that has lots of parameter to improve the API of it.
- In this case, we suggest you use <code>buildMethodName = </code> to rename the build method to <code>execute()</code> instead.
- </p><p>
- The builder class will NOT get an auto-generated implementation of <code>hashCode</code> or <code>equals</code> methods! These would suggest that it is sensible to use
- instances of a builder as keys in a set or map. However, that's not a sensible thing to do. Hence, no <code>hashCode</code> or <code>equals</code>.
- </p><p>
- Generics are sorted out for you.
- </p><p>
- If an explicit constructor is present, but <code>@Builder</code> is placed on the class, then the builder will be generated as if an explicit constructor is present with the
- same arguments list as what <code>@AllArgsConstructor</code> would produce. If this constructor does not exist, a compile time error will result. Usually you should just either let
- lombok make this constructor (delete your constructor from the source), or, move the <code>@Builder</code> annotation to the constructor.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <span class="disabled">Previous feature</span> | <a href="Accessors.html">Next feature (@Accessors)</a><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/Delegate.html b/website/features/experimental/Delegate.html
deleted file mode 100644
index bd4fc393..00000000
--- a/website/features/experimental/Delegate.html
+++ /dev/null
@@ -1,100 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>@Delegate</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>@Delegate</h1>
- <div class="byline">Don't lose your composition.</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- @Delegate was introduced as feature in lombok v0.10. It was moved to the experimental package in lombok v1.14; the old version from the main lombok package is now deprecated.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>Not used that much</li>
- <li>Difficult to support for edge cases, such as recursive delegation.</li>
- <li>API is rather unfriendly; it would be a lot nicer if you can simply implement some methods and let <code>@Delegate</code> generate delegates for whatever you didn't manually implement, but due to issues with generics erasure this also can't be made to work without caveats.
- </ul>
- Current status: <em>negative</em> - Currently we feel this feature will not move out of experimental status anytime soon, and support for this feature may be dropped if future versions of javac or ecj make it difficult to continue to maintain the feature.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- Any field or no-argument method can be annotated with <code>@Delegate</code> to let lombok generate delegate methods that forward the call to this field (or the result of invoking this method).
- </p><p>
- Lombok delegates all <code>public</code> methods of the field's type (or method's return type), as well as those of its supertypes except for all
- methods declared in <code>java.lang.Object</code>.
- </p><p>
- You can pass any number of classes into the <code>@Delegate</code> annotation's <code>types</code> parameter.
- If you do that, then lombok will delegate all <code>public</code> methods in those types (and their supertypes, except <code>java.lang.Object</code>) instead of looking at the field/method's type.
- </p><p>
- All public non-<code>Object</code> methods that are part of the calculated type(s) are copied, whether or not you also wrote implementations for those methods. That would thus result in duplicate method errors. You can avoid these
- by using the <code>@Delegate(excludes=SomeType.class)</code> parameter to exclude all public methods in the excluded type(s), and their supertypes.
- </p><p>
- To have very precise control over what is delegated and what isn't, write private inner interfaces with method signatures, then specify these
- private inner interfaces as types in <code>@Delegate(types=PrivateInnerInterfaceWithIncludesList.class, excludes=SameForExcludes.class)</code>.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.delegate.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Delegate</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- When passing classes to the annotation's <code>types</code> or <code>excludes</code> parameter, you cannot include generics.
- This is a limitation of java. Use private inner interfaces or classes that extend the intended type including the
- generics parameter to work around this problem.
- </p><p>
- When passing classes to the annotation, these classes do not need to be supertypes of the field. See the example.
- </p><p>
- <code>@Delegate</code> cannot be used on static fields or methods.
- </p><p>
- <code>@Delegate</code> cannot be used when the calculated type(s) to delegate / exclude themselves contain <code>@Delegate</code> annotations; in other words, <code>@Delegate</code> will error if you attempt to use it recursively.
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <a href="FieldDefaults.html">Previous feature (@FieldDefaults)</a> | <a href="Wither.html">Next feature (@Wither)</a><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/ExtensionMethod.html b/website/features/experimental/ExtensionMethod.html
deleted file mode 100644
index 58aaf1b3..00000000
--- a/website/features/experimental/ExtensionMethod.html
+++ /dev/null
@@ -1,116 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>EXPERIMENTAL - @ExtensionMethod</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>@ExtensionMethod</h1>
- <div class="byline">Annoying API? Fix it yourself: Add new methods to existing types!</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- @ExtensionMethod was introduced as experimental feature in lombok v0.11.2.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>High-impact on code style</li>
- <li>Really would like to ship with utility methods to expand common classes, but so far lombok doesn't have a good distribution method for such runtime dependencies</li>
- <li>Affects quite a bit of eclipse, and auto-complete e.d. do not work yet in netbeans</li>
- <li>Should @ExtensionMethod be legal on methods? Should it be legal on packages?</li>
- </ul>
- Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- You can make a class containing a bunch of <code>public</code>, <code>static</code> methods which all take at least 1
- parameter. These methods will extend the type of the first parameter, as if they were instance methods, using the
- <code>@ExtensionMethod</code> feature.
- </p>
- </p><p>
- For example, if you create <code>public static String toTitleCase(String in) { ... }</code>, you can use the
- <code>@ExtensionMethod</code> feature to make it look like the <code>java.lang.String</code> class has a method named
- <code>toTitleCase</code>, which has no arguments. The first argument of the static method fills the role of <code>this</code>
- in instance methods.
- </p><p>
- All methods that are <code>public</code>, <code>static</code>, and have at least 1 argument whose type is not primitive, are
- considered extension methods, and each will be injected into the namespace of the type of the first parameter as if they were
- instance methods. As in the above example, a call that looks like: <code>foo.toTitleCase()</code> is replaced with
- <code>ClassContainingYourExtensionMethod.toTitleCase(foo);</code>. Note that it is actually not an instant
- <code>NullPointerException</code> if <code>foo</code> is null - it is passed like any other parameter.
- </p><p>
- You can pass any number of classes to the <code>@ExtensionMethod</code> annotation; they will all be searched for
- extension methods. These extension methods apply for any code that is in the annotated class.
- </p><p>
- Lombok does not (currently) have any runtime dependencies which means lombok does not (currently) ship with any useful
- extension methods so you'll have to make your own. However, here's one that might spark your imagination:
- <pre>public class ObjectExtensions {
- public static &lt;T&gt; or(T object, T ifNull) {
- return object != null ? object : ifNull;
- }
-}</pre>
- With the above class, if you add <code>@ExtensionMethod(ObjectExtensions.class)</code> to your class definition, you can write:
- <pre>String x = null;
-System.out.println(x.or("Hello, World!"));</pre>
- The above code will not fail with a <code>NullPointerException</code>; it will actually output <code>Hello, World!</code>
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.extensionMethod.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@ExtensionMethod</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Calls are rewritten to a call to the extension method; the static method itself is not inlined. Therefore, the
- extension method must be present both at compile and at runtime.
- </p><p>
- Generics is fully applied to figure out extension methods. i.e. if the first parameter of your extension method is
- <code>List&lt;? extends String&gt;</code>, then any expression that is compatible with that will have your extension method,
- but other kinds of lists won't. So, a <code>List&lt;Object&gt;</code> won't get it, but a <code>List&lt;String&gt;</code> will.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <a href="Accessors.html">Previous feature (@Accessors)</a> | <a href="FieldDefaults.html">Next feature (@FieldDefaults)</a><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/FieldDefaults.html b/website/features/experimental/FieldDefaults.html
deleted file mode 100644
index 12ea7d80..00000000
--- a/website/features/experimental/FieldDefaults.html
+++ /dev/null
@@ -1,91 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>EXPERIMENTAL - @FieldDefaults</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>@FieldDefaults</h1>
- <div class="byline">New default field modifiers for the 21st century.</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- @FieldDefaults was introduced as experimental feature in lombok v0.11.4.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>New feature; unsure if this busts enough boilerplate</li>
- <li>Would be nice if you could stick this on the package-info.java package to set the default for all classes in that package</li>
- <li>Part of the work on @Value, which is experimental</li>
- </ul>
- Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- The <code>@FieldDefaults</code> annotation can add an access modifier (<code>public</code>, <code>private</code>, or <code>protected</code>)
- to each field in the annotated class or enum. It can also add <code>final</code> to each field in the annotated class or enum.
- </p>
- </p><p>
- To add <code>final</code> to each field, use <code>@FieldDefaults(makeFinal=true)</code>. Any non-final field which must remain nonfinal
- can be annotated with <code>@NonFinal</code> (also in the <code>lombok.experimental</code> package).
- </p><p>
- To add an access modifier to each field, use <code>@FieldDefaults(level=AccessLevel.PRIVATE)</code>. Any field that does not already have an
- access modifier (i.e. any field that looks like package private access) is changed to have the appropriate access modifier. Any package private
- field which must remain package private can be annotated with <code>@PackagePrivate</code> (also in the <code>lombok.experimental</code> package).
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.fieldDefaults.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@FieldDefaults</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Like other lombok handlers that touch fields, any field whose name starts with a dollar (<code>$</code>) symbol is skipped entirely.
- Such a field will not be modified at all.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <a href="ExtensionMethod.html">Previous feature (@ExtensionMethod)</a> | <a href="Delegate.html">Next feature (@Delegate)</a><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/Wither.html b/website/features/experimental/Wither.html
deleted file mode 100644
index 9ca43a46..00000000
--- a/website/features/experimental/Wither.html
+++ /dev/null
@@ -1,111 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>EXPERIMENTAL - @ExtensionMethod</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>@Wither</h1>
- <div class="byline">Immutable 'setters' - methods that create a clone but with one changed field.</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- @Wither was introduced as experimental feature in lombok v0.11.4.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>Still not sure that <code>@Wither</code> is an appropriate name for this feature.</li>
- <li>Should there be an option to supply a way of cloning the input somehow?</li>
- <li>Should the way that the clone is created by configurable?</li>
- <li>Should we replace @Wither entirely with a builder class?</li>
- </ul>
- Current status: <em>neutral</em> - More feedback requires on the items in the above list before promotion to the main package is warranted.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- The next best alternative to a setter for an immutable property is to construct a clone of the object, but with a new value for this one field.
- A method to generate this clone is precisely what <code>@Wither</code> generates: a <code>withFieldName(newValue)</code> method which produces a clone
- except for the new value for the associated field.
- </p><p>
- For example, if you create <code>public class Point { private final int x, y; }</code>, setters make no sense because the fields
- are final. <code>@Wither</code> can generate a <code>withX(int newXValue)</code> method for you which will return a new point with the supplied
- value for <code>x</code> and the same value for <code>y</code>.
- </p><p>
- Like <a href="../GetterSetter.html"><code>@Setter</code></a>, you can specify an access level in case you want the generated wither to be something other than <code>public</code>:<br />
- <code>@Wither(level = AccessLevel.PROTECTED)</code>. Also like <a href="../GetterSetter.html"><code>@Setter</code></a>, you can also put a <code>@Wither</code> annotation on a type, which means
- a 'wither' is generated for each field (even non-final fields).
- </p><p>
- To put annotations on the generated method, you can use <code>onMethod=@__({@AnnotationsHere})</code>; to put annotations on the only parameter of a generated wither method, you can use <code>onParam=@__({@AnnotationsHere})</code>. Be careful though! This is an experimental feature. For more details see the documentation on the <a href="onX.html">onX</a> feature.
- </p><p>
- <em>NEW in lombok v1.12.0:</em> javadoc on the field will now be copied to generated withers. Normally, all text is copied, and <code>@param</code> is <em>moved</em> to the wither, whilst <code>@return</code> lines are stripped from the wither's javadoc. Moved means: Deleted from the field's javadoc. It is also possible to define unique text for the wither's javadoc. To do that, you create a 'section' named <code>WITHER</code>. A section is a line in your javadoc containing 2 or more dashes, then the text 'WITHER', followed by 2 or more dashes, and nothing else on the line. If you use sections, <code>@return</code> and <code>@param</code> stripping / copying for that section is no longer done (move the <code>@param</code> line into the section).
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.wither.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>@Wither</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- Withers cannot be generated for static fields because that makes no sense.
- </p><p>
- When applying <code>@Wither</code> to a type, static fields and fields whose name start with a $ are skipped.
- </p><p>
- For generating the method names, the first character of the field, if it is a lowercase character, is title-cased, otherwise, it is left unmodified.
- Then, <code>with</code> is prefixed.
- </p><p>
- No method is generated if any method already exists with the same name (case insensitive) and same parameter count. For example, <code>withX(int x)</code>
- will not be generated if there's already a method <code>withX(String... x)</code> even though it is technically possible to make the method. This caveat
- exists to prevent confusion. If the generation of a method is skipped for this reason, a warning is emitted instead. Varargs count as 0 to N parameters.
- </p><p>
- For <code>boolean</code> fields that start with <code>is</code> immediately followed by a title-case letter, nothing is prefixed to generate the wither name.
- </p><p>
- Any annotations named <code>@NonNull</code> (case insensitive) on the field are interpreted as: This field must not ever hold
- <em>null</em>. Therefore, these annotations result in an explicit null check in the generated wither. Also, these
- annotations (as well as any annotation named <code>@Nullable</code> or <code>@CheckForNull</code>) are copied to wither parameter.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <a href="Delegate.html">Previous feature (@Delegate)</a> | <a href="onX.html">Next feature (onX)</a><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/index.html b/website/features/experimental/index.html
deleted file mode 100644
index f37712e0..00000000
--- a/website/features/experimental/index.html
+++ /dev/null
@@ -1,71 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Lombok feature overview</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>Lombok experimental features</h1>
- <div class="index overview">
- Experimental features are available in your normal lombok installation, but are not as robustly supported as lombok's main features.
- In particular, experimental features:<ul>
- <li>Are not tested as well as the core features.</li>
- <li>Do not get bugs fixed as quickly as core features.</li>
- <li>May have APIs that will change, possibly drastically if we find a different, better way to solve the same problem.</li>
- <li>May disappear entirely if the feature is too difficult to support or does bust enough boilerplate.</li>
- </ul>
- Features that receive positive community feedback and which seem to produce clean, flexible code will eventually become accepted
- as a core feature and move out of the experimental package.
- <dl>
- <dt><a href="Builder.html"><code>@Builder</code></a></dt>
- <dd>... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!</dd>
- <dt><a href="Accessors.html"><code>@Accessors</code></a></dt>
- <dd>A more fluent API for getters and setters.</dd>
- <dt><a href="ExtensionMethod.html"><code>@ExtensionMethod</code></a></dt>
- <dd>Annoying API? Fix it yourself: Add new methods to existing types!</dd>
- <dt><a href="FieldDefaults.html"><code>@FieldDefaults</code></a></dt>
- <dd>New default field modifiers for the 21st century.</dd>
- <dt><a href="Delegate.html"><code>@Delegate</code></a></dt>
- <dd>Don't lose your composition.</dd>
- <dt><a href="Wither.html"><code>@Wither</code></a></dt>
- <dd>Immutable 'setters' - methods that create a clone but with one changed field.</dd>
- <dt><a href="onX.html"><code>onMethod= / onConstructor= / onParam=</code></a></dt>
- <dd>Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you're annotating.</dd>
- </dl>
- </div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.experimental.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of any of the features listed here as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="index overview">
- <h3>Putting the "Ex" in "Experimental": promoted or deleted experimental features.</h3>
- <dl>
- <dt><a href="../Value.html"><code>@Value</code></a>: Promoted</dt>
- <dd><code>@Value</code> has proven its value and has been moved to the main package.</li>
- </dl>
- </div>
- <div class="footer">
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/experimental/onX.html b/website/features/experimental/onX.html
deleted file mode 100644
index ba2ead86..00000000
--- a/website/features/experimental/onX.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../features.css" />
- <link rel="shortcut icon" href="../../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>onX</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../../index.html">Project Lombok</a></div>
- <h1>onX</h1>
- <div class="byline">Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you're annotating.</div>
- <div class="since">
- <h3>Since</h3>
- <p>
- onX was introduced as experimental feature in lombok v0.11.8.
- </p>
- </div>
- <div class="experimental">
- <h3>Experimental</h3>
- <p>
- Experimental because:
- <ul>
- <li>Ugly syntax. The syntax of this feature is not optimal, but it is the least convoluted syntax that could possibly work (for now!)</li>
- <li>Possibly java 9 will offer (much) better ways of supporting this feature.</li>
- <li>Uncertainty: Future versions of javac may break this feature, and we may not be able to restore it.</li>
- </ul>
- Current status: <em>uncertain</em> - Currently we feel this feature cannot move out of experimental status.
- </div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <strong>This feature is considered 'workaround status' - it exists in order to allow users of lombok that cannot work without this feature to have access to it anyway. If we find a better way to implement this feature, or some future java version introduces an alternative strategy, this feature can disappear without a reasonable deprecation period. Also, this feature may not work in future versions of javac. Use at your own discretion.</strong>
- </p><p>
- Most annotations that make lombok generate methods or constructors can be configured to also make lombok put custom annotations on elements in the generated code.
- </p><p>
- <code>@Getter</code>, <code>@Setter</code>, and <code>@Wither</code> support the <code>onMethod</code> option, which will put the listed annotations on the generated method.
- </p><p>
- <code>@AllArgsConstructor</code>, <code>@NoArgsConstructor</code>, and <code>@RequiredArgsConstructor</code> support the <code>onConstructor</code> option which will put the listed annotations on the generated constructor.
- </p><p>
- <code>@Setter</code> and <code>@Wither</code> support <code>onParam</code> in addition to <code>onMethod</code>; annotations listed will be put on the only parameter that the generated method has. <code>@EqualsAndHashCode</code> also supports <code>onParam</code>; the listed annotation(s) will be placed on the single parameter of the generated <code>equals</code> method, as well as any generated <code>canEqual</code> method.
- </p><p>
- The syntax is a little strange; to use any of the 3 <code>onX</code> features, you must wrap the annotations to be applied to the constructor / method / parameter in <code>@__(@AnnotationGoesHere)</code>. To apply multiple annotations, use <code>@__({@Annotation1, @Annotation2})</code>. The annotations can themselves obviously have parameters as well.
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- The reason of the weird syntax is to make this feature work in javac 7 compilers; the <code>@__</code> type is an annotation reference to the annotation type <code>__</code> (double underscore) which doesn't actually exist; this makes javac 7 delay aborting the compilation process due to an error because it is possible an annotation processor will later create the <code>__</code> type. Instead, lombok applies the annotations and removes the references so that the error will never actually occur. The point is: The <code>__</code> type <em>must not exist</em>, otherwise the feature does not work. In the rare case that the <code>__</code> type does exist (and is imported or in the package), you can simply add more underscores. Technically any non-existent type would work, but to maintain consistency and readability and catch erroneous use, lombok considers it an error if the 'wrapper' annotation is anything but a series of underscores.
- </p><p>
- To reiterate: This feature can disappear at any time; if you use this feature, be prepared to adjust your code when we find a nicer way of implementing this feature, or, if a future version of javac forces us to remove this feature entirely with no alternative.
- </p><p>
- The <code>onX</code> parameter is not legal on any type-wide variant. For example, a <code>@Getter</code> annotation on a class does not support <code>onMethod</code>.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to experimental features</a> | <a href="Wither.html">Previous feature (@Wither)</a> | <span class="disabled">Next feature</span><br />
- <a href="../../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/features.css b/website/features/features.css
deleted file mode 100644
index b3017fe8..00000000
--- a/website/features/features.css
+++ /dev/null
@@ -1,179 +0,0 @@
-.confType {
- font-weight: bold;
-}
-
-body {
- font-family: Verdana;
- background-image: url(gradient.png);
- background-repeat: repeat-x;
- background-attachment: fixed;
-}
-
-#pepper {
- background-image: url(lombok-background.png);
- background-repeat: no-repeat;
- background-attachment: fixed;
- background-position: 50px 20px;
-}
-
-* html #pepper {
- background: none;
-}
-
-.meat {
- padding: 0px 48px;
-}
-
-.meat .header {
- position: absolute;
- top: 10px;
- left: 30px;
-}
-
-.minimumHeight {
- height: 700px;
- width: 1px;
- float: right;
-}
-
-* html .minimumHeight {
- height: 0px;
-}
-
-h1 {
- padding: 8px 0 10px 0;
- font-size: 20px;
- width: 100%;
- text-align: center;
-}
-
-.byline {
- width: 100%;
- text-align: center;
- font-style: italic;
- font-size: 1.3em;
-}
-
-.index {
- font-size: 1.2em;
- margin: 48px 0px 32px 64px;
-}
-
-.index dt {
- margin-top: 8px;
- font-size: 1.2em;
-}
-
-.index dd {
- margin-left: 32px;
-}
-
-dt {
- margin-top: 4px;
- font-size: 1.2em;
-}
-
-dd {
- margin-left: 16px;
-}
-
-.overview code {
- font-size: 1.1em;
- white-space: nowrap;
-}
-
-.smallprint {
- font-size: 0.8em;
- color: #444;
-}
-
-.smallprint code {
- font-size: 1em;
- white-space: nowrap;
-}
-
-.snippets {
- margin-top: 0px;
-}
-
-.snippets .pre {
- float: left;
- width: 45%;
-}
-
-.snippet {
- overflow: auto;
- padding: 4px;
- border: 1px dotted #888;
-}
-
-.snippet font {
- white-space: pre;
-}
-
-.snippets .sep {
- display: block;
- width: 5%;
- height: 1px;
- float: left;
-}
-
-.snippets .post {
- float: left;
- width: 45%;
-}
-
-.snippets .end {
- clear: both;
-}
-
-.snippet code {
- font-size: 14px;
-}
-
-.snippet.example {
- margin: 8px 16px 8px 16px;
-}
-
-.footer {
- clear: left;
- margin: 0 auto 0 auto;
- padding: 16px 0 16px 0;
- display: block;
- text-align: center;
-}
-
-.footer .disabled {
- color: #aaa;
-}
-
-.footer .copyright {
- color: #555;
- font-size: 11px;
- font-style: italic;
-}
-
-.creditsLink {
- font-style: normal;
- font-weight: bold;
-}
-
-code a {
- color: black;
- text-decoration: none;
-}
-
-code a:hover {
- color: black;
- text-decoration: underline;
-}
-
-code .keyword {
- color: #7f0055;
- font-weight: bold;
-}
-
-code .staticfield {
- color: #2a00ff;
- font-style: italic;
-} \ No newline at end of file
diff --git a/website/features/gradient.png b/website/features/gradient.png
deleted file mode 100644
index 3ffcde2c..00000000
--- a/website/features/gradient.png
+++ /dev/null
Binary files differ
diff --git a/website/features/index.html b/website/features/index.html
deleted file mode 100644
index 09a148f0..00000000
--- a/website/features/index.html
+++ /dev/null
@@ -1,88 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Lombok feature overview</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>Lombok features</h1>
- <div class="index overview">
- <dl>
- <dt><a href="val.html"><code>val</code></a></dt>
- <dd>Finally! Hassle-free final local variables.</dd>
- <dt><a href="NonNull.html"><code>@NonNull</code></a></dt>
- <dd>or: How I learned to stop worrying and love the NullPointerException.</dd>
- <dt><a href="Cleanup.html"><code>@Cleanup</code></a></dt>
- <dd>Automatic resource management: Call your <code>close()</code> methods safely with no hassle.</dd>
- <dt><a href="GetterSetter.html"><code>@Getter</code> / <code>@Setter</code></a></dt>
- <dd>Never write <code>public int getFoo() {return foo;}</code> again.</dd>
- <dt><a href="ToString.html"><code>@ToString</code></a></dt>
- <dd>No need to start a debugger to see your fields: Just let lombok generate a <code>toString</code> for you!</dd>
- <dt><a href="EqualsAndHashCode.html"><code>@EqualsAndHashCode</code></a></dt>
- <dd>Equality made easy: Generates <code>hashCode</code> and <code>equals</code> implementations from the fields of your object.</dd>
- <dt><a href="Constructor.html"><code>@NoArgsConstructor</code>, <code>@RequiredArgsConstructor</code> and <code>@AllArgsConstructor</code></a></dt>
- <dd>Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.</dd>
- <dt><a href="Data.html"><code>@Data</code></a></dt>
- <dd>All together now: A shortcut for <code>@ToString</code>, <code>@EqualsAndHashCode</code>,
- <code>@Getter</code> on all fields, and <code>@Setter</code> on all non-final fields, and <code>@RequiredArgsConstructor</code>!</dd>
- <dt><a href="Value.html"><code>@Value</code></a></dt>
- <dd>Immutable classes made very easy.</dd>
- <dt><a href="SneakyThrows.html"><code>@SneakyThrows</code></a></dt>
- <dd>To boldly throw checked exceptions where no one has thrown them before!</dd>
- <dt><a href="Synchronized.html"><code>@Synchronized</code></a></dt>
- <dd><code>synchronized</code> done right: Don't expose your locks.</dd>
- <dt><a href="GetterLazy.html"><code>@Getter(lazy=true)</code></a></dt>
- <dd>Laziness is a virtue!</dd>
- <dt><a href="Log.html"><code>@Log</code></a></dt>
- <dd>Captain's Log, stardate 24435.7: &quot;What was that line again?&quot;</dd>
- <dt><a href="configuration.html">Configuration system</a></dt>
- <dd>Lombok, made to order: Configure lombok features in one place for your entire project or even your workspace.</dd>
- <dt><a href="experimental/index.html">Experimental features</a></dt>
- <dd>Here be dragons: Extra features which aren't quite ready for prime time yet.</dd>
- </dl>
- </div>
- <div class="pointer">
- If you'd rather read a longer tutorial, <a href="http://jnb.ociweb.com/jnb/jnbJan2010.html">here is a great tutorial (including a walkthrough through some of the above features)</a> written by Michael Kimberlin.
- </div>
- <div class="pointer">
- The documentation above is a lot easier to follow, but if you want to build your own transformations,
- or you want to add javadoc to <code>lombok.jar</code> in your IDE, you can also check out <a href="../api/index.html">the javadoc</a>.
- </div>
- <h1>Running Lombok</h1>
- <h3>On eclipse</h3>
- Execute lombok.jar (doubleclick it, or run java -jar lombok.jar). Follow instructions.
- <h3>On javac (and maven, ant, and other build tools)</h3>
- Include lombok.jar on the classpath as you compile. That's all there is to it!<br />
- Lombok hosts its own maven repository, so adding lombok to maven is very simple. <a href="/mavenrepo/index.html">full instructions are here</a>.
- <h3>On GWT (Google Widget Toolkit)</h3>
- See <a href="../setup/gwt.html">gwt</a> setup.
- <h3>On javadoc, and other source-based tools</h3>
- Use <a href="delombok.html">delombok</a> first, then run javadoc or GWT on the delombok-ed code.
- <h1>Running delombok</h1>
- <div>Delombok copies your source files to another directory, replacing all lombok annotations with their desugared form. So, it'll turn <code>@Getter</code>
- back into the actual getter. It then removes the annotation. This is useful for all sorts of reasons; you can check out what's happening under the hood,
- if the unthinkable happens and you want to stop using lombok, you can easily remove all traces of it in your source, and you can use delombok to preprocess
- your source files for source-level tools such as javadoc and GWT. More information about how to run delombok, including instructions for build tools
- can be found at the <a href="delombok.html">delombok page</a>.</div>
- <div class="footer">
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/features/lombok-background.png b/website/features/lombok-background.png
deleted file mode 100644
index aac3195a..00000000
--- a/website/features/lombok-background.png
+++ /dev/null
Binary files differ
diff --git a/website/features/val.html b/website/features/val.html
deleted file mode 100644
index 84158d27..00000000
--- a/website/features/val.html
+++ /dev/null
@@ -1,76 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="features.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>val</title>
-</head><body><div id="pepper">
- <div class="minimumHeight"></div>
- <div class="meat">
- <div class="header"><a href="../index.html">Project Lombok</a></div>
- <h1>val</h1>
- <div class="byline">Finally! Hassle-free final local variables.</div>
- <div class="overview">
- <h3>Overview</h3>
- <p>
- <em>NEW in Lombok 0.10: </em>You can use <code>val</code> as the type of a local variable declaration instead of actually writing the type. When you do this,
- the type will be inferred from the initializer expression. The local variable will also be made final. This feature works
- on local variables and on foreach loops only, not on fields. The initializer expression is required.
- </p><p>
- <code>val</code> is actually a 'type' of sorts, and exists as a real class in the <code>lombok</code> package. You must import it for val to work (or use <code>lombok.val</code> as the type).
- The existence of this type on a local variable declaration triggers both the adding of the <code>final</code> keyword as well as copying the type of the initializing expression which overwrites
- the 'fake' <code>val</code> type.
- </p><p>
- <em>WARNING: This feature does not currently work in NetBeans. We're working on fixing that.</em>
- </p>
- </div>
- <div class="snippets">
- <div class="pre">
- <h3>With Lombok</h3>
- <div class="snippet">@HTML_PRE@</div>
- </div>
- <div class="sep"></div>
- <div class="post">
- <h3>Vanilla Java</h3>
- <div class="snippet">@HTML_POST@</div>
- </div>
- </div>
- <div style="clear: left;"></div>
- <div class="overview confKeys">
- <h3>Supported configuration keys:</h3>
- <dl>
- <dt><code>lombok.val.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)</dt>
- <dd>Lombok will flag any usage of <code>val</code> as a warning or error if configured.</dd>
- </dl>
- </div>
- <div class="overview">
- <h3>Small print</h3><div class="smallprint">
- <p>
- For compound types, the most common superclass is inferred, not any shared interfaces. For example, <code>bool ? new HashSet() : new ArrayList()</code>
- is an expression with a compound type: The result is both <code>AbstractCollection</code> as well as <code>Serializable</code>. The type inferred will be
- <code>AbstractCollection</code>, as that is a class, whereas <code>Serializable</code> is an interface.
- </p><p>
- In ambiguous cases, such as when the initializer expression is <code>null</code>, <code>java.lang.Object</code> is inferred.
- </p>
- </div>
- </div>
- <div class="footer">
- <a href="index.html">Back to features</a> | <span class="disabled">Previous feature</span> | <a href="NonNull.html">Next feature (@NonNull)</a><br />
- <a href="../credits.html" class="creditsLink">credits</a> | <span class="copyright">Copyright &copy; 2010-2013 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.</span>
- </div>
- <div style="clear: both;"></div>
- </div>
-</div>
-<script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
-</script>
-<script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
-</script>
-</body></html>
diff --git a/website/icon_brush_unused.png b/website/icon_brush_unused.png
deleted file mode 100644
index 7ebf2f06..00000000
--- a/website/icon_brush_unused.png
+++ /dev/null
Binary files differ
diff --git a/website/icon_bugs.png b/website/icon_bugs.png
deleted file mode 100644
index 713b6fe8..00000000
--- a/website/icon_bugs.png
+++ /dev/null
Binary files differ
diff --git a/website/icon_contribute.png b/website/icon_contribute.png
deleted file mode 100644
index a7f630a5..00000000
--- a/website/icon_contribute.png
+++ /dev/null
Binary files differ
diff --git a/website/icon_discussion.png b/website/icon_discussion.png
deleted file mode 100644
index d1e3fd5e..00000000
--- a/website/icon_discussion.png
+++ /dev/null
Binary files differ
diff --git a/website/icon_download.png b/website/icon_download.png
deleted file mode 100644
index bfe07288..00000000
--- a/website/icon_download.png
+++ /dev/null
Binary files differ
diff --git a/website/icon_overview.png b/website/icon_overview.png
deleted file mode 100644
index 806b4421..00000000
--- a/website/icon_overview.png
+++ /dev/null
Binary files differ
diff --git a/website/index.css b/website/index.css
deleted file mode 100644
index b89e65cb..00000000
--- a/website/index.css
+++ /dev/null
@@ -1,168 +0,0 @@
-img,div,a,input,button,.pngfix {
- behavior: url(logi/iepngfix.htc);
-}
-
-body {
- font-family: Verdana;
-}
-
-.meat {
- width: 800px;
- margin: 0 auto 0 auto;
-}
-
-h1 {
- padding: 8px 0 10px 0;
- font-size: 20px;
- width: 100%;
- text-align: center;
-}
-
-#buttonBar a.button, a.downloadLink {
- text-decoration: none;
- color: black;
-}
-
-#buttonBar a.button:hover, a.downloadLink:hover {
- text-decoration: underline;
- color: blue;
-}
-
-.buttonBar {
- -webkit-border-top-right-radius: 15px 15px;
- -webkit-border-top-left-radius: 15px 15px;
- -moz-border-radius-topright: 15px;
- -moz-border-radius-topleft: 15px;
- border-top-right-radius: 15px 15px;
- border-top-left-radius: 15px 15px;
- background-image: url(buttonbar.jpg);
- width: 800px;
- height: 170px;
-}
-
-.endBar {
- -webkit-border-bottom-right-radius: 15px 15px;
- -webkit-border-bottom-left-radius: 15px 15px;
- -moz-border-radius-bottomright: 15px;
- -moz-border-radius-bottomleft: 15px;
- border-bottom-right-radius: 15px 15px;
- border-bottom-left-radius: 15px 15px;
- background-image: url(buttonbar.jpg);
- width: 800px;
- height: 30px;
- line-height: 30px;
- font-size: 14px;
- text-align: center;
- clear: both;
-}
-
-.button {
- margin: 30px 16px auto 16px;
- float: left;
- width: 80px;
- height: 100px;
-}
-
-.button:first-child {
- margin-left: 64px;
-}
-
-.button img {
- padding: 0 8px 0 8px;
- display: block;
-}
-
-.button span {
- display: block;
- width: 80px;
- text-align: center;
- font-size: 14px;
-}
-
-.downloadContainer {
- float: left;
- margin: 34px 8px 57px 40px;
-}
-
-code {
- font-weight: bold;
-}
-
-.attribution {
- font-size: 0.6em;
-}
-
-.downloadLink {
- background-image: url(downloadButton.png);
- display: block;
- line-height: 56px;
- width: 225px;
- height: 56px;
-}
-
-.downloadLink img {
- margin: 4px 20px 4px 16px;
- float: left;
- width: 48px;
-}
-
-.downloadLink span {
- display: block;
- font-size: 16px;
- font-weight: bold;
-}
-
-.versionInfo {
- font-size: 12px;
- margin-top: 4px;
- font-weight: normal;
- width: 100%;
- text-align: center;
-}
-
-#downloadInfo {
- font-size: 14px;
-}
-
-#downloadInfo p {
- padding: 8px;
-}
-
-.downloadActions {
- margin-top: 8px;
- margin-left: 32px;
-}
-
-.footer {
- margin-top: 8px;
- display: block;
- color: #555;
- font-style: italic;
- font-size: 11px;
- width: 100%;
- text-align: center;
-}
-
-.creditsLink {
- font-style: normal;
- font-weight: bold;
-}
-
-.downloadHelp {
- margin: 32px 16px 32px 0px;
-}
-
-.downloadHelp .platform {
- font-size: 1.2em;
- font-weight: bold;
- padding-right: 32px;
-}
-
-.stableLink {
- font-size: 1.5em;
- margin-bottom: 16px;
-}
-
-.edgeLink {
- margin-bottom: 16px;
-}
diff --git a/website/index.html b/website/index.html
deleted file mode 100644
index 9f775fd3..00000000
--- a/website/index.html
+++ /dev/null
@@ -1,96 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <meta name="google-site-verification" content="uCgX3Or3kDRGpbJ6JCsQc3Ub4JsnR5-p0itfsKAYZ_U" />
- <script src="logi/jQuery-all.js" type="text/javascript"></script>
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="index.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <script type="text/javascript" src="videos/swfobject.js"></script>
- <script type="text/javascript">
- swfobject.registerObject("player","9.0.98","videos/expressInstall.swf");
- </script>
- <!--[if lt IE 7]><script type="text/javascript" src="logi/iepngfix_tilebg.js"></script><![endif]-->
-</head><body>
- <a id="forkMe" href="http://github.com/rzwitserloot/lombok"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
- <div class="meat">
- <h1>Project Lombok</h1>
- <div id="buttonBar" class="buttonBar">
- <a class="button" href="features/index.html">
- <img src="icon_overview.png" />
- <span>Feature Overview</span>
- </a>
- <a class="button" href="http://groups.google.com/group/project-lombok">
- <img src="icon_discussion.png" />
- <span>Discuss / Help</span>
- </a>
- <a class="button" href="http://wiki.github.com/rzwitserloot/lombok/contributing">
- <img src="icon_contribute.png" />
- <span>Contribute</span>
- </a>
- <a class="button" href="http://code.google.com/p/projectlombok/issues/list">
- <img src="icon_bugs.png" />
- <span>Report an issue</span>
- </a>
- <div class="downloadContainer">
- <a class="downloadLink" id="downloadLink" href="download.html">
- <img src="icon_download.png" />
- <span>Download!</span>
- </a>
- <div class="versionInfo">
- Version: @VERSION@ | <a href="changelog.html">changelog</a>
- </div>
- </div>
- </div>
- <div class="video">
- <video width="800" height="480" poster="videos/poster.png" controls="controls" preload="none">
- <source src="videos/lombok.ogv" type="video/ogg" />
- <source src="videos/lombok.mp4" type="video/mp4" />
- <source src="videos/lombok-iPhone.m4v" type="video/mp4" />
- <object id="player" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" width="800" height="500">
- <param name="movie" value="videos/player.swf?image=poster.png&amp;file=lombok.mp4" />
- <param name="allowfullscreen" value="true" />
- <!--[if !IE]>-->
- <object width="800" height="500" type="application/x-shockwave-flash"
- data="videos/player.swf?image=poster.png&amp;file=lombok.mp4" allowfullscreen="true">
- <!--<![endif]-->
- <h3>Video: Lombok Demo</h3>
- <p>
- <strong>No video playback capabilities detected.</strong>
- Why not download it instead?<br />
- <a href="videos/lombok.mp4">MPEG4 / H.264 (Windows / Mac)</a> |
- <a href="videos/lombok.ogv">Ogg Theora &amp; Vorbis ".ogv" (Linux)</a>
- </p><p>
- To play the video in the webpage, please do one of the following:
- </p><ul>
- <li>Upgrade to <a href="http://www.mozilla.org/firefox/">Firefox</a> or
- <a href="http://www.google.com/chrome/">Chrome</a>
- </li>
- <li>Install <a href="http://get.adobe.com/flashplayer/">Adobe Flash</a></li>
- </ul>
- <!--[if !IE]>-->
- </object>
- <!--<![endif]-->
- </object>
- </video>
- </div>
- <div class="endBar">
- <a href="novideo.html">I can't see the video</a> | <a href="http://jnb.ociweb.com/jnb/jnbJan2010.html">Show me a text and images based explanation and tutorial instead!</a>
- </div>
- <div class="footer">
- <a href="credits.html" class="creditsLink">credits</a> | Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/logi/iepngfix.htc b/website/logi/iepngfix.htc
deleted file mode 100755
index bbfb23c5..00000000
--- a/website/logi/iepngfix.htc
+++ /dev/null
@@ -1,187 +0,0 @@
-<public:component>
-<script type="text/javascript">
-
-// IE5.5+ PNG Alpha Fix v2.0 Alpha
-// (c) 2004-2008 Angus Turnbull http://www.twinhelix.com
-
-// This is licensed under the GNU LGPL, version 2.1 or later.
-// For details, see: http://creativecommons.org/licenses/LGPL/2.1/
-
-var IEPNGFix = window.IEPNGFix || {};
-IEPNGFix.data = IEPNGFix.data || {};
-
-
-// This must be a path to a blank image, relative to the HTML document(s).
-// In production use I suggest '/images/blankImg' or similar. That's all!
-IEPNGFix.blankImg = 'clear.gif';
-
-
-IEPNGFix.fix = function(elm, src, t) {
- // Applies an image 'src' to an element 'elm' using the DirectX filter.
- // If 'src' is null, filter is disabled.
- // Disables the 'hook' to prevent infinite recursion on setting BG/src.
- // 't' = type, where background tile = 0, background = 1, IMG SRC = 2.
-
- var h = this.hook.enabled;
- this.hook.enabled = 0;
-
- var f = 'DXImageTransform.Microsoft.AlphaImageLoader';
- src = (src || '').replace(/\(/g, '%28').replace(/\)/g, '%29');
-
- if (
- src && !(/IMG|INPUT/.test(elm.nodeName) && (t != 2)) &&
- elm.currentStyle.width == 'auto' && elm.currentStyle.height == 'auto'
- ) {
- elm.style.width = elm.offsetWidth + 'px';
- elm.style.height = elm.clientHeight + 'px';
- if (elm.currentStyle.display == 'inline') {
- elm.style.display = 'inline-block';
- }
- }
-
- if (t == 1) {
- elm.style.backgroundImage = 'url("' + this.blankImg + '")';
- }
- if (t == 2) {
- elm.src = this.blankImg;
- }
-
- if (elm.filters[f]) {
- elm.filters[f].enabled = src ? true : false;
- if (src) {
- elm.filters[f].src = src;
- }
- } else if (src) {
- elm.style.filter = 'progid:' + f + '(src="' + src +
- '",sizingMethod="' + (t == 2 ? 'scale' : 'crop') + '")';
- }
-
- this.hook.enabled = h;
-};
-
-
-IEPNGFix.process = function(elm, init) {
- // Checks the onpropertychange event (on first 'init' run, a fake event)
- // and calls the filter-applying-functions.
-
- if (
- !/MSIE (5\.5|6)/.test(navigator.userAgent) ||
- typeof elm.filters == 'unknown'
- ) {
- return;
- }
- if (!this.data[elm.uniqueID]) {
- this.data[elm.uniqueID] = {
- className: ''
- };
- }
- var data = this.data[elm.uniqueID],
- evt = init ? { propertyName: 'src,backgroundImage' } : event,
- isSrc = /src/.test(evt.propertyName),
- isBg = /backgroundImage/.test(evt.propertyName),
- isPos = /width|height|background(Pos|Rep)/.test(evt.propertyName),
- isClass = !init && ((elm.className != data.className) &&
- (elm.className || data.className));
- if (!(isSrc || isBg || isPos || isClass)) {
- return;
- }
- data.className = elm.className;
- var blank = this.blankImg.match(/([^\/]+)$/)[1],
- eS = elm.style,
- eCS = elm.currentStyle;
-
- // Required for Whatever:hover - erase set BG if className changes.
- if (
- isClass && (eS.backgroundImage.indexOf('url(') == -1 ||
- eS.backgroundImage.indexOf(blank) > -1)
- ) {
- return setTimeout(function() {
- eS.backgroundImage = '';
- }, 0);
- }
-
- // Foregrounds.
- if (isSrc && elm.src && { IMG: 1, INPUT: 1 }[elm.nodeName]) {
- if ((/\.png/i).test(elm.src)) {
- this.fix(elm, elm.src, 2);
- } else if (elm.src.indexOf(blank) == -1) {
- this.fix(elm, '');
- }
- }
-
- // Backgrounds.
- var bgSrc = eCS.backgroundImage || eS.backgroundImage;
- if ((bgSrc + elm.src).indexOf(blank) == -1) {
- var bgPNG = bgSrc.match(/url[("']+(.*\.png[^\)"']*)[\)"']/i);
- if (bgPNG) {
- if (this.tileBG && !{ IMG: 1, INPUT: 1 }[elm.nodeName]) {
- this.tileBG(elm, bgPNG[1]);
- this.fix(elm, '', 1);
- } else {
- if (data.tiles && data.tiles.src) {
- this.tileBG(elm, '');
- }
- this.fix(elm, bgPNG[1], 1);
- this.childFix(elm);
- }
- } else {
- if (data.tiles && data.tiles.src) {
- this.tileBG(elm, '');
- }
- this.fix(elm, '');
- }
- } else if ((isPos || isClass) && data.tiles && data.tiles.src) {
- this.tileBG(elm, data.tiles.src);
- }
-
- if (init) {
- this.hook.enabled = 1;
- elm.attachEvent('onpropertychange', this.hook);
- }
-};
-
-
-IEPNGFix.childFix = function(elm) {
- // "hasLayout" fix for unclickable children inside PNG backgrounds.
- var tags = [
- 'a',
- 'input',
- 'select',
- 'textarea',
- 'button',
- 'iframe',
- 'object'
- ],
- t = tags.length,
- tFix = [];
- while (t--) {
- var pFix = elm.all.tags(tags[t]),
- e = pFix.length;
- while (e--) {
- tFix.push(pFix[e]);
- }
- }
- t = tFix.length;
- if (t && (/relative|absolute/i).test(elm.currentStyle.position)) {
- alert('IEPNGFix: Unclickable children of element:' +
- '\n\n<' + elm.nodeName + (elm.id && ' id=' + elm.id) + '>');
- }
- while (t--) {
- if (!(/relative|absolute/i).test(tFix[t].currentStyle.position)) {
- tFix[t].style.position = 'relative';
- }
- }
-};
-
-
-IEPNGFix.hook = function() {
- if (IEPNGFix.hook.enabled) {
- IEPNGFix.process(element, 0);
- }
-};
-
-
-IEPNGFix.process(element, 1);
-
-</script>
-</public:component>
diff --git a/website/logi/iepngfix_tilebg.js b/website/logi/iepngfix_tilebg.js
deleted file mode 100755
index 48795631..00000000
--- a/website/logi/iepngfix_tilebg.js
+++ /dev/null
@@ -1,178 +0,0 @@
-// IE5.5+ PNG Alpha Fix v2.0 Alpha: Background Tiling Support
-// (c) 2008 Angus Turnbull http://www.twinhelix.com
-
-// This is licensed under the GNU LGPL, version 2.1 or later.
-// For details, see: http://creativecommons.org/licenses/LGPL/2.1/
-
-var IEPNGFix = window.IEPNGFix || {};
-
-IEPNGFix.tileBG = function(elm, pngSrc, ready) {
- // Params: A reference to a DOM element, the PNG src file pathname, and a
- // hidden "ready-to-run" passed when called back after image preloading.
-
- var data;
- try {
- data = this.data[elm.uniqueID],
- elmW = Math.max(elm.clientWidth, elm.scrollWidth),
- elmH = Math.max(elm.clientHeight, elm.scrollHeight),
- bgX = elm.currentStyle.backgroundPositionX,
- bgY = elm.currentStyle.backgroundPositionY,
- bgR = elm.currentStyle.backgroundRepeat;
- } catch ( e ) {
- return;
- }
-
- // Cache of DIVs created per element, and image preloader/data.
- if (!data.tiles) {
- data.tiles = {
- elm: elm,
- src: '',
- cache: [],
- img: new Image(),
- old: {}
- };
- }
- var tiles = data.tiles,
- pngW = tiles.img.width,
- pngH = tiles.img.height;
-
- if (pngSrc) {
- if (!ready && pngSrc != tiles.src) {
- // New image? Preload it with a callback to detect dimensions.
- tiles.img.onload = function() {
- this.onload = null;
- IEPNGFix.tileBG(elm, pngSrc, 1);
- };
- return tiles.img.src = pngSrc;
- }
- } else {
- // No image?
- if (tiles.src) ready = 1;
- pngW = pngH = 0;
- }
- tiles.src = pngSrc;
-
- if (!ready && elmW == tiles.old.w && elmH == tiles.old.h &&
- bgX == tiles.old.x && bgY == tiles.old.y && bgR == tiles.old.r) {
- return;
- }
-
- // Convert English and percentage positions to pixels.
- var pos = {
- top: '0%',
- left: '0%',
- center: '50%',
- bottom: '100%',
- right: '100%'
- },
- x,
- y,
- pc;
- x = pos[bgX] || bgX;
- y = pos[bgY] || bgY;
- if (pc = x.match(/(\d+)%/)) {
- x = Math.round((elmW - pngW) * (parseInt(pc[1]) / 100));
- }
- if (pc = y.match(/(\d+)%/)) {
- y = Math.round((elmH - pngH) * (parseInt(pc[1]) / 100));
- }
- x = parseInt(x);
- y = parseInt(y);
-
- // Handle backgroundRepeat.
- var repeatX = { 'repeat': 1, 'repeat-x': 1 }[bgR],
- repeatY = { 'repeat': 1, 'repeat-y': 1 }[bgR];
- if (repeatX) {
- x %= pngW;
- if (x > 0) x -= pngW;
- }
- if (repeatY) {
- y %= pngH;
- if (y > 0) y -= pngH;
- }
-
- // Go!
- this.hook.enabled = 0;
- if (!({ relative: 1, absolute: 1 }[elm.currentStyle.position])) {
- elm.style.position = 'relative';
- }
- var count = 0,
- xPos,
- maxX = repeatX ? elmW : x + 0.1,
- yPos,
- maxY = repeatY ? elmH : y + 0.1,
- d,
- s,
- isNew;
- if (pngW && pngH) {
- for (xPos = x; xPos < maxX; xPos += pngW) {
- for (yPos = y; yPos < maxY; yPos += pngH) {
- isNew = 0;
- if (!tiles.cache[count]) {
- tiles.cache[count] = document.createElement('div');
- isNew = 1;
- }
- var clipR = (xPos + pngW > elmW ? elmW - xPos : pngW),
- clipB = (yPos + pngH > elmH ? elmH - yPos : pngH);
- d = tiles.cache[count];
- s = d.style;
- s.behavior = 'none';
- s.left = xPos + 'px';
- s.top = yPos + 'px';
- s.width = clipR + 'px';
- s.height = clipB + 'px';
- s.clip = 'rect(' +
- (yPos < 0 ? 0 - yPos : 0) + 'px,' +
- clipR + 'px,' +
- clipB + 'px,' +
- (xPos < 0 ? 0 - xPos : 0) + 'px)';
- s.display = 'block';
- if (isNew) {
- s.position = 'absolute';
- s.zIndex = -999;
- if (elm.firstChild) {
- elm.insertBefore(d, elm.firstChild);
- } else {
- elm.appendChild(d);
- }
- }
- this.fix(d, pngSrc, 0);
- count++;
- }
- }
- }
- while (count < tiles.cache.length) {
- this.fix(tiles.cache[count], '', 0);
- tiles.cache[count++].style.display = 'none';
- }
-
- this.hook.enabled = 1;
-
- // Cache so updates are infrequent.
- tiles.old = {
- w: elmW,
- h: elmH,
- x: bgX,
- y: bgY,
- r: bgR
- };
-};
-
-
-IEPNGFix.update = function() {
- // Update all PNG backgrounds.
- for (var i in IEPNGFix.data) {
- var t = IEPNGFix.data[i].tiles;
- if (t && t.elm && t.src) {
- IEPNGFix.tileBG(t.elm, t.src);
- }
- }
-};
-IEPNGFix.update.timer = 0;
-
-if (window.attachEvent && !window.opera) {
- window.attachEvent('onresize', function() {
- clearTimeout(IEPNGFix.update.timer);
- IEPNGFix.update.timer = setTimeout(IEPNGFix.update, 100);
- });
-}
diff --git a/website/logi/jQuery-all.js b/website/logi/jQuery-all.js
deleted file mode 100644
index 9f8ffce7..00000000
--- a/website/logi/jQuery-all.js
+++ /dev/null
@@ -1,143 +0,0 @@
-/*
- * jQuery JavaScript Library v1.3.2
- * http://jquery.com/
- *
- * Copyright (c) 2009 John Resig
- * Dual licensed under the MIT and GPL licenses.
- * http://docs.jquery.com/License
- *
- * Date: 2009-02-19 17:34:21 -0500 (Thu, 19 Feb 2009)
- * Revision: 6246
- */
-(function(){var l=this,g,y=l.jQuery,p=l.$,o=l.jQuery=l.$=function(E,F){return new o.fn.init(E,F)},D=/^[^<]*(<(.|\s)+>)[^>]*$|^#([\w-]+)$/,f=/^.[^:#\[\.,]*$/;o.fn=o.prototype={init:function(E,H){E=E||document;if(E.nodeType){this[0]=E;this.length=1;this.context=E;return this}if(typeof E==="string"){var G=D.exec(E);if(G&&(G[1]||!H)){if(G[1]){E=o.clean([G[1]],H)}else{var I=document.getElementById(G[3]);if(I&&I.id!=G[3]){return o().find(E)}var F=o(I||[]);F.context=document;F.selector=E;return F}}else{return o(H).find(E)}}else{if(o.isFunction(E)){return o(document).ready(E)}}if(E.selector&&E.context){this.selector=E.selector;this.context=E.context}return this.setArray(o.isArray(E)?E:o.makeArray(E))},selector:"",jquery:"1.3.2",size:function(){return this.length},get:function(E){return E===g?Array.prototype.slice.call(this):this[E]},pushStack:function(F,H,E){var G=o(F);G.prevObject=this;G.context=this.context;if(H==="find"){G.selector=this.selector+(this.selector?" ":"")+E}else{if(H){G.selector=this.selector+"."+H+"("+E+")"}}return G},setArray:function(E){this.length=0;Array.prototype.push.apply(this,E);return this},each:function(F,E){return o.each(this,F,E)},index:function(E){return o.inArray(E&&E.jquery?E[0]:E,this)},attr:function(F,H,G){var E=F;if(typeof F==="string"){if(H===g){return this[0]&&o[G||"attr"](this[0],F)}else{E={};E[F]=H}}return this.each(function(I){for(F in E){o.attr(G?this.style:this,F,o.prop(this,E[F],G,I,F))}})},css:function(E,F){if((E=="width"||E=="height")&&parseFloat(F)<0){F=g}return this.attr(E,F,"curCSS")},text:function(F){if(typeof F!=="object"&&F!=null){return this.empty().append((this[0]&&this[0].ownerDocument||document).createTextNode(F))}var E="";o.each(F||this,function(){o.each(this.childNodes,function(){if(this.nodeType!=8){E+=this.nodeType!=1?this.nodeValue:o.fn.text([this])}})});return E},wrapAll:function(E){if(this[0]){var F=o(E,this[0].ownerDocument).clone();if(this[0].parentNode){F.insertBefore(this[0])}F.map(function(){var G=this;while(G.firstChild){G=G.firstChild}return G}).append(this)}return this},wrapInner:function(E){return this.each(function(){o(this).contents().wrapAll(E)})},wrap:function(E){return this.each(function(){o(this).wrapAll(E)})},append:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.appendChild(E)}})},prepend:function(){return this.domManip(arguments,true,function(E){if(this.nodeType==1){this.insertBefore(E,this.firstChild)}})},before:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this)})},after:function(){return this.domManip(arguments,false,function(E){this.parentNode.insertBefore(E,this.nextSibling)})},end:function(){return this.prevObject||o([])},push:[].push,sort:[].sort,splice:[].splice,find:function(E){if(this.length===1){var F=this.pushStack([],"find",E);F.length=0;o.find(E,this[0],F);return F}else{return this.pushStack(o.unique(o.map(this,function(G){return o.find(E,G)})),"find",E)}},clone:function(G){var E=this.map(function(){if(!o.support.noCloneEvent&&!o.isXMLDoc(this)){var I=this.outerHTML;if(!I){var J=this.ownerDocument.createElement("div");J.appendChild(this.cloneNode(true));I=J.innerHTML}return o.clean([I.replace(/ jQuery\d+="(?:\d+|null)"/g,"").replace(/^\s*/,"")])[0]}else{return this.cloneNode(true)}});if(G===true){var H=this.find("*").andSelf(),F=0;E.find("*").andSelf().each(function(){if(this.nodeName!==H[F].nodeName){return}var I=o.data(H[F],"events");for(var K in I){for(var J in I[K]){o.event.add(this,K,I[K][J],I[K][J].data)}}F++})}return E},filter:function(E){return this.pushStack(o.isFunction(E)&&o.grep(this,function(G,F){return E.call(G,F)})||o.multiFilter(E,o.grep(this,function(F){return F.nodeType===1})),"filter",E)},closest:function(E){var G=o.expr.match.POS.test(E)?o(E):null,F=0;return this.map(function(){var H=this;while(H&&H.ownerDocument){if(G?G.index(H)>-1:o(H).is(E)){o.data(H,"closest",F);return H}H=H.parentNode;F++}})},not:function(E){if(typeof E==="string"){if(f.test(E)){return this.pushStack(o.multiFilter(E,this,true),"not",E)}else{E=o.multiFilter(E,this)}}var F=E.length&&E[E.length-1]!==g&&!E.nodeType;return this.filter(function(){return F?o.inArray(this,E)<0:this!=E})},add:function(E){return this.pushStack(o.unique(o.merge(this.get(),typeof E==="string"?o(E):o.makeArray(E))))},is:function(E){return !!E&&o.multiFilter(E,this).length>0},hasClass:function(E){return !!E&&this.is("."+E)},val:function(K){if(K===g){var E=this[0];if(E){if(o.nodeName(E,"option")){return(E.attributes.value||{}).specified?E.value:E.text}if(o.nodeName(E,"select")){var I=E.selectedIndex,L=[],M=E.options,H=E.type=="select-one";if(I<0){return null}for(var F=H?I:0,J=H?I+1:M.length;F<J;F++){var G=M[F];if(G.selected){K=o(G).val();if(H){return K}L.push(K)}}return L}return(E.value||"").replace(/\r/g,"")}return g}if(typeof K==="number"){K+=""}return this.each(function(){if(this.nodeType!=1){return}if(o.isArray(K)&&/radio|checkbox/.test(this.type)){this.checked=(o.inArray(this.value,K)>=0||o.inArray(this.name,K)>=0)}else{if(o.nodeName(this,"select")){var N=o.makeArray(K);o("option",this).each(function(){this.selected=(o.inArray(this.value,N)>=0||o.inArray(this.text,N)>=0)});if(!N.length){this.selectedIndex=-1}}else{this.value=K}}})},html:function(E){return E===g?(this[0]?this[0].innerHTML.replace(/ jQuery\d+="(?:\d+|null)"/g,""):null):this.empty().append(E)},replaceWith:function(E){return this.after(E).remove()},eq:function(E){return this.slice(E,+E+1)},slice:function(){return this.pushStack(Array.prototype.slice.apply(this,arguments),"slice",Array.prototype.slice.call(arguments).join(","))},map:function(E){return this.pushStack(o.map(this,function(G,F){return E.call(G,F,G)}))},andSelf:function(){return this.add(this.prevObject)},domManip:function(J,M,L){if(this[0]){var I=(this[0].ownerDocument||this[0]).createDocumentFragment(),F=o.clean(J,(this[0].ownerDocument||this[0]),I),H=I.firstChild;if(H){for(var G=0,E=this.length;G<E;G++){L.call(K(this[G],H),this.length>1||G>0?I.cloneNode(true):I)}}if(F){o.each(F,z)}}return this;function K(N,O){return M&&o.nodeName(N,"table")&&o.nodeName(O,"tr")?(N.getElementsByTagName("tbody")[0]||N.appendChild(N.ownerDocument.createElement("tbody"))):N}}};o.fn.init.prototype=o.fn;function z(E,F){if(F.src){o.ajax({url:F.src,async:false,dataType:"script"})}else{o.globalEval(F.text||F.textContent||F.innerHTML||"")}if(F.parentNode){F.parentNode.removeChild(F)}}function e(){return +new Date}o.extend=o.fn.extend=function(){var J=arguments[0]||{},H=1,I=arguments.length,E=false,G;if(typeof J==="boolean"){E=J;J=arguments[1]||{};H=2}if(typeof J!=="object"&&!o.isFunction(J)){J={}}if(I==H){J=this;--H}for(;H<I;H++){if((G=arguments[H])!=null){for(var F in G){var K=J[F],L=G[F];if(J===L){continue}if(E&&L&&typeof L==="object"&&!L.nodeType){J[F]=o.extend(E,K||(L.length!=null?[]:{}),L)}else{if(L!==g){J[F]=L}}}}}return J};var b=/z-?index|font-?weight|opacity|zoom|line-?height/i,q=document.defaultView||{},s=Object.prototype.toString;o.extend({noConflict:function(E){l.$=p;if(E){l.jQuery=y}return o},isFunction:function(E){return s.call(E)==="[object Function]"},isArray:function(E){return s.call(E)==="[object Array]"},isXMLDoc:function(E){return E.nodeType===9&&E.documentElement.nodeName!=="HTML"||!!E.ownerDocument&&o.isXMLDoc(E.ownerDocument)},globalEval:function(G){if(G&&/\S/.test(G)){var F=document.getElementsByTagName("head")[0]||document.documentElement,E=document.createElement("script");E.type="text/javascript";if(o.support.scriptEval){E.appendChild(document.createTextNode(G))}else{E.text=G}F.insertBefore(E,F.firstChild);F.removeChild(E)}},nodeName:function(F,E){return F.nodeName&&F.nodeName.toUpperCase()==E.toUpperCase()},each:function(G,K,F){var E,H=0,I=G.length;if(F){if(I===g){for(E in G){if(K.apply(G[E],F)===false){break}}}else{for(;H<I;){if(K.apply(G[H++],F)===false){break}}}}else{if(I===g){for(E in G){if(K.call(G[E],E,G[E])===false){break}}}else{for(var J=G[0];H<I&&K.call(J,H,J)!==false;J=G[++H]){}}}return G},prop:function(H,I,G,F,E){if(o.isFunction(I)){I=I.call(H,F)}return typeof I==="number"&&G=="curCSS"&&!b.test(E)?I+"px":I},className:{add:function(E,F){o.each((F||"").split(/\s+/),function(G,H){if(E.nodeType==1&&!o.className.has(E.className,H)){E.className+=(E.className?" ":"")+H}})},remove:function(E,F){if(E.nodeType==1){E.className=F!==g?o.grep(E.className.split(/\s+/),function(G){return !o.className.has(F,G)}).join(" "):""}},has:function(F,E){return F&&o.inArray(E,(F.className||F).toString().split(/\s+/))>-1}},swap:function(H,G,I){var E={};for(var F in G){E[F]=H.style[F];H.style[F]=G[F]}I.call(H);for(var F in G){H.style[F]=E[F]}},css:function(H,F,J,E){if(F=="width"||F=="height"){var L,G={position:"absolute",visibility:"hidden",display:"block"},K=F=="width"?["Left","Right"]:["Top","Bottom"];function I(){L=F=="width"?H.offsetWidth:H.offsetHeight;if(E==="border"){return}o.each(K,function(){if(!E){L-=parseFloat(o.curCSS(H,"padding"+this,true))||0}if(E==="margin"){L+=parseFloat(o.curCSS(H,"margin"+this,true))||0}else{L-=parseFloat(o.curCSS(H,"border"+this+"Width",true))||0}})}if(H.offsetWidth!==0){I()}else{o.swap(H,G,I)}return Math.max(0,Math.round(L))}return o.curCSS(H,F,J)},curCSS:function(I,F,G){var L,E=I.style;if(F=="opacity"&&!o.support.opacity){L=o.attr(E,"opacity");return L==""?"1":L}if(F.match(/float/i)){F=w}if(!G&&E&&E[F]){L=E[F]}else{if(q.getComputedStyle){if(F.match(/float/i)){F="float"}F=F.replace(/([A-Z])/g,"-$1").toLowerCase();var M=q.getComputedStyle(I,null);if(M){L=M.getPropertyValue(F)}if(F=="opacity"&&L==""){L="1"}}else{if(I.currentStyle){var J=F.replace(/\-(\w)/g,function(N,O){return O.toUpperCase()});L=I.currentStyle[F]||I.currentStyle[J];if(!/^\d+(px)?$/i.test(L)&&/^\d/.test(L)){var H=E.left,K=I.runtimeStyle.left;I.runtimeStyle.left=I.currentStyle.left;E.left=L||0;L=E.pixelLeft+"px";E.left=H;I.runtimeStyle.left=K}}}}return L},clean:function(F,K,I){K=K||document;if(typeof K.createElement==="undefined"){K=K.ownerDocument||K[0]&&K[0].ownerDocument||document}if(!I&&F.length===1&&typeof F[0]==="string"){var H=/^<(\w+)\s*\/?>$/.exec(F[0]);if(H){return[K.createElement(H[1])]}}var G=[],E=[],L=K.createElement("div");o.each(F,function(P,S){if(typeof S==="number"){S+=""}if(!S){return}if(typeof S==="string"){S=S.replace(/(<(\w+)[^>]*?)\/>/g,function(U,V,T){return T.match(/^(abbr|br|col|img|input|link|meta|param|hr|area|embed)$/i)?U:V+"></"+T+">"});var O=S.replace(/^\s+/,"").substring(0,10).toLowerCase();var Q=!O.indexOf("<opt")&&[1,"<select multiple='multiple'>","</select>"]||!O.indexOf("<leg")&&[1,"<fieldset>","</fieldset>"]||O.match(/^<(thead|tbody|tfoot|colg|cap)/)&&[1,"<table>","</table>"]||!O.indexOf("<tr")&&[2,"<table><tbody>","</tbody></table>"]||(!O.indexOf("<td")||!O.indexOf("<th"))&&[3,"<table><tbody><tr>","</tr></tbody></table>"]||!O.indexOf("<col")&&[2,"<table><tbody></tbody><colgroup>","</colgroup></table>"]||!o.support.htmlSerialize&&[1,"div<div>","</div>"]||[0,"",""];L.innerHTML=Q[1]+S+Q[2];while(Q[0]--){L=L.lastChild}if(!o.support.tbody){var R=/<tbody/i.test(S),N=!O.indexOf("<table")&&!R?L.firstChild&&L.firstChild.childNodes:Q[1]=="<table>"&&!R?L.childNodes:[];for(var M=N.length-1;M>=0;--M){if(o.nodeName(N[M],"tbody")&&!N[M].childNodes.length){N[M].parentNode.removeChild(N[M])}}}if(!o.support.leadingWhitespace&&/^\s/.test(S)){L.insertBefore(K.createTextNode(S.match(/^\s*/)[0]),L.firstChild)}S=o.makeArray(L.childNodes)}if(S.nodeType){G.push(S)}else{G=o.merge(G,S)}});if(I){for(var J=0;G[J];J++){if(o.nodeName(G[J],"script")&&(!G[J].type||G[J].type.toLowerCase()==="text/javascript")){E.push(G[J].parentNode?G[J].parentNode.removeChild(G[J]):G[J])}else{if(G[J].nodeType===1){G.splice.apply(G,[J+1,0].concat(o.makeArray(G[J].getElementsByTagName("script"))))}I.appendChild(G[J])}}return E}return G},attr:function(J,G,K){if(!J||J.nodeType==3||J.nodeType==8){return g}var H=!o.isXMLDoc(J),L=K!==g;G=H&&o.props[G]||G;if(J.tagName){var F=/href|src|style/.test(G);if(G=="selected"&&J.parentNode){J.parentNode.selectedIndex}if(G in J&&H&&!F){if(L){if(G=="type"&&o.nodeName(J,"input")&&J.parentNode){throw"type property can't be changed"}J[G]=K}if(o.nodeName(J,"form")&&J.getAttributeNode(G)){return J.getAttributeNode(G).nodeValue}if(G=="tabIndex"){var I=J.getAttributeNode("tabIndex");return I&&I.specified?I.value:J.nodeName.match(/(button|input|object|select|textarea)/i)?0:J.nodeName.match(/^(a|area)$/i)&&J.href?0:g}return J[G]}if(!o.support.style&&H&&G=="style"){return o.attr(J.style,"cssText",K)}if(L){J.setAttribute(G,""+K)}var E=!o.support.hrefNormalized&&H&&F?J.getAttribute(G,2):J.getAttribute(G);return E===null?g:E}if(!o.support.opacity&&G=="opacity"){if(L){J.zoom=1;J.filter=(J.filter||"").replace(/alpha\([^)]*\)/,"")+(parseInt(K)+""=="NaN"?"":"alpha(opacity="+K*100+")")}return J.filter&&J.filter.indexOf("opacity=")>=0?(parseFloat(J.filter.match(/opacity=([^)]*)/)[1])/100)+"":""}G=G.replace(/-([a-z])/ig,function(M,N){return N.toUpperCase()});if(L){J[G]=K}return J[G]},trim:function(E){return(E||"").replace(/^\s+|\s+$/g,"")},makeArray:function(G){var E=[];if(G!=null){var F=G.length;if(F==null||typeof G==="string"||o.isFunction(G)||G.setInterval){E[0]=G}else{while(F){E[--F]=G[F]}}}return E},inArray:function(G,H){for(var E=0,F=H.length;E<F;E++){if(H[E]===G){return E}}return -1},merge:function(H,E){var F=0,G,I=H.length;if(!o.support.getAll){while((G=E[F++])!=null){if(G.nodeType!=8){H[I++]=G}}}else{while((G=E[F++])!=null){H[I++]=G}}return H},unique:function(K){var F=[],E={};try{for(var G=0,H=K.length;G<H;G++){var J=o.data(K[G]);if(!E[J]){E[J]=true;F.push(K[G])}}}catch(I){F=K}return F},grep:function(F,J,E){var G=[];for(var H=0,I=F.length;H<I;H++){if(!E!=!J(F[H],H)){G.push(F[H])}}return G},map:function(E,J){var F=[];for(var G=0,H=E.length;G<H;G++){var I=J(E[G],G);if(I!=null){F[F.length]=I}}return F.concat.apply([],F)}});var C=navigator.userAgent.toLowerCase();o.browser={version:(C.match(/.+(?:rv|it|ra|ie)[\/: ]([\d.]+)/)||[0,"0"])[1],safari:/webkit/.test(C),opera:/opera/.test(C),msie:/msie/.test(C)&&!/opera/.test(C),mozilla:/mozilla/.test(C)&&!/(compatible|webkit)/.test(C)};o.each({parent:function(E){return E.parentNode},parents:function(E){return o.dir(E,"parentNode")},next:function(E){return o.nth(E,2,"nextSibling")},prev:function(E){return o.nth(E,2,"previousSibling")},nextAll:function(E){return o.dir(E,"nextSibling")},prevAll:function(E){return o.dir(E,"previousSibling")},siblings:function(E){return o.sibling(E.parentNode.firstChild,E)},children:function(E){return o.sibling(E.firstChild)},contents:function(E){return o.nodeName(E,"iframe")?E.contentDocument||E.contentWindow.document:o.makeArray(E.childNodes)}},function(E,F){o.fn[E]=function(G){var H=o.map(this,F);if(G&&typeof G=="string"){H=o.multiFilter(G,H)}return this.pushStack(o.unique(H),E,G)}});o.each({appendTo:"append",prependTo:"prepend",insertBefore:"before",insertAfter:"after",replaceAll:"replaceWith"},function(E,F){o.fn[E]=function(G){var J=[],L=o(G);for(var K=0,H=L.length;K<H;K++){var I=(K>0?this.clone(true):this).get();o.fn[F].apply(o(L[K]),I);J=J.concat(I)}return this.pushStack(J,E,G)}});o.each({removeAttr:function(E){o.attr(this,E,"");if(this.nodeType==1){this.removeAttribute(E)}},addClass:function(E){o.className.add(this,E)},removeClass:function(E){o.className.remove(this,E)},toggleClass:function(F,E){if(typeof E!=="boolean"){E=!o.className.has(this,F)}o.className[E?"add":"remove"](this,F)},remove:function(E){if(!E||o.filter(E,[this]).length){o("*",this).add([this]).each(function(){o.event.remove(this);o.removeData(this)});if(this.parentNode){this.parentNode.removeChild(this)}}},empty:function(){o(this).children().remove();while(this.firstChild){this.removeChild(this.firstChild)}}},function(E,F){o.fn[E]=function(){return this.each(F,arguments)}});function j(E,F){return E[0]&&parseInt(o.curCSS(E[0],F,true),10)||0}var h="jQuery"+e(),v=0,A={};o.extend({cache:{},data:function(F,E,G){F=F==l?A:F;var H=F[h];if(!H){H=F[h]=++v}if(E&&!o.cache[H]){o.cache[H]={}}if(G!==g){o.cache[H][E]=G}return E?o.cache[H][E]:H},removeData:function(F,E){F=F==l?A:F;var H=F[h];if(E){if(o.cache[H]){delete o.cache[H][E];E="";for(E in o.cache[H]){break}if(!E){o.removeData(F)}}}else{try{delete F[h]}catch(G){if(F.removeAttribute){F.removeAttribute(h)}}delete o.cache[H]}},queue:function(F,E,H){if(F){E=(E||"fx")+"queue";var G=o.data(F,E);if(!G||o.isArray(H)){G=o.data(F,E,o.makeArray(H))}else{if(H){G.push(H)}}}return G},dequeue:function(H,G){var E=o.queue(H,G),F=E.shift();if(!G||G==="fx"){F=E[0]}if(F!==g){F.call(H)}}});o.fn.extend({data:function(E,G){var H=E.split(".");H[1]=H[1]?"."+H[1]:"";if(G===g){var F=this.triggerHandler("getData"+H[1]+"!",[H[0]]);if(F===g&&this.length){F=o.data(this[0],E)}return F===g&&H[1]?this.data(H[0]):F}else{return this.trigger("setData"+H[1]+"!",[H[0],G]).each(function(){o.data(this,E,G)})}},removeData:function(E){return this.each(function(){o.removeData(this,E)})},queue:function(E,F){if(typeof E!=="string"){F=E;E="fx"}if(F===g){return o.queue(this[0],E)}return this.each(function(){var G=o.queue(this,E,F);if(E=="fx"&&G.length==1){G[0].call(this)}})},dequeue:function(E){return this.each(function(){o.dequeue(this,E)})}});
-/*
- * Sizzle CSS Selector Engine - v0.9.3
- * Copyright 2009, The Dojo Foundation
- * Released under the MIT, BSD, and GPL Licenses.
- * More information: http://sizzlejs.com/
- */
-(function(){var R=/((?:\((?:\([^()]+\)|[^()]+)+\)|\[(?:\[[^[\]]*\]|['"][^'"]*['"]|[^[\]'"]+)+\]|\\.|[^ >+~,(\[\\]+)+|[>+~])(\s*,\s*)?/g,L=0,H=Object.prototype.toString;var F=function(Y,U,ab,ac){ab=ab||[];U=U||document;if(U.nodeType!==1&&U.nodeType!==9){return[]}if(!Y||typeof Y!=="string"){return ab}var Z=[],W,af,ai,T,ad,V,X=true;R.lastIndex=0;while((W=R.exec(Y))!==null){Z.push(W[1]);if(W[2]){V=RegExp.rightContext;break}}if(Z.length>1&&M.exec(Y)){if(Z.length===2&&I.relative[Z[0]]){af=J(Z[0]+Z[1],U)}else{af=I.relative[Z[0]]?[U]:F(Z.shift(),U);while(Z.length){Y=Z.shift();if(I.relative[Y]){Y+=Z.shift()}af=J(Y,af)}}}else{var ae=ac?{expr:Z.pop(),set:E(ac)}:F.find(Z.pop(),Z.length===1&&U.parentNode?U.parentNode:U,Q(U));af=F.filter(ae.expr,ae.set);if(Z.length>0){ai=E(af)}else{X=false}while(Z.length){var ah=Z.pop(),ag=ah;if(!I.relative[ah]){ah=""}else{ag=Z.pop()}if(ag==null){ag=U}I.relative[ah](ai,ag,Q(U))}}if(!ai){ai=af}if(!ai){throw"Syntax error, unrecognized expression: "+(ah||Y)}if(H.call(ai)==="[object Array]"){if(!X){ab.push.apply(ab,ai)}else{if(U.nodeType===1){for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&(ai[aa]===true||ai[aa].nodeType===1&&K(U,ai[aa]))){ab.push(af[aa])}}}else{for(var aa=0;ai[aa]!=null;aa++){if(ai[aa]&&ai[aa].nodeType===1){ab.push(af[aa])}}}}}else{E(ai,ab)}if(V){F(V,U,ab,ac);if(G){hasDuplicate=false;ab.sort(G);if(hasDuplicate){for(var aa=1;aa<ab.length;aa++){if(ab[aa]===ab[aa-1]){ab.splice(aa--,1)}}}}}return ab};F.matches=function(T,U){return F(T,null,null,U)};F.find=function(aa,T,ab){var Z,X;if(!aa){return[]}for(var W=0,V=I.order.length;W<V;W++){var Y=I.order[W],X;if((X=I.match[Y].exec(aa))){var U=RegExp.leftContext;if(U.substr(U.length-1)!=="\\"){X[1]=(X[1]||"").replace(/\\/g,"");Z=I.find[Y](X,T,ab);if(Z!=null){aa=aa.replace(I.match[Y],"");break}}}}if(!Z){Z=T.getElementsByTagName("*")}return{set:Z,expr:aa}};F.filter=function(ad,ac,ag,W){var V=ad,ai=[],aa=ac,Y,T,Z=ac&&ac[0]&&Q(ac[0]);while(ad&&ac.length){for(var ab in I.filter){if((Y=I.match[ab].exec(ad))!=null){var U=I.filter[ab],ah,af;T=false;if(aa==ai){ai=[]}if(I.preFilter[ab]){Y=I.preFilter[ab](Y,aa,ag,ai,W,Z);if(!Y){T=ah=true}else{if(Y===true){continue}}}if(Y){for(var X=0;(af=aa[X])!=null;X++){if(af){ah=U(af,Y,X,aa);var ae=W^!!ah;if(ag&&ah!=null){if(ae){T=true}else{aa[X]=false}}else{if(ae){ai.push(af);T=true}}}}}if(ah!==g){if(!ag){aa=ai}ad=ad.replace(I.match[ab],"");if(!T){return[]}break}}}if(ad==V){if(T==null){throw"Syntax error, unrecognized expression: "+ad}else{break}}V=ad}return aa};var I=F.selectors={order:["ID","NAME","TAG"],match:{ID:/#((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,CLASS:/\.((?:[\w\u00c0-\uFFFF_-]|\\.)+)/,NAME:/\[name=['"]*((?:[\w\u00c0-\uFFFF_-]|\\.)+)['"]*\]/,ATTR:/\[\s*((?:[\w\u00c0-\uFFFF_-]|\\.)+)\s*(?:(\S?=)\s*(['"]*)(.*?)\3|)\s*\]/,TAG:/^((?:[\w\u00c0-\uFFFF\*_-]|\\.)+)/,CHILD:/:(only|nth|last|first)-child(?:\((even|odd|[\dn+-]*)\))?/,POS:/:(nth|eq|gt|lt|first|last|even|odd)(?:\((\d*)\))?(?=[^-]|$)/,PSEUDO:/:((?:[\w\u00c0-\uFFFF_-]|\\.)+)(?:\((['"]*)((?:\([^\)]+\)|[^\2\(\)]*)+)\2\))?/},attrMap:{"class":"className","for":"htmlFor"},attrHandle:{href:function(T){return T.getAttribute("href")}},relative:{"+":function(aa,T,Z){var X=typeof T==="string",ab=X&&!/\W/.test(T),Y=X&&!ab;if(ab&&!Z){T=T.toUpperCase()}for(var W=0,V=aa.length,U;W<V;W++){if((U=aa[W])){while((U=U.previousSibling)&&U.nodeType!==1){}aa[W]=Y||U&&U.nodeName===T?U||false:U===T}}if(Y){F.filter(T,aa,true)}},">":function(Z,U,aa){var X=typeof U==="string";if(X&&!/\W/.test(U)){U=aa?U:U.toUpperCase();for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){var W=Y.parentNode;Z[V]=W.nodeName===U?W:false}}}else{for(var V=0,T=Z.length;V<T;V++){var Y=Z[V];if(Y){Z[V]=X?Y.parentNode:Y.parentNode===U}}if(X){F.filter(U,Z,true)}}},"":function(W,U,Y){var V=L++,T=S;if(!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("parentNode",U,V,W,X,Y)},"~":function(W,U,Y){var V=L++,T=S;if(typeof U==="string"&&!U.match(/\W/)){var X=U=Y?U:U.toUpperCase();T=P}T("previousSibling",U,V,W,X,Y)}},find:{ID:function(U,V,W){if(typeof V.getElementById!=="undefined"&&!W){var T=V.getElementById(U[1]);return T?[T]:[]}},NAME:function(V,Y,Z){if(typeof Y.getElementsByName!=="undefined"){var U=[],X=Y.getElementsByName(V[1]);for(var W=0,T=X.length;W<T;W++){if(X[W].getAttribute("name")===V[1]){U.push(X[W])}}return U.length===0?null:U}},TAG:function(T,U){return U.getElementsByTagName(T[1])}},preFilter:{CLASS:function(W,U,V,T,Z,aa){W=" "+W[1].replace(/\\/g,"")+" ";if(aa){return W}for(var X=0,Y;(Y=U[X])!=null;X++){if(Y){if(Z^(Y.className&&(" "+Y.className+" ").indexOf(W)>=0)){if(!V){T.push(Y)}}else{if(V){U[X]=false}}}}return false},ID:function(T){return T[1].replace(/\\/g,"")},TAG:function(U,T){for(var V=0;T[V]===false;V++){}return T[V]&&Q(T[V])?U[1]:U[1].toUpperCase()},CHILD:function(T){if(T[1]=="nth"){var U=/(-?)(\d*)n((?:\+|-)?\d*)/.exec(T[2]=="even"&&"2n"||T[2]=="odd"&&"2n+1"||!/\D/.test(T[2])&&"0n+"+T[2]||T[2]);T[2]=(U[1]+(U[2]||1))-0;T[3]=U[3]-0}T[0]=L++;return T},ATTR:function(X,U,V,T,Y,Z){var W=X[1].replace(/\\/g,"");if(!Z&&I.attrMap[W]){X[1]=I.attrMap[W]}if(X[2]==="~="){X[4]=" "+X[4]+" "}return X},PSEUDO:function(X,U,V,T,Y){if(X[1]==="not"){if(X[3].match(R).length>1||/^\w/.test(X[3])){X[3]=F(X[3],null,null,U)}else{var W=F.filter(X[3],U,V,true^Y);if(!V){T.push.apply(T,W)}return false}}else{if(I.match.POS.test(X[0])||I.match.CHILD.test(X[0])){return true}}return X},POS:function(T){T.unshift(true);return T}},filters:{enabled:function(T){return T.disabled===false&&T.type!=="hidden"},disabled:function(T){return T.disabled===true},checked:function(T){return T.checked===true},selected:function(T){T.parentNode.selectedIndex;return T.selected===true},parent:function(T){return !!T.firstChild},empty:function(T){return !T.firstChild},has:function(V,U,T){return !!F(T[3],V).length},header:function(T){return/h\d/i.test(T.nodeName)},text:function(T){return"text"===T.type},radio:function(T){return"radio"===T.type},checkbox:function(T){return"checkbox"===T.type},file:function(T){return"file"===T.type},password:function(T){return"password"===T.type},submit:function(T){return"submit"===T.type},image:function(T){return"image"===T.type},reset:function(T){return"reset"===T.type},button:function(T){return"button"===T.type||T.nodeName.toUpperCase()==="BUTTON"},input:function(T){return/input|select|textarea|button/i.test(T.nodeName)}},setFilters:{first:function(U,T){return T===0},last:function(V,U,T,W){return U===W.length-1},even:function(U,T){return T%2===0},odd:function(U,T){return T%2===1},lt:function(V,U,T){return U<T[3]-0},gt:function(V,U,T){return U>T[3]-0},nth:function(V,U,T){return T[3]-0==U},eq:function(V,U,T){return T[3]-0==U}},filter:{PSEUDO:function(Z,V,W,aa){var U=V[1],X=I.filters[U];if(X){return X(Z,W,V,aa)}else{if(U==="contains"){return(Z.textContent||Z.innerText||"").indexOf(V[3])>=0}else{if(U==="not"){var Y=V[3];for(var W=0,T=Y.length;W<T;W++){if(Y[W]===Z){return false}}return true}}}},CHILD:function(T,W){var Z=W[1],U=T;switch(Z){case"only":case"first":while(U=U.previousSibling){if(U.nodeType===1){return false}}if(Z=="first"){return true}U=T;case"last":while(U=U.nextSibling){if(U.nodeType===1){return false}}return true;case"nth":var V=W[2],ac=W[3];if(V==1&&ac==0){return true}var Y=W[0],ab=T.parentNode;if(ab&&(ab.sizcache!==Y||!T.nodeIndex)){var X=0;for(U=ab.firstChild;U;U=U.nextSibling){if(U.nodeType===1){U.nodeIndex=++X}}ab.sizcache=Y}var aa=T.nodeIndex-ac;if(V==0){return aa==0}else{return(aa%V==0&&aa/V>=0)}}},ID:function(U,T){return U.nodeType===1&&U.getAttribute("id")===T},TAG:function(U,T){return(T==="*"&&U.nodeType===1)||U.nodeName===T},CLASS:function(U,T){return(" "+(U.className||U.getAttribute("class"))+" ").indexOf(T)>-1},ATTR:function(Y,W){var V=W[1],T=I.attrHandle[V]?I.attrHandle[V](Y):Y[V]!=null?Y[V]:Y.getAttribute(V),Z=T+"",X=W[2],U=W[4];return T==null?X==="!=":X==="="?Z===U:X==="*="?Z.indexOf(U)>=0:X==="~="?(" "+Z+" ").indexOf(U)>=0:!U?Z&&T!==false:X==="!="?Z!=U:X==="^="?Z.indexOf(U)===0:X==="$="?Z.substr(Z.length-U.length)===U:X==="|="?Z===U||Z.substr(0,U.length+1)===U+"-":false},POS:function(X,U,V,Y){var T=U[2],W=I.setFilters[T];if(W){return W(X,V,U,Y)}}}};var M=I.match.POS;for(var O in I.match){I.match[O]=RegExp(I.match[O].source+/(?![^\[]*\])(?![^\(]*\))/.source)}var E=function(U,T){U=Array.prototype.slice.call(U);if(T){T.push.apply(T,U);return T}return U};try{Array.prototype.slice.call(document.documentElement.childNodes)}catch(N){E=function(X,W){var U=W||[];if(H.call(X)==="[object Array]"){Array.prototype.push.apply(U,X)}else{if(typeof X.length==="number"){for(var V=0,T=X.length;V<T;V++){U.push(X[V])}}else{for(var V=0;X[V];V++){U.push(X[V])}}}return U}}var G;if(document.documentElement.compareDocumentPosition){G=function(U,T){var V=U.compareDocumentPosition(T)&4?-1:U===T?0:1;if(V===0){hasDuplicate=true}return V}}else{if("sourceIndex" in document.documentElement){G=function(U,T){var V=U.sourceIndex-T.sourceIndex;if(V===0){hasDuplicate=true}return V}}else{if(document.createRange){G=function(W,U){var V=W.ownerDocument.createRange(),T=U.ownerDocument.createRange();V.selectNode(W);V.collapse(true);T.selectNode(U);T.collapse(true);var X=V.compareBoundaryPoints(Range.START_TO_END,T);if(X===0){hasDuplicate=true}return X}}}}(function(){var U=document.createElement("form"),V="script"+(new Date).getTime();U.innerHTML="<input name='"+V+"'/>";var T=document.documentElement;T.insertBefore(U,T.firstChild);if(!!document.getElementById(V)){I.find.ID=function(X,Y,Z){if(typeof Y.getElementById!=="undefined"&&!Z){var W=Y.getElementById(X[1]);return W?W.id===X[1]||typeof W.getAttributeNode!=="undefined"&&W.getAttributeNode("id").nodeValue===X[1]?[W]:g:[]}};I.filter.ID=function(Y,W){var X=typeof Y.getAttributeNode!=="undefined"&&Y.getAttributeNode("id");return Y.nodeType===1&&X&&X.nodeValue===W}}T.removeChild(U)})();(function(){var T=document.createElement("div");T.appendChild(document.createComment(""));if(T.getElementsByTagName("*").length>0){I.find.TAG=function(U,Y){var X=Y.getElementsByTagName(U[1]);if(U[1]==="*"){var W=[];for(var V=0;X[V];V++){if(X[V].nodeType===1){W.push(X[V])}}X=W}return X}}T.innerHTML="<a href='#'></a>";if(T.firstChild&&typeof T.firstChild.getAttribute!=="undefined"&&T.firstChild.getAttribute("href")!=="#"){I.attrHandle.href=function(U){return U.getAttribute("href",2)}}})();if(document.querySelectorAll){(function(){var T=F,U=document.createElement("div");U.innerHTML="<p class='TEST'></p>";if(U.querySelectorAll&&U.querySelectorAll(".TEST").length===0){return}F=function(Y,X,V,W){X=X||document;if(!W&&X.nodeType===9&&!Q(X)){try{return E(X.querySelectorAll(Y),V)}catch(Z){}}return T(Y,X,V,W)};F.find=T.find;F.filter=T.filter;F.selectors=T.selectors;F.matches=T.matches})()}if(document.getElementsByClassName&&document.documentElement.getElementsByClassName){(function(){var T=document.createElement("div");T.innerHTML="<div class='test e'></div><div class='test'></div>";if(T.getElementsByClassName("e").length===0){return}T.lastChild.className="e";if(T.getElementsByClassName("e").length===1){return}I.order.splice(1,0,"CLASS");I.find.CLASS=function(U,V,W){if(typeof V.getElementsByClassName!=="undefined"&&!W){return V.getElementsByClassName(U[1])}}})()}function P(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1&&!ac){T.sizcache=Y;T.sizset=W}if(T.nodeName===Z){X=T;break}T=T[U]}ad[W]=X}}}function S(U,Z,Y,ad,aa,ac){var ab=U=="previousSibling"&&!ac;for(var W=0,V=ad.length;W<V;W++){var T=ad[W];if(T){if(ab&&T.nodeType===1){T.sizcache=Y;T.sizset=W}T=T[U];var X=false;while(T){if(T.sizcache===Y){X=ad[T.sizset];break}if(T.nodeType===1){if(!ac){T.sizcache=Y;T.sizset=W}if(typeof Z!=="string"){if(T===Z){X=true;break}}else{if(F.filter(Z,[T]).length>0){X=T;break}}}T=T[U]}ad[W]=X}}}var K=document.compareDocumentPosition?function(U,T){return U.compareDocumentPosition(T)&16}:function(U,T){return U!==T&&(U.contains?U.contains(T):true)};var Q=function(T){return T.nodeType===9&&T.documentElement.nodeName!=="HTML"||!!T.ownerDocument&&Q(T.ownerDocument)};var J=function(T,aa){var W=[],X="",Y,V=aa.nodeType?[aa]:aa;while((Y=I.match.PSEUDO.exec(T))){X+=Y[0];T=T.replace(I.match.PSEUDO,"")}T=I.relative[T]?T+"*":T;for(var Z=0,U=V.length;Z<U;Z++){F(T,V[Z],W)}return F.filter(X,W)};o.find=F;o.filter=F.filter;o.expr=F.selectors;o.expr[":"]=o.expr.filters;F.selectors.filters.hidden=function(T){return T.offsetWidth===0||T.offsetHeight===0};F.selectors.filters.visible=function(T){return T.offsetWidth>0||T.offsetHeight>0};F.selectors.filters.animated=function(T){return o.grep(o.timers,function(U){return T===U.elem}).length};o.multiFilter=function(V,T,U){if(U){V=":not("+V+")"}return F.matches(V,T)};o.dir=function(V,U){var T=[],W=V[U];while(W&&W!=document){if(W.nodeType==1){T.push(W)}W=W[U]}return T};o.nth=function(X,T,V,W){T=T||1;var U=0;for(;X;X=X[V]){if(X.nodeType==1&&++U==T){break}}return X};o.sibling=function(V,U){var T=[];for(;V;V=V.nextSibling){if(V.nodeType==1&&V!=U){T.push(V)}}return T};return;l.Sizzle=F})();o.event={add:function(I,F,H,K){if(I.nodeType==3||I.nodeType==8){return}if(I.setInterval&&I!=l){I=l}if(!H.guid){H.guid=this.guid++}if(K!==g){var G=H;H=this.proxy(G);H.data=K}var E=o.data(I,"events")||o.data(I,"events",{}),J=o.data(I,"handle")||o.data(I,"handle",function(){return typeof o!=="undefined"&&!o.event.triggered?o.event.handle.apply(arguments.callee.elem,arguments):g});J.elem=I;o.each(F.split(/\s+/),function(M,N){var O=N.split(".");N=O.shift();H.type=O.slice().sort().join(".");var L=E[N];if(o.event.specialAll[N]){o.event.specialAll[N].setup.call(I,K,O)}if(!L){L=E[N]={};if(!o.event.special[N]||o.event.special[N].setup.call(I,K,O)===false){if(I.addEventListener){I.addEventListener(N,J,false)}else{if(I.attachEvent){I.attachEvent("on"+N,J)}}}}L[H.guid]=H;o.event.global[N]=true});I=null},guid:1,global:{},remove:function(K,H,J){if(K.nodeType==3||K.nodeType==8){return}var G=o.data(K,"events"),F,E;if(G){if(H===g||(typeof H==="string"&&H.charAt(0)==".")){for(var I in G){this.remove(K,I+(H||""))}}else{if(H.type){J=H.handler;H=H.type}o.each(H.split(/\s+/),function(M,O){var Q=O.split(".");O=Q.shift();var N=RegExp("(^|\\.)"+Q.slice().sort().join(".*\\.")+"(\\.|$)");if(G[O]){if(J){delete G[O][J.guid]}else{for(var P in G[O]){if(N.test(G[O][P].type)){delete G[O][P]}}}if(o.event.specialAll[O]){o.event.specialAll[O].teardown.call(K,Q)}for(F in G[O]){break}if(!F){if(!o.event.special[O]||o.event.special[O].teardown.call(K,Q)===false){if(K.removeEventListener){K.removeEventListener(O,o.data(K,"handle"),false)}else{if(K.detachEvent){K.detachEvent("on"+O,o.data(K,"handle"))}}}F=null;delete G[O]}}})}for(F in G){break}if(!F){var L=o.data(K,"handle");if(L){L.elem=null}o.removeData(K,"events");o.removeData(K,"handle")}}},trigger:function(I,K,H,E){var G=I.type||I;if(!E){I=typeof I==="object"?I[h]?I:o.extend(o.Event(G),I):o.Event(G);if(G.indexOf("!")>=0){I.type=G=G.slice(0,-1);I.exclusive=true}if(!H){I.stopPropagation();if(this.global[G]){o.each(o.cache,function(){if(this.events&&this.events[G]){o.event.trigger(I,K,this.handle.elem)}})}}if(!H||H.nodeType==3||H.nodeType==8){return g}I.result=g;I.target=H;K=o.makeArray(K);K.unshift(I)}I.currentTarget=H;var J=o.data(H,"handle");if(J){J.apply(H,K)}if((!H[G]||(o.nodeName(H,"a")&&G=="click"))&&H["on"+G]&&H["on"+G].apply(H,K)===false){I.result=false}if(!E&&H[G]&&!I.isDefaultPrevented()&&!(o.nodeName(H,"a")&&G=="click")){this.triggered=true;try{H[G]()}catch(L){}}this.triggered=false;if(!I.isPropagationStopped()){var F=H.parentNode||H.ownerDocument;if(F){o.event.trigger(I,K,F,true)}}},handle:function(K){var J,E;K=arguments[0]=o.event.fix(K||l.event);K.currentTarget=this;var L=K.type.split(".");K.type=L.shift();J=!L.length&&!K.exclusive;var I=RegExp("(^|\\.)"+L.slice().sort().join(".*\\.")+"(\\.|$)");E=(o.data(this,"events")||{})[K.type];for(var G in E){var H=E[G];if(J||I.test(H.type)){K.handler=H;K.data=H.data;var F=H.apply(this,arguments);if(F!==g){K.result=F;if(F===false){K.preventDefault();K.stopPropagation()}}if(K.isImmediatePropagationStopped()){break}}}},props:"altKey attrChange attrName bubbles button cancelable charCode clientX clientY ctrlKey currentTarget data detail eventPhase fromElement handler keyCode metaKey newValue originalTarget pageX pageY prevValue relatedNode relatedTarget screenX screenY shiftKey srcElement target toElement view wheelDelta which".split(" "),fix:function(H){if(H[h]){return H}var F=H;H=o.Event(F);for(var G=this.props.length,J;G;){J=this.props[--G];H[J]=F[J]}if(!H.target){H.target=H.srcElement||document}if(H.target.nodeType==3){H.target=H.target.parentNode}if(!H.relatedTarget&&H.fromElement){H.relatedTarget=H.fromElement==H.target?H.toElement:H.fromElement}if(H.pageX==null&&H.clientX!=null){var I=document.documentElement,E=document.body;H.pageX=H.clientX+(I&&I.scrollLeft||E&&E.scrollLeft||0)-(I.clientLeft||0);H.pageY=H.clientY+(I&&I.scrollTop||E&&E.scrollTop||0)-(I.clientTop||0)}if(!H.which&&((H.charCode||H.charCode===0)?H.charCode:H.keyCode)){H.which=H.charCode||H.keyCode}if(!H.metaKey&&H.ctrlKey){H.metaKey=H.ctrlKey}if(!H.which&&H.button){H.which=(H.button&1?1:(H.button&2?3:(H.button&4?2:0)))}return H},proxy:function(F,E){E=E||function(){return F.apply(this,arguments)};E.guid=F.guid=F.guid||E.guid||this.guid++;return E},special:{ready:{setup:B,teardown:function(){}}},specialAll:{live:{setup:function(E,F){o.event.add(this,F[0],c)},teardown:function(G){if(G.length){var E=0,F=RegExp("(^|\\.)"+G[0]+"(\\.|$)");o.each((o.data(this,"events").live||{}),function(){if(F.test(this.type)){E++}});if(E<1){o.event.remove(this,G[0],c)}}}}}};o.Event=function(E){if(!this.preventDefault){return new o.Event(E)}if(E&&E.type){this.originalEvent=E;this.type=E.type}else{this.type=E}this.timeStamp=e();this[h]=true};function k(){return false}function u(){return true}o.Event.prototype={preventDefault:function(){this.isDefaultPrevented=u;var E=this.originalEvent;if(!E){return}if(E.preventDefault){E.preventDefault()}E.returnValue=false},stopPropagation:function(){this.isPropagationStopped=u;var E=this.originalEvent;if(!E){return}if(E.stopPropagation){E.stopPropagation()}E.cancelBubble=true},stopImmediatePropagation:function(){this.isImmediatePropagationStopped=u;this.stopPropagation()},isDefaultPrevented:k,isPropagationStopped:k,isImmediatePropagationStopped:k};var a=function(F){var E=F.relatedTarget;while(E&&E!=this){try{E=E.parentNode}catch(G){E=this}}if(E!=this){F.type=F.data;o.event.handle.apply(this,arguments)}};o.each({mouseover:"mouseenter",mouseout:"mouseleave"},function(F,E){o.event.special[E]={setup:function(){o.event.add(this,F,a,E)},teardown:function(){o.event.remove(this,F,a)}}});o.fn.extend({bind:function(F,G,E){return F=="unload"?this.one(F,G,E):this.each(function(){o.event.add(this,F,E||G,E&&G)})},one:function(G,H,F){var E=o.event.proxy(F||H,function(I){o(this).unbind(I,E);return(F||H).apply(this,arguments)});return this.each(function(){o.event.add(this,G,E,F&&H)})},unbind:function(F,E){return this.each(function(){o.event.remove(this,F,E)})},trigger:function(E,F){return this.each(function(){o.event.trigger(E,F,this)})},triggerHandler:function(E,G){if(this[0]){var F=o.Event(E);F.preventDefault();F.stopPropagation();o.event.trigger(F,G,this[0]);return F.result}},toggle:function(G){var E=arguments,F=1;while(F<E.length){o.event.proxy(G,E[F++])}return this.click(o.event.proxy(G,function(H){this.lastToggle=(this.lastToggle||0)%F;H.preventDefault();return E[this.lastToggle++].apply(this,arguments)||false}))},hover:function(E,F){return this.mouseenter(E).mouseleave(F)},ready:function(E){B();if(o.isReady){E.call(document,o)}else{o.readyList.push(E)}return this},live:function(G,F){var E=o.event.proxy(F);E.guid+=this.selector+G;o(document).bind(i(G,this.selector),this.selector,E);return this},die:function(F,E){o(document).unbind(i(F,this.selector),E?{guid:E.guid+this.selector+F}:null);return this}});function c(H){var E=RegExp("(^|\\.)"+H.type+"(\\.|$)"),G=true,F=[];o.each(o.data(this,"events").live||[],function(I,J){if(E.test(J.type)){var K=o(H.target).closest(J.data)[0];if(K){F.push({elem:K,fn:J})}}});F.sort(function(J,I){return o.data(J.elem,"closest")-o.data(I.elem,"closest")});o.each(F,function(){if(this.fn.call(this.elem,H,this.fn.data)===false){return(G=false)}});return G}function i(F,E){return["live",F,E.replace(/\./g,"`").replace(/ /g,"|")].join(".")}o.extend({isReady:false,readyList:[],ready:function(){if(!o.isReady){o.isReady=true;if(o.readyList){o.each(o.readyList,function(){this.call(document,o)});o.readyList=null}o(document).triggerHandler("ready")}}});var x=false;function B(){if(x){return}x=true;if(document.addEventListener){document.addEventListener("DOMContentLoaded",function(){document.removeEventListener("DOMContentLoaded",arguments.callee,false);o.ready()},false)}else{if(document.attachEvent){document.attachEvent("onreadystatechange",function(){if(document.readyState==="complete"){document.detachEvent("onreadystatechange",arguments.callee);o.ready()}});if(document.documentElement.doScroll&&l==l.top){(function(){if(o.isReady){return}try{document.documentElement.doScroll("left")}catch(E){setTimeout(arguments.callee,0);return}o.ready()})()}}}o.event.add(l,"load",o.ready)}o.each(("blur,focus,load,resize,scroll,unload,click,dblclick,mousedown,mouseup,mousemove,mouseover,mouseout,mouseenter,mouseleave,change,select,submit,keydown,keypress,keyup,error").split(","),function(F,E){o.fn[E]=function(G){return G?this.bind(E,G):this.trigger(E)}});o(l).bind("unload",function(){for(var E in o.cache){if(E!=1&&o.cache[E].handle){o.event.remove(o.cache[E].handle.elem)}}});(function(){o.support={};var F=document.documentElement,G=document.createElement("script"),K=document.createElement("div"),J="script"+(new Date).getTime();K.style.display="none";K.innerHTML=' <link/><table></table><a href="/a" style="color:red;float:left;opacity:.5;">a</a><select><option>text</option></select><object><param/></object>';var H=K.getElementsByTagName("*"),E=K.getElementsByTagName("a")[0];if(!H||!H.length||!E){return}o.support={leadingWhitespace:K.firstChild.nodeType==3,tbody:!K.getElementsByTagName("tbody").length,objectAll:!!K.getElementsByTagName("object")[0].getElementsByTagName("*").length,htmlSerialize:!!K.getElementsByTagName("link").length,style:/red/.test(E.getAttribute("style")),hrefNormalized:E.getAttribute("href")==="/a",opacity:E.style.opacity==="0.5",cssFloat:!!E.style.cssFloat,scriptEval:false,noCloneEvent:true,boxModel:null};G.type="text/javascript";try{G.appendChild(document.createTextNode("window."+J+"=1;"))}catch(I){}F.insertBefore(G,F.firstChild);if(l[J]){o.support.scriptEval=true;delete l[J]}F.removeChild(G);if(K.attachEvent&&K.fireEvent){K.attachEvent("onclick",function(){o.support.noCloneEvent=false;K.detachEvent("onclick",arguments.callee)});K.cloneNode(true).fireEvent("onclick")}o(function(){var L=document.createElement("div");L.style.width=L.style.paddingLeft="1px";document.body.appendChild(L);o.boxModel=o.support.boxModel=L.offsetWidth===2;document.body.removeChild(L).style.display="none"})})();var w=o.support.cssFloat?"cssFloat":"styleFloat";o.props={"for":"htmlFor","class":"className","float":w,cssFloat:w,styleFloat:w,readonly:"readOnly",maxlength:"maxLength",cellspacing:"cellSpacing",rowspan:"rowSpan",tabindex:"tabIndex"};o.fn.extend({_load:o.fn.load,load:function(G,J,K){if(typeof G!=="string"){return this._load(G)}var I=G.indexOf(" ");if(I>=0){var E=G.slice(I,G.length);G=G.slice(0,I)}var H="GET";if(J){if(o.isFunction(J)){K=J;J=null}else{if(typeof J==="object"){J=o.param(J);H="POST"}}}var F=this;o.ajax({url:G,type:H,dataType:"html",data:J,complete:function(M,L){if(L=="success"||L=="notmodified"){F.html(E?o("<div/>").append(M.responseText.replace(/<script(.|\s)*?\/script>/g,"")).find(E):M.responseText)}if(K){F.each(K,[M.responseText,L,M])}}});return this},serialize:function(){return o.param(this.serializeArray())},serializeArray:function(){return this.map(function(){return this.elements?o.makeArray(this.elements):this}).filter(function(){return this.name&&!this.disabled&&(this.checked||/select|textarea/i.test(this.nodeName)||/text|hidden|password|search/i.test(this.type))}).map(function(E,F){var G=o(this).val();return G==null?null:o.isArray(G)?o.map(G,function(I,H){return{name:F.name,value:I}}):{name:F.name,value:G}}).get()}});o.each("ajaxStart,ajaxStop,ajaxComplete,ajaxError,ajaxSuccess,ajaxSend".split(","),function(E,F){o.fn[F]=function(G){return this.bind(F,G)}});var r=e();o.extend({get:function(E,G,H,F){if(o.isFunction(G)){H=G;G=null}return o.ajax({type:"GET",url:E,data:G,success:H,dataType:F})},getScript:function(E,F){return o.get(E,null,F,"script")},getJSON:function(E,F,G){return o.get(E,F,G,"json")},post:function(E,G,H,F){if(o.isFunction(G)){H=G;G={}}return o.ajax({type:"POST",url:E,data:G,success:H,dataType:F})},ajaxSetup:function(E){o.extend(o.ajaxSettings,E)},ajaxSettings:{url:location.href,global:true,type:"GET",contentType:"application/x-www-form-urlencoded",processData:true,async:true,xhr:function(){return l.ActiveXObject?new ActiveXObject("Microsoft.XMLHTTP"):new XMLHttpRequest()},accepts:{xml:"application/xml, text/xml",html:"text/html",script:"text/javascript, application/javascript",json:"application/json, text/javascript",text:"text/plain",_default:"*/*"}},lastModified:{},ajax:function(M){M=o.extend(true,M,o.extend(true,{},o.ajaxSettings,M));var W,F=/=\?(&|$)/g,R,V,G=M.type.toUpperCase();if(M.data&&M.processData&&typeof M.data!=="string"){M.data=o.param(M.data)}if(M.dataType=="jsonp"){if(G=="GET"){if(!M.url.match(F)){M.url+=(M.url.match(/\?/)?"&":"?")+(M.jsonp||"callback")+"=?"}}else{if(!M.data||!M.data.match(F)){M.data=(M.data?M.data+"&":"")+(M.jsonp||"callback")+"=?"}}M.dataType="json"}if(M.dataType=="json"&&(M.data&&M.data.match(F)||M.url.match(F))){W="jsonp"+r++;if(M.data){M.data=(M.data+"").replace(F,"="+W+"$1")}M.url=M.url.replace(F,"="+W+"$1");M.dataType="script";l[W]=function(X){V=X;I();L();l[W]=g;try{delete l[W]}catch(Y){}if(H){H.removeChild(T)}}}if(M.dataType=="script"&&M.cache==null){M.cache=false}if(M.cache===false&&G=="GET"){var E=e();var U=M.url.replace(/(\?|&)_=.*?(&|$)/,"$1_="+E+"$2");M.url=U+((U==M.url)?(M.url.match(/\?/)?"&":"?")+"_="+E:"")}if(M.data&&G=="GET"){M.url+=(M.url.match(/\?/)?"&":"?")+M.data;M.data=null}if(M.global&&!o.active++){o.event.trigger("ajaxStart")}var Q=/^(\w+:)?\/\/([^\/?#]+)/.exec(M.url);if(M.dataType=="script"&&G=="GET"&&Q&&(Q[1]&&Q[1]!=location.protocol||Q[2]!=location.host)){var H=document.getElementsByTagName("head")[0];var T=document.createElement("script");T.src=M.url;if(M.scriptCharset){T.charset=M.scriptCharset}if(!W){var O=false;T.onload=T.onreadystatechange=function(){if(!O&&(!this.readyState||this.readyState=="loaded"||this.readyState=="complete")){O=true;I();L();T.onload=T.onreadystatechange=null;H.removeChild(T)}}}H.appendChild(T);return g}var K=false;var J=M.xhr();if(M.username){J.open(G,M.url,M.async,M.username,M.password)}else{J.open(G,M.url,M.async)}try{if(M.data){J.setRequestHeader("Content-Type",M.contentType)}if(M.ifModified){J.setRequestHeader("If-Modified-Since",o.lastModified[M.url]||"Thu, 01 Jan 1970 00:00:00 GMT")}J.setRequestHeader("X-Requested-With","XMLHttpRequest");J.setRequestHeader("Accept",M.dataType&&M.accepts[M.dataType]?M.accepts[M.dataType]+", */*":M.accepts._default)}catch(S){}if(M.beforeSend&&M.beforeSend(J,M)===false){if(M.global&&!--o.active){o.event.trigger("ajaxStop")}J.abort();return false}if(M.global){o.event.trigger("ajaxSend",[J,M])}var N=function(X){if(J.readyState==0){if(P){clearInterval(P);P=null;if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}}else{if(!K&&J&&(J.readyState==4||X=="timeout")){K=true;if(P){clearInterval(P);P=null}R=X=="timeout"?"timeout":!o.httpSuccess(J)?"error":M.ifModified&&o.httpNotModified(J,M.url)?"notmodified":"success";if(R=="success"){try{V=o.httpData(J,M.dataType,M)}catch(Z){R="parsererror"}}if(R=="success"){var Y;try{Y=J.getResponseHeader("Last-Modified")}catch(Z){}if(M.ifModified&&Y){o.lastModified[M.url]=Y}if(!W){I()}}else{o.handleError(M,J,R)}L();if(X){J.abort()}if(M.async){J=null}}}};if(M.async){var P=setInterval(N,13);if(M.timeout>0){setTimeout(function(){if(J&&!K){N("timeout")}},M.timeout)}}try{J.send(M.data)}catch(S){o.handleError(M,J,null,S)}if(!M.async){N()}function I(){if(M.success){M.success(V,R)}if(M.global){o.event.trigger("ajaxSuccess",[J,M])}}function L(){if(M.complete){M.complete(J,R)}if(M.global){o.event.trigger("ajaxComplete",[J,M])}if(M.global&&!--o.active){o.event.trigger("ajaxStop")}}return J},handleError:function(F,H,E,G){if(F.error){F.error(H,E,G)}if(F.global){o.event.trigger("ajaxError",[H,F,G])}},active:0,httpSuccess:function(F){try{return !F.status&&location.protocol=="file:"||(F.status>=200&&F.status<300)||F.status==304||F.status==1223}catch(E){}return false},httpNotModified:function(G,E){try{var H=G.getResponseHeader("Last-Modified");return G.status==304||H==o.lastModified[E]}catch(F){}return false},httpData:function(J,H,G){var F=J.getResponseHeader("content-type"),E=H=="xml"||!H&&F&&F.indexOf("xml")>=0,I=E?J.responseXML:J.responseText;if(E&&I.documentElement.tagName=="parsererror"){throw"parsererror"}if(G&&G.dataFilter){I=G.dataFilter(I,H)}if(typeof I==="string"){if(H=="script"){o.globalEval(I)}if(H=="json"){I=l["eval"]("("+I+")")}}return I},param:function(E){var G=[];function H(I,J){G[G.length]=encodeURIComponent(I)+"="+encodeURIComponent(J)}if(o.isArray(E)||E.jquery){o.each(E,function(){H(this.name,this.value)})}else{for(var F in E){if(o.isArray(E[F])){o.each(E[F],function(){H(F,this)})}else{H(F,o.isFunction(E[F])?E[F]():E[F])}}}return G.join("&").replace(/%20/g,"+")}});var m={},n,d=[["height","marginTop","marginBottom","paddingTop","paddingBottom"],["width","marginLeft","marginRight","paddingLeft","paddingRight"],["opacity"]];function t(F,E){var G={};o.each(d.concat.apply([],d.slice(0,E)),function(){G[this]=F});return G}o.fn.extend({show:function(J,L){if(J){return this.animate(t("show",3),J,L)}else{for(var H=0,F=this.length;H<F;H++){var E=o.data(this[H],"olddisplay");this[H].style.display=E||"";if(o.css(this[H],"display")==="none"){var G=this[H].tagName,K;if(m[G]){K=m[G]}else{var I=o("<"+G+" />").appendTo("body");K=I.css("display");if(K==="none"){K="block"}I.remove();m[G]=K}o.data(this[H],"olddisplay",K)}}for(var H=0,F=this.length;H<F;H++){this[H].style.display=o.data(this[H],"olddisplay")||""}return this}},hide:function(H,I){if(H){return this.animate(t("hide",3),H,I)}else{for(var G=0,F=this.length;G<F;G++){var E=o.data(this[G],"olddisplay");if(!E&&E!=="none"){o.data(this[G],"olddisplay",o.css(this[G],"display"))}}for(var G=0,F=this.length;G<F;G++){this[G].style.display="none"}return this}},_toggle:o.fn.toggle,toggle:function(G,F){var E=typeof G==="boolean";return o.isFunction(G)&&o.isFunction(F)?this._toggle.apply(this,arguments):G==null||E?this.each(function(){var H=E?G:o(this).is(":hidden");o(this)[H?"show":"hide"]()}):this.animate(t("toggle",3),G,F)},fadeTo:function(E,G,F){return this.animate({opacity:G},E,F)},animate:function(I,F,H,G){var E=o.speed(F,H,G);return this[E.queue===false?"each":"queue"](function(){var K=o.extend({},E),M,L=this.nodeType==1&&o(this).is(":hidden"),J=this;for(M in I){if(I[M]=="hide"&&L||I[M]=="show"&&!L){return K.complete.call(this)}if((M=="height"||M=="width")&&this.style){K.display=o.css(this,"display");K.overflow=this.style.overflow}}if(K.overflow!=null){this.style.overflow="hidden"}K.curAnim=o.extend({},I);o.each(I,function(O,S){var R=new o.fx(J,K,O);if(/toggle|show|hide/.test(S)){R[S=="toggle"?L?"show":"hide":S](I)}else{var Q=S.toString().match(/^([+-]=)?([\d+-.]+)(.*)$/),T=R.cur(true)||0;if(Q){var N=parseFloat(Q[2]),P=Q[3]||"px";if(P!="px"){J.style[O]=(N||1)+P;T=((N||1)/R.cur(true))*T;J.style[O]=T+P}if(Q[1]){N=((Q[1]=="-="?-1:1)*N)+T}R.custom(T,N,P)}else{R.custom(T,S,"")}}});return true})},stop:function(F,E){var G=o.timers;if(F){this.queue([])}this.each(function(){for(var H=G.length-1;H>=0;H--){if(G[H].elem==this){if(E){G[H](true)}G.splice(H,1)}}});if(!E){this.dequeue()}return this}});o.each({slideDown:t("show",1),slideUp:t("hide",1),slideToggle:t("toggle",1),fadeIn:{opacity:"show"},fadeOut:{opacity:"hide"}},function(E,F){o.fn[E]=function(G,H){return this.animate(F,G,H)}});o.extend({speed:function(G,H,F){var E=typeof G==="object"?G:{complete:F||!F&&H||o.isFunction(G)&&G,duration:G,easing:F&&H||H&&!o.isFunction(H)&&H};E.duration=o.fx.off?0:typeof E.duration==="number"?E.duration:o.fx.speeds[E.duration]||o.fx.speeds._default;E.old=E.complete;E.complete=function(){if(E.queue!==false){o(this).dequeue()}if(o.isFunction(E.old)){E.old.call(this)}};return E},easing:{linear:function(G,H,E,F){return E+F*G},swing:function(G,H,E,F){return((-Math.cos(G*Math.PI)/2)+0.5)*F+E}},timers:[],fx:function(F,E,G){this.options=E;this.elem=F;this.prop=G;if(!E.orig){E.orig={}}}});o.fx.prototype={update:function(){if(this.options.step){this.options.step.call(this.elem,this.now,this)}(o.fx.step[this.prop]||o.fx.step._default)(this);if((this.prop=="height"||this.prop=="width")&&this.elem.style){this.elem.style.display="block"}},cur:function(F){if(this.elem[this.prop]!=null&&(!this.elem.style||this.elem.style[this.prop]==null)){return this.elem[this.prop]}var E=parseFloat(o.css(this.elem,this.prop,F));return E&&E>-10000?E:parseFloat(o.curCSS(this.elem,this.prop))||0},custom:function(I,H,G){this.startTime=e();this.start=I;this.end=H;this.unit=G||this.unit||"px";this.now=this.start;this.pos=this.state=0;var E=this;function F(J){return E.step(J)}F.elem=this.elem;if(F()&&o.timers.push(F)&&!n){n=setInterval(function(){var K=o.timers;for(var J=0;J<K.length;J++){if(!K[J]()){K.splice(J--,1)}}if(!K.length){clearInterval(n);n=g}},13)}},show:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.show=true;this.custom(this.prop=="width"||this.prop=="height"?1:0,this.cur());o(this.elem).show()},hide:function(){this.options.orig[this.prop]=o.attr(this.elem.style,this.prop);this.options.hide=true;this.custom(this.cur(),0)},step:function(H){var G=e();if(H||G>=this.options.duration+this.startTime){this.now=this.end;this.pos=this.state=1;this.update();this.options.curAnim[this.prop]=true;var E=true;for(var F in this.options.curAnim){if(this.options.curAnim[F]!==true){E=false}}if(E){if(this.options.display!=null){this.elem.style.overflow=this.options.overflow;this.elem.style.display=this.options.display;if(o.css(this.elem,"display")=="none"){this.elem.style.display="block"}}if(this.options.hide){o(this.elem).hide()}if(this.options.hide||this.options.show){for(var I in this.options.curAnim){o.attr(this.elem.style,I,this.options.orig[I])}}this.options.complete.call(this.elem)}return false}else{var J=G-this.startTime;this.state=J/this.options.duration;this.pos=o.easing[this.options.easing||(o.easing.swing?"swing":"linear")](this.state,J,0,1,this.options.duration);this.now=this.start+((this.end-this.start)*this.pos);this.update()}return true}};o.extend(o.fx,{speeds:{slow:600,fast:200,_default:400},step:{opacity:function(E){o.attr(E.elem.style,"opacity",E.now)},_default:function(E){if(E.elem.style&&E.elem.style[E.prop]!=null){E.elem.style[E.prop]=E.now+E.unit}else{E.elem[E.prop]=E.now}}}});if(document.documentElement.getBoundingClientRect){o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}var G=this[0].getBoundingClientRect(),J=this[0].ownerDocument,F=J.body,E=J.documentElement,L=E.clientTop||F.clientTop||0,K=E.clientLeft||F.clientLeft||0,I=G.top+(self.pageYOffset||o.boxModel&&E.scrollTop||F.scrollTop)-L,H=G.left+(self.pageXOffset||o.boxModel&&E.scrollLeft||F.scrollLeft)-K;return{top:I,left:H}}}else{o.fn.offset=function(){if(!this[0]){return{top:0,left:0}}if(this[0]===this[0].ownerDocument.body){return o.offset.bodyOffset(this[0])}o.offset.initialized||o.offset.initialize();var J=this[0],G=J.offsetParent,F=J,O=J.ownerDocument,M,H=O.documentElement,K=O.body,L=O.defaultView,E=L.getComputedStyle(J,null),N=J.offsetTop,I=J.offsetLeft;while((J=J.parentNode)&&J!==K&&J!==H){M=L.getComputedStyle(J,null);N-=J.scrollTop,I-=J.scrollLeft;if(J===G){N+=J.offsetTop,I+=J.offsetLeft;if(o.offset.doesNotAddBorder&&!(o.offset.doesAddBorderForTableAndCells&&/^t(able|d|h)$/i.test(J.tagName))){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}F=G,G=J.offsetParent}if(o.offset.subtractsBorderForOverflowNotVisible&&M.overflow!=="visible"){N+=parseInt(M.borderTopWidth,10)||0,I+=parseInt(M.borderLeftWidth,10)||0}E=M}if(E.position==="relative"||E.position==="static"){N+=K.offsetTop,I+=K.offsetLeft}if(E.position==="fixed"){N+=Math.max(H.scrollTop,K.scrollTop),I+=Math.max(H.scrollLeft,K.scrollLeft)}return{top:N,left:I}}}o.offset={initialize:function(){if(this.initialized){return}var L=document.body,F=document.createElement("div"),H,G,N,I,M,E,J=L.style.marginTop,K='<div style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;"><div></div></div><table style="position:absolute;top:0;left:0;margin:0;border:5px solid #000;padding:0;width:1px;height:1px;" cellpadding="0" cellspacing="0"><tr><td></td></tr></table>';M={position:"absolute",top:0,left:0,margin:0,border:0,width:"1px",height:"1px",visibility:"hidden"};for(E in M){F.style[E]=M[E]}F.innerHTML=K;L.insertBefore(F,L.firstChild);H=F.firstChild,G=H.firstChild,I=H.nextSibling.firstChild.firstChild;this.doesNotAddBorder=(G.offsetTop!==5);this.doesAddBorderForTableAndCells=(I.offsetTop===5);H.style.overflow="hidden",H.style.position="relative";this.subtractsBorderForOverflowNotVisible=(G.offsetTop===-5);L.style.marginTop="1px";this.doesNotIncludeMarginInBodyOffset=(L.offsetTop===0);L.style.marginTop=J;L.removeChild(F);this.initialized=true},bodyOffset:function(E){o.offset.initialized||o.offset.initialize();var G=E.offsetTop,F=E.offsetLeft;if(o.offset.doesNotIncludeMarginInBodyOffset){G+=parseInt(o.curCSS(E,"marginTop",true),10)||0,F+=parseInt(o.curCSS(E,"marginLeft",true),10)||0}return{top:G,left:F}}};o.fn.extend({position:function(){var I=0,H=0,F;if(this[0]){var G=this.offsetParent(),J=this.offset(),E=/^body|html$/i.test(G[0].tagName)?{top:0,left:0}:G.offset();J.top-=j(this,"marginTop");J.left-=j(this,"marginLeft");E.top+=j(G,"borderTopWidth");E.left+=j(G,"borderLeftWidth");F={top:J.top-E.top,left:J.left-E.left}}return F},offsetParent:function(){var E=this[0].offsetParent||document.body;while(E&&(!/^body|html$/i.test(E.tagName)&&o.css(E,"position")=="static")){E=E.offsetParent}return o(E)}});o.each(["Left","Top"],function(F,E){var G="scroll"+E;o.fn[G]=function(H){if(!this[0]){return null}return H!==g?this.each(function(){this==l||this==document?l.scrollTo(!F?H:o(l).scrollLeft(),F?H:o(l).scrollTop()):this[G]=H}):this[0]==l||this[0]==document?self[F?"pageYOffset":"pageXOffset"]||o.boxModel&&document.documentElement[G]||document.body[G]:this[0][G]}});o.each(["Height","Width"],function(I,G){var E=I?"Left":"Top",H=I?"Right":"Bottom",F=G.toLowerCase();o.fn["inner"+G]=function(){return this[0]?o.css(this[0],F,false,"padding"):null};o.fn["outer"+G]=function(K){return this[0]?o.css(this[0],F,false,K?"margin":"border"):null};var J=G.toLowerCase();o.fn[J]=function(K){return this[0]==l?document.compatMode=="CSS1Compat"&&document.documentElement["client"+G]||document.body["client"+G]:this[0]==document?Math.max(document.documentElement["client"+G],document.body["scroll"+G],document.documentElement["scroll"+G],document.body["offset"+G],document.documentElement["offset"+G]):K===g?(this.length?o.css(this[0],J):null):this.css(J,typeof K==="string"?K:K+"px")}})})();
-
-/*
- * jQuery Color Animations
- * Copyright 2007 John Resig
- * Released under the MIT and GPL licenses.
- */
-
-(function(jQuery){
-
- // We override the animation for all of these color styles
- jQuery.each(['backgroundColor', 'borderBottomColor', 'borderLeftColor', 'borderRightColor', 'borderTopColor', 'color', 'outlineColor'], function(i,attr){
- jQuery.fx.step[attr] = function(fx){
- if ( fx.state == 0 ) {
- fx.start = getColor( fx.elem, attr );
- fx.end = getRGB( fx.end );
- }
-
- fx.elem.style[attr] = "rgb(" + [
- Math.max(Math.min( parseInt((fx.pos * (fx.end[0] - fx.start[0])) + fx.start[0]), 255), 0),
- Math.max(Math.min( parseInt((fx.pos * (fx.end[1] - fx.start[1])) + fx.start[1]), 255), 0),
- Math.max(Math.min( parseInt((fx.pos * (fx.end[2] - fx.start[2])) + fx.start[2]), 255), 0)
- ].join(",") + ")";
- }
- });
-
- // Color Conversion functions from highlightFade
- // By Blair Mitchelmore
- // http://jquery.offput.ca/highlightFade/
-
- // Parse strings looking for color tuples [255,255,255]
- function getRGB(color) {
- var result;
-
- // Check if we're already dealing with an array of colors
- if ( color && color.constructor == Array && color.length == 3 )
- return color;
-
- // Look for rgb(num,num,num)
- if (result = /rgb\(\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*,\s*([0-9]{1,3})\s*\)/.exec(color))
- return [parseInt(result[1]), parseInt(result[2]), parseInt(result[3])];
-
- // Look for rgb(num%,num%,num%)
- if (result = /rgb\(\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*,\s*([0-9]+(?:\.[0-9]+)?)\%\s*\)/.exec(color))
- return [parseFloat(result[1])*2.55, parseFloat(result[2])*2.55, parseFloat(result[3])*2.55];
-
- // Look for #a0b1c2
- if (result = /#([a-fA-F0-9]{2})([a-fA-F0-9]{2})([a-fA-F0-9]{2})/.exec(color))
- return [parseInt(result[1],16), parseInt(result[2],16), parseInt(result[3],16)];
-
- // Look for #fff
- if (result = /#([a-fA-F0-9])([a-fA-F0-9])([a-fA-F0-9])/.exec(color))
- return [parseInt(result[1]+result[1],16), parseInt(result[2]+result[2],16), parseInt(result[3]+result[3],16)];
-
- // Otherwise, we're most likely dealing with a named color
- return colors[jQuery.trim(color).toLowerCase()];
- }
-
- function getColor(elem, attr) {
- var color;
-
- do {
- color = jQuery.curCSS(elem, attr);
-
- // Keep going until we find an element that has color, or we hit the body
- if ( color != '' && color != 'transparent' || jQuery.nodeName(elem, "body") )
- break;
-
- attr = "backgroundColor";
- } while ( elem = elem.parentNode );
-
- return getRGB(color);
- };
-
- // Some named colors to work with
- // From Interface by Stefan Petre
- // http://interface.eyecon.ro/
-
- var colors = {
- aqua:[0,255,255],
- azure:[240,255,255],
- beige:[245,245,220],
- black:[0,0,0],
- blue:[0,0,255],
- brown:[165,42,42],
- cyan:[0,255,255],
- darkblue:[0,0,139],
- darkcyan:[0,139,139],
- darkgrey:[169,169,169],
- darkgreen:[0,100,0],
- darkkhaki:[189,183,107],
- darkmagenta:[139,0,139],
- darkolivegreen:[85,107,47],
- darkorange:[255,140,0],
- darkorchid:[153,50,204],
- darkred:[139,0,0],
- darksalmon:[233,150,122],
- darkviolet:[148,0,211],
- fuchsia:[255,0,255],
- gold:[255,215,0],
- green:[0,128,0],
- indigo:[75,0,130],
- khaki:[240,230,140],
- lightblue:[173,216,230],
- lightcyan:[224,255,255],
- lightgreen:[144,238,144],
- lightgrey:[211,211,211],
- lightpink:[255,182,193],
- lightyellow:[255,255,224],
- lime:[0,255,0],
- magenta:[255,0,255],
- maroon:[128,0,0],
- navy:[0,0,128],
- olive:[128,128,0],
- orange:[255,165,0],
- pink:[255,192,203],
- purple:[128,0,128],
- violet:[128,0,128],
- red:[255,0,0],
- silver:[192,192,192],
- white:[255,255,255],
- yellow:[255,255,0]
- };
-
-})(jQuery);
diff --git a/website/logi/reset.css b/website/logi/reset.css
deleted file mode 100644
index 91c616e9..00000000
--- a/website/logi/reset.css
+++ /dev/null
@@ -1,67 +0,0 @@
-html,body,div,span,applet,object,iframe,
-pre,abbr,address,cite,code,del,dfn,em,img,
-ins,kbd,q,strong,tt,var,dl,dt,dd,blockquote,
-fieldset,form,i,b,caption,tbody,tfoot,thead,tr,th,td{
- margin:0;
- padding:0;
- vertical-align:baseline;
-}
-
-body{
- background:#fff;
- color:#000;
- font:75%/1.5em Verdana, Helvetica, Arial, sans-serif;
-}
-
-:focus{
- outline:0;
-}
-
-code,kbd,tt{
- font-family: "Courier new", Courier;
- line-height:1;
- *line-height:1.5;
-}
-
-del{
- text-decoration:line-through;
-}
-
-*::-moz-focus-inner {
- border: 0;
-}
-
-img{
- border: 0;
- display:inline-block;
- vertical-align:bottom;
-}
-
-ol{
- list-style:inside decimal;
-}
-
-ul{
- list-style:inside disc;
-}
-
-pre{
- font-family:"Courier New", Courier;
- margin:0 0 1.5em;
-}
-
-sub{
- top:0.4em;
- font-size:0.85em;
- line-height:1;
- position:relative;
- vertical-align:baseline;
-}
-
-sup{
- font-size:0.85em;
- line-height:1;
- position:relative;
- bottom:0.5em;
- vertical-align:baseline;
-}
diff --git a/website/lombokBullet.png b/website/lombokBullet.png
deleted file mode 100644
index b19beee2..00000000
--- a/website/lombokBullet.png
+++ /dev/null
Binary files differ
diff --git a/website/mavenrepo/index.html b/website/mavenrepo/index.html
deleted file mode 100644
index 01227bbd..00000000
--- a/website/mavenrepo/index.html
+++ /dev/null
@@ -1,87 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <style type="text/css">
- code {
- font-size: 12px;
- font-family: monospaced;
- }
-
- .snippet {
- white-space: pre;
- border: 1px dashed #888;
- margin: 8px 8px 8px 0px;
- padding: 8px;
- font-family: "Courier New", Courier;
- }
-
- .meat {
- margin: 16px auto 0 auto;
- width: 800px;
- }
-
- .backLink {
- padding-top: 100px;
- width: 100%;
- text-align: right;
- }
-
- h1 {
- padding-bottom: 0;
- margin-bottom: 8px;
- }
-
- #downloadLink {
- display: block;
- margin-top: 32px;
- font-size: 14px;
- }
- </style>
-</head><body>
- <div class="meat">
- <h2>Maven</h1>
- <div>
- You can use lombok with maven by adding the following to your <strong>pom.xml</strong>:
- <div class="snippet">&lt;dependencies&gt;
- &lt;dependency&gt;
- &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
- &lt;artifactId&gt;lombok&lt;/artifactId&gt;
- &lt;version&gt;@VERSION@&lt;/version&gt;
- &lt;scope&gt;provided&lt;/scope&gt;
- &lt;/dependency&gt;
-&lt;/dependencies&gt;</div>
- </div>
- <h2>Ivy</h2>
- <div>
- You can use lombok with ivy by adding the following to your <strong>ivy.xml</strong>:
- <div class="snippet">&lt;dependency org="org.projectlombok" name="lombok" rev="@VERSION@" conf="build" /&gt;</div>
- </div>
- <h2>Gradle</h2>
- <div>
- You can use lombok with gradle by adding the following to your <strong>build.gradle</strong> in the <strong>dependencies</strong> block:
- <div class="snippet">provided "org.projectlombok:lombok:@VERSION@"</div>
- </div>
- <div>
- <em>NOTE:</em> You'll still need to download lombok, or doubleclick on the lombok.jar file downloaded by maven / ivy / gradle, to install lombok into your eclipse installation.
- </div>
- <a id="downloadLink" href="http://projectlombok.googlecode.com/files/lombok.jar">Download lombok.jar</a>
- </div>
- <div class="backLink">
- <a href="../index.html">back to the project homepage</a>
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/novideo.html b/website/novideo.html
deleted file mode 100644
index 8dc3feb1..00000000
--- a/website/novideo.html
+++ /dev/null
@@ -1,55 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <link rel="stylesheet" type="text/css" href="logi/reset.css" />
- <link rel="shortcut icon" href="favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <style type="text/css">
- code {
- font-size: 12px;
- font-family: monospaced;
- }
-
- .meat {
- margin: 16px auto 0 auto;
- width: 800px;
- }
-
- .backLink {
- padding-top: 100px;
- width: 100%;
- text-align: right;
- }
- </style>
-</head><body>
- <div class="meat">
- <h1>Can't see the video?</h1>
- <p>
- Why not download it instead?<br />
- <a href="videos/lombok.mp4">MPEG4 / H.264 (Windows / Mac)</a> |
- <a href="videos/lombok.ogv">Ogg Theora &amp; Vorbis ".ogv" (Linux)</a>
- </p><p>
- If the video won't play on the webpage and you want it to, please do one of the following:
- </p><ul>
- <li>Upgrade to <a href="http://getfirefox.com/">Firefox 3.5</a>,
- <a href="http://apple.com/safari">Safari 4</a> or
- <a href="http://www.google.com/chrome/">Chrome 2</a></li>
- <li>Install <a href="http://get.adobe.com/flashplayer/">Adobe Flash</a></li>
- <li>Install <a href="http://apple.com/quicktime/download/">QuickTime</a></li>
- </ul>
- <div class="backLink">
- <a href="index.html">back to the project homepage</a>
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/peppery_background_large.jpg b/website/peppery_background_large.jpg
deleted file mode 100644
index 6524dc6f..00000000
--- a/website/peppery_background_large.jpg
+++ /dev/null
Binary files differ
diff --git a/website/poster.png b/website/poster.png
deleted file mode 100644
index 4911408f..00000000
--- a/website/poster.png
+++ /dev/null
Binary files differ
diff --git a/website/resources/W8BEN_lombok.pdf b/website/resources/W8BEN_lombok.pdf
new file mode 100644
index 00000000..b87bded8
--- /dev/null
+++ b/website/resources/W8BEN_lombok.pdf
Binary files differ
diff --git a/website/resources/css/bootstrap.css b/website/resources/css/bootstrap.css
new file mode 100644
index 00000000..8a8b0192
--- /dev/null
+++ b/website/resources/css/bootstrap.css
@@ -0,0 +1,6706 @@
+@import url("//fonts.googleapis.com/css?family=Open+Sans:400,700");
+/*!
+ * bootswatch v3.3.4+1
+ * Homepage: http://bootswatch.com
+ * Copyright 2012-2015 Thomas Park
+ * Licensed under MIT
+ * Based on Bootstrap
+*/
+/*! normalize.css v3.0.2 | MIT License | git.io/normalize */
+html {
+ font-family: sans-serif;
+ -ms-text-size-adjust: 100%;
+ -webkit-text-size-adjust: 100%;
+}
+body {
+ margin: 0;
+}
+article,
+aside,
+details,
+figcaption,
+figure,
+footer,
+header,
+hgroup,
+main,
+menu,
+nav,
+section,
+summary {
+ display: block;
+}
+audio,
+canvas,
+progress,
+video {
+ display: inline-block;
+ vertical-align: baseline;
+}
+audio:not([controls]) {
+ display: none;
+ height: 0;
+}
+[hidden],
+template {
+ display: none;
+}
+a {
+ background-color: transparent;
+}
+a:active,
+a:hover {
+ outline: 0;
+}
+abbr[title] {
+ border-bottom: 1px dotted;
+}
+b,
+strong {
+ font-weight: bold;
+}
+dfn {
+ font-style: italic;
+}
+h1 {
+ font-size: 2em;
+ margin: 0.67em 0;
+}
+mark {
+ background: #ff0;
+ color: #000;
+}
+small {
+ font-size: 80%;
+}
+sub,
+sup {
+ font-size: 75%;
+ line-height: 0;
+ position: relative;
+ vertical-align: baseline;
+}
+sup {
+ top: -0.5em;
+}
+sub {
+ bottom: -0.25em;
+}
+img {
+ border: 0;
+}
+svg:not(:root) {
+ overflow: hidden;
+}
+figure {
+ margin: 1em 40px;
+}
+hr {
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+ height: 0;
+}
+pre {
+ overflow: auto;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: monospace, monospace;
+ font-size: 1em;
+}
+button,
+input,
+optgroup,
+select,
+textarea {
+ color: inherit;
+ font: inherit;
+ margin: 0;
+}
+button {
+ overflow: visible;
+}
+button,
+select {
+ text-transform: none;
+}
+button,
+html input[type="button"],
+input[type="reset"],
+input[type="submit"] {
+ -webkit-appearance: button;
+ cursor: pointer;
+}
+button[disabled],
+html input[disabled] {
+ cursor: default;
+}
+button::-moz-focus-inner,
+input::-moz-focus-inner {
+ border: 0;
+ padding: 0;
+}
+input {
+ line-height: normal;
+}
+input[type="checkbox"],
+input[type="radio"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+ padding: 0;
+}
+input[type="number"]::-webkit-inner-spin-button,
+input[type="number"]::-webkit-outer-spin-button {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: textfield;
+ -moz-box-sizing: content-box;
+ -webkit-box-sizing: content-box;
+ box-sizing: content-box;
+}
+input[type="search"]::-webkit-search-cancel-button,
+input[type="search"]::-webkit-search-decoration {
+ -webkit-appearance: none;
+}
+fieldset {
+ border: 1px solid #c0c0c0;
+ margin: 0 2px;
+ padding: 0.35em 0.625em 0.75em;
+}
+legend {
+ border: 0;
+ padding: 0;
+}
+textarea {
+ overflow: auto;
+}
+optgroup {
+ font-weight: bold;
+}
+table {
+ border-collapse: collapse;
+ border-spacing: 0;
+}
+td,
+th {
+ padding: 0;
+}
+/*! Source: https://github.com/h5bp/html5-boilerplate/blob/master/src/css/main.css */
+@media print {
+ *,
+ *:before,
+ *:after {
+ background: transparent !important;
+ color: #000 !important;
+ -webkit-box-shadow: none !important;
+ box-shadow: none !important;
+ text-shadow: none !important;
+ }
+ a,
+ a:visited {
+ text-decoration: underline;
+ }
+ a[href]:after {
+ content: " (" attr(href) ")";
+ }
+ abbr[title]:after {
+ content: " (" attr(title) ")";
+ }
+ a[href^="#"]:after,
+ a[href^="javascript:"]:after {
+ content: "";
+ }
+ pre,
+ blockquote {
+ border: 1px solid #999;
+ page-break-inside: avoid;
+ }
+ thead {
+ display: table-header-group;
+ }
+ tr,
+ img {
+ page-break-inside: avoid;
+ }
+ img {
+ max-width: 100% !important;
+ }
+ p,
+ h2,
+ h3 {
+ orphans: 3;
+ widows: 3;
+ }
+ h2,
+ h3 {
+ page-break-after: avoid;
+ }
+ select {
+ background: #fff !important;
+ }
+ .navbar {
+ display: none;
+ }
+ .btn > .caret,
+ .dropup > .btn > .caret {
+ border-top-color: #000 !important;
+ }
+ .label {
+ border: 1px solid #000;
+ }
+ .table {
+ border-collapse: collapse !important;
+ }
+ .table td,
+ .table th {
+ background-color: #fff !important;
+ }
+ .table-bordered th,
+ .table-bordered td {
+ border: 1px solid #ddd !important;
+ }
+}
+@font-face {
+ font-family: 'Glyphicons Halflings';
+ src: url('../fonts/glyphicons-halflings-regular.eot');
+ src: url('../fonts/glyphicons-halflings-regular.eot?#iefix') format('embedded-opentype'), url('../fonts/glyphicons-halflings-regular.woff2') format('woff2'), url('../fonts/glyphicons-halflings-regular.woff') format('woff'), url('../fonts/glyphicons-halflings-regular.ttf') format('truetype'), url('../fonts/glyphicons-halflings-regular.svg#glyphicons_halflingsregular') format('svg');
+}
+.glyphicon {
+ position: relative;
+ top: 1px;
+ display: inline-block;
+ font-family: 'Glyphicons Halflings';
+ font-style: normal;
+ font-weight: normal;
+ line-height: 1;
+ -webkit-font-smoothing: antialiased;
+ -moz-osx-font-smoothing: grayscale;
+}
+.glyphicon-asterisk:before {
+ content: "\2a";
+}
+.glyphicon-plus:before {
+ content: "\2b";
+}
+.glyphicon-euro:before,
+.glyphicon-eur:before {
+ content: "\20ac";
+}
+.glyphicon-minus:before {
+ content: "\2212";
+}
+.glyphicon-cloud:before {
+ content: "\2601";
+}
+.glyphicon-envelope:before {
+ content: "\2709";
+}
+.glyphicon-pencil:before {
+ content: "\270f";
+}
+.glyphicon-glass:before {
+ content: "\e001";
+}
+.glyphicon-music:before {
+ content: "\e002";
+}
+.glyphicon-search:before {
+ content: "\e003";
+}
+.glyphicon-heart:before {
+ content: "\e005";
+}
+.glyphicon-star:before {
+ content: "\e006";
+}
+.glyphicon-star-empty:before {
+ content: "\e007";
+}
+.glyphicon-user:before {
+ content: "\e008";
+}
+.glyphicon-film:before {
+ content: "\e009";
+}
+.glyphicon-th-large:before {
+ content: "\e010";
+}
+.glyphicon-th:before {
+ content: "\e011";
+}
+.glyphicon-th-list:before {
+ content: "\e012";
+}
+.glyphicon-ok:before {
+ content: "\e013";
+}
+.glyphicon-remove:before {
+ content: "\e014";
+}
+.glyphicon-zoom-in:before {
+ content: "\e015";
+}
+.glyphicon-zoom-out:before {
+ content: "\e016";
+}
+.glyphicon-off:before {
+ content: "\e017";
+}
+.glyphicon-signal:before {
+ content: "\e018";
+}
+.glyphicon-cog:before {
+ content: "\e019";
+}
+.glyphicon-trash:before {
+ content: "\e020";
+}
+.glyphicon-home:before {
+ content: "\e021";
+}
+.glyphicon-file:before {
+ content: "\e022";
+}
+.glyphicon-time:before {
+ content: "\e023";
+}
+.glyphicon-road:before {
+ content: "\e024";
+}
+.glyphicon-download-alt:before {
+ content: "\e025";
+}
+.glyphicon-download:before {
+ content: "\e026";
+}
+.glyphicon-upload:before {
+ content: "\e027";
+}
+.glyphicon-inbox:before {
+ content: "\e028";
+}
+.glyphicon-play-circle:before {
+ content: "\e029";
+}
+.glyphicon-repeat:before {
+ content: "\e030";
+}
+.glyphicon-refresh:before {
+ content: "\e031";
+}
+.glyphicon-list-alt:before {
+ content: "\e032";
+}
+.glyphicon-lock:before {
+ content: "\e033";
+}
+.glyphicon-flag:before {
+ content: "\e034";
+}
+.glyphicon-headphones:before {
+ content: "\e035";
+}
+.glyphicon-volume-off:before {
+ content: "\e036";
+}
+.glyphicon-volume-down:before {
+ content: "\e037";
+}
+.glyphicon-volume-up:before {
+ content: "\e038";
+}
+.glyphicon-qrcode:before {
+ content: "\e039";
+}
+.glyphicon-barcode:before {
+ content: "\e040";
+}
+.glyphicon-tag:before {
+ content: "\e041";
+}
+.glyphicon-tags:before {
+ content: "\e042";
+}
+.glyphicon-book:before {
+ content: "\e043";
+}
+.glyphicon-bookmark:before {
+ content: "\e044";
+}
+.glyphicon-print:before {
+ content: "\e045";
+}
+.glyphicon-camera:before {
+ content: "\e046";
+}
+.glyphicon-font:before {
+ content: "\e047";
+}
+.glyphicon-bold:before {
+ content: "\e048";
+}
+.glyphicon-italic:before {
+ content: "\e049";
+}
+.glyphicon-text-height:before {
+ content: "\e050";
+}
+.glyphicon-text-width:before {
+ content: "\e051";
+}
+.glyphicon-align-left:before {
+ content: "\e052";
+}
+.glyphicon-align-center:before {
+ content: "\e053";
+}
+.glyphicon-align-right:before {
+ content: "\e054";
+}
+.glyphicon-align-justify:before {
+ content: "\e055";
+}
+.glyphicon-list:before {
+ content: "\e056";
+}
+.glyphicon-indent-left:before {
+ content: "\e057";
+}
+.glyphicon-indent-right:before {
+ content: "\e058";
+}
+.glyphicon-facetime-video:before {
+ content: "\e059";
+}
+.glyphicon-picture:before {
+ content: "\e060";
+}
+.glyphicon-map-marker:before {
+ content: "\e062";
+}
+.glyphicon-adjust:before {
+ content: "\e063";
+}
+.glyphicon-tint:before {
+ content: "\e064";
+}
+.glyphicon-edit:before {
+ content: "\e065";
+}
+.glyphicon-share:before {
+ content: "\e066";
+}
+.glyphicon-check:before {
+ content: "\e067";
+}
+.glyphicon-move:before {
+ content: "\e068";
+}
+.glyphicon-step-backward:before {
+ content: "\e069";
+}
+.glyphicon-fast-backward:before {
+ content: "\e070";
+}
+.glyphicon-backward:before {
+ content: "\e071";
+}
+.glyphicon-play:before {
+ content: "\e072";
+}
+.glyphicon-pause:before {
+ content: "\e073";
+}
+.glyphicon-stop:before {
+ content: "\e074";
+}
+.glyphicon-forward:before {
+ content: "\e075";
+}
+.glyphicon-fast-forward:before {
+ content: "\e076";
+}
+.glyphicon-step-forward:before {
+ content: "\e077";
+}
+.glyphicon-eject:before {
+ content: "\e078";
+}
+.glyphicon-chevron-left:before {
+ content: "\e079";
+}
+.glyphicon-chevron-right:before {
+ content: "\e080";
+}
+.glyphicon-plus-sign:before {
+ content: "\e081";
+}
+.glyphicon-minus-sign:before {
+ content: "\e082";
+}
+.glyphicon-remove-sign:before {
+ content: "\e083";
+}
+.glyphicon-ok-sign:before {
+ content: "\e084";
+}
+.glyphicon-question-sign:before {
+ content: "\e085";
+}
+.glyphicon-info-sign:before {
+ content: "\e086";
+}
+.glyphicon-screenshot:before {
+ content: "\e087";
+}
+.glyphicon-remove-circle:before {
+ content: "\e088";
+}
+.glyphicon-ok-circle:before {
+ content: "\e089";
+}
+.glyphicon-ban-circle:before {
+ content: "\e090";
+}
+.glyphicon-arrow-left:before {
+ content: "\e091";
+}
+.glyphicon-arrow-right:before {
+ content: "\e092";
+}
+.glyphicon-arrow-up:before {
+ content: "\e093";
+}
+.glyphicon-arrow-down:before {
+ content: "\e094";
+}
+.glyphicon-share-alt:before {
+ content: "\e095";
+}
+.glyphicon-resize-full:before {
+ content: "\e096";
+}
+.glyphicon-resize-small:before {
+ content: "\e097";
+}
+.glyphicon-exclamation-sign:before {
+ content: "\e101";
+}
+.glyphicon-gift:before {
+ content: "\e102";
+}
+.glyphicon-leaf:before {
+ content: "\e103";
+}
+.glyphicon-fire:before {
+ content: "\e104";
+}
+.glyphicon-eye-open:before {
+ content: "\e105";
+}
+.glyphicon-eye-close:before {
+ content: "\e106";
+}
+.glyphicon-warning-sign:before {
+ content: "\e107";
+}
+.glyphicon-plane:before {
+ content: "\e108";
+}
+.glyphicon-calendar:before {
+ content: "\e109";
+}
+.glyphicon-random:before {
+ content: "\e110";
+}
+.glyphicon-comment:before {
+ content: "\e111";
+}
+.glyphicon-magnet:before {
+ content: "\e112";
+}
+.glyphicon-chevron-up:before {
+ content: "\e113";
+}
+.glyphicon-chevron-down:before {
+ content: "\e114";
+}
+.glyphicon-retweet:before {
+ content: "\e115";
+}
+.glyphicon-shopping-cart:before {
+ content: "\e116";
+}
+.glyphicon-folder-close:before {
+ content: "\e117";
+}
+.glyphicon-folder-open:before {
+ content: "\e118";
+}
+.glyphicon-resize-vertical:before {
+ content: "\e119";
+}
+.glyphicon-resize-horizontal:before {
+ content: "\e120";
+}
+.glyphicon-hdd:before {
+ content: "\e121";
+}
+.glyphicon-bullhorn:before {
+ content: "\e122";
+}
+.glyphicon-bell:before {
+ content: "\e123";
+}
+.glyphicon-certificate:before {
+ content: "\e124";
+}
+.glyphicon-thumbs-up:before {
+ content: "\e125";
+}
+.glyphicon-thumbs-down:before {
+ content: "\e126";
+}
+.glyphicon-hand-right:before {
+ content: "\e127";
+}
+.glyphicon-hand-left:before {
+ content: "\e128";
+}
+.glyphicon-hand-up:before {
+ content: "\e129";
+}
+.glyphicon-hand-down:before {
+ content: "\e130";
+}
+.glyphicon-circle-arrow-right:before {
+ content: "\e131";
+}
+.glyphicon-circle-arrow-left:before {
+ content: "\e132";
+}
+.glyphicon-circle-arrow-up:before {
+ content: "\e133";
+}
+.glyphicon-circle-arrow-down:before {
+ content: "\e134";
+}
+.glyphicon-globe:before {
+ content: "\e135";
+}
+.glyphicon-wrench:before {
+ content: "\e136";
+}
+.glyphicon-tasks:before {
+ content: "\e137";
+}
+.glyphicon-filter:before {
+ content: "\e138";
+}
+.glyphicon-briefcase:before {
+ content: "\e139";
+}
+.glyphicon-fullscreen:before {
+ content: "\e140";
+}
+.glyphicon-dashboard:before {
+ content: "\e141";
+}
+.glyphicon-paperclip:before {
+ content: "\e142";
+}
+.glyphicon-heart-empty:before {
+ content: "\e143";
+}
+.glyphicon-link:before {
+ content: "\e144";
+}
+.glyphicon-phone:before {
+ content: "\e145";
+}
+.glyphicon-pushpin:before {
+ content: "\e146";
+}
+.glyphicon-usd:before {
+ content: "\e148";
+}
+.glyphicon-gbp:before {
+ content: "\e149";
+}
+.glyphicon-sort:before {
+ content: "\e150";
+}
+.glyphicon-sort-by-alphabet:before {
+ content: "\e151";
+}
+.glyphicon-sort-by-alphabet-alt:before {
+ content: "\e152";
+}
+.glyphicon-sort-by-order:before {
+ content: "\e153";
+}
+.glyphicon-sort-by-order-alt:before {
+ content: "\e154";
+}
+.glyphicon-sort-by-attributes:before {
+ content: "\e155";
+}
+.glyphicon-sort-by-attributes-alt:before {
+ content: "\e156";
+}
+.glyphicon-unchecked:before {
+ content: "\e157";
+}
+.glyphicon-expand:before {
+ content: "\e158";
+}
+.glyphicon-collapse-down:before {
+ content: "\e159";
+}
+.glyphicon-collapse-up:before {
+ content: "\e160";
+}
+.glyphicon-log-in:before {
+ content: "\e161";
+}
+.glyphicon-flash:before {
+ content: "\e162";
+}
+.glyphicon-log-out:before {
+ content: "\e163";
+}
+.glyphicon-new-window:before {
+ content: "\e164";
+}
+.glyphicon-record:before {
+ content: "\e165";
+}
+.glyphicon-save:before {
+ content: "\e166";
+}
+.glyphicon-open:before {
+ content: "\e167";
+}
+.glyphicon-saved:before {
+ content: "\e168";
+}
+.glyphicon-import:before {
+ content: "\e169";
+}
+.glyphicon-export:before {
+ content: "\e170";
+}
+.glyphicon-send:before {
+ content: "\e171";
+}
+.glyphicon-floppy-disk:before {
+ content: "\e172";
+}
+.glyphicon-floppy-saved:before {
+ content: "\e173";
+}
+.glyphicon-floppy-remove:before {
+ content: "\e174";
+}
+.glyphicon-floppy-save:before {
+ content: "\e175";
+}
+.glyphicon-floppy-open:before {
+ content: "\e176";
+}
+.glyphicon-credit-card:before {
+ content: "\e177";
+}
+.glyphicon-transfer:before {
+ content: "\e178";
+}
+.glyphicon-cutlery:before {
+ content: "\e179";
+}
+.glyphicon-header:before {
+ content: "\e180";
+}
+.glyphicon-compressed:before {
+ content: "\e181";
+}
+.glyphicon-earphone:before {
+ content: "\e182";
+}
+.glyphicon-phone-alt:before {
+ content: "\e183";
+}
+.glyphicon-tower:before {
+ content: "\e184";
+}
+.glyphicon-stats:before {
+ content: "\e185";
+}
+.glyphicon-sd-video:before {
+ content: "\e186";
+}
+.glyphicon-hd-video:before {
+ content: "\e187";
+}
+.glyphicon-subtitles:before {
+ content: "\e188";
+}
+.glyphicon-sound-stereo:before {
+ content: "\e189";
+}
+.glyphicon-sound-dolby:before {
+ content: "\e190";
+}
+.glyphicon-sound-5-1:before {
+ content: "\e191";
+}
+.glyphicon-sound-6-1:before {
+ content: "\e192";
+}
+.glyphicon-sound-7-1:before {
+ content: "\e193";
+}
+.glyphicon-copyright-mark:before {
+ content: "\e194";
+}
+.glyphicon-registration-mark:before {
+ content: "\e195";
+}
+.glyphicon-cloud-download:before {
+ content: "\e197";
+}
+.glyphicon-cloud-upload:before {
+ content: "\e198";
+}
+.glyphicon-tree-conifer:before {
+ content: "\e199";
+}
+.glyphicon-tree-deciduous:before {
+ content: "\e200";
+}
+.glyphicon-cd:before {
+ content: "\e201";
+}
+.glyphicon-save-file:before {
+ content: "\e202";
+}
+.glyphicon-open-file:before {
+ content: "\e203";
+}
+.glyphicon-level-up:before {
+ content: "\e204";
+}
+.glyphicon-copy:before {
+ content: "\e205";
+}
+.glyphicon-paste:before {
+ content: "\e206";
+}
+.glyphicon-alert:before {
+ content: "\e209";
+}
+.glyphicon-equalizer:before {
+ content: "\e210";
+}
+.glyphicon-king:before {
+ content: "\e211";
+}
+.glyphicon-queen:before {
+ content: "\e212";
+}
+.glyphicon-pawn:before {
+ content: "\e213";
+}
+.glyphicon-bishop:before {
+ content: "\e214";
+}
+.glyphicon-knight:before {
+ content: "\e215";
+}
+.glyphicon-baby-formula:before {
+ content: "\e216";
+}
+.glyphicon-tent:before {
+ content: "\26fa";
+}
+.glyphicon-blackboard:before {
+ content: "\e218";
+}
+.glyphicon-bed:before {
+ content: "\e219";
+}
+.glyphicon-apple:before {
+ content: "\f8ff";
+}
+.glyphicon-erase:before {
+ content: "\e221";
+}
+.glyphicon-hourglass:before {
+ content: "\231b";
+}
+.glyphicon-lamp:before {
+ content: "\e223";
+}
+.glyphicon-duplicate:before {
+ content: "\e224";
+}
+.glyphicon-piggy-bank:before {
+ content: "\e225";
+}
+.glyphicon-scissors:before {
+ content: "\e226";
+}
+.glyphicon-bitcoin:before {
+ content: "\e227";
+}
+.glyphicon-btc:before {
+ content: "\e227";
+}
+.glyphicon-xbt:before {
+ content: "\e227";
+}
+.glyphicon-yen:before {
+ content: "\00a5";
+}
+.glyphicon-jpy:before {
+ content: "\00a5";
+}
+.glyphicon-ruble:before {
+ content: "\20bd";
+}
+.glyphicon-rub:before {
+ content: "\20bd";
+}
+.glyphicon-scale:before {
+ content: "\e230";
+}
+.glyphicon-ice-lolly:before {
+ content: "\e231";
+}
+.glyphicon-ice-lolly-tasted:before {
+ content: "\e232";
+}
+.glyphicon-education:before {
+ content: "\e233";
+}
+.glyphicon-option-horizontal:before {
+ content: "\e234";
+}
+.glyphicon-option-vertical:before {
+ content: "\e235";
+}
+.glyphicon-menu-hamburger:before {
+ content: "\e236";
+}
+.glyphicon-modal-window:before {
+ content: "\e237";
+}
+.glyphicon-oil:before {
+ content: "\e238";
+}
+.glyphicon-grain:before {
+ content: "\e239";
+}
+.glyphicon-sunglasses:before {
+ content: "\e240";
+}
+.glyphicon-text-size:before {
+ content: "\e241";
+}
+.glyphicon-text-color:before {
+ content: "\e242";
+}
+.glyphicon-text-background:before {
+ content: "\e243";
+}
+.glyphicon-object-align-top:before {
+ content: "\e244";
+}
+.glyphicon-object-align-bottom:before {
+ content: "\e245";
+}
+.glyphicon-object-align-horizontal:before {
+ content: "\e246";
+}
+.glyphicon-object-align-left:before {
+ content: "\e247";
+}
+.glyphicon-object-align-vertical:before {
+ content: "\e248";
+}
+.glyphicon-object-align-right:before {
+ content: "\e249";
+}
+.glyphicon-triangle-right:before {
+ content: "\e250";
+}
+.glyphicon-triangle-left:before {
+ content: "\e251";
+}
+.glyphicon-triangle-bottom:before {
+ content: "\e252";
+}
+.glyphicon-triangle-top:before {
+ content: "\e253";
+}
+.glyphicon-console:before {
+ content: "\e254";
+}
+.glyphicon-superscript:before {
+ content: "\e255";
+}
+.glyphicon-subscript:before {
+ content: "\e256";
+}
+.glyphicon-menu-left:before {
+ content: "\e257";
+}
+.glyphicon-menu-right:before {
+ content: "\e258";
+}
+.glyphicon-menu-down:before {
+ content: "\e259";
+}
+.glyphicon-menu-up:before {
+ content: "\e260";
+}
+* {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+*:before,
+*:after {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+html {
+ font-size: 10px;
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+}
+body {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #777777;
+ background-color: #fcfcfc;
+}
+input,
+button,
+select,
+textarea {
+ font-family: inherit;
+ font-size: inherit;
+ line-height: inherit;
+}
+a {
+ color: #d9230f;
+ text-decoration: none;
+}
+a:hover,
+a:focus {
+ color: #91170a;
+ text-decoration: underline;
+}
+a:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+figure {
+ margin: 0;
+}
+img {
+ vertical-align: middle;
+}
+.img-responsive,
+.thumbnail > img,
+.thumbnail a > img,
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ display: block;
+ max-width: 100%;
+ height: auto;
+}
+.img-rounded {
+ border-radius: 6px;
+}
+.img-thumbnail {
+ padding: 4px;
+ line-height: 1.42857143;
+ background-color: #fcfcfc;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+ -webkit-transition: all 0.2s ease-in-out;
+ -o-transition: all 0.2s ease-in-out;
+ transition: all 0.2s ease-in-out;
+ display: inline-block;
+ max-width: 100%;
+ height: auto;
+}
+.img-circle {
+ border-radius: 50%;
+}
+hr {
+ margin-top: 18px;
+ margin-bottom: 18px;
+ border: 0;
+ border-top: 1px solid #dddddd;
+}
+.sr-only {
+ position: absolute;
+ width: 1px;
+ height: 1px;
+ margin: -1px;
+ padding: 0;
+ overflow: hidden;
+ clip: rect(0, 0, 0, 0);
+ border: 0;
+}
+.sr-only-focusable:active,
+.sr-only-focusable:focus {
+ position: static;
+ width: auto;
+ height: auto;
+ margin: 0;
+ overflow: visible;
+ clip: auto;
+}
+[role="button"] {
+ cursor: pointer;
+}
+h1,
+h2,
+h3,
+h4,
+h5,
+h6,
+.h1,
+.h2,
+.h3,
+.h4,
+.h5,
+.h6 {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-weight: 300;
+ line-height: 1.1;
+ color: #444444;
+}
+h1 small,
+h2 small,
+h3 small,
+h4 small,
+h5 small,
+h6 small,
+.h1 small,
+.h2 small,
+.h3 small,
+.h4 small,
+.h5 small,
+.h6 small,
+h1 .small,
+h2 .small,
+h3 .small,
+h4 .small,
+h5 .small,
+h6 .small,
+.h1 .small,
+.h2 .small,
+.h3 .small,
+.h4 .small,
+.h5 .small,
+.h6 .small {
+ font-weight: normal;
+ line-height: 1;
+ color: #808080;
+}
+h1,
+.h1,
+h2,
+.h2,
+h3,
+.h3 {
+ margin-top: 18px;
+ margin-bottom: 9px;
+}
+h1 small,
+.h1 small,
+h2 small,
+.h2 small,
+h3 small,
+.h3 small,
+h1 .small,
+.h1 .small,
+h2 .small,
+.h2 .small,
+h3 .small,
+.h3 .small {
+ font-size: 65%;
+}
+h4,
+.h4,
+h5,
+.h5,
+h6,
+.h6 {
+ margin-top: 9px;
+ margin-bottom: 9px;
+}
+h4 small,
+.h4 small,
+h5 small,
+.h5 small,
+h6 small,
+.h6 small,
+h4 .small,
+.h4 .small,
+h5 .small,
+.h5 .small,
+h6 .small,
+.h6 .small {
+ font-size: 75%;
+}
+h1,
+.h1 {
+ font-size: 33px;
+}
+h2,
+.h2 {
+ font-size: 27px;
+}
+h3,
+.h3 {
+ font-size: 23px;
+}
+h4,
+.h4 {
+ font-size: 17px;
+}
+h5,
+.h5 {
+ font-size: 13px;
+}
+h6,
+.h6 {
+ font-size: 12px;
+}
+p {
+ margin: 0 0 9px;
+}
+.lead {
+ margin-bottom: 18px;
+ font-size: 14px;
+ font-weight: 300;
+ line-height: 1.4;
+}
+@media (min-width: 768px) {
+ .lead {
+ font-size: 19.5px;
+ }
+}
+small,
+.small {
+ font-size: 92%;
+}
+mark,
+.mark {
+ background-color: #fcf8e3;
+ padding: .2em;
+}
+.text-left {
+ text-align: left;
+}
+.text-right {
+ text-align: right;
+}
+.text-center {
+ text-align: center;
+}
+.text-justify {
+ text-align: justify;
+}
+.text-nowrap {
+ white-space: nowrap;
+}
+.text-lowercase {
+ text-transform: lowercase;
+}
+.text-uppercase {
+ text-transform: uppercase;
+}
+.text-capitalize {
+ text-transform: capitalize;
+}
+.text-muted {
+ color: #808080;
+}
+.text-primary {
+ color: #d9230f;
+}
+a.text-primary:hover {
+ color: #a91b0c;
+}
+.text-success {
+ color: #468847;
+}
+a.text-success:hover {
+ color: #356635;
+}
+.text-info {
+ color: #3a87ad;
+}
+a.text-info:hover {
+ color: #2d6987;
+}
+.text-warning {
+ color: #c09853;
+}
+a.text-warning:hover {
+ color: #a47e3c;
+}
+.text-danger {
+ color: #b94a48;
+}
+a.text-danger:hover {
+ color: #953b39;
+}
+.bg-primary {
+ color: #fff;
+ background-color: #d9230f;
+}
+a.bg-primary:hover {
+ background-color: #a91b0c;
+}
+.bg-success {
+ background-color: #dff0d8;
+}
+a.bg-success:hover {
+ background-color: #c1e2b3;
+}
+.bg-info {
+ background-color: #d9edf7;
+}
+a.bg-info:hover {
+ background-color: #afd9ee;
+}
+.bg-warning {
+ background-color: #fcf8e3;
+}
+a.bg-warning:hover {
+ background-color: #f7ecb5;
+}
+.bg-danger {
+ background-color: #f2dede;
+}
+a.bg-danger:hover {
+ background-color: #e4b9b9;
+}
+.page-header {
+ padding-bottom: 8px;
+ margin: 36px 0 18px;
+ border-bottom: 1px solid #dddddd;
+}
+ul,
+ol {
+ margin-top: 0;
+ margin-bottom: 9px;
+}
+ul ul,
+ol ul,
+ul ol,
+ol ol {
+ margin-bottom: 0;
+}
+.list-unstyled {
+ padding-left: 0;
+ list-style: none;
+}
+.list-inline {
+ padding-left: 0;
+ list-style: none;
+ margin-left: -5px;
+}
+.list-inline > li {
+ display: inline-block;
+ padding-left: 5px;
+ padding-right: 5px;
+}
+dl {
+ margin-top: 0;
+ margin-bottom: 18px;
+}
+dt,
+dd {
+ line-height: 1.42857143;
+}
+dt {
+ font-weight: bold;
+}
+dd {
+ margin-left: 0;
+}
+@media (min-width: 768px) {
+ .dl-horizontal dt {
+ float: left;
+ width: 160px;
+ clear: left;
+ text-align: right;
+ overflow: hidden;
+ text-overflow: ellipsis;
+ white-space: nowrap;
+ }
+ .dl-horizontal dd {
+ margin-left: 180px;
+ }
+}
+abbr[title],
+abbr[data-original-title] {
+ cursor: help;
+ border-bottom: 1px dotted #808080;
+}
+.initialism {
+ font-size: 90%;
+ text-transform: uppercase;
+}
+blockquote {
+ padding: 9px 18px;
+ margin: 0 0 18px;
+ font-size: 16.25px;
+ border-left: 5px solid #dddddd;
+}
+blockquote p:last-child,
+blockquote ul:last-child,
+blockquote ol:last-child {
+ margin-bottom: 0;
+}
+blockquote footer,
+blockquote small,
+blockquote .small {
+ display: block;
+ font-size: 80%;
+ line-height: 1.42857143;
+ color: #808080;
+}
+blockquote footer:before,
+blockquote small:before,
+blockquote .small:before {
+ content: '\2014 \00A0';
+}
+.blockquote-reverse,
+blockquote.pull-right {
+ padding-right: 15px;
+ padding-left: 0;
+ border-right: 5px solid #dddddd;
+ border-left: 0;
+ text-align: right;
+}
+.blockquote-reverse footer:before,
+blockquote.pull-right footer:before,
+.blockquote-reverse small:before,
+blockquote.pull-right small:before,
+.blockquote-reverse .small:before,
+blockquote.pull-right .small:before {
+ content: '';
+}
+.blockquote-reverse footer:after,
+blockquote.pull-right footer:after,
+.blockquote-reverse small:after,
+blockquote.pull-right small:after,
+.blockquote-reverse .small:after,
+blockquote.pull-right .small:after {
+ content: '\00A0 \2014';
+}
+address {
+ margin-bottom: 18px;
+ font-style: normal;
+ line-height: 1.42857143;
+}
+code,
+kbd,
+pre,
+samp {
+ font-family: Menlo, Monaco, Consolas, "Courier New", monospace;
+}
+code {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #c7254e;
+ background-color: #f9f2f4;
+ border-radius: 4px;
+}
+kbd {
+ padding: 2px 4px;
+ font-size: 90%;
+ color: #ffffff;
+ background-color: #333333;
+ border-radius: 3px;
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.25);
+}
+kbd kbd {
+ padding: 0;
+ font-size: 100%;
+ font-weight: bold;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+pre {
+ display: block;
+ padding: 8.5px;
+ margin: 0 0 9px;
+ font-size: 12px;
+ line-height: 1.42857143;
+ word-break: break-all;
+ word-wrap: break-word;
+ color: #444444;
+ background-color: #f5f5f5;
+ border: 1px solid #cccccc;
+ border-radius: 4px;
+}
+pre code {
+ padding: 0;
+ font-size: inherit;
+ color: inherit;
+ white-space: pre-wrap;
+ background-color: transparent;
+ border-radius: 0;
+}
+.pre-scrollable {
+ max-height: 340px;
+ overflow-y: scroll;
+}
+.container {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+@media (min-width: 768px) {
+ .container {
+ width: 750px;
+ }
+}
+@media (min-width: 992px) {
+ .container {
+ width: 970px;
+ }
+}
+@media (min-width: 1200px) {
+ .container {
+ width: 1170px;
+ }
+}
+.container-fluid {
+ margin-right: auto;
+ margin-left: auto;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.row {
+ margin-left: -15px;
+ margin-right: -15px;
+}
+.col-xs-1, .col-sm-1, .col-md-1, .col-lg-1, .col-xs-2, .col-sm-2, .col-md-2, .col-lg-2, .col-xs-3, .col-sm-3, .col-md-3, .col-lg-3, .col-xs-4, .col-sm-4, .col-md-4, .col-lg-4, .col-xs-5, .col-sm-5, .col-md-5, .col-lg-5, .col-xs-6, .col-sm-6, .col-md-6, .col-lg-6, .col-xs-7, .col-sm-7, .col-md-7, .col-lg-7, .col-xs-8, .col-sm-8, .col-md-8, .col-lg-8, .col-xs-9, .col-sm-9, .col-md-9, .col-lg-9, .col-xs-10, .col-sm-10, .col-md-10, .col-lg-10, .col-xs-11, .col-sm-11, .col-md-11, .col-lg-11, .col-xs-12, .col-sm-12, .col-md-12, .col-lg-12 {
+ position: relative;
+ min-height: 1px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.col-xs-1, .col-xs-2, .col-xs-3, .col-xs-4, .col-xs-5, .col-xs-6, .col-xs-7, .col-xs-8, .col-xs-9, .col-xs-10, .col-xs-11, .col-xs-12 {
+ float: left;
+}
+.col-xs-12 {
+ width: 100%;
+}
+.col-xs-11 {
+ width: 91.66666667%;
+}
+.col-xs-10 {
+ width: 83.33333333%;
+}
+.col-xs-9 {
+ width: 75%;
+}
+.col-xs-8 {
+ width: 66.66666667%;
+}
+.col-xs-7 {
+ width: 58.33333333%;
+}
+.col-xs-6 {
+ width: 50%;
+}
+.col-xs-5 {
+ width: 41.66666667%;
+}
+.col-xs-4 {
+ width: 33.33333333%;
+}
+.col-xs-3 {
+ width: 25%;
+}
+.col-xs-2 {
+ width: 16.66666667%;
+}
+.col-xs-1 {
+ width: 8.33333333%;
+}
+.col-xs-pull-12 {
+ right: 100%;
+}
+.col-xs-pull-11 {
+ right: 91.66666667%;
+}
+.col-xs-pull-10 {
+ right: 83.33333333%;
+}
+.col-xs-pull-9 {
+ right: 75%;
+}
+.col-xs-pull-8 {
+ right: 66.66666667%;
+}
+.col-xs-pull-7 {
+ right: 58.33333333%;
+}
+.col-xs-pull-6 {
+ right: 50%;
+}
+.col-xs-pull-5 {
+ right: 41.66666667%;
+}
+.col-xs-pull-4 {
+ right: 33.33333333%;
+}
+.col-xs-pull-3 {
+ right: 25%;
+}
+.col-xs-pull-2 {
+ right: 16.66666667%;
+}
+.col-xs-pull-1 {
+ right: 8.33333333%;
+}
+.col-xs-pull-0 {
+ right: auto;
+}
+.col-xs-push-12 {
+ left: 100%;
+}
+.col-xs-push-11 {
+ left: 91.66666667%;
+}
+.col-xs-push-10 {
+ left: 83.33333333%;
+}
+.col-xs-push-9 {
+ left: 75%;
+}
+.col-xs-push-8 {
+ left: 66.66666667%;
+}
+.col-xs-push-7 {
+ left: 58.33333333%;
+}
+.col-xs-push-6 {
+ left: 50%;
+}
+.col-xs-push-5 {
+ left: 41.66666667%;
+}
+.col-xs-push-4 {
+ left: 33.33333333%;
+}
+.col-xs-push-3 {
+ left: 25%;
+}
+.col-xs-push-2 {
+ left: 16.66666667%;
+}
+.col-xs-push-1 {
+ left: 8.33333333%;
+}
+.col-xs-push-0 {
+ left: auto;
+}
+.col-xs-offset-12 {
+ margin-left: 100%;
+}
+.col-xs-offset-11 {
+ margin-left: 91.66666667%;
+}
+.col-xs-offset-10 {
+ margin-left: 83.33333333%;
+}
+.col-xs-offset-9 {
+ margin-left: 75%;
+}
+.col-xs-offset-8 {
+ margin-left: 66.66666667%;
+}
+.col-xs-offset-7 {
+ margin-left: 58.33333333%;
+}
+.col-xs-offset-6 {
+ margin-left: 50%;
+}
+.col-xs-offset-5 {
+ margin-left: 41.66666667%;
+}
+.col-xs-offset-4 {
+ margin-left: 33.33333333%;
+}
+.col-xs-offset-3 {
+ margin-left: 25%;
+}
+.col-xs-offset-2 {
+ margin-left: 16.66666667%;
+}
+.col-xs-offset-1 {
+ margin-left: 8.33333333%;
+}
+.col-xs-offset-0 {
+ margin-left: 0%;
+}
+@media (min-width: 768px) {
+ .col-sm-1, .col-sm-2, .col-sm-3, .col-sm-4, .col-sm-5, .col-sm-6, .col-sm-7, .col-sm-8, .col-sm-9, .col-sm-10, .col-sm-11, .col-sm-12 {
+ float: left;
+ }
+ .col-sm-12 {
+ width: 100%;
+ }
+ .col-sm-11 {
+ width: 91.66666667%;
+ }
+ .col-sm-10 {
+ width: 83.33333333%;
+ }
+ .col-sm-9 {
+ width: 75%;
+ }
+ .col-sm-8 {
+ width: 66.66666667%;
+ }
+ .col-sm-7 {
+ width: 58.33333333%;
+ }
+ .col-sm-6 {
+ width: 50%;
+ }
+ .col-sm-5 {
+ width: 41.66666667%;
+ }
+ .col-sm-4 {
+ width: 33.33333333%;
+ }
+ .col-sm-3 {
+ width: 25%;
+ }
+ .col-sm-2 {
+ width: 16.66666667%;
+ }
+ .col-sm-1 {
+ width: 8.33333333%;
+ }
+ .col-sm-pull-12 {
+ right: 100%;
+ }
+ .col-sm-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-sm-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-sm-pull-9 {
+ right: 75%;
+ }
+ .col-sm-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-sm-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-sm-pull-6 {
+ right: 50%;
+ }
+ .col-sm-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-sm-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-sm-pull-3 {
+ right: 25%;
+ }
+ .col-sm-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-sm-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-sm-pull-0 {
+ right: auto;
+ }
+ .col-sm-push-12 {
+ left: 100%;
+ }
+ .col-sm-push-11 {
+ left: 91.66666667%;
+ }
+ .col-sm-push-10 {
+ left: 83.33333333%;
+ }
+ .col-sm-push-9 {
+ left: 75%;
+ }
+ .col-sm-push-8 {
+ left: 66.66666667%;
+ }
+ .col-sm-push-7 {
+ left: 58.33333333%;
+ }
+ .col-sm-push-6 {
+ left: 50%;
+ }
+ .col-sm-push-5 {
+ left: 41.66666667%;
+ }
+ .col-sm-push-4 {
+ left: 33.33333333%;
+ }
+ .col-sm-push-3 {
+ left: 25%;
+ }
+ .col-sm-push-2 {
+ left: 16.66666667%;
+ }
+ .col-sm-push-1 {
+ left: 8.33333333%;
+ }
+ .col-sm-push-0 {
+ left: auto;
+ }
+ .col-sm-offset-12 {
+ margin-left: 100%;
+ }
+ .col-sm-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-sm-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-sm-offset-9 {
+ margin-left: 75%;
+ }
+ .col-sm-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-sm-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-sm-offset-6 {
+ margin-left: 50%;
+ }
+ .col-sm-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-sm-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-sm-offset-3 {
+ margin-left: 25%;
+ }
+ .col-sm-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-sm-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-sm-offset-0 {
+ margin-left: 0%;
+ }
+}
+@media (min-width: 992px) {
+ .col-md-1, .col-md-2, .col-md-3, .col-md-4, .col-md-5, .col-md-6, .col-md-7, .col-md-8, .col-md-9, .col-md-10, .col-md-11, .col-md-12 {
+ float: left;
+ }
+ .col-md-12 {
+ width: 100%;
+ }
+ .col-md-11 {
+ width: 91.66666667%;
+ }
+ .col-md-10 {
+ width: 83.33333333%;
+ }
+ .col-md-9 {
+ width: 75%;
+ }
+ .col-md-8 {
+ width: 66.66666667%;
+ }
+ .col-md-7 {
+ width: 58.33333333%;
+ }
+ .col-md-6 {
+ width: 50%;
+ }
+ .col-md-5 {
+ width: 41.66666667%;
+ }
+ .col-md-4 {
+ width: 33.33333333%;
+ }
+ .col-md-3 {
+ width: 25%;
+ }
+ .col-md-2 {
+ width: 16.66666667%;
+ }
+ .col-md-1 {
+ width: 8.33333333%;
+ }
+ .col-md-pull-12 {
+ right: 100%;
+ }
+ .col-md-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-md-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-md-pull-9 {
+ right: 75%;
+ }
+ .col-md-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-md-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-md-pull-6 {
+ right: 50%;
+ }
+ .col-md-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-md-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-md-pull-3 {
+ right: 25%;
+ }
+ .col-md-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-md-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-md-pull-0 {
+ right: auto;
+ }
+ .col-md-push-12 {
+ left: 100%;
+ }
+ .col-md-push-11 {
+ left: 91.66666667%;
+ }
+ .col-md-push-10 {
+ left: 83.33333333%;
+ }
+ .col-md-push-9 {
+ left: 75%;
+ }
+ .col-md-push-8 {
+ left: 66.66666667%;
+ }
+ .col-md-push-7 {
+ left: 58.33333333%;
+ }
+ .col-md-push-6 {
+ left: 50%;
+ }
+ .col-md-push-5 {
+ left: 41.66666667%;
+ }
+ .col-md-push-4 {
+ left: 33.33333333%;
+ }
+ .col-md-push-3 {
+ left: 25%;
+ }
+ .col-md-push-2 {
+ left: 16.66666667%;
+ }
+ .col-md-push-1 {
+ left: 8.33333333%;
+ }
+ .col-md-push-0 {
+ left: auto;
+ }
+ .col-md-offset-12 {
+ margin-left: 100%;
+ }
+ .col-md-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-md-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-md-offset-9 {
+ margin-left: 75%;
+ }
+ .col-md-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-md-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-md-offset-6 {
+ margin-left: 50%;
+ }
+ .col-md-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-md-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-md-offset-3 {
+ margin-left: 25%;
+ }
+ .col-md-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-md-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-md-offset-0 {
+ margin-left: 0%;
+ }
+}
+@media (min-width: 1200px) {
+ .col-lg-1, .col-lg-2, .col-lg-3, .col-lg-4, .col-lg-5, .col-lg-6, .col-lg-7, .col-lg-8, .col-lg-9, .col-lg-10, .col-lg-11, .col-lg-12 {
+ float: left;
+ }
+ .col-lg-12 {
+ width: 100%;
+ }
+ .col-lg-11 {
+ width: 91.66666667%;
+ }
+ .col-lg-10 {
+ width: 83.33333333%;
+ }
+ .col-lg-9 {
+ width: 75%;
+ }
+ .col-lg-8 {
+ width: 66.66666667%;
+ }
+ .col-lg-7 {
+ width: 58.33333333%;
+ }
+ .col-lg-6 {
+ width: 50%;
+ }
+ .col-lg-5 {
+ width: 41.66666667%;
+ }
+ .col-lg-4 {
+ width: 33.33333333%;
+ }
+ .col-lg-3 {
+ width: 25%;
+ }
+ .col-lg-2 {
+ width: 16.66666667%;
+ }
+ .col-lg-1 {
+ width: 8.33333333%;
+ }
+ .col-lg-pull-12 {
+ right: 100%;
+ }
+ .col-lg-pull-11 {
+ right: 91.66666667%;
+ }
+ .col-lg-pull-10 {
+ right: 83.33333333%;
+ }
+ .col-lg-pull-9 {
+ right: 75%;
+ }
+ .col-lg-pull-8 {
+ right: 66.66666667%;
+ }
+ .col-lg-pull-7 {
+ right: 58.33333333%;
+ }
+ .col-lg-pull-6 {
+ right: 50%;
+ }
+ .col-lg-pull-5 {
+ right: 41.66666667%;
+ }
+ .col-lg-pull-4 {
+ right: 33.33333333%;
+ }
+ .col-lg-pull-3 {
+ right: 25%;
+ }
+ .col-lg-pull-2 {
+ right: 16.66666667%;
+ }
+ .col-lg-pull-1 {
+ right: 8.33333333%;
+ }
+ .col-lg-pull-0 {
+ right: auto;
+ }
+ .col-lg-push-12 {
+ left: 100%;
+ }
+ .col-lg-push-11 {
+ left: 91.66666667%;
+ }
+ .col-lg-push-10 {
+ left: 83.33333333%;
+ }
+ .col-lg-push-9 {
+ left: 75%;
+ }
+ .col-lg-push-8 {
+ left: 66.66666667%;
+ }
+ .col-lg-push-7 {
+ left: 58.33333333%;
+ }
+ .col-lg-push-6 {
+ left: 50%;
+ }
+ .col-lg-push-5 {
+ left: 41.66666667%;
+ }
+ .col-lg-push-4 {
+ left: 33.33333333%;
+ }
+ .col-lg-push-3 {
+ left: 25%;
+ }
+ .col-lg-push-2 {
+ left: 16.66666667%;
+ }
+ .col-lg-push-1 {
+ left: 8.33333333%;
+ }
+ .col-lg-push-0 {
+ left: auto;
+ }
+ .col-lg-offset-12 {
+ margin-left: 100%;
+ }
+ .col-lg-offset-11 {
+ margin-left: 91.66666667%;
+ }
+ .col-lg-offset-10 {
+ margin-left: 83.33333333%;
+ }
+ .col-lg-offset-9 {
+ margin-left: 75%;
+ }
+ .col-lg-offset-8 {
+ margin-left: 66.66666667%;
+ }
+ .col-lg-offset-7 {
+ margin-left: 58.33333333%;
+ }
+ .col-lg-offset-6 {
+ margin-left: 50%;
+ }
+ .col-lg-offset-5 {
+ margin-left: 41.66666667%;
+ }
+ .col-lg-offset-4 {
+ margin-left: 33.33333333%;
+ }
+ .col-lg-offset-3 {
+ margin-left: 25%;
+ }
+ .col-lg-offset-2 {
+ margin-left: 16.66666667%;
+ }
+ .col-lg-offset-1 {
+ margin-left: 8.33333333%;
+ }
+ .col-lg-offset-0 {
+ margin-left: 0%;
+ }
+}
+table {
+ background-color: transparent;
+}
+caption {
+ padding-top: 8px;
+ padding-bottom: 8px;
+ color: #808080;
+ text-align: left;
+}
+th {
+ text-align: left;
+}
+.table {
+ width: 100%;
+ max-width: 100%;
+ margin-bottom: 18px;
+}
+.table > thead > tr > th,
+.table > tbody > tr > th,
+.table > tfoot > tr > th,
+.table > thead > tr > td,
+.table > tbody > tr > td,
+.table > tfoot > tr > td {
+ padding: 8px;
+ line-height: 1.42857143;
+ vertical-align: top;
+ border-top: 1px solid #dddddd;
+}
+.table > thead > tr > th {
+ vertical-align: bottom;
+ border-bottom: 2px solid #dddddd;
+}
+.table > caption + thead > tr:first-child > th,
+.table > colgroup + thead > tr:first-child > th,
+.table > thead:first-child > tr:first-child > th,
+.table > caption + thead > tr:first-child > td,
+.table > colgroup + thead > tr:first-child > td,
+.table > thead:first-child > tr:first-child > td {
+ border-top: 0;
+}
+.table > tbody + tbody {
+ border-top: 2px solid #dddddd;
+}
+.table .table {
+ background-color: #fcfcfc;
+}
+.table-condensed > thead > tr > th,
+.table-condensed > tbody > tr > th,
+.table-condensed > tfoot > tr > th,
+.table-condensed > thead > tr > td,
+.table-condensed > tbody > tr > td,
+.table-condensed > tfoot > tr > td {
+ padding: 5px;
+}
+.table-bordered {
+ border: 1px solid #dddddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > tbody > tr > th,
+.table-bordered > tfoot > tr > th,
+.table-bordered > thead > tr > td,
+.table-bordered > tbody > tr > td,
+.table-bordered > tfoot > tr > td {
+ border: 1px solid #dddddd;
+}
+.table-bordered > thead > tr > th,
+.table-bordered > thead > tr > td {
+ border-bottom-width: 2px;
+}
+.table-striped > tbody > tr:nth-of-type(odd) {
+ background-color: #f9f9f9;
+}
+.table-hover > tbody > tr:hover {
+ background-color: #f5f5f5;
+}
+table col[class*="col-"] {
+ position: static;
+ float: none;
+ display: table-column;
+}
+table td[class*="col-"],
+table th[class*="col-"] {
+ position: static;
+ float: none;
+ display: table-cell;
+}
+.table > thead > tr > td.active,
+.table > tbody > tr > td.active,
+.table > tfoot > tr > td.active,
+.table > thead > tr > th.active,
+.table > tbody > tr > th.active,
+.table > tfoot > tr > th.active,
+.table > thead > tr.active > td,
+.table > tbody > tr.active > td,
+.table > tfoot > tr.active > td,
+.table > thead > tr.active > th,
+.table > tbody > tr.active > th,
+.table > tfoot > tr.active > th {
+ background-color: #f5f5f5;
+}
+.table-hover > tbody > tr > td.active:hover,
+.table-hover > tbody > tr > th.active:hover,
+.table-hover > tbody > tr.active:hover > td,
+.table-hover > tbody > tr:hover > .active,
+.table-hover > tbody > tr.active:hover > th {
+ background-color: #e8e8e8;
+}
+.table > thead > tr > td.success,
+.table > tbody > tr > td.success,
+.table > tfoot > tr > td.success,
+.table > thead > tr > th.success,
+.table > tbody > tr > th.success,
+.table > tfoot > tr > th.success,
+.table > thead > tr.success > td,
+.table > tbody > tr.success > td,
+.table > tfoot > tr.success > td,
+.table > thead > tr.success > th,
+.table > tbody > tr.success > th,
+.table > tfoot > tr.success > th {
+ background-color: #dff0d8;
+}
+.table-hover > tbody > tr > td.success:hover,
+.table-hover > tbody > tr > th.success:hover,
+.table-hover > tbody > tr.success:hover > td,
+.table-hover > tbody > tr:hover > .success,
+.table-hover > tbody > tr.success:hover > th {
+ background-color: #d0e9c6;
+}
+.table > thead > tr > td.info,
+.table > tbody > tr > td.info,
+.table > tfoot > tr > td.info,
+.table > thead > tr > th.info,
+.table > tbody > tr > th.info,
+.table > tfoot > tr > th.info,
+.table > thead > tr.info > td,
+.table > tbody > tr.info > td,
+.table > tfoot > tr.info > td,
+.table > thead > tr.info > th,
+.table > tbody > tr.info > th,
+.table > tfoot > tr.info > th {
+ background-color: #d9edf7;
+}
+.table-hover > tbody > tr > td.info:hover,
+.table-hover > tbody > tr > th.info:hover,
+.table-hover > tbody > tr.info:hover > td,
+.table-hover > tbody > tr:hover > .info,
+.table-hover > tbody > tr.info:hover > th {
+ background-color: #c4e3f3;
+}
+.table > thead > tr > td.warning,
+.table > tbody > tr > td.warning,
+.table > tfoot > tr > td.warning,
+.table > thead > tr > th.warning,
+.table > tbody > tr > th.warning,
+.table > tfoot > tr > th.warning,
+.table > thead > tr.warning > td,
+.table > tbody > tr.warning > td,
+.table > tfoot > tr.warning > td,
+.table > thead > tr.warning > th,
+.table > tbody > tr.warning > th,
+.table > tfoot > tr.warning > th {
+ background-color: #fcf8e3;
+}
+.table-hover > tbody > tr > td.warning:hover,
+.table-hover > tbody > tr > th.warning:hover,
+.table-hover > tbody > tr.warning:hover > td,
+.table-hover > tbody > tr:hover > .warning,
+.table-hover > tbody > tr.warning:hover > th {
+ background-color: #faf2cc;
+}
+.table > thead > tr > td.danger,
+.table > tbody > tr > td.danger,
+.table > tfoot > tr > td.danger,
+.table > thead > tr > th.danger,
+.table > tbody > tr > th.danger,
+.table > tfoot > tr > th.danger,
+.table > thead > tr.danger > td,
+.table > tbody > tr.danger > td,
+.table > tfoot > tr.danger > td,
+.table > thead > tr.danger > th,
+.table > tbody > tr.danger > th,
+.table > tfoot > tr.danger > th {
+ background-color: #f2dede;
+}
+.table-hover > tbody > tr > td.danger:hover,
+.table-hover > tbody > tr > th.danger:hover,
+.table-hover > tbody > tr.danger:hover > td,
+.table-hover > tbody > tr:hover > .danger,
+.table-hover > tbody > tr.danger:hover > th {
+ background-color: #ebcccc;
+}
+.table-responsive {
+ overflow-x: auto;
+ min-height: 0.01%;
+}
+@media screen and (max-width: 767px) {
+ .table-responsive {
+ width: 100%;
+ margin-bottom: 13.5px;
+ overflow-y: hidden;
+ -ms-overflow-style: -ms-autohiding-scrollbar;
+ border: 1px solid #dddddd;
+ }
+ .table-responsive > .table {
+ margin-bottom: 0;
+ }
+ .table-responsive > .table > thead > tr > th,
+ .table-responsive > .table > tbody > tr > th,
+ .table-responsive > .table > tfoot > tr > th,
+ .table-responsive > .table > thead > tr > td,
+ .table-responsive > .table > tbody > tr > td,
+ .table-responsive > .table > tfoot > tr > td {
+ white-space: nowrap;
+ }
+ .table-responsive > .table-bordered {
+ border: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:first-child,
+ .table-responsive > .table-bordered > tbody > tr > th:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+ .table-responsive > .table-bordered > thead > tr > td:first-child,
+ .table-responsive > .table-bordered > tbody > tr > td:first-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+ }
+ .table-responsive > .table-bordered > thead > tr > th:last-child,
+ .table-responsive > .table-bordered > tbody > tr > th:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+ .table-responsive > .table-bordered > thead > tr > td:last-child,
+ .table-responsive > .table-bordered > tbody > tr > td:last-child,
+ .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+ }
+ .table-responsive > .table-bordered > tbody > tr:last-child > th,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > th,
+ .table-responsive > .table-bordered > tbody > tr:last-child > td,
+ .table-responsive > .table-bordered > tfoot > tr:last-child > td {
+ border-bottom: 0;
+ }
+}
+fieldset {
+ padding: 0;
+ margin: 0;
+ border: 0;
+ min-width: 0;
+}
+legend {
+ display: block;
+ width: 100%;
+ padding: 0;
+ margin-bottom: 18px;
+ font-size: 19.5px;
+ line-height: inherit;
+ color: #777777;
+ border: 0;
+ border-bottom: 1px solid #e5e5e5;
+}
+label {
+ display: inline-block;
+ max-width: 100%;
+ margin-bottom: 5px;
+ font-weight: bold;
+}
+input[type="search"] {
+ -webkit-box-sizing: border-box;
+ -moz-box-sizing: border-box;
+ box-sizing: border-box;
+}
+input[type="radio"],
+input[type="checkbox"] {
+ margin: 4px 0 0;
+ margin-top: 1px \9;
+ line-height: normal;
+}
+input[type="file"] {
+ display: block;
+}
+input[type="range"] {
+ display: block;
+ width: 100%;
+}
+select[multiple],
+select[size] {
+ height: auto;
+}
+input[type="file"]:focus,
+input[type="radio"]:focus,
+input[type="checkbox"]:focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+output {
+ display: block;
+ padding-top: 9px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #777777;
+}
+.form-control {
+ display: block;
+ width: 100%;
+ height: 36px;
+ padding: 8px 12px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ color: #777777;
+ background-color: #ffffff;
+ background-image: none;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ -webkit-transition: border-color ease-in-out .15s, -webkit-box-shadow ease-in-out .15s;
+ -o-transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+ transition: border-color ease-in-out .15s, box-shadow ease-in-out .15s;
+}
+.form-control:focus {
+ border-color: #66afe9;
+ outline: 0;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+ box-shadow: inset 0 1px 1px rgba(0,0,0,.075), 0 0 8px rgba(102, 175, 233, 0.6);
+}
+.form-control::-moz-placeholder {
+ color: #dddddd;
+ opacity: 1;
+}
+.form-control:-ms-input-placeholder {
+ color: #dddddd;
+}
+.form-control::-webkit-input-placeholder {
+ color: #dddddd;
+}
+.form-control[disabled],
+.form-control[readonly],
+fieldset[disabled] .form-control {
+ background-color: #dddddd;
+ opacity: 1;
+}
+.form-control[disabled],
+fieldset[disabled] .form-control {
+ cursor: not-allowed;
+}
+textarea.form-control {
+ height: auto;
+}
+input[type="search"] {
+ -webkit-appearance: none;
+}
+@media screen and (-webkit-min-device-pixel-ratio: 0) {
+ input[type="date"],
+ input[type="time"],
+ input[type="datetime-local"],
+ input[type="month"] {
+ line-height: 36px;
+ }
+ input[type="date"].input-sm,
+ input[type="time"].input-sm,
+ input[type="datetime-local"].input-sm,
+ input[type="month"].input-sm,
+ .input-group-sm input[type="date"],
+ .input-group-sm input[type="time"],
+ .input-group-sm input[type="datetime-local"],
+ .input-group-sm input[type="month"] {
+ line-height: 30px;
+ }
+ input[type="date"].input-lg,
+ input[type="time"].input-lg,
+ input[type="datetime-local"].input-lg,
+ input[type="month"].input-lg,
+ .input-group-lg input[type="date"],
+ .input-group-lg input[type="time"],
+ .input-group-lg input[type="datetime-local"],
+ .input-group-lg input[type="month"] {
+ line-height: 53px;
+ }
+}
+.form-group {
+ margin-bottom: 15px;
+}
+.radio,
+.checkbox {
+ position: relative;
+ display: block;
+ margin-top: 10px;
+ margin-bottom: 10px;
+}
+.radio label,
+.checkbox label {
+ min-height: 18px;
+ padding-left: 20px;
+ margin-bottom: 0;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio input[type="radio"],
+.radio-inline input[type="radio"],
+.checkbox input[type="checkbox"],
+.checkbox-inline input[type="checkbox"] {
+ position: absolute;
+ margin-left: -20px;
+ margin-top: 4px \9;
+}
+.radio + .radio,
+.checkbox + .checkbox {
+ margin-top: -5px;
+}
+.radio-inline,
+.checkbox-inline {
+ position: relative;
+ display: inline-block;
+ padding-left: 20px;
+ margin-bottom: 0;
+ vertical-align: middle;
+ font-weight: normal;
+ cursor: pointer;
+}
+.radio-inline + .radio-inline,
+.checkbox-inline + .checkbox-inline {
+ margin-top: 0;
+ margin-left: 10px;
+}
+input[type="radio"][disabled],
+input[type="checkbox"][disabled],
+input[type="radio"].disabled,
+input[type="checkbox"].disabled,
+fieldset[disabled] input[type="radio"],
+fieldset[disabled] input[type="checkbox"] {
+ cursor: not-allowed;
+}
+.radio-inline.disabled,
+.checkbox-inline.disabled,
+fieldset[disabled] .radio-inline,
+fieldset[disabled] .checkbox-inline {
+ cursor: not-allowed;
+}
+.radio.disabled label,
+.checkbox.disabled label,
+fieldset[disabled] .radio label,
+fieldset[disabled] .checkbox label {
+ cursor: not-allowed;
+}
+.form-control-static {
+ padding-top: 9px;
+ padding-bottom: 9px;
+ margin-bottom: 0;
+ min-height: 31px;
+}
+.form-control-static.input-lg,
+.form-control-static.input-sm {
+ padding-left: 0;
+ padding-right: 0;
+}
+.input-sm {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-sm {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-sm,
+select[multiple].input-sm {
+ height: auto;
+}
+.form-group-sm .form-control {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.form-group-sm .form-control {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.form-group-sm .form-control,
+select[multiple].form-group-sm .form-control {
+ height: auto;
+}
+.form-group-sm .form-control-static {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ min-height: 30px;
+}
+.input-lg {
+ height: 53px;
+ padding: 14px 16px;
+ font-size: 17px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-lg {
+ height: 53px;
+ line-height: 53px;
+}
+textarea.input-lg,
+select[multiple].input-lg {
+ height: auto;
+}
+.form-group-lg .form-control {
+ height: 53px;
+ padding: 14px 16px;
+ font-size: 17px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.form-group-lg .form-control {
+ height: 53px;
+ line-height: 53px;
+}
+textarea.form-group-lg .form-control,
+select[multiple].form-group-lg .form-control {
+ height: auto;
+}
+.form-group-lg .form-control-static {
+ height: 53px;
+ padding: 14px 16px;
+ font-size: 17px;
+ line-height: 1.3333333;
+ min-height: 35px;
+}
+.has-feedback {
+ position: relative;
+}
+.has-feedback .form-control {
+ padding-right: 45px;
+}
+.form-control-feedback {
+ position: absolute;
+ top: 0;
+ right: 0;
+ z-index: 2;
+ display: block;
+ width: 36px;
+ height: 36px;
+ line-height: 36px;
+ text-align: center;
+ pointer-events: none;
+}
+.input-lg + .form-control-feedback {
+ width: 53px;
+ height: 53px;
+ line-height: 53px;
+}
+.input-sm + .form-control-feedback {
+ width: 30px;
+ height: 30px;
+ line-height: 30px;
+}
+.has-success .help-block,
+.has-success .control-label,
+.has-success .radio,
+.has-success .checkbox,
+.has-success .radio-inline,
+.has-success .checkbox-inline,
+.has-success.radio label,
+.has-success.checkbox label,
+.has-success.radio-inline label,
+.has-success.checkbox-inline label {
+ color: #468847;
+}
+.has-success .form-control {
+ border-color: #468847;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-success .form-control:focus {
+ border-color: #356635;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #7aba7b;
+}
+.has-success .input-group-addon {
+ color: #468847;
+ border-color: #468847;
+ background-color: #dff0d8;
+}
+.has-success .form-control-feedback {
+ color: #468847;
+}
+.has-warning .help-block,
+.has-warning .control-label,
+.has-warning .radio,
+.has-warning .checkbox,
+.has-warning .radio-inline,
+.has-warning .checkbox-inline,
+.has-warning.radio label,
+.has-warning.checkbox label,
+.has-warning.radio-inline label,
+.has-warning.checkbox-inline label {
+ color: #c09853;
+}
+.has-warning .form-control {
+ border-color: #c09853;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-warning .form-control:focus {
+ border-color: #a47e3c;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #dbc59e;
+}
+.has-warning .input-group-addon {
+ color: #c09853;
+ border-color: #c09853;
+ background-color: #fcf8e3;
+}
+.has-warning .form-control-feedback {
+ color: #c09853;
+}
+.has-error .help-block,
+.has-error .control-label,
+.has-error .radio,
+.has-error .checkbox,
+.has-error .radio-inline,
+.has-error .checkbox-inline,
+.has-error.radio label,
+.has-error.checkbox label,
+.has-error.radio-inline label,
+.has-error.checkbox-inline label {
+ color: #b94a48;
+}
+.has-error .form-control {
+ border-color: #b94a48;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075);
+}
+.has-error .form-control:focus {
+ border-color: #953b39;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.075), 0 0 6px #d59392;
+}
+.has-error .input-group-addon {
+ color: #b94a48;
+ border-color: #b94a48;
+ background-color: #f2dede;
+}
+.has-error .form-control-feedback {
+ color: #b94a48;
+}
+.has-feedback label ~ .form-control-feedback {
+ top: 23px;
+}
+.has-feedback label.sr-only ~ .form-control-feedback {
+ top: 0;
+}
+.help-block {
+ display: block;
+ margin-top: 5px;
+ margin-bottom: 10px;
+ color: #b7b7b7;
+}
+@media (min-width: 768px) {
+ .form-inline .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .form-inline .form-control-static {
+ display: inline-block;
+ }
+ .form-inline .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .form-inline .input-group .input-group-addon,
+ .form-inline .input-group .input-group-btn,
+ .form-inline .input-group .form-control {
+ width: auto;
+ }
+ .form-inline .input-group > .form-control {
+ width: 100%;
+ }
+ .form-inline .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio,
+ .form-inline .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .form-inline .radio label,
+ .form-inline .checkbox label {
+ padding-left: 0;
+ }
+ .form-inline .radio input[type="radio"],
+ .form-inline .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .form-inline .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox,
+.form-horizontal .radio-inline,
+.form-horizontal .checkbox-inline {
+ margin-top: 0;
+ margin-bottom: 0;
+ padding-top: 9px;
+}
+.form-horizontal .radio,
+.form-horizontal .checkbox {
+ min-height: 27px;
+}
+.form-horizontal .form-group {
+ margin-left: -15px;
+ margin-right: -15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .control-label {
+ text-align: right;
+ margin-bottom: 0;
+ padding-top: 9px;
+ }
+}
+.form-horizontal .has-feedback .form-control-feedback {
+ right: 15px;
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-lg .control-label {
+ padding-top: 19.6666662px;
+ }
+}
+@media (min-width: 768px) {
+ .form-horizontal .form-group-sm .control-label {
+ padding-top: 6px;
+ }
+}
+.btn {
+ display: inline-block;
+ margin-bottom: 0;
+ font-weight: normal;
+ text-align: center;
+ vertical-align: middle;
+ -ms-touch-action: manipulation;
+ touch-action: manipulation;
+ cursor: pointer;
+ background-image: none;
+ border: 1px solid transparent;
+ white-space: nowrap;
+ padding: 8px 12px;
+ font-size: 13px;
+ line-height: 1.42857143;
+ border-radius: 4px;
+ -webkit-user-select: none;
+ -moz-user-select: none;
+ -ms-user-select: none;
+ user-select: none;
+}
+.btn:focus,
+.btn:active:focus,
+.btn.active:focus,
+.btn.focus,
+.btn:active.focus,
+.btn.active.focus {
+ outline: thin dotted;
+ outline: 5px auto -webkit-focus-ring-color;
+ outline-offset: -2px;
+}
+.btn:hover,
+.btn:focus,
+.btn.focus {
+ color: #ffffff;
+ text-decoration: none;
+}
+.btn:active,
+.btn.active {
+ outline: 0;
+ background-image: none;
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn.disabled,
+.btn[disabled],
+fieldset[disabled] .btn {
+ cursor: not-allowed;
+ pointer-events: none;
+ opacity: 0.65;
+ filter: alpha(opacity=65);
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-default {
+ color: #ffffff;
+ background-color: #474949;
+ border-color: #474949;
+}
+.btn-default:hover,
+.btn-default:focus,
+.btn-default.focus,
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ color: #ffffff;
+ background-color: #2e2f2f;
+ border-color: #292a2a;
+}
+.btn-default:active,
+.btn-default.active,
+.open > .dropdown-toggle.btn-default {
+ background-image: none;
+}
+.btn-default.disabled,
+.btn-default[disabled],
+fieldset[disabled] .btn-default,
+.btn-default.disabled:hover,
+.btn-default[disabled]:hover,
+fieldset[disabled] .btn-default:hover,
+.btn-default.disabled:focus,
+.btn-default[disabled]:focus,
+fieldset[disabled] .btn-default:focus,
+.btn-default.disabled.focus,
+.btn-default[disabled].focus,
+fieldset[disabled] .btn-default.focus,
+.btn-default.disabled:active,
+.btn-default[disabled]:active,
+fieldset[disabled] .btn-default:active,
+.btn-default.disabled.active,
+.btn-default[disabled].active,
+fieldset[disabled] .btn-default.active {
+ background-color: #474949;
+ border-color: #474949;
+}
+.btn-default .badge {
+ color: #474949;
+ background-color: #ffffff;
+}
+.btn-primary {
+ color: #ffffff;
+ background-color: #d9230f;
+ border-color: #d9230f;
+}
+.btn-primary:hover,
+.btn-primary:focus,
+.btn-primary.focus,
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ color: #ffffff;
+ background-color: #a91b0c;
+ border-color: #a01a0b;
+}
+.btn-primary:active,
+.btn-primary.active,
+.open > .dropdown-toggle.btn-primary {
+ background-image: none;
+}
+.btn-primary.disabled,
+.btn-primary[disabled],
+fieldset[disabled] .btn-primary,
+.btn-primary.disabled:hover,
+.btn-primary[disabled]:hover,
+fieldset[disabled] .btn-primary:hover,
+.btn-primary.disabled:focus,
+.btn-primary[disabled]:focus,
+fieldset[disabled] .btn-primary:focus,
+.btn-primary.disabled.focus,
+.btn-primary[disabled].focus,
+fieldset[disabled] .btn-primary.focus,
+.btn-primary.disabled:active,
+.btn-primary[disabled]:active,
+fieldset[disabled] .btn-primary:active,
+.btn-primary.disabled.active,
+.btn-primary[disabled].active,
+fieldset[disabled] .btn-primary.active {
+ background-color: #d9230f;
+ border-color: #d9230f;
+}
+.btn-primary .badge {
+ color: #d9230f;
+ background-color: #ffffff;
+}
+.btn-success {
+ color: #ffffff;
+ background-color: #469408;
+ border-color: #469408;
+}
+.btn-success:hover,
+.btn-success:focus,
+.btn-success.focus,
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ color: #ffffff;
+ background-color: #2f6405;
+ border-color: #2b5a05;
+}
+.btn-success:active,
+.btn-success.active,
+.open > .dropdown-toggle.btn-success {
+ background-image: none;
+}
+.btn-success.disabled,
+.btn-success[disabled],
+fieldset[disabled] .btn-success,
+.btn-success.disabled:hover,
+.btn-success[disabled]:hover,
+fieldset[disabled] .btn-success:hover,
+.btn-success.disabled:focus,
+.btn-success[disabled]:focus,
+fieldset[disabled] .btn-success:focus,
+.btn-success.disabled.focus,
+.btn-success[disabled].focus,
+fieldset[disabled] .btn-success.focus,
+.btn-success.disabled:active,
+.btn-success[disabled]:active,
+fieldset[disabled] .btn-success:active,
+.btn-success.disabled.active,
+.btn-success[disabled].active,
+fieldset[disabled] .btn-success.active {
+ background-color: #469408;
+ border-color: #469408;
+}
+.btn-success .badge {
+ color: #469408;
+ background-color: #ffffff;
+}
+.btn-info {
+ color: #ffffff;
+ background-color: #029acf;
+ border-color: #029acf;
+}
+.btn-info:hover,
+.btn-info:focus,
+.btn-info.focus,
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ color: #ffffff;
+ background-color: #02749c;
+ border-color: #016d92;
+}
+.btn-info:active,
+.btn-info.active,
+.open > .dropdown-toggle.btn-info {
+ background-image: none;
+}
+.btn-info.disabled,
+.btn-info[disabled],
+fieldset[disabled] .btn-info,
+.btn-info.disabled:hover,
+.btn-info[disabled]:hover,
+fieldset[disabled] .btn-info:hover,
+.btn-info.disabled:focus,
+.btn-info[disabled]:focus,
+fieldset[disabled] .btn-info:focus,
+.btn-info.disabled.focus,
+.btn-info[disabled].focus,
+fieldset[disabled] .btn-info.focus,
+.btn-info.disabled:active,
+.btn-info[disabled]:active,
+fieldset[disabled] .btn-info:active,
+.btn-info.disabled.active,
+.btn-info[disabled].active,
+fieldset[disabled] .btn-info.active {
+ background-color: #029acf;
+ border-color: #029acf;
+}
+.btn-info .badge {
+ color: #029acf;
+ background-color: #ffffff;
+}
+.btn-warning {
+ color: #ffffff;
+ background-color: #9b479f;
+ border-color: #9b479f;
+}
+.btn-warning:hover,
+.btn-warning:focus,
+.btn-warning.focus,
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ color: #ffffff;
+ background-color: #79377c;
+ border-color: #723475;
+}
+.btn-warning:active,
+.btn-warning.active,
+.open > .dropdown-toggle.btn-warning {
+ background-image: none;
+}
+.btn-warning.disabled,
+.btn-warning[disabled],
+fieldset[disabled] .btn-warning,
+.btn-warning.disabled:hover,
+.btn-warning[disabled]:hover,
+fieldset[disabled] .btn-warning:hover,
+.btn-warning.disabled:focus,
+.btn-warning[disabled]:focus,
+fieldset[disabled] .btn-warning:focus,
+.btn-warning.disabled.focus,
+.btn-warning[disabled].focus,
+fieldset[disabled] .btn-warning.focus,
+.btn-warning.disabled:active,
+.btn-warning[disabled]:active,
+fieldset[disabled] .btn-warning:active,
+.btn-warning.disabled.active,
+.btn-warning[disabled].active,
+fieldset[disabled] .btn-warning.active {
+ background-color: #9b479f;
+ border-color: #9b479f;
+}
+.btn-warning .badge {
+ color: #9b479f;
+ background-color: #ffffff;
+}
+.btn-danger {
+ color: #ffffff;
+ background-color: #d9831f;
+ border-color: #d9831f;
+}
+.btn-danger:hover,
+.btn-danger:focus,
+.btn-danger.focus,
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ color: #ffffff;
+ background-color: #ac6819;
+ border-color: #a36317;
+}
+.btn-danger:active,
+.btn-danger.active,
+.open > .dropdown-toggle.btn-danger {
+ background-image: none;
+}
+.btn-danger.disabled,
+.btn-danger[disabled],
+fieldset[disabled] .btn-danger,
+.btn-danger.disabled:hover,
+.btn-danger[disabled]:hover,
+fieldset[disabled] .btn-danger:hover,
+.btn-danger.disabled:focus,
+.btn-danger[disabled]:focus,
+fieldset[disabled] .btn-danger:focus,
+.btn-danger.disabled.focus,
+.btn-danger[disabled].focus,
+fieldset[disabled] .btn-danger.focus,
+.btn-danger.disabled:active,
+.btn-danger[disabled]:active,
+fieldset[disabled] .btn-danger:active,
+.btn-danger.disabled.active,
+.btn-danger[disabled].active,
+fieldset[disabled] .btn-danger.active {
+ background-color: #d9831f;
+ border-color: #d9831f;
+}
+.btn-danger .badge {
+ color: #d9831f;
+ background-color: #ffffff;
+}
+.btn-link {
+ color: #d9230f;
+ font-weight: normal;
+ border-radius: 0;
+}
+.btn-link,
+.btn-link:active,
+.btn-link.active,
+.btn-link[disabled],
+fieldset[disabled] .btn-link {
+ background-color: transparent;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn-link,
+.btn-link:hover,
+.btn-link:focus,
+.btn-link:active {
+ border-color: transparent;
+}
+.btn-link:hover,
+.btn-link:focus {
+ color: #91170a;
+ text-decoration: underline;
+ background-color: transparent;
+}
+.btn-link[disabled]:hover,
+fieldset[disabled] .btn-link:hover,
+.btn-link[disabled]:focus,
+fieldset[disabled] .btn-link:focus {
+ color: #808080;
+ text-decoration: none;
+}
+.btn-lg,
+.btn-group-lg > .btn {
+ padding: 14px 16px;
+ font-size: 17px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+.btn-sm,
+.btn-group-sm > .btn {
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-xs,
+.btn-group-xs > .btn {
+ padding: 1px 5px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+.btn-block {
+ display: block;
+ width: 100%;
+}
+.btn-block + .btn-block {
+ margin-top: 5px;
+}
+input[type="submit"].btn-block,
+input[type="reset"].btn-block,
+input[type="button"].btn-block {
+ width: 100%;
+}
+.fade {
+ opacity: 0;
+ -webkit-transition: opacity 0.15s linear;
+ -o-transition: opacity 0.15s linear;
+ transition: opacity 0.15s linear;
+}
+.fade.in {
+ opacity: 1;
+}
+.collapse {
+ display: none;
+}
+.collapse.in {
+ display: block;
+}
+tr.collapse.in {
+ display: table-row;
+}
+tbody.collapse.in {
+ display: table-row-group;
+}
+.collapsing {
+ position: relative;
+ height: 0;
+ overflow: hidden;
+ -webkit-transition-property: height, visibility;
+ -o-transition-property: height, visibility;
+ transition-property: height, visibility;
+ -webkit-transition-duration: 0.35s;
+ -o-transition-duration: 0.35s;
+ transition-duration: 0.35s;
+ -webkit-transition-timing-function: ease;
+ -o-transition-timing-function: ease;
+ transition-timing-function: ease;
+}
+.caret {
+ display: inline-block;
+ width: 0;
+ height: 0;
+ margin-left: 2px;
+ vertical-align: middle;
+ border-top: 4px dashed;
+ border-right: 4px solid transparent;
+ border-left: 4px solid transparent;
+}
+.dropup,
+.dropdown {
+ position: relative;
+}
+.dropdown-toggle:focus {
+ outline: 0;
+}
+.dropdown-menu {
+ position: absolute;
+ top: 100%;
+ left: 0;
+ z-index: 1000;
+ display: none;
+ float: left;
+ min-width: 160px;
+ padding: 5px 0;
+ margin: 2px 0 0;
+ list-style: none;
+ font-size: 13px;
+ text-align: left;
+ background-color: #ffffff;
+ border: 1px solid #cccccc;
+ border: 1px solid rgba(0, 0, 0, 0.15);
+ border-radius: 4px;
+ -webkit-box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ box-shadow: 0 6px 12px rgba(0, 0, 0, 0.175);
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+}
+.dropdown-menu.pull-right {
+ right: 0;
+ left: auto;
+}
+.dropdown-menu .divider {
+ height: 1px;
+ margin: 8px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.dropdown-menu > li > a {
+ display: block;
+ padding: 3px 20px;
+ clear: both;
+ font-weight: normal;
+ line-height: 1.42857143;
+ color: #444444;
+ white-space: nowrap;
+}
+.dropdown-menu > li > a:hover,
+.dropdown-menu > li > a:focus {
+ text-decoration: none;
+ color: #ffffff;
+ background-color: #d9230f;
+}
+.dropdown-menu > .active > a,
+.dropdown-menu > .active > a:hover,
+.dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ text-decoration: none;
+ outline: 0;
+ background-color: #d9230f;
+}
+.dropdown-menu > .disabled > a,
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ color: #808080;
+}
+.dropdown-menu > .disabled > a:hover,
+.dropdown-menu > .disabled > a:focus {
+ text-decoration: none;
+ background-color: transparent;
+ background-image: none;
+ filter: progid:DXImageTransform.Microsoft.gradient(enabled = false);
+ cursor: not-allowed;
+}
+.open > .dropdown-menu {
+ display: block;
+}
+.open > a {
+ outline: 0;
+}
+.dropdown-menu-right {
+ left: auto;
+ right: 0;
+}
+.dropdown-menu-left {
+ left: 0;
+ right: auto;
+}
+.dropdown-header {
+ display: block;
+ padding: 3px 20px;
+ font-size: 12px;
+ line-height: 1.42857143;
+ color: #808080;
+ white-space: nowrap;
+}
+.dropdown-backdrop {
+ position: fixed;
+ left: 0;
+ right: 0;
+ bottom: 0;
+ top: 0;
+ z-index: 990;
+}
+.pull-right > .dropdown-menu {
+ right: 0;
+ left: auto;
+}
+.dropup .caret,
+.navbar-fixed-bottom .dropdown .caret {
+ border-top: 0;
+ border-bottom: 4px solid;
+ content: "";
+}
+.dropup .dropdown-menu,
+.navbar-fixed-bottom .dropdown .dropdown-menu {
+ top: auto;
+ bottom: 100%;
+ margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+ .navbar-right .dropdown-menu {
+ left: auto;
+ right: 0;
+ }
+ .navbar-right .dropdown-menu-left {
+ left: 0;
+ right: auto;
+ }
+}
+.btn-group,
+.btn-group-vertical {
+ position: relative;
+ display: inline-block;
+ vertical-align: middle;
+}
+.btn-group > .btn,
+.btn-group-vertical > .btn {
+ position: relative;
+ float: left;
+}
+.btn-group > .btn:hover,
+.btn-group-vertical > .btn:hover,
+.btn-group > .btn:focus,
+.btn-group-vertical > .btn:focus,
+.btn-group > .btn:active,
+.btn-group-vertical > .btn:active,
+.btn-group > .btn.active,
+.btn-group-vertical > .btn.active {
+ z-index: 2;
+}
+.btn-group .btn + .btn,
+.btn-group .btn + .btn-group,
+.btn-group .btn-group + .btn,
+.btn-group .btn-group + .btn-group {
+ margin-left: -1px;
+}
+.btn-toolbar {
+ margin-left: -5px;
+}
+.btn-toolbar .btn-group,
+.btn-toolbar .input-group {
+ float: left;
+}
+.btn-toolbar > .btn,
+.btn-toolbar > .btn-group,
+.btn-toolbar > .input-group {
+ margin-left: 5px;
+}
+.btn-group > .btn:not(:first-child):not(:last-child):not(.dropdown-toggle) {
+ border-radius: 0;
+}
+.btn-group > .btn:first-child {
+ margin-left: 0;
+}
+.btn-group > .btn:first-child:not(:last-child):not(.dropdown-toggle) {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group > .btn:last-child:not(:first-child),
+.btn-group > .dropdown-toggle:not(:first-child) {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group > .btn-group {
+ float: left;
+}
+.btn-group > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.btn-group > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group .dropdown-toggle:active,
+.btn-group.open .dropdown-toggle {
+ outline: 0;
+}
+.btn-group > .btn + .dropdown-toggle {
+ padding-left: 8px;
+ padding-right: 8px;
+}
+.btn-group > .btn-lg + .dropdown-toggle {
+ padding-left: 12px;
+ padding-right: 12px;
+}
+.btn-group.open .dropdown-toggle {
+ -webkit-box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+ box-shadow: inset 0 3px 5px rgba(0, 0, 0, 0.125);
+}
+.btn-group.open .dropdown-toggle.btn-link {
+ -webkit-box-shadow: none;
+ box-shadow: none;
+}
+.btn .caret {
+ margin-left: 0;
+}
+.btn-lg .caret {
+ border-width: 5px 5px 0;
+ border-bottom-width: 0;
+}
+.dropup .btn-lg .caret {
+ border-width: 0 5px 5px;
+}
+.btn-group-vertical > .btn,
+.btn-group-vertical > .btn-group,
+.btn-group-vertical > .btn-group > .btn {
+ display: block;
+ float: none;
+ width: 100%;
+ max-width: 100%;
+}
+.btn-group-vertical > .btn-group > .btn {
+ float: none;
+}
+.btn-group-vertical > .btn + .btn,
+.btn-group-vertical > .btn + .btn-group,
+.btn-group-vertical > .btn-group + .btn,
+.btn-group-vertical > .btn-group + .btn-group {
+ margin-top: -1px;
+ margin-left: 0;
+}
+.btn-group-vertical > .btn:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn:first-child:not(:last-child) {
+ border-top-right-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn:last-child:not(:first-child) {
+ border-bottom-left-radius: 4px;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:not(:first-child):not(:last-child) > .btn {
+ border-radius: 0;
+}
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .btn:last-child,
+.btn-group-vertical > .btn-group:first-child:not(:last-child) > .dropdown-toggle {
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.btn-group-vertical > .btn-group:last-child:not(:first-child) > .btn:first-child {
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.btn-group-justified {
+ display: table;
+ width: 100%;
+ table-layout: fixed;
+ border-collapse: separate;
+}
+.btn-group-justified > .btn,
+.btn-group-justified > .btn-group {
+ float: none;
+ display: table-cell;
+ width: 1%;
+}
+.btn-group-justified > .btn-group .btn {
+ width: 100%;
+}
+.btn-group-justified > .btn-group .dropdown-menu {
+ left: auto;
+}
+[data-toggle="buttons"] > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="radio"],
+[data-toggle="buttons"] > .btn input[type="checkbox"],
+[data-toggle="buttons"] > .btn-group > .btn input[type="checkbox"] {
+ position: absolute;
+ clip: rect(0, 0, 0, 0);
+ pointer-events: none;
+}
+.input-group {
+ position: relative;
+ display: table;
+ border-collapse: separate;
+}
+.input-group[class*="col-"] {
+ float: none;
+ padding-left: 0;
+ padding-right: 0;
+}
+.input-group .form-control {
+ position: relative;
+ z-index: 2;
+ float: left;
+ width: 100%;
+ margin-bottom: 0;
+}
+.input-group-lg > .form-control,
+.input-group-lg > .input-group-addon,
+.input-group-lg > .input-group-btn > .btn {
+ height: 53px;
+ padding: 14px 16px;
+ font-size: 17px;
+ line-height: 1.3333333;
+ border-radius: 6px;
+}
+select.input-group-lg > .form-control,
+select.input-group-lg > .input-group-addon,
+select.input-group-lg > .input-group-btn > .btn {
+ height: 53px;
+ line-height: 53px;
+}
+textarea.input-group-lg > .form-control,
+textarea.input-group-lg > .input-group-addon,
+textarea.input-group-lg > .input-group-btn > .btn,
+select[multiple].input-group-lg > .form-control,
+select[multiple].input-group-lg > .input-group-addon,
+select[multiple].input-group-lg > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-sm > .form-control,
+.input-group-sm > .input-group-addon,
+.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ padding: 5px 10px;
+ font-size: 12px;
+ line-height: 1.5;
+ border-radius: 3px;
+}
+select.input-group-sm > .form-control,
+select.input-group-sm > .input-group-addon,
+select.input-group-sm > .input-group-btn > .btn {
+ height: 30px;
+ line-height: 30px;
+}
+textarea.input-group-sm > .form-control,
+textarea.input-group-sm > .input-group-addon,
+textarea.input-group-sm > .input-group-btn > .btn,
+select[multiple].input-group-sm > .form-control,
+select[multiple].input-group-sm > .input-group-addon,
+select[multiple].input-group-sm > .input-group-btn > .btn {
+ height: auto;
+}
+.input-group-addon,
+.input-group-btn,
+.input-group .form-control {
+ display: table-cell;
+}
+.input-group-addon:not(:first-child):not(:last-child),
+.input-group-btn:not(:first-child):not(:last-child),
+.input-group .form-control:not(:first-child):not(:last-child) {
+ border-radius: 0;
+}
+.input-group-addon,
+.input-group-btn {
+ width: 1%;
+ white-space: nowrap;
+ vertical-align: middle;
+}
+.input-group-addon {
+ padding: 8px 12px;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 1;
+ color: #777777;
+ text-align: center;
+ background-color: #dddddd;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+}
+.input-group-addon.input-sm {
+ padding: 5px 10px;
+ font-size: 12px;
+ border-radius: 3px;
+}
+.input-group-addon.input-lg {
+ padding: 14px 16px;
+ font-size: 17px;
+ border-radius: 6px;
+}
+.input-group-addon input[type="radio"],
+.input-group-addon input[type="checkbox"] {
+ margin-top: 0;
+}
+.input-group .form-control:first-child,
+.input-group-addon:first-child,
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group > .btn,
+.input-group-btn:first-child > .dropdown-toggle,
+.input-group-btn:last-child > .btn:not(:last-child):not(.dropdown-toggle),
+.input-group-btn:last-child > .btn-group:not(:last-child) > .btn {
+ border-bottom-right-radius: 0;
+ border-top-right-radius: 0;
+}
+.input-group-addon:first-child {
+ border-right: 0;
+}
+.input-group .form-control:last-child,
+.input-group-addon:last-child,
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group > .btn,
+.input-group-btn:last-child > .dropdown-toggle,
+.input-group-btn:first-child > .btn:not(:first-child),
+.input-group-btn:first-child > .btn-group:not(:first-child) > .btn {
+ border-bottom-left-radius: 0;
+ border-top-left-radius: 0;
+}
+.input-group-addon:last-child {
+ border-left: 0;
+}
+.input-group-btn {
+ position: relative;
+ font-size: 0;
+ white-space: nowrap;
+}
+.input-group-btn > .btn {
+ position: relative;
+}
+.input-group-btn > .btn + .btn {
+ margin-left: -1px;
+}
+.input-group-btn > .btn:hover,
+.input-group-btn > .btn:focus,
+.input-group-btn > .btn:active {
+ z-index: 2;
+}
+.input-group-btn:first-child > .btn,
+.input-group-btn:first-child > .btn-group {
+ margin-right: -1px;
+}
+.input-group-btn:last-child > .btn,
+.input-group-btn:last-child > .btn-group {
+ margin-left: -1px;
+}
+.nav {
+ margin-bottom: 0;
+ padding-left: 0;
+ list-style: none;
+}
+.nav > li {
+ position: relative;
+ display: block;
+}
+.nav > li > a {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+}
+.nav > li > a:hover,
+.nav > li > a:focus {
+ text-decoration: none;
+ background-color: #dddddd;
+}
+.nav > li.disabled > a {
+ color: #808080;
+}
+.nav > li.disabled > a:hover,
+.nav > li.disabled > a:focus {
+ color: #808080;
+ text-decoration: none;
+ background-color: transparent;
+ cursor: not-allowed;
+}
+.nav .open > a,
+.nav .open > a:hover,
+.nav .open > a:focus {
+ background-color: #dddddd;
+ border-color: #d9230f;
+}
+.nav .nav-divider {
+ height: 1px;
+ margin: 8px 0;
+ overflow: hidden;
+ background-color: #e5e5e5;
+}
+.nav > li > a > img {
+ max-width: none;
+}
+.nav-tabs {
+ border-bottom: 1px solid #dddddd;
+}
+.nav-tabs > li {
+ float: left;
+ margin-bottom: -1px;
+}
+.nav-tabs > li > a {
+ margin-right: 2px;
+ line-height: 1.42857143;
+ border: 1px solid transparent;
+ border-radius: 4px 4px 0 0;
+}
+.nav-tabs > li > a:hover {
+ border-color: #dddddd #dddddd #dddddd;
+}
+.nav-tabs > li.active > a,
+.nav-tabs > li.active > a:hover,
+.nav-tabs > li.active > a:focus {
+ color: #777777;
+ background-color: #fcfcfc;
+ border: 1px solid #dddddd;
+ border-bottom-color: transparent;
+ cursor: default;
+}
+.nav-tabs.nav-justified {
+ width: 100%;
+ border-bottom: 0;
+}
+.nav-tabs.nav-justified > li {
+ float: none;
+}
+.nav-tabs.nav-justified > li > a {
+ text-align: center;
+ margin-bottom: 5px;
+}
+.nav-tabs.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-tabs.nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs.nav-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs.nav-justified > .active > a,
+.nav-tabs.nav-justified > .active > a:hover,
+.nav-tabs.nav-justified > .active > a:focus {
+ border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs.nav-justified > li > a {
+ border-bottom: 1px solid #dddddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs.nav-justified > .active > a,
+ .nav-tabs.nav-justified > .active > a:hover,
+ .nav-tabs.nav-justified > .active > a:focus {
+ border-bottom-color: #fcfcfc;
+ }
+}
+.nav-pills > li {
+ float: left;
+}
+.nav-pills > li > a {
+ border-radius: 4px;
+}
+.nav-pills > li + li {
+ margin-left: 2px;
+}
+.nav-pills > li.active > a,
+.nav-pills > li.active > a:hover,
+.nav-pills > li.active > a:focus {
+ color: #ffffff;
+ background-color: #d9230f;
+}
+.nav-stacked > li {
+ float: none;
+}
+.nav-stacked > li + li {
+ margin-top: 2px;
+ margin-left: 0;
+}
+.nav-justified {
+ width: 100%;
+}
+.nav-justified > li {
+ float: none;
+}
+.nav-justified > li > a {
+ text-align: center;
+ margin-bottom: 5px;
+}
+.nav-justified > .dropdown .dropdown-menu {
+ top: auto;
+ left: auto;
+}
+@media (min-width: 768px) {
+ .nav-justified > li {
+ display: table-cell;
+ width: 1%;
+ }
+ .nav-justified > li > a {
+ margin-bottom: 0;
+ }
+}
+.nav-tabs-justified {
+ border-bottom: 0;
+}
+.nav-tabs-justified > li > a {
+ margin-right: 0;
+ border-radius: 4px;
+}
+.nav-tabs-justified > .active > a,
+.nav-tabs-justified > .active > a:hover,
+.nav-tabs-justified > .active > a:focus {
+ border: 1px solid #dddddd;
+}
+@media (min-width: 768px) {
+ .nav-tabs-justified > li > a {
+ border-bottom: 1px solid #dddddd;
+ border-radius: 4px 4px 0 0;
+ }
+ .nav-tabs-justified > .active > a,
+ .nav-tabs-justified > .active > a:hover,
+ .nav-tabs-justified > .active > a:focus {
+ border-bottom-color: #fcfcfc;
+ }
+}
+.tab-content > .tab-pane {
+ display: none;
+}
+.tab-content > .active {
+ display: block;
+}
+.nav-tabs .dropdown-menu {
+ margin-top: -1px;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.navbar {
+ position: relative;
+ min-height: 40px;
+ margin-bottom: 18px;
+ border: 1px solid transparent;
+}
+@media (min-width: 768px) {
+ .navbar {
+ border-radius: 4px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-header {
+ float: left;
+ }
+}
+.navbar-collapse {
+ overflow-x: visible;
+ padding-right: 15px;
+ padding-left: 15px;
+ border-top: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1);
+ -webkit-overflow-scrolling: touch;
+}
+.navbar-collapse.in {
+ overflow-y: auto;
+}
+@media (min-width: 768px) {
+ .navbar-collapse {
+ width: auto;
+ border-top: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+ .navbar-collapse.collapse {
+ display: block !important;
+ height: auto !important;
+ padding-bottom: 0;
+ overflow: visible !important;
+ }
+ .navbar-collapse.in {
+ overflow-y: visible;
+ }
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-static-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ padding-left: 0;
+ padding-right: 0;
+ }
+}
+.navbar-fixed-top .navbar-collapse,
+.navbar-fixed-bottom .navbar-collapse {
+ max-height: 340px;
+}
+@media (max-device-width: 480px) and (orientation: landscape) {
+ .navbar-fixed-top .navbar-collapse,
+ .navbar-fixed-bottom .navbar-collapse {
+ max-height: 200px;
+ }
+}
+.container > .navbar-header,
+.container-fluid > .navbar-header,
+.container > .navbar-collapse,
+.container-fluid > .navbar-collapse {
+ margin-right: -15px;
+ margin-left: -15px;
+}
+@media (min-width: 768px) {
+ .container > .navbar-header,
+ .container-fluid > .navbar-header,
+ .container > .navbar-collapse,
+ .container-fluid > .navbar-collapse {
+ margin-right: 0;
+ margin-left: 0;
+ }
+}
+.navbar-static-top {
+ z-index: 1000;
+ border-width: 0 0 1px;
+}
+@media (min-width: 768px) {
+ .navbar-static-top {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top,
+.navbar-fixed-bottom {
+ position: fixed;
+ right: 0;
+ left: 0;
+ z-index: 1030;
+}
+@media (min-width: 768px) {
+ .navbar-fixed-top,
+ .navbar-fixed-bottom {
+ border-radius: 0;
+ }
+}
+.navbar-fixed-top {
+ top: 0;
+ border-width: 0 0 1px;
+}
+.navbar-fixed-bottom {
+ bottom: 0;
+ margin-bottom: 0;
+ border-width: 1px 0 0;
+}
+.navbar-brand {
+ float: left;
+ padding: 11px 15px;
+ font-size: 17px;
+ line-height: 18px;
+ height: 40px;
+}
+.navbar-brand:hover,
+.navbar-brand:focus {
+ text-decoration: none;
+}
+.navbar-brand > img {
+ display: block;
+}
+@media (min-width: 768px) {
+ .navbar > .container .navbar-brand,
+ .navbar > .container-fluid .navbar-brand {
+ margin-left: -15px;
+ }
+}
+.navbar-toggle {
+ position: relative;
+ float: right;
+ margin-right: 15px;
+ padding: 9px 10px;
+ margin-top: 3px;
+ margin-bottom: 3px;
+ background-color: transparent;
+ background-image: none;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.navbar-toggle:focus {
+ outline: 0;
+}
+.navbar-toggle .icon-bar {
+ display: block;
+ width: 22px;
+ height: 2px;
+ border-radius: 1px;
+}
+.navbar-toggle .icon-bar + .icon-bar {
+ margin-top: 4px;
+}
+@media (min-width: 768px) {
+ .navbar-toggle {
+ display: none;
+ }
+}
+.navbar-nav {
+ margin: 5.5px -15px;
+}
+.navbar-nav > li > a {
+ padding-top: 10px;
+ padding-bottom: 10px;
+ line-height: 18px;
+}
+@media (max-width: 767px) {
+ .navbar-nav .open .dropdown-menu {
+ position: static;
+ float: none;
+ width: auto;
+ margin-top: 0;
+ background-color: transparent;
+ border: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+ .navbar-nav .open .dropdown-menu > li > a,
+ .navbar-nav .open .dropdown-menu .dropdown-header {
+ padding: 5px 15px 5px 25px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a {
+ line-height: 18px;
+ }
+ .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-nav .open .dropdown-menu > li > a:focus {
+ background-image: none;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-nav {
+ float: left;
+ margin: 0;
+ }
+ .navbar-nav > li {
+ float: left;
+ }
+ .navbar-nav > li > a {
+ padding-top: 11px;
+ padding-bottom: 11px;
+ }
+}
+.navbar-form {
+ margin-left: -15px;
+ margin-right: -15px;
+ padding: 10px 15px;
+ border-top: 1px solid transparent;
+ border-bottom: 1px solid transparent;
+ -webkit-box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ box-shadow: inset 0 1px 0 rgba(255, 255, 255, 0.1), 0 1px 0 rgba(255, 255, 255, 0.1);
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+@media (min-width: 768px) {
+ .navbar-form .form-group {
+ display: inline-block;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control {
+ display: inline-block;
+ width: auto;
+ vertical-align: middle;
+ }
+ .navbar-form .form-control-static {
+ display: inline-block;
+ }
+ .navbar-form .input-group {
+ display: inline-table;
+ vertical-align: middle;
+ }
+ .navbar-form .input-group .input-group-addon,
+ .navbar-form .input-group .input-group-btn,
+ .navbar-form .input-group .form-control {
+ width: auto;
+ }
+ .navbar-form .input-group > .form-control {
+ width: 100%;
+ }
+ .navbar-form .control-label {
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio,
+ .navbar-form .checkbox {
+ display: inline-block;
+ margin-top: 0;
+ margin-bottom: 0;
+ vertical-align: middle;
+ }
+ .navbar-form .radio label,
+ .navbar-form .checkbox label {
+ padding-left: 0;
+ }
+ .navbar-form .radio input[type="radio"],
+ .navbar-form .checkbox input[type="checkbox"] {
+ position: relative;
+ margin-left: 0;
+ }
+ .navbar-form .has-feedback .form-control-feedback {
+ top: 0;
+ }
+}
+@media (max-width: 767px) {
+ .navbar-form .form-group {
+ margin-bottom: 5px;
+ }
+ .navbar-form .form-group:last-child {
+ margin-bottom: 0;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-form {
+ width: auto;
+ border: 0;
+ margin-left: 0;
+ margin-right: 0;
+ padding-top: 0;
+ padding-bottom: 0;
+ -webkit-box-shadow: none;
+ box-shadow: none;
+ }
+}
+.navbar-nav > li > .dropdown-menu {
+ margin-top: 0;
+ border-top-right-radius: 0;
+ border-top-left-radius: 0;
+}
+.navbar-fixed-bottom .navbar-nav > li > .dropdown-menu {
+ margin-bottom: 0;
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+ border-bottom-right-radius: 0;
+ border-bottom-left-radius: 0;
+}
+.navbar-btn {
+ margin-top: 2px;
+ margin-bottom: 2px;
+}
+.navbar-btn.btn-sm {
+ margin-top: 5px;
+ margin-bottom: 5px;
+}
+.navbar-btn.btn-xs {
+ margin-top: 9px;
+ margin-bottom: 9px;
+}
+.navbar-text {
+ margin-top: 11px;
+ margin-bottom: 11px;
+}
+@media (min-width: 768px) {
+ .navbar-text {
+ float: left;
+ margin-left: 15px;
+ margin-right: 15px;
+ }
+}
+@media (min-width: 768px) {
+ .navbar-left {
+ float: left !important;
+ }
+ .navbar-right {
+ float: right !important;
+ margin-right: -15px;
+ }
+ .navbar-right ~ .navbar-right {
+ margin-right: 0;
+ }
+}
+.navbar-default {
+ background-color: #ffffff;
+ border-color: #eeeeee;
+}
+.navbar-default .navbar-brand {
+ color: #777777;
+}
+.navbar-default .navbar-brand:hover,
+.navbar-default .navbar-brand:focus {
+ color: #d9230f;
+ background-color: transparent;
+}
+.navbar-default .navbar-text {
+ color: #777777;
+}
+.navbar-default .navbar-nav > li > a {
+ color: #777777;
+}
+.navbar-default .navbar-nav > li > a:hover,
+.navbar-default .navbar-nav > li > a:focus {
+ color: #d9230f;
+ background-color: transparent;
+}
+.navbar-default .navbar-nav > .active > a,
+.navbar-default .navbar-nav > .active > a:hover,
+.navbar-default .navbar-nav > .active > a:focus {
+ color: #d9230f;
+ background-color: transparent;
+}
+.navbar-default .navbar-nav > .disabled > a,
+.navbar-default .navbar-nav > .disabled > a:hover,
+.navbar-default .navbar-nav > .disabled > a:focus {
+ color: #444444;
+ background-color: transparent;
+}
+.navbar-default .navbar-toggle {
+ border-color: #dddddd;
+}
+.navbar-default .navbar-toggle:hover,
+.navbar-default .navbar-toggle:focus {
+ background-color: #dddddd;
+}
+.navbar-default .navbar-toggle .icon-bar {
+ background-color: #cccccc;
+}
+.navbar-default .navbar-collapse,
+.navbar-default .navbar-form {
+ border-color: #eeeeee;
+}
+.navbar-default .navbar-nav > .open > a,
+.navbar-default .navbar-nav > .open > a:hover,
+.navbar-default .navbar-nav > .open > a:focus {
+ background-color: transparent;
+ color: #d9230f;
+}
+@media (max-width: 767px) {
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a {
+ color: #777777;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #d9230f;
+ background-color: transparent;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #d9230f;
+ background-color: transparent;
+ }
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-default .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #444444;
+ background-color: transparent;
+ }
+}
+.navbar-default .navbar-link {
+ color: #777777;
+}
+.navbar-default .navbar-link:hover {
+ color: #d9230f;
+}
+.navbar-default .btn-link {
+ color: #777777;
+}
+.navbar-default .btn-link:hover,
+.navbar-default .btn-link:focus {
+ color: #d9230f;
+}
+.navbar-default .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-default .btn-link:hover,
+.navbar-default .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-default .btn-link:focus {
+ color: #444444;
+}
+.navbar-inverse {
+ background-color: #d9230f;
+ border-color: #a91b0c;
+}
+.navbar-inverse .navbar-brand {
+ color: #fac0ba;
+}
+.navbar-inverse .navbar-brand:hover,
+.navbar-inverse .navbar-brand:focus {
+ color: #ffffff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-text {
+ color: #fac0ba;
+}
+.navbar-inverse .navbar-nav > li > a {
+ color: #fac0ba;
+}
+.navbar-inverse .navbar-nav > li > a:hover,
+.navbar-inverse .navbar-nav > li > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .active > a,
+.navbar-inverse .navbar-nav > .active > a:hover,
+.navbar-inverse .navbar-nav > .active > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-nav > .disabled > a,
+.navbar-inverse .navbar-nav > .disabled > a:hover,
+.navbar-inverse .navbar-nav > .disabled > a:focus {
+ color: #cccccc;
+ background-color: transparent;
+}
+.navbar-inverse .navbar-toggle {
+ border-color: #a91b0c;
+}
+.navbar-inverse .navbar-toggle:hover,
+.navbar-inverse .navbar-toggle:focus {
+ background-color: #a91b0c;
+}
+.navbar-inverse .navbar-toggle .icon-bar {
+ background-color: #ffffff;
+}
+.navbar-inverse .navbar-collapse,
+.navbar-inverse .navbar-form {
+ border-color: #b81e0d;
+}
+.navbar-inverse .navbar-nav > .open > a,
+.navbar-inverse .navbar-nav > .open > a:hover,
+.navbar-inverse .navbar-nav > .open > a:focus {
+ background-color: transparent;
+ color: #ffffff;
+}
+@media (max-width: 767px) {
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .dropdown-header {
+ border-color: #a91b0c;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu .divider {
+ background-color: #a91b0c;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a {
+ color: #fac0ba;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > li > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .active > a:focus {
+ color: #ffffff;
+ background-color: transparent;
+ }
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:hover,
+ .navbar-inverse .navbar-nav .open .dropdown-menu > .disabled > a:focus {
+ color: #cccccc;
+ background-color: transparent;
+ }
+}
+.navbar-inverse .navbar-link {
+ color: #fac0ba;
+}
+.navbar-inverse .navbar-link:hover {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link {
+ color: #fac0ba;
+}
+.navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link:focus {
+ color: #ffffff;
+}
+.navbar-inverse .btn-link[disabled]:hover,
+fieldset[disabled] .navbar-inverse .btn-link:hover,
+.navbar-inverse .btn-link[disabled]:focus,
+fieldset[disabled] .navbar-inverse .btn-link:focus {
+ color: #cccccc;
+}
+.breadcrumb {
+ padding: 8px 15px;
+ margin-bottom: 18px;
+ list-style: none;
+ background-color: transparent;
+ border-radius: 4px;
+}
+.breadcrumb > li {
+ display: inline-block;
+}
+.breadcrumb > li + li:before {
+ content: "/\00a0";
+ padding: 0 5px;
+ color: #cccccc;
+}
+.breadcrumb > .active {
+ color: #808080;
+}
+.pagination {
+ display: inline-block;
+ padding-left: 0;
+ margin: 18px 0;
+ border-radius: 4px;
+}
+.pagination > li {
+ display: inline;
+}
+.pagination > li > a,
+.pagination > li > span {
+ position: relative;
+ float: left;
+ padding: 8px 12px;
+ line-height: 1.42857143;
+ text-decoration: none;
+ color: #444444;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ margin-left: -1px;
+}
+.pagination > li:first-child > a,
+.pagination > li:first-child > span {
+ margin-left: 0;
+ border-bottom-left-radius: 4px;
+ border-top-left-radius: 4px;
+}
+.pagination > li:last-child > a,
+.pagination > li:last-child > span {
+ border-bottom-right-radius: 4px;
+ border-top-right-radius: 4px;
+}
+.pagination > li > a:hover,
+.pagination > li > span:hover,
+.pagination > li > a:focus,
+.pagination > li > span:focus {
+ color: #ffffff;
+ background-color: #d9230f;
+ border-color: #d9230f;
+}
+.pagination > .active > a,
+.pagination > .active > span,
+.pagination > .active > a:hover,
+.pagination > .active > span:hover,
+.pagination > .active > a:focus,
+.pagination > .active > span:focus {
+ z-index: 2;
+ color: #ffffff;
+ background-color: #d9230f;
+ border-color: #d9230f;
+ cursor: default;
+}
+.pagination > .disabled > span,
+.pagination > .disabled > span:hover,
+.pagination > .disabled > span:focus,
+.pagination > .disabled > a,
+.pagination > .disabled > a:hover,
+.pagination > .disabled > a:focus {
+ color: #dddddd;
+ background-color: #ffffff;
+ border-color: #dddddd;
+ cursor: not-allowed;
+}
+.pagination-lg > li > a,
+.pagination-lg > li > span {
+ padding: 14px 16px;
+ font-size: 17px;
+}
+.pagination-lg > li:first-child > a,
+.pagination-lg > li:first-child > span {
+ border-bottom-left-radius: 6px;
+ border-top-left-radius: 6px;
+}
+.pagination-lg > li:last-child > a,
+.pagination-lg > li:last-child > span {
+ border-bottom-right-radius: 6px;
+ border-top-right-radius: 6px;
+}
+.pagination-sm > li > a,
+.pagination-sm > li > span {
+ padding: 5px 10px;
+ font-size: 12px;
+}
+.pagination-sm > li:first-child > a,
+.pagination-sm > li:first-child > span {
+ border-bottom-left-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.pagination-sm > li:last-child > a,
+.pagination-sm > li:last-child > span {
+ border-bottom-right-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.pager {
+ padding-left: 0;
+ margin: 18px 0;
+ list-style: none;
+ text-align: center;
+}
+.pager li {
+ display: inline;
+}
+.pager li > a,
+.pager li > span {
+ display: inline-block;
+ padding: 5px 14px;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+ border-radius: 15px;
+}
+.pager li > a:hover,
+.pager li > a:focus {
+ text-decoration: none;
+ background-color: #d9230f;
+}
+.pager .next > a,
+.pager .next > span {
+ float: right;
+}
+.pager .previous > a,
+.pager .previous > span {
+ float: left;
+}
+.pager .disabled > a,
+.pager .disabled > a:hover,
+.pager .disabled > a:focus,
+.pager .disabled > span {
+ color: #dddddd;
+ background-color: #ffffff;
+ cursor: not-allowed;
+}
+.label {
+ display: inline;
+ padding: .2em .6em .3em;
+ font-size: 75%;
+ font-weight: bold;
+ line-height: 1;
+ color: #ffffff;
+ text-align: center;
+ white-space: nowrap;
+ vertical-align: baseline;
+ border-radius: .25em;
+}
+a.label:hover,
+a.label:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.label:empty {
+ display: none;
+}
+.btn .label {
+ position: relative;
+ top: -1px;
+}
+.label-default {
+ background-color: #474949;
+}
+.label-default[href]:hover,
+.label-default[href]:focus {
+ background-color: #2e2f2f;
+}
+.label-primary {
+ background-color: #d9230f;
+}
+.label-primary[href]:hover,
+.label-primary[href]:focus {
+ background-color: #a91b0c;
+}
+.label-success {
+ background-color: #469408;
+}
+.label-success[href]:hover,
+.label-success[href]:focus {
+ background-color: #2f6405;
+}
+.label-info {
+ background-color: #029acf;
+}
+.label-info[href]:hover,
+.label-info[href]:focus {
+ background-color: #02749c;
+}
+.label-warning {
+ background-color: #9b479f;
+}
+.label-warning[href]:hover,
+.label-warning[href]:focus {
+ background-color: #79377c;
+}
+.label-danger {
+ background-color: #d9831f;
+}
+.label-danger[href]:hover,
+.label-danger[href]:focus {
+ background-color: #ac6819;
+}
+.badge {
+ display: inline-block;
+ min-width: 10px;
+ padding: 3px 7px;
+ font-size: 12px;
+ font-weight: bold;
+ color: #ffffff;
+ line-height: 1;
+ vertical-align: baseline;
+ white-space: nowrap;
+ text-align: center;
+ background-color: #d9230f;
+ border-radius: 10px;
+}
+.badge:empty {
+ display: none;
+}
+.btn .badge {
+ position: relative;
+ top: -1px;
+}
+.btn-xs .badge,
+.btn-group-xs > .btn .badge {
+ top: 0;
+ padding: 1px 5px;
+}
+a.badge:hover,
+a.badge:focus {
+ color: #ffffff;
+ text-decoration: none;
+ cursor: pointer;
+}
+.list-group-item.active > .badge,
+.nav-pills > .active > a > .badge {
+ color: #d9230f;
+ background-color: #ffffff;
+}
+.list-group-item > .badge {
+ float: right;
+}
+.list-group-item > .badge + .badge {
+ margin-right: 5px;
+}
+.nav-pills > li > a > .badge {
+ margin-left: 3px;
+}
+.jumbotron {
+ padding: 30px 15px;
+ margin-bottom: 30px;
+ color: inherit;
+ background-color: #f4f4f4;
+}
+.jumbotron h1,
+.jumbotron .h1 {
+ color: inherit;
+}
+.jumbotron p {
+ margin-bottom: 15px;
+ font-size: 20px;
+ font-weight: 200;
+}
+.jumbotron > hr {
+ border-top-color: #dbdbdb;
+}
+.container .jumbotron,
+.container-fluid .jumbotron {
+ border-radius: 6px;
+}
+.jumbotron .container {
+ max-width: 100%;
+}
+@media screen and (min-width: 768px) {
+ .jumbotron {
+ padding: 48px 0;
+ }
+ .container .jumbotron,
+ .container-fluid .jumbotron {
+ padding-left: 60px;
+ padding-right: 60px;
+ }
+ .jumbotron h1,
+ .jumbotron .h1 {
+ font-size: 58.5px;
+ }
+}
+.thumbnail {
+ display: block;
+ padding: 4px;
+ margin-bottom: 18px;
+ line-height: 1.42857143;
+ background-color: #fcfcfc;
+ border: 1px solid #dddddd;
+ border-radius: 4px;
+ -webkit-transition: border 0.2s ease-in-out;
+ -o-transition: border 0.2s ease-in-out;
+ transition: border 0.2s ease-in-out;
+}
+.thumbnail > img,
+.thumbnail a > img {
+ margin-left: auto;
+ margin-right: auto;
+}
+a.thumbnail:hover,
+a.thumbnail:focus,
+a.thumbnail.active {
+ border-color: #d9230f;
+}
+.thumbnail .caption {
+ padding: 9px;
+ color: #777777;
+}
+.alert {
+ padding: 15px;
+ margin-bottom: 18px;
+ border: 1px solid transparent;
+ border-radius: 4px;
+}
+.alert h4 {
+ margin-top: 0;
+ color: inherit;
+}
+.alert .alert-link {
+ font-weight: bold;
+}
+.alert > p,
+.alert > ul {
+ margin-bottom: 0;
+}
+.alert > p + p {
+ margin-top: 5px;
+}
+.alert-dismissable,
+.alert-dismissible {
+ padding-right: 35px;
+}
+.alert-dismissable .close,
+.alert-dismissible .close {
+ position: relative;
+ top: -2px;
+ right: -21px;
+ color: inherit;
+}
+.alert-success {
+ background-color: #dff0d8;
+ border-color: #d6e9c6;
+ color: #468847;
+}
+.alert-success hr {
+ border-top-color: #c9e2b3;
+}
+.alert-success .alert-link {
+ color: #356635;
+}
+.alert-info {
+ background-color: #d9edf7;
+ border-color: #bce8f1;
+ color: #3a87ad;
+}
+.alert-info hr {
+ border-top-color: #a6e1ec;
+}
+.alert-info .alert-link {
+ color: #2d6987;
+}
+.alert-warning {
+ background-color: #fcf8e3;
+ border-color: #fbeed5;
+ color: #c09853;
+}
+.alert-warning hr {
+ border-top-color: #f8e5be;
+}
+.alert-warning .alert-link {
+ color: #a47e3c;
+}
+.alert-danger {
+ background-color: #f2dede;
+ border-color: #eed3d7;
+ color: #b94a48;
+}
+.alert-danger hr {
+ border-top-color: #e6c1c7;
+}
+.alert-danger .alert-link {
+ color: #953b39;
+}
+@-webkit-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@-o-keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+@keyframes progress-bar-stripes {
+ from {
+ background-position: 40px 0;
+ }
+ to {
+ background-position: 0 0;
+ }
+}
+.progress {
+ overflow: hidden;
+ height: 18px;
+ margin-bottom: 18px;
+ background-color: #f5f5f5;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+ box-shadow: inset 0 1px 2px rgba(0, 0, 0, 0.1);
+}
+.progress-bar {
+ float: left;
+ width: 0%;
+ height: 100%;
+ font-size: 12px;
+ line-height: 18px;
+ color: #ffffff;
+ text-align: center;
+ background-color: #d9230f;
+ -webkit-box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ box-shadow: inset 0 -1px 0 rgba(0, 0, 0, 0.15);
+ -webkit-transition: width 0.6s ease;
+ -o-transition: width 0.6s ease;
+ transition: width 0.6s ease;
+}
+.progress-striped .progress-bar,
+.progress-bar-striped {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ -webkit-background-size: 40px 40px;
+ background-size: 40px 40px;
+}
+.progress.active .progress-bar,
+.progress-bar.active {
+ -webkit-animation: progress-bar-stripes 2s linear infinite;
+ -o-animation: progress-bar-stripes 2s linear infinite;
+ animation: progress-bar-stripes 2s linear infinite;
+}
+.progress-bar-success {
+ background-color: #469408;
+}
+.progress-striped .progress-bar-success {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.progress-bar-info {
+ background-color: #029acf;
+}
+.progress-striped .progress-bar-info {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.progress-bar-warning {
+ background-color: #9b479f;
+}
+.progress-striped .progress-bar-warning {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.progress-bar-danger {
+ background-color: #d9831f;
+}
+.progress-striped .progress-bar-danger {
+ background-image: -webkit-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: -o-linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+ background-image: linear-gradient(45deg, rgba(255, 255, 255, 0.15) 25%, transparent 25%, transparent 50%, rgba(255, 255, 255, 0.15) 50%, rgba(255, 255, 255, 0.15) 75%, transparent 75%, transparent);
+}
+.media {
+ margin-top: 15px;
+}
+.media:first-child {
+ margin-top: 0;
+}
+.media,
+.media-body {
+ zoom: 1;
+ overflow: hidden;
+}
+.media-body {
+ width: 10000px;
+}
+.media-object {
+ display: block;
+}
+.media-right,
+.media > .pull-right {
+ padding-left: 10px;
+}
+.media-left,
+.media > .pull-left {
+ padding-right: 10px;
+}
+.media-left,
+.media-right,
+.media-body {
+ display: table-cell;
+ vertical-align: top;
+}
+.media-middle {
+ vertical-align: middle;
+}
+.media-bottom {
+ vertical-align: bottom;
+}
+.media-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.media-list {
+ padding-left: 0;
+ list-style: none;
+}
+.list-group {
+ margin-bottom: 20px;
+ padding-left: 0;
+}
+.list-group-item {
+ position: relative;
+ display: block;
+ padding: 10px 15px;
+ margin-bottom: -1px;
+ background-color: #ffffff;
+ border: 1px solid #dddddd;
+}
+.list-group-item:first-child {
+ border-top-right-radius: 4px;
+ border-top-left-radius: 4px;
+}
+.list-group-item:last-child {
+ margin-bottom: 0;
+ border-bottom-right-radius: 4px;
+ border-bottom-left-radius: 4px;
+}
+a.list-group-item {
+ color: #555555;
+}
+a.list-group-item .list-group-item-heading {
+ color: #333333;
+}
+a.list-group-item:hover,
+a.list-group-item:focus {
+ text-decoration: none;
+ color: #555555;
+ background-color: #f5f5f5;
+}
+.list-group-item.disabled,
+.list-group-item.disabled:hover,
+.list-group-item.disabled:focus {
+ background-color: #dddddd;
+ color: #808080;
+ cursor: not-allowed;
+}
+.list-group-item.disabled .list-group-item-heading,
+.list-group-item.disabled:hover .list-group-item-heading,
+.list-group-item.disabled:focus .list-group-item-heading {
+ color: inherit;
+}
+.list-group-item.disabled .list-group-item-text,
+.list-group-item.disabled:hover .list-group-item-text,
+.list-group-item.disabled:focus .list-group-item-text {
+ color: #808080;
+}
+.list-group-item.active,
+.list-group-item.active:hover,
+.list-group-item.active:focus {
+ z-index: 2;
+ color: #ffffff;
+ background-color: #d9230f;
+ border-color: #d9230f;
+}
+.list-group-item.active .list-group-item-heading,
+.list-group-item.active:hover .list-group-item-heading,
+.list-group-item.active:focus .list-group-item-heading,
+.list-group-item.active .list-group-item-heading > small,
+.list-group-item.active:hover .list-group-item-heading > small,
+.list-group-item.active:focus .list-group-item-heading > small,
+.list-group-item.active .list-group-item-heading > .small,
+.list-group-item.active:hover .list-group-item-heading > .small,
+.list-group-item.active:focus .list-group-item-heading > .small {
+ color: inherit;
+}
+.list-group-item.active .list-group-item-text,
+.list-group-item.active:hover .list-group-item-text,
+.list-group-item.active:focus .list-group-item-text {
+ color: #fac0ba;
+}
+.list-group-item-success {
+ color: #468847;
+ background-color: #dff0d8;
+}
+a.list-group-item-success {
+ color: #468847;
+}
+a.list-group-item-success .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-success:hover,
+a.list-group-item-success:focus {
+ color: #468847;
+ background-color: #d0e9c6;
+}
+a.list-group-item-success.active,
+a.list-group-item-success.active:hover,
+a.list-group-item-success.active:focus {
+ color: #fff;
+ background-color: #468847;
+ border-color: #468847;
+}
+.list-group-item-info {
+ color: #3a87ad;
+ background-color: #d9edf7;
+}
+a.list-group-item-info {
+ color: #3a87ad;
+}
+a.list-group-item-info .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-info:hover,
+a.list-group-item-info:focus {
+ color: #3a87ad;
+ background-color: #c4e3f3;
+}
+a.list-group-item-info.active,
+a.list-group-item-info.active:hover,
+a.list-group-item-info.active:focus {
+ color: #fff;
+ background-color: #3a87ad;
+ border-color: #3a87ad;
+}
+.list-group-item-warning {
+ color: #c09853;
+ background-color: #fcf8e3;
+}
+a.list-group-item-warning {
+ color: #c09853;
+}
+a.list-group-item-warning .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-warning:hover,
+a.list-group-item-warning:focus {
+ color: #c09853;
+ background-color: #faf2cc;
+}
+a.list-group-item-warning.active,
+a.list-group-item-warning.active:hover,
+a.list-group-item-warning.active:focus {
+ color: #fff;
+ background-color: #c09853;
+ border-color: #c09853;
+}
+.list-group-item-danger {
+ color: #b94a48;
+ background-color: #f2dede;
+}
+a.list-group-item-danger {
+ color: #b94a48;
+}
+a.list-group-item-danger .list-group-item-heading {
+ color: inherit;
+}
+a.list-group-item-danger:hover,
+a.list-group-item-danger:focus {
+ color: #b94a48;
+ background-color: #ebcccc;
+}
+a.list-group-item-danger.active,
+a.list-group-item-danger.active:hover,
+a.list-group-item-danger.active:focus {
+ color: #fff;
+ background-color: #b94a48;
+ border-color: #b94a48;
+}
+.list-group-item-heading {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+.list-group-item-text {
+ margin-bottom: 0;
+ line-height: 1.3;
+}
+.panel {
+ margin-bottom: 18px;
+ background-color: #ffffff;
+ border: 1px solid transparent;
+ border-radius: 4px;
+ -webkit-box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+ box-shadow: 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+.panel-body {
+ padding: 15px;
+}
+.panel-heading {
+ padding: 10px 15px;
+ border-bottom: 1px solid transparent;
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.panel-heading > .dropdown .dropdown-toggle {
+ color: inherit;
+}
+.panel-title {
+ margin-top: 0;
+ margin-bottom: 0;
+ font-size: 15px;
+ color: inherit;
+}
+.panel-title > a,
+.panel-title > small,
+.panel-title > .small,
+.panel-title > small > a,
+.panel-title > .small > a {
+ color: inherit;
+}
+.panel-footer {
+ padding: 10px 15px;
+ background-color: #fcfcfc;
+ border-top: 1px solid #dddddd;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .list-group,
+.panel > .panel-collapse > .list-group {
+ margin-bottom: 0;
+}
+.panel > .list-group .list-group-item,
+.panel > .panel-collapse > .list-group .list-group-item {
+ border-width: 1px 0;
+ border-radius: 0;
+}
+.panel > .list-group:first-child .list-group-item:first-child,
+.panel > .panel-collapse > .list-group:first-child .list-group-item:first-child {
+ border-top: 0;
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.panel > .list-group:last-child .list-group-item:last-child,
+.panel > .panel-collapse > .list-group:last-child .list-group-item:last-child {
+ border-bottom: 0;
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel-heading + .list-group .list-group-item:first-child {
+ border-top-width: 0;
+}
+.list-group + .panel-footer {
+ border-top-width: 0;
+}
+.panel > .table,
+.panel > .table-responsive > .table,
+.panel > .panel-collapse > .table {
+ margin-bottom: 0;
+}
+.panel > .table caption,
+.panel > .table-responsive > .table caption,
+.panel > .panel-collapse > .table caption {
+ padding-left: 15px;
+ padding-right: 15px;
+}
+.panel > .table:first-child,
+.panel > .table-responsive:first-child > .table:first-child {
+ border-top-right-radius: 3px;
+ border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child {
+ border-top-left-radius: 3px;
+ border-top-right-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:first-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:first-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:first-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:first-child {
+ border-top-left-radius: 3px;
+}
+.panel > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child td:last-child,
+.panel > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > thead:first-child > tr:first-child th:last-child,
+.panel > .table:first-child > tbody:first-child > tr:first-child th:last-child,
+.panel > .table-responsive:first-child > .table:first-child > tbody:first-child > tr:first-child th:last-child {
+ border-top-right-radius: 3px;
+}
+.panel > .table:last-child,
+.panel > .table-responsive:last-child > .table:last-child {
+ border-bottom-right-radius: 3px;
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child {
+ border-bottom-left-radius: 3px;
+ border-bottom-right-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:first-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:first-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:first-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:first-child {
+ border-bottom-left-radius: 3px;
+}
+.panel > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child td:last-child,
+.panel > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tbody:last-child > tr:last-child th:last-child,
+.panel > .table:last-child > tfoot:last-child > tr:last-child th:last-child,
+.panel > .table-responsive:last-child > .table:last-child > tfoot:last-child > tr:last-child th:last-child {
+ border-bottom-right-radius: 3px;
+}
+.panel > .panel-body + .table,
+.panel > .panel-body + .table-responsive,
+.panel > .table + .panel-body,
+.panel > .table-responsive + .panel-body {
+ border-top: 1px solid #dddddd;
+}
+.panel > .table > tbody:first-child > tr:first-child th,
+.panel > .table > tbody:first-child > tr:first-child td {
+ border-top: 0;
+}
+.panel > .table-bordered,
+.panel > .table-responsive > .table-bordered {
+ border: 0;
+}
+.panel > .table-bordered > thead > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:first-child,
+.panel > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:first-child,
+.panel > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:first-child,
+.panel > .table-bordered > thead > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:first-child,
+.panel > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:first-child,
+.panel > .table-bordered > tfoot > tr > td:first-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:first-child {
+ border-left: 0;
+}
+.panel > .table-bordered > thead > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > th:last-child,
+.panel > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > th:last-child,
+.panel > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > th:last-child,
+.panel > .table-bordered > thead > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > thead > tr > td:last-child,
+.panel > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tbody > tr > td:last-child,
+.panel > .table-bordered > tfoot > tr > td:last-child,
+.panel > .table-responsive > .table-bordered > tfoot > tr > td:last-child {
+ border-right: 0;
+}
+.panel > .table-bordered > thead > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > td,
+.panel > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > td,
+.panel > .table-bordered > thead > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > thead > tr:first-child > th,
+.panel > .table-bordered > tbody > tr:first-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:first-child > th {
+ border-bottom: 0;
+}
+.panel > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > td,
+.panel > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > td,
+.panel > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tbody > tr:last-child > th,
+.panel > .table-bordered > tfoot > tr:last-child > th,
+.panel > .table-responsive > .table-bordered > tfoot > tr:last-child > th {
+ border-bottom: 0;
+}
+.panel > .table-responsive {
+ border: 0;
+ margin-bottom: 0;
+}
+.panel-group {
+ margin-bottom: 18px;
+}
+.panel-group .panel {
+ margin-bottom: 0;
+ border-radius: 4px;
+}
+.panel-group .panel + .panel {
+ margin-top: 5px;
+}
+.panel-group .panel-heading {
+ border-bottom: 0;
+}
+.panel-group .panel-heading + .panel-collapse > .panel-body,
+.panel-group .panel-heading + .panel-collapse > .list-group {
+ border-top: 1px solid #dddddd;
+}
+.panel-group .panel-footer {
+ border-top: 0;
+}
+.panel-group .panel-footer + .panel-collapse .panel-body {
+ border-bottom: 1px solid #dddddd;
+}
+.panel-default {
+ border-color: #dddddd;
+}
+.panel-default > .panel-heading {
+ color: #444444;
+ background-color: #fcfcfc;
+ border-color: #dddddd;
+}
+.panel-default > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #dddddd;
+}
+.panel-default > .panel-heading .badge {
+ color: #fcfcfc;
+ background-color: #444444;
+}
+.panel-default > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #dddddd;
+}
+.panel-primary {
+ border-color: #d9230f;
+}
+.panel-primary > .panel-heading {
+ color: #ffffff;
+ background-color: #d9230f;
+ border-color: #d9230f;
+}
+.panel-primary > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #d9230f;
+}
+.panel-primary > .panel-heading .badge {
+ color: #d9230f;
+ background-color: #ffffff;
+}
+.panel-primary > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #d9230f;
+}
+.panel-success {
+ border-color: #469408;
+}
+.panel-success > .panel-heading {
+ color: #ffffff;
+ background-color: #469408;
+ border-color: #469408;
+}
+.panel-success > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #469408;
+}
+.panel-success > .panel-heading .badge {
+ color: #469408;
+ background-color: #ffffff;
+}
+.panel-success > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #469408;
+}
+.panel-info {
+ border-color: #029acf;
+}
+.panel-info > .panel-heading {
+ color: #ffffff;
+ background-color: #029acf;
+ border-color: #029acf;
+}
+.panel-info > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #029acf;
+}
+.panel-info > .panel-heading .badge {
+ color: #029acf;
+ background-color: #ffffff;
+}
+.panel-info > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #029acf;
+}
+.panel-warning {
+ border-color: #9b479f;
+}
+.panel-warning > .panel-heading {
+ color: #ffffff;
+ background-color: #9b479f;
+ border-color: #9b479f;
+}
+.panel-warning > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #9b479f;
+}
+.panel-warning > .panel-heading .badge {
+ color: #9b479f;
+ background-color: #ffffff;
+}
+.panel-warning > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #9b479f;
+}
+.panel-danger {
+ border-color: #d9831f;
+}
+.panel-danger > .panel-heading {
+ color: #ffffff;
+ background-color: #d9831f;
+ border-color: #d9831f;
+}
+.panel-danger > .panel-heading + .panel-collapse > .panel-body {
+ border-top-color: #d9831f;
+}
+.panel-danger > .panel-heading .badge {
+ color: #d9831f;
+ background-color: #ffffff;
+}
+.panel-danger > .panel-footer + .panel-collapse > .panel-body {
+ border-bottom-color: #d9831f;
+}
+.embed-responsive {
+ position: relative;
+ display: block;
+ height: 0;
+ padding: 0;
+ overflow: hidden;
+}
+.embed-responsive .embed-responsive-item,
+.embed-responsive iframe,
+.embed-responsive embed,
+.embed-responsive object,
+.embed-responsive video {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ height: 100%;
+ width: 100%;
+ border: 0;
+}
+.embed-responsive-16by9 {
+ padding-bottom: 56.25%;
+}
+.embed-responsive-4by3 {
+ padding-bottom: 75%;
+}
+.well {
+ min-height: 20px;
+ padding: 19px;
+ margin-bottom: 20px;
+ background-color: #f4f4f4;
+ border: 1px solid #e3e3e3;
+ border-radius: 4px;
+ -webkit-box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+ box-shadow: inset 0 1px 1px rgba(0, 0, 0, 0.05);
+}
+.well blockquote {
+ border-color: #ddd;
+ border-color: rgba(0, 0, 0, 0.15);
+}
+.well-lg {
+ padding: 24px;
+ border-radius: 6px;
+}
+.well-sm {
+ padding: 9px;
+ border-radius: 3px;
+}
+.close {
+ float: right;
+ font-size: 19.5px;
+ font-weight: bold;
+ line-height: 1;
+ color: #000000;
+ text-shadow: 0 1px 0 #ffffff;
+ opacity: 0.2;
+ filter: alpha(opacity=20);
+}
+.close:hover,
+.close:focus {
+ color: #000000;
+ text-decoration: none;
+ cursor: pointer;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+button.close {
+ padding: 0;
+ cursor: pointer;
+ background: transparent;
+ border: 0;
+ -webkit-appearance: none;
+}
+.modal-open {
+ overflow: hidden;
+}
+.modal {
+ display: none;
+ overflow: hidden;
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1050;
+ -webkit-overflow-scrolling: touch;
+ outline: 0;
+}
+.modal.fade .modal-dialog {
+ -webkit-transform: translate(0, -25%);
+ -ms-transform: translate(0, -25%);
+ -o-transform: translate(0, -25%);
+ transform: translate(0, -25%);
+ -webkit-transition: -webkit-transform 0.3s ease-out;
+ -o-transition: -o-transform 0.3s ease-out;
+ transition: transform 0.3s ease-out;
+}
+.modal.in .modal-dialog {
+ -webkit-transform: translate(0, 0);
+ -ms-transform: translate(0, 0);
+ -o-transform: translate(0, 0);
+ transform: translate(0, 0);
+}
+.modal-open .modal {
+ overflow-x: hidden;
+ overflow-y: auto;
+}
+.modal-dialog {
+ position: relative;
+ width: auto;
+ margin: 10px;
+}
+.modal-content {
+ position: relative;
+ background-color: #ffffff;
+ border: 1px solid #999999;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 6px;
+ -webkit-box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 3px 9px rgba(0, 0, 0, 0.5);
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ outline: 0;
+}
+.modal-backdrop {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ z-index: 1040;
+ background-color: #000000;
+}
+.modal-backdrop.fade {
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.modal-backdrop.in {
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+}
+.modal-header {
+ padding: 15px;
+ border-bottom: 1px solid #e5e5e5;
+ min-height: 16.42857143px;
+}
+.modal-header .close {
+ margin-top: -2px;
+}
+.modal-title {
+ margin: 0;
+ line-height: 1.42857143;
+}
+.modal-body {
+ position: relative;
+ padding: 20px;
+}
+.modal-footer {
+ padding: 20px;
+ text-align: right;
+ border-top: 1px solid #e5e5e5;
+}
+.modal-footer .btn + .btn {
+ margin-left: 5px;
+ margin-bottom: 0;
+}
+.modal-footer .btn-group .btn + .btn {
+ margin-left: -1px;
+}
+.modal-footer .btn-block + .btn-block {
+ margin-left: 0;
+}
+.modal-scrollbar-measure {
+ position: absolute;
+ top: -9999px;
+ width: 50px;
+ height: 50px;
+ overflow: scroll;
+}
+@media (min-width: 768px) {
+ .modal-dialog {
+ width: 600px;
+ margin: 30px auto;
+ }
+ .modal-content {
+ -webkit-box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
+ box-shadow: 0 5px 15px rgba(0, 0, 0, 0.5);
+ }
+ .modal-sm {
+ width: 300px;
+ }
+}
+@media (min-width: 992px) {
+ .modal-lg {
+ width: 900px;
+ }
+}
+.tooltip {
+ position: absolute;
+ z-index: 1070;
+ display: block;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 12px;
+ font-weight: normal;
+ line-height: 1.4;
+ opacity: 0;
+ filter: alpha(opacity=0);
+}
+.tooltip.in {
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+.tooltip.top {
+ margin-top: -3px;
+ padding: 5px 0;
+}
+.tooltip.right {
+ margin-left: 3px;
+ padding: 0 5px;
+}
+.tooltip.bottom {
+ margin-top: 3px;
+ padding: 5px 0;
+}
+.tooltip.left {
+ margin-left: -3px;
+ padding: 0 5px;
+}
+.tooltip-inner {
+ max-width: 200px;
+ padding: 3px 8px;
+ color: #ffffff;
+ text-align: center;
+ text-decoration: none;
+ background-color: #000000;
+ border-radius: 4px;
+}
+.tooltip-arrow {
+ position: absolute;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.tooltip.top .tooltip-arrow {
+ bottom: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.top-left .tooltip-arrow {
+ bottom: 0;
+ right: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.top-right .tooltip-arrow {
+ bottom: 0;
+ left: 5px;
+ margin-bottom: -5px;
+ border-width: 5px 5px 0;
+ border-top-color: #000000;
+}
+.tooltip.right .tooltip-arrow {
+ top: 50%;
+ left: 0;
+ margin-top: -5px;
+ border-width: 5px 5px 5px 0;
+ border-right-color: #000000;
+}
+.tooltip.left .tooltip-arrow {
+ top: 50%;
+ right: 0;
+ margin-top: -5px;
+ border-width: 5px 0 5px 5px;
+ border-left-color: #000000;
+}
+.tooltip.bottom .tooltip-arrow {
+ top: 0;
+ left: 50%;
+ margin-left: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.tooltip.bottom-left .tooltip-arrow {
+ top: 0;
+ right: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.tooltip.bottom-right .tooltip-arrow {
+ top: 0;
+ left: 5px;
+ margin-top: -5px;
+ border-width: 0 5px 5px;
+ border-bottom-color: #000000;
+}
+.popover {
+ position: absolute;
+ top: 0;
+ left: 0;
+ z-index: 1060;
+ display: none;
+ max-width: 276px;
+ padding: 1px;
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+ font-size: 13px;
+ font-weight: normal;
+ line-height: 1.42857143;
+ text-align: left;
+ background-color: #ffffff;
+ -webkit-background-clip: padding-box;
+ background-clip: padding-box;
+ border: 1px solid #cccccc;
+ border: 1px solid rgba(0, 0, 0, 0.2);
+ border-radius: 6px;
+ -webkit-box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ box-shadow: 0 5px 10px rgba(0, 0, 0, 0.2);
+ white-space: normal;
+}
+.popover.top {
+ margin-top: -10px;
+}
+.popover.right {
+ margin-left: 10px;
+}
+.popover.bottom {
+ margin-top: 10px;
+}
+.popover.left {
+ margin-left: -10px;
+}
+.popover-title {
+ margin: 0;
+ padding: 8px 14px;
+ font-size: 13px;
+ background-color: #f7f7f7;
+ border-bottom: 1px solid #ebebeb;
+ border-radius: 5px 5px 0 0;
+}
+.popover-content {
+ padding: 9px 14px;
+}
+.popover > .arrow,
+.popover > .arrow:after {
+ position: absolute;
+ display: block;
+ width: 0;
+ height: 0;
+ border-color: transparent;
+ border-style: solid;
+}
+.popover > .arrow {
+ border-width: 11px;
+}
+.popover > .arrow:after {
+ border-width: 10px;
+ content: "";
+}
+.popover.top > .arrow {
+ left: 50%;
+ margin-left: -11px;
+ border-bottom-width: 0;
+ border-top-color: #999999;
+ border-top-color: rgba(0, 0, 0, 0.25);
+ bottom: -11px;
+}
+.popover.top > .arrow:after {
+ content: " ";
+ bottom: 1px;
+ margin-left: -10px;
+ border-bottom-width: 0;
+ border-top-color: #ffffff;
+}
+.popover.right > .arrow {
+ top: 50%;
+ left: -11px;
+ margin-top: -11px;
+ border-left-width: 0;
+ border-right-color: #999999;
+ border-right-color: rgba(0, 0, 0, 0.25);
+}
+.popover.right > .arrow:after {
+ content: " ";
+ left: 1px;
+ bottom: -10px;
+ border-left-width: 0;
+ border-right-color: #ffffff;
+}
+.popover.bottom > .arrow {
+ left: 50%;
+ margin-left: -11px;
+ border-top-width: 0;
+ border-bottom-color: #999999;
+ border-bottom-color: rgba(0, 0, 0, 0.25);
+ top: -11px;
+}
+.popover.bottom > .arrow:after {
+ content: " ";
+ top: 1px;
+ margin-left: -10px;
+ border-top-width: 0;
+ border-bottom-color: #ffffff;
+}
+.popover.left > .arrow {
+ top: 50%;
+ right: -11px;
+ margin-top: -11px;
+ border-right-width: 0;
+ border-left-color: #999999;
+ border-left-color: rgba(0, 0, 0, 0.25);
+}
+.popover.left > .arrow:after {
+ content: " ";
+ right: 1px;
+ border-right-width: 0;
+ border-left-color: #ffffff;
+ bottom: -10px;
+}
+.carousel {
+ position: relative;
+}
+.carousel-inner {
+ position: relative;
+ overflow: hidden;
+ width: 100%;
+}
+.carousel-inner > .item {
+ display: none;
+ position: relative;
+ -webkit-transition: 0.6s ease-in-out left;
+ -o-transition: 0.6s ease-in-out left;
+ transition: 0.6s ease-in-out left;
+}
+.carousel-inner > .item > img,
+.carousel-inner > .item > a > img {
+ line-height: 1;
+}
+@media all and (transform-3d), (-webkit-transform-3d) {
+ .carousel-inner > .item {
+ -webkit-transition: -webkit-transform 0.6s ease-in-out;
+ -o-transition: -o-transform 0.6s ease-in-out;
+ transition: transform 0.6s ease-in-out;
+ -webkit-backface-visibility: hidden;
+ backface-visibility: hidden;
+ -webkit-perspective: 1000;
+ perspective: 1000;
+ }
+ .carousel-inner > .item.next,
+ .carousel-inner > .item.active.right {
+ -webkit-transform: translate3d(100%, 0, 0);
+ transform: translate3d(100%, 0, 0);
+ left: 0;
+ }
+ .carousel-inner > .item.prev,
+ .carousel-inner > .item.active.left {
+ -webkit-transform: translate3d(-100%, 0, 0);
+ transform: translate3d(-100%, 0, 0);
+ left: 0;
+ }
+ .carousel-inner > .item.next.left,
+ .carousel-inner > .item.prev.right,
+ .carousel-inner > .item.active {
+ -webkit-transform: translate3d(0, 0, 0);
+ transform: translate3d(0, 0, 0);
+ left: 0;
+ }
+}
+.carousel-inner > .active,
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ display: block;
+}
+.carousel-inner > .active {
+ left: 0;
+}
+.carousel-inner > .next,
+.carousel-inner > .prev {
+ position: absolute;
+ top: 0;
+ width: 100%;
+}
+.carousel-inner > .next {
+ left: 100%;
+}
+.carousel-inner > .prev {
+ left: -100%;
+}
+.carousel-inner > .next.left,
+.carousel-inner > .prev.right {
+ left: 0;
+}
+.carousel-inner > .active.left {
+ left: -100%;
+}
+.carousel-inner > .active.right {
+ left: 100%;
+}
+.carousel-control {
+ position: absolute;
+ top: 0;
+ left: 0;
+ bottom: 0;
+ width: 15%;
+ opacity: 0.5;
+ filter: alpha(opacity=50);
+ font-size: 20px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+.carousel-control.left {
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.5)), to(rgba(0, 0, 0, 0.0001)));
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.5) 0%, rgba(0, 0, 0, 0.0001) 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#80000000', endColorstr='#00000000', GradientType=1);
+}
+.carousel-control.right {
+ left: auto;
+ right: 0;
+ background-image: -webkit-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-image: -o-linear-gradient(left, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-image: -webkit-gradient(linear, left top, right top, from(rgba(0, 0, 0, 0.0001)), to(rgba(0, 0, 0, 0.5)));
+ background-image: linear-gradient(to right, rgba(0, 0, 0, 0.0001) 0%, rgba(0, 0, 0, 0.5) 100%);
+ background-repeat: repeat-x;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#00000000', endColorstr='#80000000', GradientType=1);
+}
+.carousel-control:hover,
+.carousel-control:focus {
+ outline: 0;
+ color: #ffffff;
+ text-decoration: none;
+ opacity: 0.9;
+ filter: alpha(opacity=90);
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-left,
+.carousel-control .glyphicon-chevron-right {
+ position: absolute;
+ top: 50%;
+ z-index: 5;
+ display: inline-block;
+}
+.carousel-control .icon-prev,
+.carousel-control .glyphicon-chevron-left {
+ left: 50%;
+ margin-left: -10px;
+}
+.carousel-control .icon-next,
+.carousel-control .glyphicon-chevron-right {
+ right: 50%;
+ margin-right: -10px;
+}
+.carousel-control .icon-prev,
+.carousel-control .icon-next {
+ width: 20px;
+ height: 20px;
+ margin-top: -10px;
+ line-height: 1;
+ font-family: serif;
+}
+.carousel-control .icon-prev:before {
+ content: '\2039';
+}
+.carousel-control .icon-next:before {
+ content: '\203a';
+}
+.carousel-indicators {
+ position: absolute;
+ bottom: 10px;
+ left: 50%;
+ z-index: 15;
+ width: 60%;
+ margin-left: -30%;
+ padding-left: 0;
+ list-style: none;
+ text-align: center;
+}
+.carousel-indicators li {
+ display: inline-block;
+ width: 10px;
+ height: 10px;
+ margin: 1px;
+ text-indent: -999px;
+ border: 1px solid #ffffff;
+ border-radius: 10px;
+ cursor: pointer;
+ background-color: #000 \9;
+ background-color: rgba(0, 0, 0, 0);
+}
+.carousel-indicators .active {
+ margin: 0;
+ width: 12px;
+ height: 12px;
+ background-color: #ffffff;
+}
+.carousel-caption {
+ position: absolute;
+ left: 15%;
+ right: 15%;
+ bottom: 20px;
+ z-index: 10;
+ padding-top: 20px;
+ padding-bottom: 20px;
+ color: #ffffff;
+ text-align: center;
+ text-shadow: 0 1px 2px rgba(0, 0, 0, 0.6);
+}
+.carousel-caption .btn {
+ text-shadow: none;
+}
+@media screen and (min-width: 768px) {
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-prev,
+ .carousel-control .icon-next {
+ width: 30px;
+ height: 30px;
+ margin-top: -15px;
+ font-size: 30px;
+ }
+ .carousel-control .glyphicon-chevron-left,
+ .carousel-control .icon-prev {
+ margin-left: -15px;
+ }
+ .carousel-control .glyphicon-chevron-right,
+ .carousel-control .icon-next {
+ margin-right: -15px;
+ }
+ .carousel-caption {
+ left: 20%;
+ right: 20%;
+ padding-bottom: 30px;
+ }
+ .carousel-indicators {
+ bottom: 20px;
+ }
+}
+.clearfix:before,
+.clearfix:after,
+.dl-horizontal dd:before,
+.dl-horizontal dd:after,
+.container:before,
+.container:after,
+.container-fluid:before,
+.container-fluid:after,
+.row:before,
+.row:after,
+.form-horizontal .form-group:before,
+.form-horizontal .form-group:after,
+.btn-toolbar:before,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:before,
+.btn-group-vertical > .btn-group:after,
+.nav:before,
+.nav:after,
+.navbar:before,
+.navbar:after,
+.navbar-header:before,
+.navbar-header:after,
+.navbar-collapse:before,
+.navbar-collapse:after,
+.pager:before,
+.pager:after,
+.panel-body:before,
+.panel-body:after,
+.modal-footer:before,
+.modal-footer:after {
+ content: " ";
+ display: table;
+}
+.clearfix:after,
+.dl-horizontal dd:after,
+.container:after,
+.container-fluid:after,
+.row:after,
+.form-horizontal .form-group:after,
+.btn-toolbar:after,
+.btn-group-vertical > .btn-group:after,
+.nav:after,
+.navbar:after,
+.navbar-header:after,
+.navbar-collapse:after,
+.pager:after,
+.panel-body:after,
+.modal-footer:after {
+ clear: both;
+}
+.center-block {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+}
+.pull-right {
+ float: right !important;
+}
+.pull-left {
+ float: left !important;
+}
+.hide {
+ display: none !important;
+}
+.show {
+ display: block !important;
+}
+.invisible {
+ visibility: hidden;
+}
+.text-hide {
+ font: 0/0 a;
+ color: transparent;
+ text-shadow: none;
+ background-color: transparent;
+ border: 0;
+}
+.hidden {
+ display: none !important;
+}
+.affix {
+ position: fixed;
+}
+@-ms-viewport {
+ width: device-width;
+}
+.visible-xs,
+.visible-sm,
+.visible-md,
+.visible-lg {
+ display: none !important;
+}
+.visible-xs-block,
+.visible-xs-inline,
+.visible-xs-inline-block,
+.visible-sm-block,
+.visible-sm-inline,
+.visible-sm-inline-block,
+.visible-md-block,
+.visible-md-inline,
+.visible-md-inline-block,
+.visible-lg-block,
+.visible-lg-inline,
+.visible-lg-inline-block {
+ display: none !important;
+}
+@media (max-width: 767px) {
+ .visible-xs {
+ display: block !important;
+ }
+ table.visible-xs {
+ display: table;
+ }
+ tr.visible-xs {
+ display: table-row !important;
+ }
+ th.visible-xs,
+ td.visible-xs {
+ display: table-cell !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-block {
+ display: block !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline {
+ display: inline !important;
+ }
+}
+@media (max-width: 767px) {
+ .visible-xs-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm {
+ display: block !important;
+ }
+ table.visible-sm {
+ display: table;
+ }
+ tr.visible-sm {
+ display: table-row !important;
+ }
+ th.visible-sm,
+ td.visible-sm {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-block {
+ display: block !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .visible-sm-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md {
+ display: block !important;
+ }
+ table.visible-md {
+ display: table;
+ }
+ tr.visible-md {
+ display: table-row !important;
+ }
+ th.visible-md,
+ td.visible-md {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-block {
+ display: block !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .visible-md-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg {
+ display: block !important;
+ }
+ table.visible-lg {
+ display: table;
+ }
+ tr.visible-lg {
+ display: table-row !important;
+ }
+ th.visible-lg,
+ td.visible-lg {
+ display: table-cell !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-block {
+ display: block !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline {
+ display: inline !important;
+ }
+}
+@media (min-width: 1200px) {
+ .visible-lg-inline-block {
+ display: inline-block !important;
+ }
+}
+@media (max-width: 767px) {
+ .hidden-xs {
+ display: none !important;
+ }
+}
+@media (min-width: 768px) and (max-width: 991px) {
+ .hidden-sm {
+ display: none !important;
+ }
+}
+@media (min-width: 992px) and (max-width: 1199px) {
+ .hidden-md {
+ display: none !important;
+ }
+}
+@media (min-width: 1200px) {
+ .hidden-lg {
+ display: none !important;
+ }
+}
+.visible-print {
+ display: none !important;
+}
+@media print {
+ .visible-print {
+ display: block !important;
+ }
+ table.visible-print {
+ display: table;
+ }
+ tr.visible-print {
+ display: table-row !important;
+ }
+ th.visible-print,
+ td.visible-print {
+ display: table-cell !important;
+ }
+}
+.visible-print-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-block {
+ display: block !important;
+ }
+}
+.visible-print-inline {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline {
+ display: inline !important;
+ }
+}
+.visible-print-inline-block {
+ display: none !important;
+}
+@media print {
+ .visible-print-inline-block {
+ display: inline-block !important;
+ }
+}
+@media print {
+ .hidden-print {
+ display: none !important;
+ }
+}
+.navbar-inverse .badge {
+ background-color: #fff;
+ color: #d9230f;
+}
+.btn {
+ font-family: "Open Sans", "Helvetica Neue", Helvetica, Arial, sans-serif;
+}
+.btn-default,
+.btn-default:hover {
+ background-image: -webkit-linear-gradient(#4f5151, #474949 6%, #3f4141);
+ background-image: -o-linear-gradient(#4f5151, #474949 6%, #3f4141);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#4f5151), color-stop(6%, #474949), to(#3f4141));
+ background-image: linear-gradient(#4f5151, #474949 6%, #3f4141);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff4f5151', endColorstr='#ff3f4141', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #2e2f2f;
+}
+.btn-primary,
+.btn-primary:hover {
+ background-image: -webkit-linear-gradient(#e72510, #d9230f 6%, #cb210e);
+ background-image: -o-linear-gradient(#e72510, #d9230f 6%, #cb210e);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e72510), color-stop(6%, #d9230f), to(#cb210e));
+ background-image: linear-gradient(#e72510, #d9230f 6%, #cb210e);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe72510', endColorstr='#ffcb210e', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #a91b0c;
+}
+.btn-success,
+.btn-success:hover {
+ background-image: -webkit-linear-gradient(#4da309, #469408 6%, #3f8507);
+ background-image: -o-linear-gradient(#4da309, #469408 6%, #3f8507);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#4da309), color-stop(6%, #469408), to(#3f8507));
+ background-image: linear-gradient(#4da309, #469408 6%, #3f8507);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff4da309', endColorstr='#ff3f8507', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #2f6405;
+}
+.btn-info,
+.btn-info:hover {
+ background-image: -webkit-linear-gradient(#02a5de, #029acf 6%, #028fc0);
+ background-image: -o-linear-gradient(#02a5de, #029acf 6%, #028fc0);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#02a5de), color-stop(6%, #029acf), to(#028fc0));
+ background-image: linear-gradient(#02a5de, #029acf 6%, #028fc0);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff02a5de', endColorstr='#ff028fc0', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #02749c;
+}
+.btn-warning,
+.btn-warning:hover {
+ background-image: -webkit-linear-gradient(#a54caa, #9b479f 6%, #914294);
+ background-image: -o-linear-gradient(#a54caa, #9b479f 6%, #914294);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#a54caa), color-stop(6%, #9b479f), to(#914294));
+ background-image: linear-gradient(#a54caa, #9b479f 6%, #914294);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffa54caa', endColorstr='#ff914294', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #79377c;
+}
+.btn-danger,
+.btn-danger:hover {
+ background-image: -webkit-linear-gradient(#e08b27, #d9831f 6%, #cc7b1d);
+ background-image: -o-linear-gradient(#e08b27, #d9831f 6%, #cc7b1d);
+ background-image: -webkit-gradient(linear, left top, left bottom, from(#e08b27), color-stop(6%, #d9831f), to(#cc7b1d));
+ background-image: linear-gradient(#e08b27, #d9831f 6%, #cc7b1d);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ffe08b27', endColorstr='#ffcc7b1d', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #ac6819;
+}
+body {
+ font-weight: 200;
+}
+th {
+ color: #444444;
+}
+legend {
+ color: #444444;
+}
+label {
+ font-weight: normal;
+}
+.has-warning .help-block,
+.has-warning .control-label {
+ color: #d9831f;
+}
+.has-warning .form-control,
+.has-warning .form-control:focus {
+ border-color: #d9831f;
+}
+.has-error .help-block,
+.has-error .control-label {
+ color: #d9230f;
+}
+.has-error .form-control,
+.has-error .form-control:focus {
+ border-color: #d9230f;
+}
+.has-success .help-block,
+.has-success .control-label {
+ color: #469408;
+}
+.has-success .form-control,
+.has-success .form-control:focus {
+ border-color: #469408;
+}
+.pager a {
+ color: #444444;
+}
+.pager a:hover,
+.pager .active > a {
+ border-color: #d9230f;
+ color: #fff;
+}
+.pager .disabled > a {
+ border-color: #dddddd;
+} \ No newline at end of file
diff --git a/website/resources/css/custom.css b/website/resources/css/custom.css
new file mode 100644
index 00000000..f81a3dd9
--- /dev/null
+++ b/website/resources/css/custom.css
@@ -0,0 +1,355 @@
+#clickForVideo {
+ padding: 20px 30px;
+ background-color: #DDD;
+ cursor: pointer;
+ margin-left: auto;
+ margin-right: auto;
+ margin-bottom: 40px;
+}
+
+.buttonLike {
+ cursor: pointer;
+ background: -webkit-linear-gradient(top, #FFFEF7, #CFCEC7);
+ background: -moz-linear-gradient(top, #FFFEF7, #CFCEC7);
+ background: -o-linear-gradient(#FFFEF7, #CFCEC7);
+ background: -ms-linear-gradient(#FFFEF7, #CFCEC7);
+ background: linear-gradient(top, #FFFEF7, #CFCEC7);
+ line-height: 1;
+ padding: 3px 10px;
+ border: 1px solid black;
+ position: relative;
+ overflow: visible;
+ color: black;
+ margin: 2px;
+ border-radius: 5px;
+ display: inline-block;
+ text-align: center;
+}
+
+.orderButton {
+ width: 280px;
+}
+
+.orderDetails {
+ font-style: italic;
+ font-size: 10px;
+ margin-top: 20px;
+}
+
+.formErr {
+ color: #FF7777;
+}
+
+.order-license #deleteCompanyLogo {
+ margin-top: 12px;
+}
+
+.formSubmitFail {
+ color: #FF6666;
+ font-size: 1.2em;
+ font-style: italic;
+}
+
+.order-license .btn-primary {
+ float: left;
+ margin-right: 20px;
+ background: -webkit-linear-gradient(#1725e0, #0923df 6%, #0b21ce);
+ background: -o-linear-gradient(#1725e0, #0923df 6%, #0b21ce);
+ background: -webkit-gradient(linear, left top, left bottom, from(#1725e0), color-stop(6%, #0923df), to(#0b21ce));
+ background: linear-gradient(#1725e0, #0923df 6%, #0b21ce);
+ background-repeat: no-repeat;
+ filter: progid:DXImageTransform.Microsoft.gradient(startColorstr='#ff1725e0', endColorstr='#ff0b21ce', GradientType=0);
+ -webkit-filter: none;
+ filter: none;
+ border: 1px solid #091bac;
+}
+
+#onlyYearlyWarning {
+ font-size: 0.8em;
+ padding-left: 16px;
+}
+
+.deemphasize {
+ color: #AAAAAA;
+ font-size: 0.8em;
+ font-style: italic;
+}
+
+.supporterBar .introText {
+ margin-top: 16px;
+}
+
+.barItem {
+ margin: 16px;
+ max-width: 168px;
+}
+
+.barItem img {
+ width: 100%;
+}
+
+.supportItem, .barItem {
+ display: inline-block;
+}
+
+.supporters .supportItem {
+ margin: 6px 10px;
+}
+
+.supporterBar {
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+}
+
+.errorBox {
+ border: 1px dashed #F44;
+ font-size: 1.2em;
+ padding: 20px;
+ background-color: #EEE;
+ text-align: center;
+}
+
+.noSupportersBox {
+ font-size: 1.2em;
+ padding: 20px;
+ background-color: #EEE;
+ text-align: center;
+}
+
+.spinner {
+ display: block;
+ margin-left: auto;
+ margin-right: auto;
+ width: 16px;
+ height: 16px;
+}
+
+#companyLogo {
+ margin-right: 8px;
+}
+
+html {
+ position: relative;
+ min-height: 100%;
+}
+
+body {
+ margin-bottom: 60px;
+ overflow-y: scroll;
+}
+
+ul.dropdown-menu .header {
+ padding-left: 10px;
+}
+
+div.snippet code {
+ padding: 0;
+}
+
+.fork-me {
+ position: fixed;
+ width: 150px;
+ height: 150px;
+ top: 0;
+ right: 0;
+ z-index: 2000;
+}
+
+.video {
+ padding-top: 4%;
+}
+
+.name {
+ font-weight: bold;
+}
+
+.bs-callout {
+ padding: 10px;
+ margin: 20px 0;
+ border: 1px solid #eee;
+ border-left-width: 5px;
+ border-radius: 3px;
+}
+
+.bs-callout h4 {
+ margin-top: 0;
+ margin-bottom: 5px;
+}
+
+.bs-callout p:last-child {
+ margin-bottom: 0;
+}
+
+.bs-callout code {
+ border-radius: 3px;
+}
+
+.bs-callout + .bs-callout {
+ margin-top: -5px;
+}
+
+.bs-callout-danger {
+ border-left-color: #ce4844;
+}
+
+.bs-callout-danger h4 {
+ color: #ce4844;
+}
+
+.bs-callout-warning {
+ border-left-color: #aa6708;
+}
+
+.bs-callout-warning h4 {
+ color: #aa6708;
+}
+
+.bs-callout-info {
+ border-left-color: #1b809e;
+}
+
+.bs-callout-info h4 {
+ color: #1b809e;
+}
+
+.color-swatches {
+ margin: 0 -5px;
+ overflow: hidden;
+}
+
+.footer {
+ position: absolute;
+ bottom: 0;
+ height: 60px;
+ border-top: 1px solid #eee;
+ padding-top: 15px;
+}
+
+h1, h2, h3 {
+ padding: 12px 40px;
+ text-align: center;
+}
+
+.page-center {
+ padding-top: 10%;
+ padding-bottom: 19%;
+}
+
+.page-header {
+ border-bottom: 0;
+}
+
+.header-group > h1, h2, h3 {
+ padding: 5px;
+}
+
+.snippet {
+ overflow: auto;
+ padding: 4px;
+ border: 1px dotted #888;
+ text-align: left;
+}
+
+.snippet font {
+ white-space: pre;
+}
+
+.snippet code {
+ font-size: 14px;
+ background-color: transparent;
+}
+
+.snippet.example {
+ margin: 8px 16px 8px 16px;
+}
+
+.snippet-col {
+ position: relative;
+ min-height: 1px;
+ padding-left: 15px;
+ padding-right: 15px;
+}
+
+@media (min-width: 769px) {
+ .snippet-col {
+ margin-left: -60px;
+ margin-right: -60px;
+ }
+}
+
+@media (min-width: 1000px) {
+ .snippet-col {
+ margin-left: -120px;
+ margin-right: -120px;
+ }
+}
+
+a {
+ cursor: pointer;
+}
+
+.main-section {
+ padding-left: 100px;
+ padding-right: 100px;
+ max-width: 900px;
+}
+
+.changelog li {
+ text-align: left;
+}
+
+@media (max-width: 767px) {
+ .fork-me {
+ display: none;
+ }
+
+ h1 {
+ font-size: 20px;
+ }
+
+ h2 {
+ font-size: 18px;
+ }
+
+ h3 {
+ font-size: 16px;
+ }
+
+ .main-section {
+ padding-left: 30px;
+ padding-right: 30px;
+ }
+
+ video {
+ width: 100%;
+ height: auto;
+ }
+
+ .smallOnly {
+ display: block !important;
+ }
+
+ .wideOnly {
+ display: none !important;
+ }
+}
+
+@media (min-width: 768px) {
+ .smallOnly {
+ display: none !important;
+ }
+
+ .wideOnly {
+ display: block !important;
+ }
+}
+
+img {
+ max-width: 100%;
+ height: auto;
+}
+
+h3.listHeader {
+ text-align: left;
+}
diff --git a/website/resources/files/pom.xml b/website/resources/files/pom.xml
new file mode 100644
index 00000000..6562afe8
--- /dev/null
+++ b/website/resources/files/pom.xml
@@ -0,0 +1,78 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<project xmlns="http://maven.apache.org/POM/4.0.0"
+ xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+ xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+ <modelVersion>4.0.0</modelVersion>
+
+ <groupId>org.projectlombok</groupId>
+ <artifactId>eclipse-compiler-test</artifactId>
+ <version>1.0-SNAPSHOT</version>
+
+ <properties>
+ <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+ <lombok.version>1.16.8</lombok.version>
+ </properties>
+
+ <dependencies>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>${lombok.version}</version>
+ <scope>provided</scope>
+ </dependency>
+ </dependencies>
+
+ <build>
+ <pluginManagement>
+ <plugins>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-compiler-plugin</artifactId>
+ <version>3.5.1</version>
+ <configuration>
+ <compilerId>eclipse</compilerId>
+ <source>1.8</source>
+ <target>1.8</target>
+ </configuration>
+ <dependencies>
+ <dependency>
+ <groupId>org.codehaus.plexus</groupId>
+ <artifactId>plexus-compiler-eclipse</artifactId>
+ <version>2.7</version>
+ </dependency>
+ <dependency>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>${lombok.version}</version>
+ </dependency>
+ </dependencies>
+ </plugin>
+ <plugin>
+ <groupId>org.apache.maven.plugins</groupId>
+ <artifactId>maven-dependency-plugin</artifactId>
+ <version>2.10</version>
+ <executions>
+ <execution>
+ <id>get-lombok</id>
+ <goals>
+ <goal>copy</goal>
+ </goals>
+ <configuration>
+ <artifactItems>
+ <artifactItem>
+ <groupId>org.projectlombok</groupId>
+ <artifactId>lombok</artifactId>
+ <version>${lombok.version}</version>
+ <type>jar</type>
+ <outputDirectory>${project.build.directory}</outputDirectory>
+ <destFileName>lombok.jar</destFileName>
+ </artifactItem>
+ </artifactItems>
+ </configuration>
+ </execution>
+ </executions>
+ </plugin>
+ </plugins>
+ </pluginManagement>
+ </build>
+</project>
diff --git a/website/resources/files/supporters.json b/website/resources/files/supporters.json
new file mode 100644
index 00000000..a895f95b
--- /dev/null
+++ b/website/resources/files/supporters.json
@@ -0,0 +1,13 @@
+{
+ "modWeight": {
+ "professional": 2.0,
+ "enterprise": 4.0,
+ "patron": 1.0
+ },
+ "professional": [
+ ],
+ "enterprise": [
+ ],
+ "patron": [
+ ]
+}
diff --git a/website/resources/img/eclipse-about.png b/website/resources/img/eclipse-about.png
new file mode 100644
index 00000000..71b18e99
--- /dev/null
+++ b/website/resources/img/eclipse-about.png
Binary files differ
diff --git a/website/resources/img/lombok-installer.png b/website/resources/img/lombok-installer.png
new file mode 100644
index 00000000..d71148f5
--- /dev/null
+++ b/website/resources/img/lombok-installer.png
Binary files differ
diff --git a/website/setup/netbeans-enable-annotation-processing-in-editor.png b/website/resources/img/netbeans-enable-annotation-processing-in-editor.png
index d8a6b4c3..d8a6b4c3 100644
--- a/website/setup/netbeans-enable-annotation-processing-in-editor.png
+++ b/website/resources/img/netbeans-enable-annotation-processing-in-editor.png
Binary files differ
diff --git a/website/resources/img/poster.png b/website/resources/img/poster.png
new file mode 100644
index 00000000..36c1a843
--- /dev/null
+++ b/website/resources/img/poster.png
Binary files differ
diff --git a/website/reinier.jpg b/website/resources/img/reinier.jpg
index dcb09700..dcb09700 100644
--- a/website/reinier.jpg
+++ b/website/resources/img/reinier.jpg
Binary files differ
diff --git a/website/roel.jpg b/website/resources/img/roel.jpg
index e5ce02ce..e5ce02ce 100644
--- a/website/roel.jpg
+++ b/website/resources/img/roel.jpg
Binary files differ
diff --git a/website/resources/img/spinner.gif b/website/resources/img/spinner.gif
new file mode 100644
index 00000000..f627b993
--- /dev/null
+++ b/website/resources/img/spinner.gif
Binary files differ
diff --git a/website/resources/js/history.js b/website/resources/js/history.js
new file mode 100644
index 00000000..9e18d9ee
--- /dev/null
+++ b/website/resources/js/history.js
@@ -0,0 +1 @@
+typeof JSON!="object"&&(JSON={}),function(){"use strict";function f(e){return e<10?"0"+e:e}function quote(e){return escapable.lastIndex=0,escapable.test(e)?'"'+e.replace(escapable,function(e){var t=meta[e];return typeof t=="string"?t:"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)})+'"':'"'+e+'"'}function str(e,t){var n,r,i,s,o=gap,u,a=t[e];a&&typeof a=="object"&&typeof a.toJSON=="function"&&(a=a.toJSON(e)),typeof rep=="function"&&(a=rep.call(t,e,a));switch(typeof a){case"string":return quote(a);case"number":return isFinite(a)?String(a):"null";case"boolean":case"null":return String(a);case"object":if(!a)return"null";gap+=indent,u=[];if(Object.prototype.toString.apply(a)==="[object Array]"){s=a.length;for(n=0;n<s;n+=1)u[n]=str(n,a)||"null";return i=u.length===0?"[]":gap?"[\n"+gap+u.join(",\n"+gap)+"\n"+o+"]":"["+u.join(",")+"]",gap=o,i}if(rep&&typeof rep=="object"){s=rep.length;for(n=0;n<s;n+=1)typeof rep[n]=="string"&&(r=rep[n],i=str(r,a),i&&u.push(quote(r)+(gap?": ":":")+i))}else for(r in a)Object.prototype.hasOwnProperty.call(a,r)&&(i=str(r,a),i&&u.push(quote(r)+(gap?": ":":")+i));return i=u.length===0?"{}":gap?"{\n"+gap+u.join(",\n"+gap)+"\n"+o+"}":"{"+u.join(",")+"}",gap=o,i}}typeof Date.prototype.toJSON!="function"&&(Date.prototype.toJSON=function(e){return isFinite(this.valueOf())?this.getUTCFullYear()+"-"+f(this.getUTCMonth()+1)+"-"+f(this.getUTCDate())+"T"+f(this.getUTCHours())+":"+f(this.getUTCMinutes())+":"+f(this.getUTCSeconds())+"Z":null},String.prototype.toJSON=Number.prototype.toJSON=Boolean.prototype.toJSON=function(e){return this.valueOf()});var cx=/[\u0000\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,escapable=/[\\\"\x00-\x1f\x7f-\x9f\u00ad\u0600-\u0604\u070f\u17b4\u17b5\u200c-\u200f\u2028-\u202f\u2060-\u206f\ufeff\ufff0-\uffff]/g,gap,indent,meta={"\b":"\\b"," ":"\\t","\n":"\\n","\f":"\\f","\r":"\\r",'"':'\\"',"\\":"\\\\"},rep;typeof JSON.stringify!="function"&&(JSON.stringify=function(e,t,n){var r;gap="",indent="";if(typeof n=="number")for(r=0;r<n;r+=1)indent+=" ";else typeof n=="string"&&(indent=n);rep=t;if(!t||typeof t=="function"||typeof t=="object"&&typeof t.length=="number")return str("",{"":e});throw new Error("JSON.stringify")}),typeof JSON.parse!="function"&&(JSON.parse=function(text,reviver){function walk(e,t){var n,r,i=e[t];if(i&&typeof i=="object")for(n in i)Object.prototype.hasOwnProperty.call(i,n)&&(r=walk(i,n),r!==undefined?i[n]=r:delete i[n]);return reviver.call(e,t,i)}var j;text=String(text),cx.lastIndex=0,cx.test(text)&&(text=text.replace(cx,function(e){return"\\u"+("0000"+e.charCodeAt(0).toString(16)).slice(-4)}));if(/^[\],:{}\s]*$/.test(text.replace(/\\(?:["\\\/bfnrt]|u[0-9a-fA-F]{4})/g,"@").replace(/"[^"\\\n\r]*"|true|false|null|-?\d+(?:\.\d*)?(?:[eE][+\-]?\d+)?/g,"]").replace(/(?:^|:|,)(?:\s*\[)+/g,"")))return j=eval("("+text+")"),typeof reviver=="function"?walk({"":j},""):j;throw new SyntaxError("JSON.parse")})}(),function(e,t){"use strict";var n=e.History=e.History||{},r=e.jQuery;if(typeof n.Adapter!="undefined")throw new Error("History.js Adapter has already been loaded...");n.Adapter={bind:function(e,t,n){r(e).bind(t,n)},trigger:function(e,t,n){r(e).trigger(t,n)},extractEventData:function(e,n,r){var i=n&&n.originalEvent&&n.originalEvent[e]||r&&r[e]||t;return i},onDomLoad:function(e){r(e)}},typeof n.init!="undefined"&&n.init()}(window),function(e,t){"use strict";var n=e.document,r=e.setTimeout||r,i=e.clearTimeout||i,s=e.setInterval||s,o=e.History=e.History||{};if(typeof o.initHtml4!="undefined")throw new Error("History.js HTML4 Support has already been loaded...");o.initHtml4=function(){if(typeof o.initHtml4.initialized!="undefined")return!1;o.initHtml4.initialized=!0,o.enabled=!0,o.savedHashes=[],o.isLastHash=function(e){var t=o.getHashByIndex(),n;return n=e===t,n},o.isHashEqual=function(e,t){return e=encodeURIComponent(e).replace(/%25/g,"%"),t=encodeURIComponent(t).replace(/%25/g,"%"),e===t},o.saveHash=function(e){return o.isLastHash(e)?!1:(o.savedHashes.push(e),!0)},o.getHashByIndex=function(e){var t=null;return typeof e=="undefined"?t=o.savedHashes[o.savedHashes.length-1]:e<0?t=o.savedHashes[o.savedHashes.length+e]:t=o.savedHashes[e],t},o.discardedHashes={},o.discardedStates={},o.discardState=function(e,t,n){var r=o.getHashByState(e),i;return i={discardedState:e,backState:n,forwardState:t},o.discardedStates[r]=i,!0},o.discardHash=function(e,t,n){var r={discardedHash:e,backState:n,forwardState:t};return o.discardedHashes[e]=r,!0},o.discardedState=function(e){var t=o.getHashByState(e),n;return n=o.discardedStates[t]||!1,n},o.discardedHash=function(e){var t=o.discardedHashes[e]||!1;return t},o.recycleState=function(e){var t=o.getHashByState(e);return o.discardedState(e)&&delete o.discardedStates[t],!0},o.emulated.hashChange&&(o.hashChangeInit=function(){o.checkerFunction=null;var t="",r,i,u,a,f=Boolean(o.getHash());return o.isInternetExplorer()?(r="historyjs-iframe",i=n.createElement("iframe"),i.setAttribute("id",r),i.setAttribute("src","#"),i.style.display="none",n.body.appendChild(i),i.contentWindow.document.open(),i.contentWindow.document.close(),u="",a=!1,o.checkerFunction=function(){if(a)return!1;a=!0;var n=o.getHash(),r=o.getHash(i.contentWindow.document);return n!==t?(t=n,r!==n&&(u=r=n,i.contentWindow.document.open(),i.contentWindow.document.close(),i.contentWindow.document.location.hash=o.escapeHash(n)),o.Adapter.trigger(e,"hashchange")):r!==u&&(u=r,f&&r===""?o.back():o.setHash(r,!1)),a=!1,!0}):o.checkerFunction=function(){var n=o.getHash()||"";return n!==t&&(t=n,o.Adapter.trigger(e,"hashchange")),!0},o.intervalList.push(s(o.checkerFunction,o.options.hashChangeInterval)),!0},o.Adapter.onDomLoad(o.hashChangeInit)),o.emulated.pushState&&(o.onHashChange=function(t){var n=t&&t.newURL||o.getLocationHref(),r=o.getHashByUrl(n),i=null,s=null,u=null,a;return o.isLastHash(r)?(o.busy(!1),!1):(o.doubleCheckComplete(),o.saveHash(r),r&&o.isTraditionalAnchor(r)?(o.Adapter.trigger(e,"anchorchange"),o.busy(!1),!1):(i=o.extractState(o.getFullUrl(r||o.getLocationHref()),!0),o.isLastSavedState(i)?(o.busy(!1),!1):(s=o.getHashByState(i),a=o.discardedState(i),a?(o.getHashByIndex(-2)===o.getHashByState(a.forwardState)?o.back(!1):o.forward(!1),!1):(o.pushState(i.data,i.title,encodeURI(i.url),!1),!0))))},o.Adapter.bind(e,"hashchange",o.onHashChange),o.pushState=function(t,n,r,i){r=encodeURI(r).replace(/%25/g,"%");if(o.getHashByUrl(r))throw new Error("History.js does not support states with fragment-identifiers (hashes/anchors).");if(i!==!1&&o.busy())return o.pushQueue({scope:o,callback:o.pushState,args:arguments,queue:i}),!1;o.busy(!0);var s=o.createStateObject(t,n,r),u=o.getHashByState(s),a=o.getState(!1),f=o.getHashByState(a),l=o.getHash(),c=o.expectedStateId==s.id;return o.storeState(s),o.expectedStateId=s.id,o.recycleState(s),o.setTitle(s),u===f?(o.busy(!1),!1):(o.saveState(s),c||o.Adapter.trigger(e,"statechange"),!o.isHashEqual(u,l)&&!o.isHashEqual(u,o.getShortUrl(o.getLocationHref()))&&o.setHash(u,!1),o.busy(!1),!0)},o.replaceState=function(t,n,r,i){r=encodeURI(r).replace(/%25/g,"%");if(o.getHashByUrl(r))throw new Error("History.js does not support states with fragment-identifiers (hashes/anchors).");if(i!==!1&&o.busy())return o.pushQueue({scope:o,callback:o.replaceState,args:arguments,queue:i}),!1;o.busy(!0);var s=o.createStateObject(t,n,r),u=o.getHashByState(s),a=o.getState(!1),f=o.getHashByState(a),l=o.getStateByIndex(-2);return o.discardState(a,s,l),u===f?(o.storeState(s),o.expectedStateId=s.id,o.recycleState(s),o.setTitle(s),o.saveState(s),o.Adapter.trigger(e,"statechange"),o.busy(!1)):o.pushState(s.data,s.title,s.url,!1),!0}),o.emulated.pushState&&o.getHash()&&!o.emulated.hashChange&&o.Adapter.onDomLoad(function(){o.Adapter.trigger(e,"hashchange")})},typeof o.init!="undefined"&&o.init()}(window),function(e,t){"use strict";var n=e.console||t,r=e.document,i=e.navigator,s=!1,o=e.setTimeout,u=e.clearTimeout,a=e.setInterval,f=e.clearInterval,l=e.JSON,c=e.alert,h=e.History=e.History||{},p=e.history;try{s=e.sessionStorage,s.setItem("TEST","1"),s.removeItem("TEST")}catch(d){s=!1}l.stringify=l.stringify||l.encode,l.parse=l.parse||l.decode;if(typeof h.init!="undefined")throw new Error("History.js Core has already been loaded...");h.init=function(e){return typeof h.Adapter=="undefined"?!1:(typeof h.initCore!="undefined"&&h.initCore(),typeof h.initHtml4!="undefined"&&h.initHtml4(),!0)},h.initCore=function(d){if(typeof h.initCore.initialized!="undefined")return!1;h.initCore.initialized=!0,h.options=h.options||{},h.options.hashChangeInterval=h.options.hashChangeInterval||100,h.options.safariPollInterval=h.options.safariPollInterval||500,h.options.doubleCheckInterval=h.options.doubleCheckInterval||500,h.options.disableSuid=h.options.disableSuid||!1,h.options.storeInterval=h.options.storeInterval||1e3,h.options.busyDelay=h.options.busyDelay||250,h.options.debug=h.options.debug||!1,h.options.initialTitle=h.options.initialTitle||r.title,h.options.html4Mode=h.options.html4Mode||!1,h.options.delayInit=h.options.delayInit||!1,h.intervalList=[],h.clearAllIntervals=function(){var e,t=h.intervalList;if(typeof t!="undefined"&&t!==null){for(e=0;e<t.length;e++)f(t[e]);h.intervalList=null}},h.debug=function(){(h.options.debug||!1)&&h.log.apply(h,arguments)},h.log=function(){var e=typeof n!="undefined"&&typeof n.log!="undefined"&&typeof n.log.apply!="undefined",t=r.getElementById("log"),i,s,o,u,a;e?(u=Array.prototype.slice.call(arguments),i=u.shift(),typeof n.debug!="undefined"?n.debug.apply(n,[i,u]):n.log.apply(n,[i,u])):i="\n"+arguments[0]+"\n";for(s=1,o=arguments.length;s<o;++s){a=arguments[s];if(typeof a=="object"&&typeof l!="undefined")try{a=l.stringify(a)}catch(f){}i+="\n"+a+"\n"}return t?(t.value+=i+"\n-----\n",t.scrollTop=t.scrollHeight-t.clientHeight):e||c(i),!0},h.getInternetExplorerMajorVersion=function(){var e=h.getInternetExplorerMajorVersion.cached=typeof h.getInternetExplorerMajorVersion.cached!="undefined"?h.getInternetExplorerMajorVersion.cached:function(){var e=3,t=r.createElement("div"),n=t.getElementsByTagName("i");while((t.innerHTML="<!--[if gt IE "+ ++e+"]><i></i><![endif]-->")&&n[0]);return e>4?e:!1}();return e},h.isInternetExplorer=function(){var e=h.isInternetExplorer.cached=typeof h.isInternetExplorer.cached!="undefined"?h.isInternetExplorer.cached:Boolean(h.getInternetExplorerMajorVersion());return e},h.options.html4Mode?h.emulated={pushState:!0,hashChange:!0}:h.emulated={pushState:!Boolean(e.history&&e.history.pushState&&e.history.replaceState&&!/ Mobile\/([1-7][a-z]|(8([abcde]|f(1[0-8]))))/i.test(i.userAgent)&&!/AppleWebKit\/5([0-2]|3[0-2])/i.test(i.userAgent)),hashChange:Boolean(!("onhashchange"in e||"onhashchange"in r)||h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8)},h.enabled=!h.emulated.pushState,h.bugs={setHash:Boolean(!h.emulated.pushState&&i.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(i.userAgent)),safariPoll:Boolean(!h.emulated.pushState&&i.vendor==="Apple Computer, Inc."&&/AppleWebKit\/5([0-2]|3[0-3])/.test(i.userAgent)),ieDoubleCheck:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<8),hashEscape:Boolean(h.isInternetExplorer()&&h.getInternetExplorerMajorVersion()<7)},h.isEmptyObject=function(e){for(var t in e)if(e.hasOwnProperty(t))return!1;return!0},h.cloneObject=function(e){var t,n;return e?(t=l.stringify(e),n=l.parse(t)):n={},n},h.getRootUrl=function(){var e=r.location.protocol+"//"+(r.location.hostname||r.location.host);if(r.location.port||!1)e+=":"+r.location.port;return e+="/",e},h.getBaseHref=function(){var e=r.getElementsByTagName("base"),t=null,n="";return e.length===1&&(t=e[0],n=t.href.replace(/[^\/]+$/,"")),n=n.replace(/\/+$/,""),n&&(n+="/"),n},h.getBaseUrl=function(){var e=h.getBaseHref()||h.getBasePageUrl()||h.getRootUrl();return e},h.getPageUrl=function(){var e=h.getState(!1,!1),t=(e||{}).url||h.getLocationHref(),n;return n=t.replace(/\/+$/,"").replace(/[^\/]+$/,function(e,t,n){return/\./.test(e)?e:e+"/"}),n},h.getBasePageUrl=function(){var e=h.getLocationHref().replace(/[#\?].*/,"").replace(/[^\/]+$/,function(e,t,n){return/[^\/]$/.test(e)?"":e}).replace(/\/+$/,"")+"/";return e},h.getFullUrl=function(e,t){var n=e,r=e.substring(0,1);return t=typeof t=="undefined"?!0:t,/[a-z]+\:\/\//.test(e)||(r==="/"?n=h.getRootUrl()+e.replace(/^\/+/,""):r==="#"?n=h.getPageUrl().replace(/#.*/,"")+e:r==="?"?n=h.getPageUrl().replace(/[\?#].*/,"")+e:t?n=h.getBaseUrl()+e.replace(/^(\.\/)+/,""):n=h.getBasePageUrl()+e.replace(/^(\.\/)+/,"")),n.replace(/\#$/,"")},h.getShortUrl=function(e){var t=e,n=h.getBaseUrl(),r=h.getRootUrl();return h.emulated.pushState&&(t=t.replace(n,"")),t=t.replace(r,"/"),h.isTraditionalAnchor(t)&&(t="./"+t),t=t.replace(/^(\.\/)+/g,"./").replace(/\#$/,""),t},h.getLocationHref=function(e){return e=e||r,e.URL===e.location.href?e.location.href:e.location.href===decodeURIComponent(e.URL)?e.URL:e.location.hash&&decodeURIComponent(e.location.href.replace(/^[^#]+/,""))===e.location.hash?e.location.href:e.URL.indexOf("#")==-1&&e.location.href.indexOf("#")!=-1?e.location.href:e.URL||e.location.href},h.store={},h.idToState=h.idToState||{},h.stateToId=h.stateToId||{},h.urlToId=h.urlToId||{},h.storedStates=h.storedStates||[],h.savedStates=h.savedStates||[],h.normalizeStore=function(){h.store.idToState=h.store.idToState||{},h.store.urlToId=h.store.urlToId||{},h.store.stateToId=h.store.stateToId||{}},h.getState=function(e,t){typeof e=="undefined"&&(e=!0),typeof t=="undefined"&&(t=!0);var n=h.getLastSavedState();return!n&&t&&(n=h.createStateObject()),e&&(n=h.cloneObject(n),n.url=n.cleanUrl||n.url),n},h.getIdByState=function(e){var t=h.extractId(e.url),n;if(!t){n=h.getStateString(e);if(typeof h.stateToId[n]!="undefined")t=h.stateToId[n];else if(typeof h.store.stateToId[n]!="undefined")t=h.store.stateToId[n];else{for(;;){t=(new Date).getTime()+String(Math.random()).replace(/\D/g,"");if(typeof h.idToState[t]=="undefined"&&typeof h.store.idToState[t]=="undefined")break}h.stateToId[n]=t,h.idToState[t]=e}}return t},h.normalizeState=function(e){var t,n;if(!e||typeof e!="object")e={};if(typeof e.normalized!="undefined")return e;if(!e.data||typeof e.data!="object")e.data={};return t={},t.normalized=!0,t.title=e.title||"",t.url=h.getFullUrl(e.url?e.url:h.getLocationHref()),t.hash=h.getShortUrl(t.url),t.data=h.cloneObject(e.data),t.id=h.getIdByState(t),t.cleanUrl=t.url.replace(/\??\&_suid.*/,""),t.url=t.cleanUrl,n=!h.isEmptyObject(t.data),(t.title||n)&&h.options.disableSuid!==!0&&(t.hash=h.getShortUrl(t.url).replace(/\??\&_suid.*/,""),/\?/.test(t.hash)||(t.hash+="?"),t.hash+="&_suid="+t.id),t.hashedUrl=h.getFullUrl(t.hash),(h.emulated.pushState||h.bugs.safariPoll)&&h.hasUrlDuplicate(t)&&(t.url=t.hashedUrl),t},h.createStateObject=function(e,t,n){var r={data:e,title:t,url:n};return r=h.normalizeState(r),r},h.getStateById=function(e){e=String(e);var n=h.idToState[e]||h.store.idToState[e]||t;return n},h.getStateString=function(e){var t,n,r;return t=h.normalizeState(e),n={data:t.data,title:e.title,url:e.url},r=l.stringify(n),r},h.getStateId=function(e){var t,n;return t=h.normalizeState(e),n=t.id,n},h.getHashByState=function(e){var t,n;return t=h.normalizeState(e),n=t.hash,n},h.extractId=function(e){var t,n,r,i;return e.indexOf("#")!=-1?i=e.split("#")[0]:i=e,n=/(.*)\&_suid=([0-9]+)$/.exec(i),r=n?n[1]||e:e,t=n?String(n[2]||""):"",t||!1},h.isTraditionalAnchor=function(e){var t=!/[\/\?\.]/.test(e);return t},h.extractState=function(e,t){var n=null,r,i;return t=t||!1,r=h.extractId(e),r&&(n=h.getStateById(r)),n||(i=h.getFullUrl(e),r=h.getIdByUrl(i)||!1,r&&(n=h.getStateById(r)),!n&&t&&!h.isTraditionalAnchor(e)&&(n=h.createStateObject(null,null,i))),n},h.getIdByUrl=function(e){var n=h.urlToId[e]||h.store.urlToId[e]||t;return n},h.getLastSavedState=function(){return h.savedStates[h.savedStates.length-1]||t},h.getLastStoredState=function(){return h.storedStates[h.storedStates.length-1]||t},h.hasUrlDuplicate=function(e){var t=!1,n;return n=h.extractState(e.url),t=n&&n.id!==e.id,t},h.storeState=function(e){return h.urlToId[e.url]=e.id,h.storedStates.push(h.cloneObject(e)),e},h.isLastSavedState=function(e){var t=!1,n,r,i;return h.savedStates.length&&(n=e.id,r=h.getLastSavedState(),i=r.id,t=n===i),t},h.saveState=function(e){return h.isLastSavedState(e)?!1:(h.savedStates.push(h.cloneObject(e)),!0)},h.getStateByIndex=function(e){var t=null;return typeof e=="undefined"?t=h.savedStates[h.savedStates.length-1]:e<0?t=h.savedStates[h.savedStates.length+e]:t=h.savedStates[e],t},h.getCurrentIndex=function(){var e=null;return h.savedStates.length<1?e=0:e=h.savedStates.length-1,e},h.getHash=function(e){var t=h.getLocationHref(e),n;return n=h.getHashByUrl(t),n},h.unescapeHash=function(e){var t=h.normalizeHash(e);return t=decodeURIComponent(t),t},h.normalizeHash=function(e){var t=e.replace(/[^#]*#/,"").replace(/#.*/,"");return t},h.setHash=function(e,t){var n,i;return t!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.setHash,args:arguments,queue:t}),!1):(h.busy(!0),n=h.extractState(e,!0),n&&!h.emulated.pushState?h.pushState(n.data,n.title,n.url,!1):h.getHash()!==e&&(h.bugs.setHash?(i=h.getPageUrl(),h.pushState(null,null,i+"#"+e,!1)):r.location.hash=e),h)},h.escapeHash=function(t){var n=h.normalizeHash(t);return n=e.encodeURIComponent(n),h.bugs.hashEscape||(n=n.replace(/\%21/g,"!").replace(/\%26/g,"&").replace(/\%3D/g,"=").replace(/\%3F/g,"?")),n},h.getHashByUrl=function(e){var t=String(e).replace(/([^#]*)#?([^#]*)#?(.*)/,"$2");return t=h.unescapeHash(t),t},h.setTitle=function(e){var t=e.title,n;t||(n=h.getStateByIndex(0),n&&n.url===e.url&&(t=n.title||h.options.initialTitle));try{r.getElementsByTagName("title")[0].innerHTML=t.replace("<","&lt;").replace(">","&gt;").replace(" & "," &amp; ")}catch(i){}return r.title=t,h},h.queues=[],h.busy=function(e){typeof e!="undefined"?h.busy.flag=e:typeof h.busy.flag=="undefined"&&(h.busy.flag=!1);if(!h.busy.flag){u(h.busy.timeout);var t=function(){var e,n,r;if(h.busy.flag)return;for(e=h.queues.length-1;e>=0;--e){n=h.queues[e];if(n.length===0)continue;r=n.shift(),h.fireQueueItem(r),h.busy.timeout=o(t,h.options.busyDelay)}};h.busy.timeout=o(t,h.options.busyDelay)}return h.busy.flag},h.busy.flag=!1,h.fireQueueItem=function(e){return e.callback.apply(e.scope||h,e.args||[])},h.pushQueue=function(e){return h.queues[e.queue||0]=h.queues[e.queue||0]||[],h.queues[e.queue||0].push(e),h},h.queue=function(e,t){return typeof e=="function"&&(e={callback:e}),typeof t!="undefined"&&(e.queue=t),h.busy()?h.pushQueue(e):h.fireQueueItem(e),h},h.clearQueue=function(){return h.busy.flag=!1,h.queues=[],h},h.stateChanged=!1,h.doubleChecker=!1,h.doubleCheckComplete=function(){return h.stateChanged=!0,h.doubleCheckClear(),h},h.doubleCheckClear=function(){return h.doubleChecker&&(u(h.doubleChecker),h.doubleChecker=!1),h},h.doubleCheck=function(e){return h.stateChanged=!1,h.doubleCheckClear(),h.bugs.ieDoubleCheck&&(h.doubleChecker=o(function(){return h.doubleCheckClear(),h.stateChanged||e(),!0},h.options.doubleCheckInterval)),h},h.safariStatePoll=function(){var t=h.extractState(h.getLocationHref()),n;if(!h.isLastSavedState(t))return n=t,n||(n=h.createStateObject()),h.Adapter.trigger(e,"popstate"),h;return},h.back=function(e){return e!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.back,args:arguments,queue:e}),!1):(h.busy(!0),h.doubleCheck(function(){h.back(!1)}),p.go(-1),!0)},h.forward=function(e){return e!==!1&&h.busy()?(h.pushQueue({scope:h,callback:h.forward,args:arguments,queue:e}),!1):(h.busy(!0),h.doubleCheck(function(){h.forward(!1)}),p.go(1),!0)},h.go=function(e,t){var n;if(e>0)for(n=1;n<=e;++n)h.forward(t);else{if(!(e<0))throw new Error("History.go: History.go requires a positive or negative integer passed.");for(n=-1;n>=e;--n)h.back(t)}return h};if(h.emulated.pushState){var v=function(){};h.pushState=h.pushState||v,h.replaceState=h.replaceState||v}else h.onPopState=function(t,n){var r=!1,i=!1,s,o;return h.doubleCheckComplete(),s=h.getHash(),s?(o=h.extractState(s||h.getLocationHref(),!0),o?h.replaceState(o.data,o.title,o.url,!1):(h.Adapter.trigger(e,"anchorchange"),h.busy(!1)),h.expectedStateId=!1,!1):(r=h.Adapter.extractEventData("state",t,n)||!1,r?i=h.getStateById(r):h.expectedStateId?i=h.getStateById(h.expectedStateId):i=h.extractState(h.getLocationHref()),i||(i=h.createStateObject(null,null,h.getLocationHref())),h.expectedStateId=!1,h.isLastSavedState(i)?(h.busy(!1),!1):(h.storeState(i),h.saveState(i),h.setTitle(i),h.Adapter.trigger(e,"statechange"),h.busy(!1),!0))},h.Adapter.bind(e,"popstate",h.onPopState),h.pushState=function(t,n,r,i){if(h.getHashByUrl(r)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(i!==!1&&h.busy())return h.pushQueue({scope:h,callback:h.pushState,args:arguments,queue:i}),!1;h.busy(!0);var s=h.createStateObject(t,n,r);return h.isLastSavedState(s)?h.busy(!1):(h.storeState(s),h.expectedStateId=s.id,p.pushState(s.id,s.title,s.url),h.Adapter.trigger(e,"popstate")),!0},h.replaceState=function(t,n,r,i){if(h.getHashByUrl(r)&&h.emulated.pushState)throw new Error("History.js does not support states with fragement-identifiers (hashes/anchors).");if(i!==!1&&h.busy())return h.pushQueue({scope:h,callback:h.replaceState,args:arguments,queue:i}),!1;h.busy(!0);var s=h.createStateObject(t,n,r);return h.isLastSavedState(s)?h.busy(!1):(h.storeState(s),h.expectedStateId=s.id,p.replaceState(s.id,s.title,s.url),h.Adapter.trigger(e,"popstate")),!0};if(s){try{h.store=l.parse(s.getItem("History.store"))||{}}catch(m){h.store={}}h.normalizeStore()}else h.store={},h.normalizeStore();h.Adapter.bind(e,"unload",h.clearAllIntervals),h.saveState(h.storeState(h.extractState(h.getLocationHref(),!0))),s&&(h.onUnload=function(){var e,t,n;try{e=l.parse(s.getItem("History.store"))||{}}catch(r){e={}}e.idToState=e.idToState||{},e.urlToId=e.urlToId||{},e.stateToId=e.stateToId||{};for(t in h.idToState){if(!h.idToState.hasOwnProperty(t))continue;e.idToState[t]=h.idToState[t]}for(t in h.urlToId){if(!h.urlToId.hasOwnProperty(t))continue;e.urlToId[t]=h.urlToId[t]}for(t in h.stateToId){if(!h.stateToId.hasOwnProperty(t))continue;e.stateToId[t]=h.stateToId[t]}h.store=e,h.normalizeStore(),n=l.stringify(e);try{s.setItem("History.store",n)}catch(i){if(i.code!==DOMException.QUOTA_EXCEEDED_ERR)throw i;s.length&&(s.removeItem("History.store"),s.setItem("History.store",n))}},h.intervalList.push(a(h.onUnload,h.options.storeInterval)),h.Adapter.bind(e,"beforeunload",h.onUnload),h.Adapter.bind(e,"unload",h.onUnload));if(!h.emulated.pushState){h.bugs.safariPoll&&h.intervalList.push(a(h.safariStatePoll,h.options.safariPollInterval));if(i.vendor==="Apple Computer, Inc."||(i.appCodeName||"")==="Mozilla")h.Adapter.bind(e,"hashchange",function(){h.Adapter.trigger(e,"popstate")}),h.getHash()&&h.Adapter.onDomLoad(function(){h.Adapter.trigger(e,"hashchange")})}},(!h.options||!h.options.delayInit)&&h.init()}(window) \ No newline at end of file
diff --git a/website/resources/js/main.js b/website/resources/js/main.js
new file mode 100644
index 00000000..f07da70d
--- /dev/null
+++ b/website/resources/js/main.js
@@ -0,0 +1,100 @@
+"use strict";
+
+(function($) {
+ function clickToTap() {
+ if (matchMedia && matchMedia('(hover: none)').matches) $(".clickToTap").each(function() {
+ var x = $(this);
+ if (x.text() === "Click") x.text("Tap");
+ else x.text("tap");
+ });
+ }
+
+ function clickForVideo() {
+ var cfv = $("#clickForVideo");
+ var f = function() {
+ if (!cfv.is(":visible")) return;
+ cfv.hide();
+ $("#demoVideo").show().get(0).play();
+ };
+
+ cfv.css("cursor", "pointer").on("click", f).on("touchstart", function() {
+ $(this).data("moved", 0);
+ }).on("touchmove", function() {
+ $(this).data("moved", 1);
+ }).on("touchend", function() {
+ if ($(this).data("moved") === 0) f();
+ });
+ }
+
+ function toKey(href) {
+ var lnk = "__savedContent_" + href.replace(/\//g, '_');
+ if (lnk.substring(lnk.length - 5) === ".html") lnk = lnk.substring(0, lnk.length - 5);
+ return lnk;
+ }
+
+ function captureLinkClick() {
+ var self = $(this);
+ if (self.data("clc")) return;
+ var href = self.attr("href");
+ self.data("clc", true);
+ if (!href || href.substr(0, 4) === "http" || href === "/api/" || href === "/" || href === "/supporters" || href === "/order-license") return;
+ var ext = href.substr(href.length - 4, 4);
+ if (ext === ".xml" || ext === ".jar") return;
+ self.on("click", function(evt) {
+ evt.preventDefault();
+ var key = toKey(window.location.pathname);
+ if ($("#" + key).length < 1) {
+ var d = $("<div />").attr("id", key).append($("#main-section").contents()).hide();
+ $("body").append(d);
+ }
+ History.pushState({urlPath: href}, self.text(), href);
+ });
+ }
+
+ function collapseMenu() {
+ if ($(".navbar-collapse").is(".in")) $(".navbar-toggle").click();
+ }
+
+ function ajaxFeaturePages() {
+ if (!History.enabled) return;
+ History.replaceState({urlPath: window.location.pathname}, $("title").text(), History.getState().urlpath);
+
+ $("a").each(captureLinkClick);
+
+ $(window).on("statechange", function() {
+ var hs = History.getState();
+ var u = hs.data.urlPath;
+ if (u === "/" || u === "") u = "/main.html";
+ if (u.substring(u.length - 5) !== ".html") u += ".html";
+ if (u.substring(u.length - 8) === "all.html") u = u.substring(0, u.length - 8) + "index.html";
+ var key = toKey(u);
+ var sc = $("#" + key);
+ if (sc.length > 0) {
+ var a = $("#main-section");
+ sc.show().attr("id", "main-section").attr("class", "container-fluid main-section");
+ a.replaceWith(sc);
+ collapseMenu();
+ } else {
+ $.ajax({
+ url: u,
+ success: function(response) {
+ var x = '<div class="container-fluid main-section" id="main-section">';
+ var y = '<footer';
+ var start = response.indexOf(x);
+ var end = response.indexOf(y);
+ var newH = $(response.substr(start, end - start));
+ $("#main-section").replaceWith(newH);
+ collapseMenu();
+ $("a").each(captureLinkClick);
+ }, error: function() {
+ window.location = u;
+ }
+ });
+ }
+ });
+ }
+
+ $(ajaxFeaturePages);
+ $(clickToTap);
+ $(clickForVideo);
+})($);
diff --git a/website/resources/js/order-license.js b/website/resources/js/order-license.js
new file mode 100644
index 00000000..b2842456
--- /dev/null
+++ b/website/resources/js/order-license.js
@@ -0,0 +1,231 @@
+"use strict";
+
+(function() {
+ if (!String.prototype.trim) {
+ String.prototype.trim = function () {
+ return this.replace(/^[\s\uFEFF\xA0]+|[\s\uFEFF\xA0]+$/g, '');
+ };
+ }
+
+ var imgDataUrl = null;
+
+ function updateLocationInfo() {
+ var locationType = $("input:radio[name='locationType']:checked").val();
+ $("#locationType_usa").toggle(locationType === "usa");
+ $("#locationType_eu").toggle(locationType === "eu");
+ $("#locationType_other").toggle(locationType === "other");
+ $("#paymentMethod_iban").toggle(locationType === "eu");
+ if ($("#paymentMethod_iban input").is(":checked") && locationType !== "eu") $("#paymentMethod_payoneer input").prop("checked", true);
+ if ($("#paymentMethod_intl input").is(":checked") && locationType === "eu") $("#paymentMethod_iban input").prop("checked", true);
+ $("#paymentMethod_intl").toggle(locationType !== "eu");
+ }
+
+ function updatePriceIndication() {
+ $("#onlyYearlyWarning").hide();
+ var x = getPriceIndication();
+ if (x === "") {
+ $("#costIndicator").text("").hide();
+ } else {
+ $("#costIndicator").text(x).show();
+ }
+ }
+
+ function getPriceIndication() {
+ try {
+ var seats = parseInt($("#seats").val());
+ if (isNaN(seats) || seats < 1) return "";
+ var licenseType = $("input:radio[name='licenseType']:checked").val();
+ var costPer;
+ if (licenseType === "enterprise") costPer = 5;
+ else if (licenseType === "professional") costPer = 2;
+ else return "";
+ var periodRaw = $("input:radio[name='paymentType']:checked").val();
+ if (periodRaw === "monthly") {
+ if (costPer*seats < 50) {
+ $("#onlyYearlyWarning").show();
+ return "Your license will cost €" + (costPer*seats*12) + ",- per year.";
+ }
+ return "Your license will cost €" + (costPer*seats) + ",- per month.";
+ }
+ return "Your license will cost €" + (costPer*seats*12) + ",- per year.";
+ } catch (e) {
+ return "";
+ }
+ }
+
+ function showError(elemName) {
+ var elem = $("#" + elemName + "Err");
+ elem.fadeIn();
+ $("#" + elemName).on("change keyup", function() {
+ elem.hide();
+ });
+ }
+
+ function applyLicense() {
+ var submitButton = $("#submit");
+ var spinner = $("<img>").attr("src", "/img/spinner.gif").attr("alt", "submitting").css("float", "left").css("margin-right", "20px");
+
+ submitButton.on("click", function(evt) {
+ evt.preventDefault();
+
+ var onSuccess = function() {
+ $("#orderHelp").hide();
+ var okMsg = $("<div>").addClass("formSubmitOk").html("Thank you for ordering a Project Lombok license! We'll send your bill via email. If you have any further questions please contact us at <a href=\"mailto:orders@projectlombok.org\"><code>orders@projectlombok.org</code></a>.");
+ spinner.replaceWith(okMsg);
+ };
+
+ var onFailure = function() {
+ $("#orderHelp").hide();
+ var errMsg = $("<div>").addClass("formSubmitFail").html("Our order form appears to be broken. Could you do us a favour and contact us at <a href=\"mailto:orders@projectlombok.org\"><code>orders@projectlombok.org</code></a>? Thank you!");
+ spinner.replaceWith(errMsg);
+ };
+
+ var data = {};
+ data.name = $("#companyName").val();
+ data.email = $("#email").val();
+ data.licenseType = $("input:radio[name='licenseType']:checked").val();
+ data.seats = parseInt($("#seats").val());
+ data.paymentType = $("input:radio[name='paymentType']:checked").val();
+ data.mentionMe = $("#mentionMe").prop("checked");
+ data.companyUrl = $("#companyUrl").val();
+ data.locationType = $("input:radio[name='locationType']:checked").val();
+ data.euVat = $("#euVat").val();
+ data.paymentMethod = $("input:radio[name='paymentMethod']:checked").val();
+
+ var formFail = false;
+
+ if (!data.paymentMethod) {
+ showError("paymentMethod");
+ formFail = true;
+ }
+
+ if (!data.euVat && data.locationType === 'eu') {
+ $("#euVat").focus();
+ showError("euVat");
+ formFail = true;
+ }
+
+ if (!data.locationType) {
+ showError("locationType");
+ formFail = true;
+ }
+
+ if (!data.seats || isNaN(data.seats) || data.seats < 1) {
+ $("#seats").focus();
+ showError("seats");
+ formFail = true;
+ }
+
+ if (!data.paymentType) {
+ showError("paymentType");
+ formFail = true;
+ }
+
+ if (data.email.indexOf('@') === -1) {
+ $("#email").focus();
+ showError("email");
+ formFail = true;
+ }
+
+ if (data.name.trim().length < 1) {
+ $("#companyName").focus();
+ showError("companyName");
+ formFail = true;
+ }
+
+ if (formFail) return;
+
+ var rnd = generateRandom();
+ var err = processImageUpload();
+ if (err) {
+ alert(err);
+ $("#logo")[0].value = null;
+ return;
+ }
+ if (imgDataUrl) data.logo = imgDataUrl;
+
+ submitButton.replaceWith(spinner);
+
+ $.ajax({
+ url: "/license-submit/" + rnd,
+ method: "PUT",
+ contentType: "application/json",
+ data: JSON.stringify(data),
+ processData: false,
+ success: onSuccess,
+ error: onFailure
+ });
+ });
+
+ $("#companyLogo").on("click", function(evt) {
+ evt.preventDefault();
+ $("#logo").click();
+ });
+
+ $("#deleteCompanyLogo").on("click", function(evt) {
+ evt.preventDefault();
+ $("#logo")[0].value = null;
+ $("#logoCnt").empty().hide();
+ $("#companyLogo").show();
+ $("#deleteCompanyLogo").hide();
+ });
+
+ $("#logo").on("change", function() {
+ var err = showImage();
+ if (err) {
+ alert(err);
+ $("#logo")[0].value = null;
+ } else {
+ $("#companyLogo").hide();
+ $("#deleteCompanyLogo").show();
+ }
+ });
+
+ $("#seats,.paymentType,.licenseType").on("change keyup", function() {
+ updatePriceIndication();
+ });
+ $(".locationType").on("change", function() {
+ updateLocationInfo();
+ });
+ }
+
+ function generateRandom() {
+ var buf = new Uint8Array(40);
+ window.crypto.getRandomValues(buf);
+ return btoa(String.fromCharCode.apply(null, buf)).replace(/\+/g, '_').replace(/\//gi, '-');
+ }
+
+ function showImage() {
+ $("#logoCnt").empty().hide();
+ try {
+ return processImageUpload(function(dataUrl) {
+ var img = $("<img />");
+ img.css({
+ "max-width": "500px",
+ "max-height": "300px"
+ });
+ $("#logoCnt").append(img).show();
+ img.attr("src", dataUrl);
+ });
+ } catch (e) {
+ if (console && console.log) console.log(e);
+ }
+ }
+
+ function processImageUpload(fnc) {
+ var f = $("#logo")[0].files[0];
+ if (!f) return;
+ if (f.size > 10000000) return "Logo too large; please give us a logo below 10MiB in size.";
+ var imageType = /^image\//;
+ if (!imageType.test(f.type)) return "Please upload an image, for example in PNG format.";
+ var reader = new FileReader();
+ reader.onload = function(e) {
+ imgDataUrl = e.target.result;
+ if (fnc) fnc(e.target.result);
+ };
+ reader.readAsDataURL(f);
+ return null;
+ }
+
+ $(applyLicense);
+})();
diff --git a/website/resources/js/supporters.js b/website/resources/js/supporters.js
new file mode 100644
index 00000000..07319226
--- /dev/null
+++ b/website/resources/js/supporters.js
@@ -0,0 +1,223 @@
+"use strict";
+
+(function($) {
+ var supporters = {};
+ var weights = {};
+ var types = ["enterprise", "professional", "patron"];
+
+ function shuffle(array) {
+ var i = 0, j = 0, temp = null;
+ for (i = array.length - 1; i > 0; i -= 1) {
+ j = Math.floor(Math.random() * (i + 1));
+ temp = array[i];
+ array[i] = array[j];
+ array[j] = temp;
+ }
+ }
+
+ function pad(number) {
+ return number < 10 ? '0' + number : number;
+ }
+
+ function fromDate(d) {
+ return d.getUTCFullYear() + '-' + pad(d.getUTCMonth() + 1) + '-' + pad(d.getUTCDate());
+
+ }
+
+ function toDate(s) {
+ var x = /^(\d{4})-(\d{2})-(\d{2})$/.exec(s);
+ if (x) return new Date(parseInt(x[1]), parseInt(x[2]), parseInt(x[3]));
+ return null;
+ }
+
+ function Supporter(type, json) {
+ this.type = type;
+ this.name = json.name;
+ this.logo = json.logo;
+ this.url = json.url;
+ this.showName = json.showName;
+ this.start = json.range ? toDate(json.range[0]) : null;
+ this.end = json.range ? toDate(json.range[1]) : null;
+ this.weight = (!json.weight && json.weight !== 0.0) ? 1.0 : json.weight;
+ }
+
+ Supporter.prototype.inRange = function(d) {
+ return (!this.start || this.start <= d) && (!this.end || this.end > d);
+ };
+
+ Supporter.prototype.render = function() {
+ var d = $("<div />").addClass("supportItem").addClass(this.type);
+ var a = d;
+ if (this.url) {
+ a = $("<a />").attr("href", this.url).attr("rel", "noopener").attr("target", "_blank");
+ d.append(a);
+ }
+ var n = $("<span />").text(this.name);
+ a.append(n);
+
+ if (this.logo) {
+ a.addClass("logo");
+ var i = new Image();
+ var showName = this.showName;
+ i.onload = function() {
+ var w = i.width;
+ var h = i.height;
+ var wf = w / 162;
+ var hf = h / 80;
+ var f = hf > wf ? hf : wf;
+ var wt = Math.round(w / f);
+ var ht = Math.round(h / f);
+ i.width = wt;
+ i.height = ht;
+ var ji = $(i);
+ if (!showName) a.empty();
+ ji.css("width", wt + "px");
+ ji.css("height", ht + "px");
+ ji.attr("alt", n.text());
+ ji.attr("title", n.text());
+ a.prepend(ji);
+ };
+ i.src = 'files/' + this.logo;
+ }
+ return d;
+ }
+
+ function errorHandler(xhr, statusText, err) {
+ var errMsg = "Can't connect to projectlombok.org to fetch the list of licensees and supporters.";
+ if (console && console.log) {
+ console.log("AJAX error for loading list of supporters:");
+ console.log(err);
+ }
+ var errBox = $("<div />").addClass("errorBox").text(errMsg);
+ $(".supporters").text("").append(errBox);
+ }
+
+ function successHandler(data) {
+ $.each(types, function() {
+ var t = this;
+ supporters[t] = [];
+ if (data && data[t]) $.each(data[t], function() {
+ supporters[t].push(new Supporter(t, this));
+ });
+ });
+ weights = data.modWeight;
+ if (typeof weights !== 'object') weights = {};
+ updatePage();
+ }
+
+ function build() {
+ var spinner = $("<img />").attr("title", "loading").attr("src", "/img/spinner.gif").addClass("spinner");
+ $(".supporters").append(spinner);
+ $.ajax({
+ url: "/files/supporters.json",
+ dataType: "json",
+ cache: true,
+ error: errorHandler,
+ success: function(data) {
+ spinner.remove();
+ successHandler(data);
+ }
+ });
+ }
+
+ function applySupporters() {
+ build();
+ }
+
+ function updatePage() {
+ updateSupporters();
+ updateSupporterBar();
+ }
+
+ var supPerBar = 4;
+ function updateSupporterBar() {
+ var s = $(".supporterBar");
+ s.find(".introText").show();
+ s.append($("<div />").addClass("sbCnt"));
+ var sf = s.find(".supporterFooter").show();
+ s.append(sf);
+ s = s.find(".sbCnt");
+ var now = new Date();
+ var list = [];
+ $.each(types, function() {
+ var t = this;
+ $.each(supporters[t], function() {
+ if (this.inRange(now)) {
+ var w = weights[t] ? weights[t] : 1.0;
+ if (this.weight) w = w * this.weight;
+ for (var i = 0; i < w; i++) list.push(this);
+ }
+ });
+ });
+
+ shuffle(list);
+
+ var len = list.length;
+ if (!len) return;
+
+ var pos = 0;
+ var c = [], cd = [];
+ for (var i = 0; i < supPerBar; i++) {
+ c[i] = null;
+ cd[i] = $("<div />").addClass("barItem");
+ }
+
+ var upd = function() {
+ var nw = [], a = [], fo = $(), fi = $();
+ var sPos = pos;
+ for (var i = 0; i < supPerBar; i++) {
+ if (++pos === len) pos = 0;
+ var z = false;
+ for (var j = 0; j < i; j++) if (nw[j] === list[pos]) z = true;
+ if (z) i--;
+ else nw[i] = list[pos];
+ if (pos === sPos) break;
+ }
+ for (var i = 0; i < supPerBar; i++) a[i] = (nw[i] === c[i] || !nw[i]) ? null : nw[i].render(i + 1).hide();
+ for (var i = 0; i < supPerBar; i++) {
+ if (a[i]) {
+ fi = fi.add(a[i]);
+ fo = fo.add(cd[i].children());
+ if (cd[i].parent().length === 0) s.append(cd[i]);
+ cd[i].append(a[i]);
+ c[i] = nw[i];
+ }
+ }
+
+ if (fo.length === 0) fi.fadeIn();
+ else {
+ fo.fadeOut("normal", function() {
+ fi.fadeIn();
+ fo.remove();
+ });
+ }
+ };
+
+ setInterval(upd, 10000);
+ upd();
+ }
+
+ function updateSupporters() {
+ var s = $(".supporters");
+ s.empty();
+ var now = new Date();
+ $.each(types, function() {
+ var t = this;
+ var d = $("<div />").addClass("row");
+ var h = $("<h2 />").text(t);
+ d.append(h);
+ $.each(supporters[t], function() {
+ if (this.inRange(now)) d.append(this.render());
+ });
+ if (d.children().length > 1) s.append(d);
+ });
+ if (s.children().length < 1) {
+ var x = $("<div />").addClass("noSupportersBox").html(
+ "We don't have any supporters yet this month.<br /><a href=\"https://patreon.com/lombok\" rel=\"noopener\">Become a patron</a> " +
+ "or <a href=\"/order-license-info\">order a professional or enterprise license</a> today!");
+ s.append(x);
+ }
+ }
+
+ $(applySupporters);
+})($); \ No newline at end of file
diff --git a/website/resources/robots.txt b/website/resources/robots.txt
new file mode 100644
index 00000000..af2eebd5
--- /dev/null
+++ b/website/resources/robots.txt
@@ -0,0 +1,2 @@
+User-Agent: *
+Disallow: /tmp/
diff --git a/website/robbertjan.jpg b/website/robbertjan.jpg
deleted file mode 100644
index a0839e6c..00000000
--- a/website/robbertjan.jpg
+++ /dev/null
Binary files differ
diff --git a/website/sander.jpg b/website/sander.jpg
deleted file mode 100644
index f3be1b28..00000000
--- a/website/sander.jpg
+++ /dev/null
Binary files differ
diff --git a/website/setup/android.html b/website/setup/android.html
deleted file mode 100644
index 2e3eb023..00000000
--- a/website/setup/android.html
+++ /dev/null
@@ -1,131 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script src="../logi/jQuery-all.js" type="text/javascript"></script>
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../index.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <!--[if lt IE 7]><script type="text/javascript" src="../logi/iepngfix_tilebg.js"></script><![endif]-->
-</head><body>
- <a id="forkMe" href="http://github.com/rzwitserloot/lombok"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
- <div class="meat">
- <h1><a href="/">Project Lombok</a> - android instructions</h1>
- <div id="buttonBar" class="buttonBar">
- <a class="button" href="../features/index.html">
- <img src="../icon_overview.png" />
- <span>Feature Overview</span>
- </a>
- <a class="button" href="http://groups.google.com/group/project-lombok">
- <img src="../icon_discussion.png" />
- <span>Discuss / Help</span>
- </a>
- <a class="button" href="http://wiki.github.com/rzwitserloot/lombok/contributing">
- <img src="../icon_contribute.png" />
- <span>Contribute</span>
- </a>
- <a class="button" href="http://code.google.com/p/projectlombok/issues/list">
- <img src="../icon_bugs.png" />
- <span>Report an issue</span>
- </a>
- <div class="downloadContainer">
- <a class="downloadLink" id="downloadLink" href="../download.html">
- <img src="../icon_download.png" />
- <span>Download!</span>
- </a>
- <div class="versionInfo">
- Version: @VERSION@ | <a href="../changelog.html">changelog</a>
- </div>
- </div>
- </div>
- <div class="downloadHelp">
- <p>
- Android development with lombok is possible. Lombok should be a compile-time only dependency, as otherwise
- the entirety of lombok will end up in your DEX files, wasting precious space on android devices. Also, errors will occur due
- to the native libraries present in lombok.jar itself. Unfortunately, android does not (yet) understand the concept of a
- compile-time-only dependency, so you need to mess with your build files to make it work.
- </p><p>
- Android also does not have a complete JRE library stack; in particular, it does not have the <code>@java.beans.ConstructorProperties</code> annotation, therefore you have to stop lombok from generating these:
- <ul>
- <li>The <code>suppressConstructorProperties</code> property can be set to <code>false</code> when using <a href="/features/Constructor.html">@XArgsConstructor Annotations</a>.</li>
- <li>Starting with Lombok <code>&gt;= 1.14.0</code> you can instead a <code>lombok.config</code> file to the root of your project to disable <code>ConstructorProperties</code> project wide. Add the following line to <code>lombok.config</code>:<br />
- <pre>lombok.anyConstructor.suppressConstructorProperties = true</pre><br />
- See the <a href="/features/experimental/configuration.html">configuration</a> documentation for more information on how to set up your project with a lombok config file.
- </ul>
- </p><p>
- The instructions listed below are excerpts from <a href="https://github.com/excilys/androidannotations/wiki/Cookbook">The
- AndroidAnnotations project cookbook</a>. You may wish to refer to that documentation for complete instructions; lombok is just
- the equivalent to <code>androidannotations-VERSION.jar</code>; there is no <code>-api</code> aspect.
- </p>
- <h3>Eclipse</h3>
- <div>
- In eclipse, create a 'lightweight' lombok jar that contains only the annotations by running:<br /><br />
- <pre>
-java -jar lombok.jar publicApi</pre>
- Then, add the <code>lombok-api.jar</code> file created by running this command
- to your android project instead of the complete <code>lombok.jar</code>, and,
- as usual, install lombok into eclipse by double-clicking <code>lombok.jar</code>.
- </div>
- <h3>Ant</h3>
- <div>
- <ul>
- <li>Find <code>build.xml</code> in <code>${ANDROID_SDK_ROOT}/tools/ant/build.xml</code> and copy the <code>-compile</code> target into the paste buffer.
- <li>Copy this to the <code>build.xml</code> of your own project, right before the <code>&lt;import file="${sdk.dir}/tools/ant/build.xml"&gt;</code> line.
- <li>Create a <code>compile-libs</code> directory in your own project and copy the complete <code>lombok.jar</code> to it.
- <li>Now modify the <code>&lt;classpath&gt;</code> entry inside the <code>&lt;javac&gt;</code> task in the <code>-compile</code> target you just copied:<br />
- add <code>&lt;fileset dir="compile-libs" includes="*.jar" /&gt;</code> to it.
- </ul>
- </div>
- <h3>Maven</h3>
- <div>
- You should be able to just follow the normal <a href="../mavenrepo/index.html">lombok with maven instructions</a>.<br />
- Note that if you use android, eclipse, and maven together you may have to replace <code>lombok.jar</code> in your eclipse android project's build path
- (which you can modify in that project's properties page) with <code>lombok-api.jar</code>, as produced in the procedure explained for <em>Eclipse</em>,
- above.
- </div>
- <h3>Gradle</h3>
- <div>
- <ul>
- <li>Make sure that the version of your android plugin is <code>&gt;= 0.4.3</code></li>
- <li>Add Lombok to your application's <code>dependencies</code> block:<br /><br />
-<pre>
- provided "org.projectlombok:lombok:1.12.6"
-</pre>
- </li>
- <li>When using <a href="https://bitbucket.org/hvisser/android-apt">android-apt</a>, you also have to specify Lombok as an annotation processor (with the <code>apt</code> directive) in the <code>dependencies</code> block:<br /><br />
-<pre>
- provided "org.projectlombok:lombok:1.12.6"
- apt "org.projectlombok:lombok:1.12.6"
-</pre>
- </li>
- </ul>
- </div>
- <h3>Android Studio</h3>
- <div>
- Follow the previous instructions (<em>Gradle</em>). In addition to setting up your gradle project correctly, you need to add the <a href="http://plugins.jetbrains.com/plugin/6317">Lombok IntelliJ plugin</a> to add lombok support to Android Studio:
- <ul>
- <li>Go to <code>File &gt; Settings &gt; Plugins</code></li>
- <li>Click on <code>Browse repositories...</code></li>
- <li>Search for <code>Lombok Plugin</code></li>
- <li>Click on <code>Install plugin</code></li>
- <li>Restart Android Studio</li>
- </ul>
- </div>
- <div class="endBar">
- </div>
- <div class="footer">
- <a href="../credits.html" class="creditsLink">credits</a> | Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/setup/ecj.html b/website/setup/ecj.html
deleted file mode 100644
index 7c3ff1bb..00000000
--- a/website/setup/ecj.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script src="../logi/jQuery-all.js" type="text/javascript"></script>
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../index.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <!--[if lt IE 7]><script type="text/javascript" src="../logi/iepngfix_tilebg.js"></script><![endif]-->
-</head><body>
- <a id="forkMe" href="http://github.com/rzwitserloot/lombok"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
- <div class="meat">
- <h1><a href="/">Project Lombok</a> - ecj instructions</h1>
- <div id="buttonBar" class="buttonBar">
- <a class="button" href="../features/index.html">
- <img src="../icon_overview.png" />
- <span>Feature Overview</span>
- </a>
- <a class="button" href="http://groups.google.com/group/project-lombok">
- <img src="../icon_discussion.png" />
- <span>Discuss / Help</span>
- </a>
- <a class="button" href="http://wiki.github.com/rzwitserloot/lombok/contributing">
- <img src="../icon_contribute.png" />
- <span>Contribute</span>
- </a>
- <a class="button" href="http://code.google.com/p/projectlombok/issues/list">
- <img src="../icon_bugs.png" />
- <span>Report an issue</span>
- </a>
- <div class="downloadContainer">
- <a class="downloadLink" id="downloadLink" href="../download.html">
- <img src="../icon_download.png" />
- <span>Download!</span>
- </a>
- <div class="versionInfo">
- Version: @VERSION@ | <a href="../changelog.html">changelog</a>
- </div>
- </div>
- </div>
- <div class="downloadHelp">
- ecj (the eclipse standalone compiler) is compatible with lombok. Use the following command line to enable lombok with ecj:
- <p>
- <pre>
-java <strong>-javaagent:lombok.jar=ECJ -Xbootclasspath/p:lombok.jar</strong> -jar ecj.jar -cp lombok.jar <em>(rest of arguments)</em></pre>
- If you're using a tool based on ecj, adding these VM arguments and adding lombok.jar to the classpath should work.
- </div>
- <div class="endBar">
- </div>
- <div class="footer">
- <a href="../credits.html" class="creditsLink">credits</a> | Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/setup/gwt.html b/website/setup/gwt.html
deleted file mode 100644
index 84e760bc..00000000
--- a/website/setup/gwt.html
+++ /dev/null
@@ -1,68 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script src="../logi/jQuery-all.js" type="text/javascript"></script>
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../index.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <!--[if lt IE 7]><script type="text/javascript" src="../logi/iepngfix_tilebg.js"></script><![endif]-->
-</head><body>
- <a id="forkMe" href="http://github.com/rzwitserloot/lombok"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
- <div class="meat">
- <h1><a href="/">Project Lombok</a> - gwt instructions</h1>
- <div id="buttonBar" class="buttonBar">
- <a class="button" href="../features/index.html">
- <img src="../icon_overview.png" />
- <span>Feature Overview</span>
- </a>
- <a class="button" href="http://groups.google.com/group/project-lombok">
- <img src="../icon_discussion.png" />
- <span>Discuss / Help</span>
- </a>
- <a class="button" href="http://wiki.github.com/rzwitserloot/lombok/contributing">
- <img src="../icon_contribute.png" />
- <span>Contribute</span>
- </a>
- <a class="button" href="http://code.google.com/p/projectlombok/issues/list">
- <img src="../icon_bugs.png" />
- <span>Report an issue</span>
- </a>
- <div class="downloadContainer">
- <a class="downloadLink" id="downloadLink" href="../download.html">
- <img src="../icon_download.png" />
- <span>Download!</span>
- </a>
- <div class="versionInfo">
- Version: @VERSION@ | <a href="../changelog.html">changelog</a>
- </div>
- </div>
- </div>
- <div class="downloadHelp">
- gwt (Google Web Toolkit) is compatible with lombok.
- <p>
- Edit your proj-debug and proj-compile batch scripts to add the following VM arguments:
- <pre>
-java <strong>-javaagent:lombok.jar=ECJ</strong> <em>(rest of arguments)</em>
- </pre>
- <p>
- Thanks to Stephen Haberman for figuring this out.
- </div>
- <div class="endBar">
- </div>
- <div class="footer">
- <a href="../credits.html" class="creditsLink">credits</a> | Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/setup/netbeans.html b/website/setup/netbeans.html
deleted file mode 100644
index 03775206..00000000
--- a/website/setup/netbeans.html
+++ /dev/null
@@ -1,65 +0,0 @@
-<!DOCTYPE html>
-<html><head>
- <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
- <script src="../logi/jQuery-all.js" type="text/javascript"></script>
- <link rel="stylesheet" type="text/css" href="../logi/reset.css" />
- <link rel="stylesheet" type="text/css" href="../index.css" />
- <link rel="shortcut icon" href="../favicon.ico" type="image/x-icon" />
- <meta name="description" content="Spice up your java" />
- <title>Project Lombok</title>
- <!--[if lt IE 7]><script type="text/javascript" src="../logi/iepngfix_tilebg.js"></script><![endif]-->
-</head><body>
- <a id="forkMe" href="http://github.com/rzwitserloot/lombok"><img style="position: absolute; top: 0; right: 0; border: 0;" src="http://s3.amazonaws.com/github/ribbons/forkme_right_darkblue_121621.png" alt="Fork me on GitHub" /></a>
- <div class="meat">
- <h1><a href="/">Project Lombok</a> - NetBeans instructions</h1>
- <div id="buttonBar" class="buttonBar">
- <a class="button" href="../features/index.html">
- <img src="../icon_overview.png" />
- <span>Feature Overview</span>
- </a>
- <a class="button" href="http://groups.google.com/group/project-lombok">
- <img src="../icon_discussion.png" />
- <span>Discuss / Help</span>
- </a>
- <a class="button" href="http://wiki.github.com/rzwitserloot/lombok/contributing">
- <img src="../icon_contribute.png" />
- <span>Contribute</span>
- </a>
- <a class="button" href="http://code.google.com/p/projectlombok/issues/list">
- <img src="../icon_bugs.png" />
- <span>Report an issue</span>
- </a>
- <div class="downloadContainer">
- <a class="downloadLink" id="downloadLink" href="../download.html">
- <img src="../icon_download.png" />
- <span>Download!</span>
- </a>
- <div class="versionInfo">
- Version: @VERSION@ | <a href="../changelog.html">changelog</a>
- </div>
- </div>
- </div>
- <div class="downloadHelp">
- <ol>
- <li>Add <code>lombok.jar</code> to the project Libraries.</li>
- <li>In the project Properties, in the section Build &ndash; Compiling, check the &#39;Enable Annotation Processing in Editor&#39; checkbox.</li>
- </ol>
- <img src="netbeans-enable-annotation-processing-in-editor.png" />
- </div>
- <div class="endBar">
- </div>
- <div class="footer">
- <a href="../credits.html" class="creditsLink">credits</a> | Copyright &copy; 2009-2014 The Project Lombok Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT license</a>.
- </div>
- </div>
- <script type="text/javascript">
- var gaJsHost = (("https:" == document.location.protocol) ? "https://ssl." : "http://www.");
- document.write(unescape("%3Cscript src='" + gaJsHost + "google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E"));
- </script>
- <script type="text/javascript">
- try {
- var pageTracker = _gat._getTracker("UA-9884254-1");
- pageTracker._trackPageview();
- } catch(err) {}
- </script>
-</body></html>
diff --git a/website/templates/_download-edge.html b/website/templates/_download-edge.html
new file mode 100644
index 00000000..e7eb856c
--- /dev/null
+++ b/website/templates/_download-edge.html
@@ -0,0 +1,18 @@
+<#import "/_scaffold.html" as main>
+<@main.scaffold title="snapshot">
+ <div class="page-header top5">
+ <div class="row text-center versionInfo">
+ <@main.h1 title="Download 'Edgy Guinea Pig' - the Lombok Cutting Edge build" />
+ </div><div class="row versionInfo">
+ version: ${version} (${timestampString})
+ </div><div class="row" id="changelog">
+ ${changelogEdge?no_esc}
+ </div><div class="row text-center">
+ <h2><a href="/lombok-edge.jar" id="downloadLink">Download edge release now!</a></h2>
+ </div><div class="row text-center">
+ <p>
+ Cutting edge a bit too gutsy for you? You can grab the <a href="download.html">stable release</a> instead.
+ </p>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/_scaffold.html b/website/templates/_scaffold.html
new file mode 100644
index 00000000..e3096d7d
--- /dev/null
+++ b/website/templates/_scaffold.html
@@ -0,0 +1,160 @@
+<#macro feature title href>
+ <div class="bs-callout bs-callout-danger">
+ <h4><a href="${href}"><code>${title}</code></a></h4>
+ <p><#nested></p>
+ </div>
+</#macro>
+
+<#assign setupTargets = {
+ "Compilers": {
+ "Javac": "javac",
+ "ECJ": "ecj"
+ },
+ "Build tools": {
+ "maven": "maven",
+ "gradle": "gradle",
+ "ant": "ant",
+ "kobalt": "kobalt"
+ },
+ "IDEs": {
+ "Eclipse": "eclipse",
+ "IntelliJ IDEA": "intellij",
+ "Netbeans": "netbeans",
+ "MyEclipse": "eclipse",
+ "Spring Tool Suite": "eclipse",
+ "JBoss Developer Studio": "eclipse",
+ "Visual Studio Code": "vscode"
+ },
+ "Platforms": {
+ "Android": "android",
+ "GWT": "gwt"
+ }
+}>
+
+<#macro scaffold load=[] title='Project Lombok'>
+ <!DOCTYPE html>
+ <html lang="en">
+ <head>
+ <meta charset="utf-8" />
+ <meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1" />
+ <meta name="google-site-verification" content="uCgX3Or3kDRGpbJ6JCsQc3Ub4JsnR5-p0itfsKAYZ_U" />
+ <meta name="viewport" content="width=device-width, initial-scale=1.0" />
+ <link href="/favicon.ico" rel="icon" type="image/x-icon" />
+
+ <title>${title}</title>
+
+ <script src="//cdnjs.cloudflare.com/ajax/libs/modernizr/2.8.3/modernizr.min.js"
+ integrity="sha384-bPV3mA2eo3edoq56VzcPBmG1N1QVUfjYMxVIJPPzyFJyFZ8GFfN7Npt06Zr23qts" crossorigin="anonymous"></script>
+
+ <link href="/css/bootstrap.css" rel="stylesheet" />
+ <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.2.0/css/font-awesome.min.css"
+ integrity="sha384-CmLV3WR+cw/TcN50vJSYAs2EAzhDD77tQvGcmoZ1KEzxtpl2K5xkrpFz9N2H9ClN" crossorigin="anonymous">
+
+ <link href="/css/custom.css" rel="stylesheet" />
+
+ <#list load as ld>
+ <#if ld?ends_with(".css")>
+ <link href="${ld?url_path}" rel="stylesheet" />
+ </#if>
+ </#list>
+ <script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.2/jquery.min.js"
+ integrity="sha384-Pn+PczAsODRZ2PiGg0IheRROpP7lXO1NTIjiPo6cca8TliBvaeil42fobhzvZd74" crossorigin="anonymous"></script>
+ <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.2.0/js/bootstrap.min.js"
+ integrity="sha384-VI5+XuguQ/l3kUhh4knz7Hxptx47wpQbVRDnp8v7Vvuhzwn1PEYb/uvtH6KLxv6d" crossorigin="anonymous"></script>
+
+ <script src="/js/history.js"></script>
+ <script src="/js/main.js"></script>
+ <#list load as ld>
+ <#if ld?ends_with(".js")>
+ <script src="${ld?url_path}"></script>
+ </#if>
+ </#list>
+ </head><body>
+ <script>
+ (function(i,s,o,g,r,a,m){i['GoogleAnalyticsObject']=r;i[r]=i[r]||function(){
+(i[r].q=i[r].q||[]).push(arguments)},i[r].l=1*new Date();a=s.createElement(o),
+m=s.getElementsByTagName(o)[0];a.async=1;a.src=g;m.parentNode.insertBefore(a,m)
+})(window,document,'script','https://www.google-analytics.com/analytics.js','ga');
+ga('create', 'UA-9884254-1', 'auto');
+ga('send', 'pageview');
+ </script>
+ <div class="navbar navbar-default navbar-fixed-top">
+ <div class="container">
+ <div class="navbar-header">
+ <a href="/" class="navbar-brand">Lombok Project</a>
+ <button class="navbar-toggle" type="button" data-toggle="collapse" data-target="#navbar-main">
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ <span class="icon-bar"></span>
+ </button>
+ </div>
+ <div class="navbar-collapse collapse" id="navbar-main">
+ <ul class="nav navbar-nav">
+ <li class="dropdown">
+ <a class="dropdown-toggle pointer" data-toggle="dropdown">Features<span class="caret"></span></a>
+ <ul class="dropdown-menu" aria-labelledby="themes">
+ <li><a href="/features/all">Stable</a></li>
+ <li><a href="/features/experimental/all">Experimental</a></li>
+ </ul>
+ </li>
+ <li class="dropdown">
+ <a class="dropdown-toggle pointer" data-toggle="dropdown">Community<span class="caret"></span></a>
+ <ul class="dropdown-menu" aria-labelledby="themes">
+ <li><a href="https://groups.google.com/group/project-lombok" rel="noopener">Discuss / Help</a></li>
+ <li><a href="https://github.com/rzwitserloot/lombok/issues" rel="noopener">Issues</a></li>
+ <li><a href="/contributing">Contribute</a></li>
+ </ul>
+ </li>
+ <li>
+ <a href="/order-license-info">
+ <span>Order / Donate</span>
+ </a>
+ </li>
+ <li class="dropdown">
+ <a href="/setup/overview" class="smallOnly"><span>Install</span></a>
+ <a class="dropdown-toggle pointer wideOnly" data-toggle="dropdown">Install<span class="caret"></span></a>
+ <ul class="dropdown-menu" aria-labelledby="themes">
+ <#list setupTargets as cat, tgtList>
+ <li class="header">${cat}</li>
+ <#list tgtList as name, url>
+ <li class="target"><a href="/setup/${url}">${name}</a></li>
+ </#list>
+ <#sep><li class="divider"></li></#sep>
+ </#list>
+ </ul>
+ </li>
+ <li><a href="/download">Download</a></li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ <div class="container-fluid main-section" id="main-section">
+ <#nested>
+ </div>
+ <footer class="container">
+ <footer class="footer text-center">
+ <div class="container">
+ <a href="/credits">credits</a> | Copyright &copy; 2009-${year} The Project Lombok
+ Authors, licensed under the <a href="http://www.opensource.org/licenses/mit-license.php">MIT
+ license</a>.
+ </div>
+ </footer>
+ </footer>
+ </body>
+</html>
+</#macro>
+
+<#macro h1 title class="">
+<#assign idvalue="*"?no_esc + "${title}"/>
+<h1 class="${class}" id="${idvalue?markup_string?replace("[ _]", "-", "r")?lower_case?replace("[^a-zA-Z0-9-]", "", "r")}">${title}</h1>
+</#macro>
+
+<#macro h2 title class="">
+<#assign idvalue="*"?no_esc + "${title}"/>
+<h2 class="${class}" id="${idvalue?markup_string?replace("[ _]", "-", "r")?lower_case?replace("[^a-zA-Z0-9-]", "", "r")}">${title}</h2>
+</#macro>
+
+<#macro h3 title class="">
+<#assign idvalue="*"?no_esc + "${title}"/>
+<h3 class="${class}" id="${idvalue?markup_string?replace("[ _]", "-", "r")?lower_case?replace("[^a-zA-Z0-9-]", "", "r")}">${title}</h3>
+</#macro>
diff --git a/website/templates/all-versions.html b/website/templates/all-versions.html
new file mode 100644
index 00000000..0207b351
--- /dev/null
+++ b/website/templates/all-versions.html
@@ -0,0 +1,31 @@
+<#import "/_scaffold.html" as main>
+<@main.scaffold title="older versions">
+ <div class="page-header top5">
+ <div>
+ <div>
+ <h1 class="text-center">
+ <div class="row">
+ <icon class="fa fa-download"></icon>
+ <a class="currentVersion" href="downloads/lombok.jar">
+ ${version} [Current Version]
+ </a>
+ </div>
+ </h1>
+ </div>
+ <#list linksToVersions as lnk>
+ <div class="row">
+ <icon class="fa fa-download"></icon>
+ <a class="oldVersion" href="${lnk[0]}">${lnk[1]}</a>
+ </div>
+ </#list>
+ <div class="row">
+ <div class="text-center">
+ <h3>
+ Feeling adventurous? Download the latest <a href="/download-edge">snapshot</a>
+ release.
+ </h3>
+ </div>
+ </div>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/changelog.html b/website/templates/changelog.html
new file mode 100644
index 00000000..79ba7b2a
--- /dev/null
+++ b/website/templates/changelog.html
@@ -0,0 +1,8 @@
+<#import "/_scaffold.html" as main>
+<@main.scaffold title="changelog">
+ <div class="page-header top5">
+ <div class="row text-center changelog">
+ ${changelog?no_esc}
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/contributing.html b/website/templates/contributing.html
new file mode 100644
index 00000000..16d68f32
--- /dev/null
+++ b/website/templates/contributing.html
@@ -0,0 +1,40 @@
+<#import "/_scaffold.html" as main>
+
+<@main.scaffold title="Contribute">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <@main.h1 title="Contributing to Project Lombok's development" />
+ </div><div class="row">
+ You can choose to <a href="/order-license-info">become a project lombok licensee or support us on patreon</a>.
+ </div>
+ <div class="row text-center">
+ <@main.h1 title="How to work on Project Lombok yourself" />
+ </div><div class="row">
+ Project Lombok is being developed via the <a href="https://github.com/rzwitserloot/lombok">lombok git repository on github</a>.
+ </div><div class="row">
+ <p>
+ If you want to start development on lombok, clone the repository and run <code>ant eclipse</code> or <code>ant intellij</code>, then open the working directory as a project in eclipse / intellij. Because the main contributors of lombok all use eclipse, that'll probably work a little more smoothly.
+ </p><p>
+ To produce a lombok jar, run <code>ant dist</code>; in general run <code>ant -p</code>; there's lots of stuff there, including downloading various versions of java runtimes to run the test suite against, and building this website.
+ </p>
+ </div><div class="row text-center">
+ <@main.h2 title="Adding your own handlers and annotations to Lombok" />
+ </div><div class="row">
+ <p>
+ If you want to extend lombok, we advise that you fork lombok and add handlers directly into the same place and package that lombok's handlers are in (<code>lombok.javac.handlers</code> and <code>lombok.eclipse.handlers</code>) – lombok does some fancy footwork to ensure various modular class loading systems don't interface with finding the lombok classes, but that system is not (currently) easily expanded to include separate jars.
+ </p>
+ </div><div class="row text-center">
+ <@main.h2 title="Contributing to Project Lombok" />
+ </div><div class="row">
+ <p>
+ To create new features and add them to project lombok itself, send us pull requests via github. However, before you start, discuss the feature or fix you'd like to contribute, preferably via the <a href="https://groups.google.com/forum/#!forum/project-lombok">Project Lombok Forum</a>. If you're going to add a new feature, make sure to post 2 snippets (one with the annotation, the other with what that would generate), similar to how the feature pages list 'with lombok' and 'without lombok' variants.
+ </p><p>
+ We've considered many designs and features amongst ourselves and with the community, and often there are complications or interesting design choices that have already been mentioned. We'd like to share them with you before you set out.
+ </p><p>
+ Pull requests for new features that haven't been discussed are unlikely to be accepted. Of course, if you've already built a proof of concept implementation prior to bringing a new idea to the forum, we'll take it that much more seriously.
+ </p><p>
+ Happy coding!
+ </p>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/credits.html b/website/templates/credits.html
new file mode 100644
index 00000000..3390d762
--- /dev/null
+++ b/website/templates/credits.html
@@ -0,0 +1,50 @@
+<#import "/_scaffold.html" as main>
+
+<@main.scaffold title="Credits">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <@main.h1 title="Project Lombok - About the authors and everyone that's helped us create Project Lombok." />
+ </div>
+ <div class="row">
+ <div class="credits">
+ <div class="committers personList">
+ <@main.h3 title="Regular contributors to Project Lombok:" />
+
+ <div class="row text-center">
+ <div class="person col-md-2">
+ <div class="imgCt"><img class="reinierImg" src="/img/reinier.jpg" /></div>
+ <span class="name">Reinier Zwitserloot</span>
+ </div>
+ <div class="person col-md-2">
+ <div class="imgCt"><img class="roelImg" src="/img/roel.jpg" /></div>
+ <span class="name">Roel Spilker</span>
+ </div>
+ </div>
+ </div>
+ <div class="thanks">
+ We'd like to thank:
+ <ul>
+ <li>
+ <strong>Perry Nguyen</strong> (pfn on ##java on freenode) for creating the inspiration for project lombok.
+ </li><li>
+ <strong>Tor Norbye</strong>, <strong>Jan Lahoda</strong>, and <strong>Petr Jiricka</strong> for helping out with Netbeans internals and/or javac.
+ </li><li>
+ All contributors who submitted patches or helped answering questions!</li>
+ </ul>
+
+ as well as the authors of the following tools that we use:
+
+ <ul>
+ <li>
+ <a href="https://github.com/">Github</a> for hosting lombok's repository and issue tracker.
+ </li><li>
+ The <a href="http://asm.ow2.org/index.html">ASM team</a> at ObjectWeb for creating an excellent class file editing tool. Lombok uses ASM to interact with Eclipse.
+ </li><li>
+ <strong>Markus Gebhard</strong> for creating <a href="http://java2html.de/">java2html</a> which we use for the example code snippets on the features pages.
+ </li>
+ </ul>
+ </div>
+ </div>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/disable-checked-exceptions.html b/website/templates/disable-checked-exceptions.html
new file mode 100644
index 00000000..4a758b11
--- /dev/null
+++ b/website/templates/disable-checked-exceptions.html
@@ -0,0 +1,28 @@
+<#import "/_scaffold.html" as main>
+
+<@main.scaffold title="Disable Checked Exceptions">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <h1 class="text-center">Tired of checked exceptions?</h1>
+ </div>
+ <div class="row">
+ <p>
+ This lombok spinoff project consists of a hack that only works in javac - not eclipse or any other IDE.<br />
+ It will completely disable the notion of checked exceptions. You may throw any exception anywhere, and you may also catch any exception anywhere. In standard javac, you may not catch a checked exception that is not declared as thrown by at least 1 statement in your try block, unless it is <code>Exception</code> or <code>Throwable</code>.<br />
+ This restriction is lifted as well.
+ </p>
+ </div>
+ <div class="row">
+ <h2 class="text-center">Usage</h2>
+
+ <p>
+ Just make sure <code>disableCheckedExceptions-alpha.jar</code> is on the classpath as you compile. For example:<br />
+ <code>javac -cp disableCheckedExceptions-alpha.jar MySource.java</code>
+ </p><p>
+ Ready to try it out? download it here: <a href="/downloads/disableCheckedExceptions-alpha.jar">disableCheckedExceptions-alpha.jar</a>
+ </p><p>
+ Want to know how its done? Grab the lombok repository <a href="https://github.com/rzwitserloot/lombok/tree/disableCheckedExceptions">here on github</a>, and look in the <code>experimental</code> directory.
+ </p>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/download-edge.html b/website/templates/download-edge.html
new file mode 100644
index 00000000..22044842
--- /dev/null
+++ b/website/templates/download-edge.html
@@ -0,0 +1,8 @@
+<#import "/_scaffold.html" as main>
+<@main.scaffold title="snapshot">
+ <div class="page-header top5">
+ <div class="row text-center versionInfo">
+ No edge build has been released since the last <a href="/download">stable release</a> of lombok.
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/download.html b/website/templates/download.html
new file mode 100644
index 00000000..3eb5787b
--- /dev/null
+++ b/website/templates/download.html
@@ -0,0 +1,38 @@
+<#import "/_scaffold.html" as main>
+<@main.scaffold title="Download">
+ <div class="page-header top5">
+ <div>
+ <div class="row page-center">
+ <div>
+ <h1 class="text-center">
+ <div class="row">
+ <icon class="fa fa-download"></icon>
+ <a href="/downloads/lombok.jar">
+ Download <span id="currentVersion">${version}</span>
+ <span id="currentVersionFull" style="display: none;">${fullVersion}</span>
+ </a>
+ </div>
+ </h1>
+ </div>
+ <div class="row">
+ <a href="/changelog">
+ changelog
+ </a>
+ </div>
+ <div class="row">
+ <a href="/all-versions">
+ older versions
+ </a>
+ </div>
+ </div>
+ <div class="row">
+ <div class="text-center">
+ <h3>
+ Feeling adventurous? Download the latest <a href="/download-edge">snapshot</a>
+ release.
+ </h3>
+ </div>
+ </div>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/features/Builder.html b/website/templates/features/Builder.html
new file mode 100644
index 00000000..96a30d99
--- /dev/null
+++ b/website/templates/features/Builder.html
@@ -0,0 +1,163 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Builder" logline="... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!">
+ <@f.history>
+ <p>
+ <code>@Builder</code> was introduced as experimental feature in lombok v0.12.0.
+ </p><p>
+ <code>@Builder</code> gained <code>@Singular</code> support and was promoted to the main <code>lombok</code> package since lombok v1.16.0.
+ </p><p>
+ <code>@Builder</code> with <code>@Singular</code> adds a clear method since lombok v1.16.8.
+ </p><p>
+ <code>@Builder.Default</code> functionality was added in lombok v1.16.16.
+ </p>
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ The <code>@Builder</code> annotation produces complex builder APIs for your classes.
+ </p><p>
+ <code>@Builder</code> lets you automatically produce the code required to have your class be instantiable with code such as:<br />
+ <code>Person.builder().name("Adam Savage").city("San Francisco").job("Mythbusters").job("Unchained Reaction").build();</code>
+ </p><p>
+ <code>@Builder</code> can be placed on a class, or on a constructor, or on a method. While the "on a class" and "on a constructor" mode are the most common use-case, <code>@Builder</code> is most easily explained with the "method" use-case.
+ </p><p>
+ A method annotated with <code>@Builder</code> (from now on called the <em>target</em>) causes the following 7 things to be generated:
+ <ul>
+ <li>
+ An inner static class named <code><em>Foo</em>Builder</code>, with the same type arguments as the static method (called the <em>builder</em>).
+ </li><li>
+ In the <em>builder</em>: One private non-static non-final field for each parameter of the <em>target</em>.
+ </li><li>
+ In the <em>builder</em>: A package private no-args empty constructor.
+ </li><li>
+ In the <em>builder</em>: A 'setter'-like method for each parameter of the <em>target</em>: It has the same type as that parameter and the same name. It returns the builder itself, so that the setter calls can be chained, as in the above example.
+ </li><li>
+ In the <em>builder</em>: A <code>build()</code> method which calls the method, passing in each field. It returns the same type that the <em>target</em> returns.
+ </li><li>
+ In the <em>builder</em>: A sensible <code>toString()</code> implementation.
+ </li><li>
+ In the class containing the <em>target</em>: A <code>builder()</code> method, which creates a new instance of the <em>builder</em>.
+ </li>
+ </ul>
+ Each listed generated element will be silently skipped if that element already exists (disregarding parameter counts and looking only at names). This includes the <em>builder</em> itself: If that class already exists, lombok will simply start injecting fields and methods inside this already existing class, unless of course the fields / methods to be injected already exist. You may not put any other method (or constructor) generating lombok annotation on a builder class though; for example, you can not put <code>@EqualsAndHashCode</code> on the builder class.
+ </p><p>
+ <code>@Builder</code> can generate so-called 'singular' methods for collection parameters/fields. These take 1 element instead of an entire list, and add the element to the list. For example: <code>Person.builder().job("Mythbusters").job("Unchained Reaction").build();</code> would result in the <code>List&lt;String&gt; jobs</code> field to have 2 strings in it. To get this behaviour, the field/parameter needs to be annotated with <code>@Singular</code>. The feature has <a href="#singular">its own documentation</a>.
+ </p><p>
+ Now that the "method" mode is clear, putting a <code>@Builder</code> annotation on a constructor functions similarly; effectively, constructors are just static methods that have a special syntax to invoke them: Their 'return type' is the class they construct, and their type parameters are the same as the type parameters of the class itself.
+ </p><p>
+ Finally, applying <code>@Builder</code> to a class is as if you added <code>@AllArgsConstructor(access = AccessLevel.PACKAGE)</code> to the class and applied the <code>@Builder</code> annotation to this all-args-constructor. This only works if you haven't written any explicit constructors yourself. If you do have an explicit constructor, put the <code>@Builder</code> annotation on the constructor instead of on the class.
+ </p><p>
+ If using <code>@Builder</code> to generate builders to produce instances of your own class (this is always the case unless adding <code>@Builder</code> to a method that doesn't return your own type), you can use <code>@Builder(toBuilder = true)</code> to also generate an instance method in your class called <code>toBuilder()</code>; it creates a new builder that starts out with all the values of this instance. You can put the <code>@Builder.ObtainVia</code> annotation on the parameters (in case of a constructor or method) or fields (in case of <code>@Builder</code> on a type) to indicate alternative means by which the value for that field/parameter is obtained from this instance. For example, you can specify a method to be invoked: <code>@Builder.ObtainVia(method = "calculateFoo")</code>.
+ </p><p>
+ The name of the builder class is <code><em>Foobar</em>Builder</code>, where <em>Foobar</em> is the simplified, title-cased form of the return type of the <em>target</em> - that is, the name of your type for <code>@Builder</code> on constructors and types, and the name of the return type for <code>@Builder</code> on methods. For example, if <code>@Builder</code> is applied to a class named <code>com.yoyodyne.FancyList&lt;T&gt;</code>, then the builder name will be <code>FancyListBuilder&lt;T&gt;</code>. If <code>@Builder</code> is applied to a method that returns <code>void</code>, the builder will be named <code>VoidBuilder</code>.
+ </p><p>
+ The configurable aspects of builder are:
+ <ul>
+ <li>
+ The <em>builder's class name</em> (default: return type + 'Builder')
+ </li><li>
+ The <em>build()</em> method's name (default: <code>"build"</code>)
+ </li><li>
+ The <em>builder()</em> method's name (default: <code>"builder"</code>)
+ </li><li>
+ If you want <code>toBuilder()</code> (default: no)
+ </li>
+ </ul>
+ Example usage where all options are changed from their defaults:<br />
+ <code>@Builder(builderClassName = "HelloWorldBuilder", buildMethodName = "execute", builderMethodName = "helloWorld", toBuilder = true)</code><br />
+ </p>
+ </@f.overview>
+
+ <@f.featureSection>
+ <h3 id="builderdefault"><a name="builderdefault">@Builder.Default</a></h3>
+
+ <p>
+ If a certain field/parameter is never set during a build session, then it always gets 0 / <code>null</code> / false. If you've put <code>@Builder</code> on a class (and not a method or constructor) you can instead specify the default directly on the field, and annotate the field with <code>@Builder.Default</code>:<br />
+ <code>@Builder.Default private final long created = System.currentTimeMillis();</code>
+ </p>
+ </@f.featureSection>
+
+ <@f.featureSection>
+ <h3 id="singular"><a name="singular">@Singular</a></h3>
+
+ <p>
+ By annotating one of the parameters (if annotating a method or constructor with <code>@Builder</code>) or fields (if annotating a class with <code>@Builder</code>) with the <code>@Singular</code> annotation, lombok will treat that builder node as a collection, and it generates 2 'adder' methods instead of a 'setter' method. One which adds a single element to the collection, and one which adds all elements of another collection to the collection. No setter to just set the collection (replacing whatever was already added) will be generated. A 'clear' method is also generated. These 'singular' builders are very complicated in order to guarantee the following properties:
+ <ul>
+ <li>
+ When invoking <code>build()</code>, the produced collection will be immutable.
+ </li><li>
+ Calling one of the 'adder' methods, or the 'clear' method, after invoking <code>build()</code> does not modify any already generated objects, and, if <code>build()</code> is later called again, another collection with all the elements added since the creation of the builder is generated.
+ </li><li>
+ The produced collection will be compacted to the smallest feasible format while remaining efficient.
+ </li>
+ </ul>
+ </p><p>
+ <code>@Singular</code> can only be applied to collection types known to lombok. Currently, the supported types are:
+ <ul>
+ <li>
+ <a href="https://docs.oracle.com/javase/8/docs/api/java/util/package-summary.html"><code>java.util</code></a>:
+ <ul>
+ <li>
+ <code>Iterable</code>, <code>Collection</code>, and <code>List</code> (backed by a compacted unmodifiable <code>ArrayList</code> in the general case).
+ </li><li>
+ <code>Set</code>, <code>SortedSet</code>, and <code>NavigableSet</code> (backed by a smartly sized unmodifiable <code>HashSet</code> or <code>TreeSet</code> in the general case).
+ </li><li>
+ <code>Map</code>, <code>SortedMap</code>, and <code>NavigableMap</code> (backed by a smartly sized unmodifiable <code>HashMap</code> or <code>TreeMap</code> in the general case).
+ </li>
+ </ul>
+ </li><li>
+ <a href="https://github.com/google/guava">Guava</a>'s <code>com.google.common.collect</code>:
+ <ul>
+ <li>
+ <code>ImmutableCollection</code> and <code>ImmutableList</code> (backed by the builder feature of <code>ImmutableList</code>).
+ </li><li>
+ <code>ImmutableSet</code> and <code>ImmutableSortedSet</code> (backed by the builder feature of those types).
+ </li><li>
+ <code>ImmutableMap</code>, <code>ImmutableBiMap</code>, and <code>ImmutableSortedMap</code> (backed by the builder feature of those types).
+ </li><li>
+ <code>ImmutableTable</code> (backed by the builder feature of <code>ImmutableTable</code>).
+ </li>
+ </ul>
+ </li>
+ </ul>
+ </p><p>
+ If your identifiers are written in common english, lombok assumes that the name of any collection with <code>@Singular</code> on it is an english plural and will attempt to automatically singularize that name. If this is possible, the add-one method will use this name. For example, if your collection is called <code>statuses</code>, then the add-one method will automatically be called <code>status</code>. You can also specify the singular form of your identifier explictly by passing the singular form as argument to the annotation like so: <code>@Singular("axis") List&lt;Line&gt; axes;</code>.<br />
+ If lombok cannot singularize your identifier, or it is ambiguous, lombok will generate an error and force you to explicitly specify the singular name.
+ </p><p>
+ The snippet below does not show what lombok generates for a <code>@Singular</code> field/parameter because it is rather complicated. You can view a snippet <a href="builderSingular">here</a>.
+ </p>
+ </@f.featureSection>
+
+ <@f.snippets name="Builder" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.builder.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Builder</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.singular.useGuava</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If <code>true</code>, lombok will use guava's <code>ImmutableXxx</code> builders and types to implement <code>java.util</code> collection interfaces, instead of creating implementations based on <code>Collections.unmodifiableXxx</code>. You must ensure that guava is actually available on the classpath and buildpath if you use this setting. Guava is used automatically if your field/parameter has one of the guava <code>ImmutableXxx</code> types.
+ </dd><dt>
+ <code>lombok.singular.auto</code> = [<code>true</code> | <code>false</code>] (default: true)
+ </dt><dd>
+ If <code>true</code> (which is the default), lombok automatically tries to singularize your identifier name by assuming that it is a common english plural. If <code>false</code>, you must always explicitly specify the singular name, and lombok will generate an error if you don't (useful if you write your code in a language other than english).
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ @Singular support for <code>java.util.NavigableMap/Set</code> only works if you are compiling with JDK1.8 or higher.
+ </p><p>
+ You cannot manually provide some or all parts of a <code>@Singular</code> node; the code lombok generates is too complex for this. If you want to manually control (part of) the builder code associated with some field or parameter, don't use <code>@Singular</code> and add everything you need manually.
+ </p><p>
+ The sorted collections (java.util: <code>SortedSet</code>, <code>NavigableSet</code>, <code>SortedMap</code>, <code>NavigableMap</code> and guava: <code>ImmutableSortedSet</code>, <code>ImmutableSortedMap</code>) require that the type argument of the collection has natural order (implements <code>java.util.Comparable</code>). There is no way to pass an explicit <code>Comparator</code> to use in the builder.
+ </p><p>
+ An <code>ArrayList</code> is used to store added elements as call methods of a <code>@Singular</code> marked field, if the target collection is from the <code>java.util</code> package, <em>even if the collection is a set or map</em>. Because lombok ensures that generated collections are compacted, a new backing instance of a set or map must be constructed anyway, and storing the data as an <code>ArrayList</code> during the build process is more efficient that storing it as a map or set. This behaviour is not externally visible, an implementation detail of the current implementation of the <code>java.util</code> recipes for <code>@Singular @Builder</code>.
+ </p><p>
+ With <code>toBuilder = true</code> applied to methods, any type parameter of the annotated method itself must also show up in the return type.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/BuilderSingular.html b/website/templates/features/BuilderSingular.html
new file mode 100644
index 00000000..10253365
--- /dev/null
+++ b/website/templates/features/BuilderSingular.html
@@ -0,0 +1,5 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Builder @Singular" logline="... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!">
+ <@f.snippets name="Singular-snippet" />
+</@f.scaffold>
diff --git a/website/templates/features/Cleanup.html b/website/templates/features/Cleanup.html
new file mode 100644
index 00000000..e868c40d
--- /dev/null
+++ b/website/templates/features/Cleanup.html
@@ -0,0 +1,35 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Cleanup" logline="Automatic resource management: Call your <code>close()</code> methods safely with no hassle.">
+ <@f.overview>
+ <p>
+ You can use <code>@Cleanup</code> to ensure a given resource is automatically cleaned up before the code execution path exits your current scope. You do this by annotating any local variable declaration with the <code>@Cleanup</code> annotation like so:<br />
+ <code>@Cleanup InputStream in = new FileInputStream("some/file");</code><br />
+ As a result, at the end of the scope you're in, <code>in.close()</code> is called. This call is guaranteed to run by way of a try/finally construct. Look at the example below to see how this works.
+ </p><p>
+ If the type of object you'd like to cleanup does not have a <code>close()</code> method, but some other no-argument method, you can specify the name of this method like so:<br />
+ <code>@Cleanup("dispose") org.eclipse.swt.widgets.CoolBar bar = new CoolBar(parent, 0);</code><br />
+ By default, the cleanup method is presumed to be <code>close()</code>. A cleanup method that takes 1 or more arguments cannot be called via <code>@Cleanup</code>.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="Cleanup" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.cleanup.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt></dd>
+ Lombok will flag any usage of <code>@Cleanup</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ In the finally block, the cleanup method is only called if the given resource is not <code>null</code>. However, if you use <code>delombok</code> on the code, a call to <code>lombok.Lombok.preventNullAnalysis(Object o)</code> is inserted to prevent warnings if static code analysis could determine that a null-check would not be needed. Compilation with <code>lombok.jar</code> on the classpath removes that method call, so there is no runtime dependency.
+ </p><p>
+ If your code throws an exception, and the cleanup method call that is then triggered also throws an exception, then the original exception is hidden by the exception thrown by the cleanup call. You should <em>not</em> rely on this 'feature'. Preferably, lombok would like to generate code so that, if the main body has thrown an exception, any exception thrown by the close call is silently swallowed (but if the main body exited in any other way, exceptions by the close call will not be swallowed). The authors of lombok do not currently know of a feasible way to implement this scheme, but if java updates allow it, or we find a way, we'll fix it.
+ </p><p>
+ You do still need to handle any exception that the cleanup method can generate!
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/Data.html b/website/templates/features/Data.html
new file mode 100644
index 00000000..59370cc8
--- /dev/null
+++ b/website/templates/features/Data.html
@@ -0,0 +1,41 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Data"
+ logline="All together now: A shortcut for <code>@ToString</code>, <code>@EqualsAndHashCode</code>, <code>@Getter</code> on all fields, <code>@Setter</code> on all non-final fields, and <code>@RequiredArgsConstructor</code>!">
+
+ <@f.overview>
+ <p>
+ <code>@Data</code> is a convenient shortcut annotation that bundles the features of <a href="/features/ToString"><code>@ToString</code></a>, <a href="/features/EqualsAndHashCode"><code>@EqualsAndHashCode</code></a>, <a href="/features/GetterSetter"><code>@Getter</code> / <code>@Setter</code></a> and <a href="/features/constructor"><code>@RequiredArgsConstructor</code></a> together: In other words, <code>@Data</code> generates <em>all</em> the boilerplate that is normally associated with simple POJOs (Plain Old Java Objects) and beans: getters for all fields, setters for all non-final fields, and appropriate <code>toString</code>, <code>equals</code> and <code>hashCode</code> implementations that involve the fields of the class, and a constructor that initializes all final fields, as well as all non-final fields with no initializer that have been marked with <code>@NonNull</code>, in order to ensure the field is never null.
+ </p><p>
+ <code>@Data</code> is like having implicit <code>@Getter</code>, <code>@Setter</code>, <code>@ToString</code>, <code>@EqualsAndHashCode</code> and <code>@RequiredArgsConstructor</code> annotations on the class (except that no constructor will be generated if any explicitly written constructors already exist). However, the parameters of these annotations (such as <code>callSuper</code>, <code>includeFieldNames</code> and <code>exclude</code>) cannot be set with <code>@Data</code>. If you need to set non-default values for any of these parameters, just add those annotations explicitly; <code>@Data</code> is smart enough to defer to those annotations.
+ </p><p>
+ All generated getters and setters will be <code>public</code>. To override the access level, annotate the field or class with an explicit <code>@Setter</code> and/or <code>@Getter</code> annotation. You can also use this annotation (by combining it with <code>AccessLevel.NONE</code>) to suppress generating a getter and/or setter altogether.
+ </p><p>
+ All fields marked as <code>transient</code> will not be considered for <code>hashCode</code> and <code>equals</code>. All static fields will be skipped entirely (not considered for any of the generated methods, and no setter/getter will be made for them).
+ </p><p>
+ If the class already contains a method with the same name and parameter count as any method that would normally be generated, that method is not generated, and no warning or error is emitted. For example, if you already have a method with signature <code>equals(AnyType param)</code>, no <code>equals</code> method will be generated, even though technically it might be an entirely different method due to having different parameter types. The same rule applies to the constructor (any explicit constructor will prevent <code>@Data</code> from generating one), as well as <code>toString</code>, <code>equals</code>, and all getters and setters. You can mark any constructor or method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
+ </p><p>
+ <code>@Data</code> can handle generics parameters for fields just fine. In order to reduce the boilerplate when constructing objects for classes with generics, you can use the <code>staticConstructor</code> parameter to generate a private constructor, as well as a static method that returns a new instance. This way, javac will infer the variable name. Thus, by declaring like so: <code>@Data(staticConstructor="of") class Foo&lt;T&gt; { private T x;}</code> you can create new instances of <code>Foo</code> by writing: <code>Foo.of(5);</code> instead of having to write: <code>new Foo&lt;Integer&gt;(5);</code>.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="Data" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.data.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Data</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ See the small print of <a href="/features/ToString"><code>@ToString</code></a>, <a href="/features/EqualsAndHashCode"><code>@EqualsAndHashCode</code></a>, <a href="/features/GetterSetter"><code>@Getter / @Setter</code></a> and <a href="/features/constructor">@RequiredArgsConstructor</a>.
+ </p><p>
+ Any annotations named <code>@NonNull</code> (case insensitive) on a field are interpreted as: This field must not ever hold <em>null</em>. Therefore, these annotations result in an explicit null check in the generated constructor for the provided field. Also, these annotations (as well as any annotation named <code>@Nullable</code>) are copied to the constructor parameter, in both the true constructor and any static constructor. The same principle applies to generated getters and setters (see the documentation for <a href="/features/GetterSetter">@Getter / @Setter</a>)
+ </p><p>
+ By default, any variables that start with a $ symbol are excluded automatically. You can include them by specifying an explicit annotation (<code>@Getter</code> or <code>@ToString</code>, for example) and using the 'of' parameter.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/EqualsAndHashCode.html b/website/templates/features/EqualsAndHashCode.html
new file mode 100644
index 00000000..3c11367f
--- /dev/null
+++ b/website/templates/features/EqualsAndHashCode.html
@@ -0,0 +1,56 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@EqualsAndHashCode" logline="Equality made easy: Generates <code>hashCode</code> and <code>equals</code> implementations from the fields of your object.">
+ <@f.overview>
+ <p>
+ Any class definition may be annotated with <code>@EqualsAndHashCode</code> to let lombok generate implementations of the <code>equals(Object other)</code> and <code>hashCode()</code> methods. By default, it'll use all non-static, non-transient fields, but you can exclude more fields by naming them in the optional <code>exclude</code> parameter to the annotation. Alternatively, you can specify exactly which fields you wish to be used by naming them in the <code>of</code> parameter.
+ </p><p>
+ If applying <code>@EqualsAndHashCode</code> to a class that extends another, this feature gets a bit trickier. Normally, auto-generating an <code>equals</code> and <code>hashCode</code> method for such classes is a bad idea, as the superclass also defines fields, which also need equals/hashCode code but this code will not be generated. By setting <code>callSuper</code> to <em>true</em>, you can include the <code>equals</code> and <code>hashCode</code> methods of your superclass in the generated methods. For <code>hashCode</code>, the result of <code>super.hashCode()</code> is included in the hash algorithm, and for<code>equals</code>, the generated method will return false if the super implementation thinks it is not equal to the passed in object. Be aware that not all <code>equals</code> implementations handle this situation properly. However, lombok-generated <code>equals</code> implementations <strong>do</strong> handle this situation properly, so you can safely call your superclass equals if it, too, has a lombok-generated <code>equals</code> method. If you have an explicit superclass you are forced to supply some value for <code>callSuper</code> to acknowledge that you've considered it; failure to do so results in a warning.
+ </p><p>
+ Setting <code>callSuper</code> to <em>true</em> when you don't extend anything (you extend <code>java.lang.Object</code>) is a compile-time error, because it would turn the generated <code>equals()</code> and <code>hashCode()</code> implementations into having the same behaviour as simply inheriting these methods from <code>java.lang.Object</code>: only the same object will be equal to each other and will have the same hashCode. Not setting <code>callSuper</code> to <em>true</em> when you extend another class generates a warning, because unless the superclass has no (equality-important) fields, lombok cannot generate an implementation for you that takes into account the fields declared by your superclasses. You'll need to write your own implementations, or rely on the <code>callSuper</code> chaining facility. You can also use the <code>lombok.equalsAndHashCode.callSuper</code> config key.
+ </p><p>
+ <em>NEW in Lombok 0.10: </em>Unless your class is <code>final</code> and extends <code>java.lang.Object</code>, lombok generates a <code>canEqual</code> method which means JPA proxies can still be equal to their base class, but subclasses that add new state don't break the equals contract. The complicated reasons for why such a method is necessary are explained in this paper: <a href="https://www.artima.com/lejava/articles/equality.html">How to Write an Equality Method in Java</a>. If all classes in a hierarchy are a mix of scala case classes and classes with lombok-generated equals methods, all equality will 'just work'. If you need to write your own equals methods, you should always override <code>canEqual</code> if you change <code>equals</code> and <code>hashCode</code>.
+ </p><p>
+ <em>NEW in Lombok 1.14.0: </em>To put annotations on the <code>other</code> parameter of the <code>equals</code> (and, if relevant, <code>canEqual</code>) method, you can use <code>onParam=@__({@AnnotationsHere})</code>. Be careful though! This is an experimental feature. For more details see the documentation on the <a ng-click="toFeature('on-x')">onX</a> feature.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="EqualsAndHashCode" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.equalsAndHashCode.doNotUseGetters</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, lombok will access fields directly instead of using getters (if available) when generating <code>equals</code> and <code>hashCode</code> methods. The annotation parameter '<code>doNotUseGetters</code>', if explicitly specified, takes precedence over this setting.
+ </dd><dt>
+ <code>lombok.equalsAndHashCode.callSuper</code> = [<code>call</code> | <code>skip</code> | <code>warn</code>] (default: warn)
+ </dt><dd>
+ If set to <code>call</code>, lombok will generate calls to the superclass implementation of <code>hashCode</code> and <code>equals</code> if your class extends something. If set to <code>skip</code> no such calls are generated. The default behaviour is like <code>skip</code>, with an additional warning.
+ </dd><dt>
+ <code>lombok.equalsAndHashCode.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@EqualsAndHashCode</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Arrays are 'deep' compared/hashCoded, which means that arrays that contain themselves will result in <code>StackOverflowError</code>s. However, this behaviour is no different from e.g. <code>ArrayList</code>.
+ </p><p>
+ You may safely presume that the hashCode implementation used will not change between versions of lombok, however this guarantee is not set in stone; if there's a significant performance improvement to be gained from using an alternate hash algorithm, that will be substituted in a future version.
+ </p><p>
+ For the purposes of equality, 2 <code>NaN</code> (not a number) values for floats and doubles are considered equal, eventhough 'NaN == NaN' would return false. This is analogous to <code>java.lang.Double</code>'s equals method, and is in fact required to ensure that comparing an object to an exact copy of itself returns <code>true</code> for equality.
+ </p><p>
+ If there is <em>any</em> method named either <code>hashCode</code> or <code>equals</code>, regardless of return type, no methods will be generated, and a warning is emitted instead. These 2 methods need to be in sync with each other, which lombok cannot guarantee unless it generates all the methods, hence you always get a warning if one <em>or</em> both of the methods already exist. You can mark any method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
+ </p><p>
+ Attempting to exclude fields that don't exist or would have been excluded anyway (because they are static or transient) results in warnings on the named fields. You therefore don't have to worry about typos.
+ </p><p>
+ Having both <code>exclude</code> and <code>of</code> generates a warning; the <code>exclude</code> parameter will be ignored in that case.
+ </p><p>
+ By default, any variables that start with a $ symbol are excluded automatically. You can onlyinclude them by using the 'of' parameter.
+ </p><p>
+ If a getter exists for a field to be included, it is called instead of using a direct field reference. This behaviour can be suppressed:<br />
+ <code>@EqualsAndHashCode(doNotUseGetters = true)</code>
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/GetterLazy.html b/website/templates/features/GetterLazy.html
new file mode 100644
index 00000000..b1f374a8
--- /dev/null
+++ b/website/templates/features/GetterLazy.html
@@ -0,0 +1,31 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Getter(lazy=true)" logline="Laziness is a virtue!">
+ <@f.history>
+ <code>@Getter(lazy=true)</code> was introduced in Lombok v0.10.
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ You can let lombok generate a getter which will calculate a value once, the first time this getter is called, and cache it from then on. This can be useful if calculating the value takes a lot of CPU, or the value takes a lot of memory. To use this feature, create a <code>private final</code> variable, initialize it with the expression that's expensive to run, and annotate your field with <code>@Getter(lazy=true)</code>. The field will be hidden from the rest of your code, and the expression will be evaluated no more than once, when the getter is first called. There are no magic marker values (i.e. even if the result of your expensive calculation is <code>null</code>, the result is cached) and your expensive calculation need not be thread-safe, as lombok takes care of locking.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="GetterLazy" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.getter.lazy.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Getter(lazy=true)</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ You should never refer to the field directly, always use the getter generated by lombok, because the type of the field will be mangled into an <code>AtomicReference</code>. Do not try to directly access this <code>AtomicReference</code>; if it points to itself, the value has been calculated, and it is <code>null</code>. If the reference points to <code>null</code>, then the value has not been calculated. This behaviour may change in future versions. Therefore, <em>always</em> use the generated getter to access your field!
+ </p><p>
+ Other Lombok annotations such as <code>@ToString</code> always call the getter even if you use <code>doNotUseGetters=true</code>.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/GetterSetter.html b/website/templates/features/GetterSetter.html
new file mode 100644
index 00000000..1baa5bd0
--- /dev/null
+++ b/website/templates/features/GetterSetter.html
@@ -0,0 +1,70 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Getter and @Setter" logline="Never write <code>public int getFoo() {return foo;}</code> again.">
+ <@f.overview>
+ <p>
+ You can annotate any field with <code>@Getter</code> and/or <code>@Setter</code>, to let lombok generate the default getter/setter automatically.<br />
+ A default getter simply returns the field, and is named <code>getFoo</code> if the field is called <code>foo</code> (or <code>isFoo</code> if the field's type is <code>boolean</code>). A default setter is named <code>setFoo</code> if the field is called <code>foo</code>, returns <code>void</code>, and takes 1 parameter of the same type as the field. It simply sets the field to this value.
+ </p><p>
+ The generated getter/setter method will be <code>public</code> unless you explicitly specify an <code>AccessLevel</code>, as shown in the example below. Legal access levels are <code>PUBLIC</code>, <code>PROTECTED</code>, <code>PACKAGE</code>, and <code>PRIVATE</code>.
+ </p><p>
+ You can also put a <code>@Getter</code> and/or <code>@Setter</code> annotation on a class. In that case, it's as if you annotate all the non-static fields in that class with the annotation.
+ </p><p>
+ You can always manually disable getter/setter generation for any field by using the special <code>AccessLevel.NONE</code> access level. This lets you override the behaviour of a <code>@Getter</code>, <code>@Setter</code> or <code>@Data</code> annotation on a class.
+ </p><p>
+ To put annotations on the generated method, you can use <code>onMethod=@__({@AnnotationsHere})</code>; to put annotations on the only parameter of a generated setter method, you can use <code>onParam=@__({@AnnotationsHere})</code>. Be careful though! This is an experimental feature. For more details see the documentation on the <a href="/features/experimental/onX">onX</a> feature.
+ </p><p>
+ <em>NEW in lombok v1.12.0:</em> javadoc on the field will now be copied to generated getters and setters. Normally, all text is copied, and <code>@return</code> is <em>moved</em> to the getter, whilst <code>@param</code> lines are <em>moved</em> to the setter. Moved means: Deleted from the field's javadoc. It is also possible to define unique text for each getter/setter. To do that, you create a 'section' named <code>GETTER</code> and/or <code>SETTER</code>. A section is a line in your javadoc containing 2 or more dashes, then the text 'GETTER' or 'SETTER', followed by 2 or more dashes, and nothing else on the line. If you use sections, <code>@return</code> and <code>@param</code> stripping for that section is no longer done (move the <code>@return</code> or <code>@param</code> line into the section).
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="GetterSetter" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.accessors.chain</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, generated setters will return <code>this</code> (instead of <code>void</code>). An explicitly configured <code>chain</code> parameter of an <a href="/features/experimental/Accessors"><code>@Accessors</code></a> annotation takes precedence over this setting.
+ </dd><dt>
+ <code>lombok.accessors.fluent</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, generated getters and setters will not be prefixed with the bean-standard '<code>get</code>, <code>is</code> or <code>set</code>; instead, the methods will use the same name as the field (minus prefixes). An explicitly configured <code>chain</code> parameter of an <a href="/features/experimental/Accessors"><code>@Accessors</code></a> annotation takes precedence over this setting.
+ </dd><dt>
+ <code>lombok.accessors.prefix</code> += <em>a field prefix</em> (default: empty list)
+ </dt><dd>
+ This is a list property; entries can be added with the <code>+=</code> operator. Inherited prefixes from parent config files can be removed with the <code>-=</code> operator. Lombok will strip any matching field prefix from the name of a field in order to determine the name of the getter/setter to generate. For example, if <code>m</code> is one of the prefixes listed in this setting, then a field named <code>mFoobar</code> will result in a getter named <code>getFoobar()</code>, not <code>getMFoobar()</code>. An explicitly configured <code>prefix</code> parameter of an <a href="/features/experimental/Accessors"><code>@Accessors</code></a> annotation takes precedence over this setting.
+ </dd><dt>
+ <code>lombok.getter.noIsPrefix</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, getters generated for <code>boolean</code> fields will use the <code>get</code> prefix instead of the default<code>is</code> prefix, and any generated code that calls getters, such as <code>@ToString</code>, will also use <code>get</code> instead of <code>is</code>
+ </dd><dt>
+ <code>lombok.setter.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Setter</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.getter.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Getter</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ For generating the method names, the first character of the field, if it is a lowercase character, is title-cased, otherwise, it is left unmodified. Then, get/set/is is prefixed.
+ </p><p>
+ No method is generated if any method already exists with the same name (case insensitive) and same parameter count. For example, <code>getFoo()</code> will not be generated if there's already a method <code>getFoo(String... x)</code> even though it is technically possible to make the method. This caveat exists to prevent confusion. If the generation of a method is skipped for this reason, a warning is emitted instead. Varargs count as 0 to N parameters. You can mark any method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
+ </p><p>
+ For <code>boolean</code> fields that start with <code>is</code> immediately followed by a title-case letter, nothing is prefixed to generate the getter name.
+ </p><p>
+ Any variation on <code>boolean</code> will <em>not</em> result in using the <code>is</code> prefix instead of the <code>get</code> prefix; for example, returning <code>java.lang.Boolean</code> results in a <code>get</code> prefix, not an <code>is</code> prefix.
+ </p><p>
+ Any annotations named <code>@NonNull</code> (case insensitive) on the field are interpreted as: This field must not ever hold <em>null</em>. Therefore, these annotations result in an explicit null check in the generated setter. Also, these annotations (as well as any annotation named <code>@Nullable</code> or <code>@CheckForNull</code>) are copied to setter parameter and getter method.
+ </p><p>
+ You can annotate a class with a <code>@Getter</code> or <code>@Setter</code> annotation. Doing so is equivalent to annotating all non-static fields in that class with that annotation. <code>@Getter</code>/<code>@Setter</code> annotations on fields take precedence over the ones on classes.
+ </p><p>
+ Using the <code>AccessLevel.NONE</code> access level simply generates nothing. It's useful only in combination with <a href="/features/Data"><code>@Data</code></a> or a class-wide <code>@Getter</code> or <code>@Setter</code>.
+ </p><p>
+ <code>@Getter</code> can also be used on enums. <code>@Setter</code> can't, not for a technical reason, but for a pragmatic one: Setters on enums are an extremely bad idea.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/NonNull.html b/website/templates/features/NonNull.html
new file mode 100644
index 00000000..28d083d0
--- /dev/null
+++ b/website/templates/features/NonNull.html
@@ -0,0 +1,45 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@NonNull" logline="or: How I learned to stop worrying and love the NullPointerException.">
+ <@f.history>
+ <code>@NonNull</code> was introduced in lombok v0.11.10.
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ You can use <code>@NonNull</code> on the parameter of a method or constructor to have lombok generate a null-check statement for you.
+ </p><p>
+ Lombok has always treated any annotation named <code>@NonNull</code> on a field as a signal to generate a null-check if lombok generates an entire method or constructor for you, via for example <a href="/features/Data"><code>@Data</code></a>. Now, however, using lombok's own <code>@lombok.NonNull</code> on a parameter results in the insertion of just the null-check statement inside your own method or constructor.
+ </p><p>
+ The null-check looks like <code>if (param == null) throw new NullPointerException("param");</code> and will be inserted at the very top of your method. For constructors, the null-check will be inserted immediately following any explicit <code>this()</code> or <code>super()</code> calls.
+ </p><p>
+ If a null-check is already present at the top, no additional null-check will be generated.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="NonNull" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.nonNull.exceptionType</code> = [<code>NullPointerException</code> | <code>IllegalArgumentException</code>] (default: <code>NullPointerException</code>).
+ </dt><dd>
+ When lombok generates a null-check <code>if</code> statement, by default, a <code>java.lang.NullPointerException</code> will be thrown with the field name as the exception message. However, you can use <code>IllegalArgumentException</code> in this configuration key to have lombok throw that exception, with '<em>fieldName</em> is null' as exception message.
+ </dd><dt>
+ <code>lombok.nonNull.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@NonNull</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Lombok's detection scheme for already existing null-checks consists of scanning for if statements that look just like lombok's own. Any 'throws' statement as the 'then' part of the if statement, whether in braces or not, counts. The conditional of the if statement <em>must</em> look exactly like <code>PARAMNAME == null</code>. The first statement in your method that is not such a null-check stops the process of inspecting for null-checks.
+ </p><p>
+ While <code>@Data</code> and other method-generating lombok annotations will trigger on any annotation named <code>@NonNull</code> regardless of casing or package name, this feature only triggers on lombok's own <code>@NonNull</code> annotation from the <code>lombok</code> package.
+ </p><p>
+ A <code>@NonNull</code> on a primitive parameter results in a warning. No null-check will be generated.
+ </p><p>
+ A <code>@NonNull</code> on a parameter of an abstract method used to generate a warning; starting with version 1.16.8, this is no longer the case, to acknowledge the notion that <code>@NonNull</code> also has a documentary role. For the same reason, you can annotate a method as <code>@NonNull</code>; this is allowed, generates no warning, and does not generate any code.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/SneakyThrows.html b/website/templates/features/SneakyThrows.html
new file mode 100644
index 00000000..5a2d5bbd
--- /dev/null
+++ b/website/templates/features/SneakyThrows.html
@@ -0,0 +1,44 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@SneakyThrows" logline="To boldly throw checked exceptions where no one has thrown them before!">
+ <@f.overview>
+ <p>
+ <code>@SneakyThrows</code> can be used to sneakily throw checked exceptions without actually declaring this in your method's <code>throws</code> clause. This somewhat contentious ability should be used carefully, of course. The code generated by lombok will not ignore, wrap, replace, or otherwise modify the thrown checked exception; it simply fakes out the compiler. On the JVM (class file) level, all exceptions, checked or not, can be thrown regardless of the <code>throws</code> clause of your methods, which is why this works.
+ </p><p>
+ Common use cases for when you want to opt out of the checked exception mechanism center around 2 situations:<br />
+ <ul>
+ <li>
+ A needlessly strict interface, such as <code>Runnable</code> - whatever exception propagates out of your <code>run()</code> method, checked or not, it will be passed to the <code>Thread</code>'s unhandled exception handler. Catching a checked exception and wrapping it in some sort of <code>RuntimeException</code> is only obscuring the real cause of the issue.
+ </li><li>
+ An 'impossible' exception. For example, <code>new String(someByteArray, "UTF-8");</code> declares that it can throw an <code>UnsupportedEncodingException</code> but according to the JVM specification, UTF-8 <em>must</em> always be available. An <code>UnsupportedEncodingException</code> here is about as likely as a <code>ClassNotFoundError</code> when you use a String object, and you don't catch those either!
+ </li>
+ </ul>
+ </p><p>
+ Be aware that it is <em>impossible</em> to catch sneakily thrown checked types directly, as javac will not let you write a catch block for an exception type that no method call in the try body declares as thrown. This problem is not relevant in either of the use cases listed above, so let this serve as a warning that you should not use the <code>@SneakyThrows</code> mechanism without some deliberation!
+ </p><p>
+ You can pass any number of exceptions to the <code>@SneakyThrows</code> annotation. If you pass no exceptions, you may throw any exception sneakily.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="SneakyThrows" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.sneakyThrows.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@SneakyThrows</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Because <code>@SneakyThrows</code> is an implementation detail and not part of your method signature, it is an error if you try to declare a checked exception as sneakily thrown when you don't call any methods that throw this exception. (Doing so is perfectly legal for <code>throws</code> statements to accommodate subclasses). Similarly, <code>@SneakyThrows</code> does not inherit.
+ </p><p>
+ For the nay-sayers in the crowd: Out of the box, Eclipse will offer a 'quick-fix' for uncaught exceptions that wraps the offending statement in a try/catch block with just <code>e.printStackTrace()</code> in the catch block. This is so spectacularly non-productive compared to just sneakily throwing the exception onwards, that Roel and Reinier feel more than justified in claiming that the checked exception system is far from perfect, and thus an opt-out mechanism is warranted.
+ </p><p>
+ If you put <code>@SneakyThrows</code> on a constructor, any call to a sibling or super constructor is <em>excluded</em> from the <code>@SneakyThrows</code> treatment. This is a java restriction we cannot work around: Calls to sibling/super constructors MUST be the first statement in the constructor; they cannot be placed inside try/catch blocks.
+ </p><p>
+ <code>@SneakyThrows</code> on an empty method, or a constructor that is empty or only has a call to a sibling / super constructor results in no try/catch block and a warning.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/Synchronized.html b/website/templates/features/Synchronized.html
new file mode 100644
index 00000000..113add0e
--- /dev/null
+++ b/website/templates/features/Synchronized.html
@@ -0,0 +1,34 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Synchronized" logline="<code>synchronized</code> done right: Don't expose your locks.">
+ <@f.overview>
+ <p>
+ <code>@Synchronized</code> is a safer variant of the <code>synchronized</code> method modifier. Like <code>synchronized</code>, the annotation can be used on static and instance methods only. It operates similarly to the <code>synchronized</code> keyword, but it locks on different objects. The keyword locks on <code>this</code>, but the annotation locks on a field named <code>$lock</code>, which is private.<br />
+ If the field does not exist, it is created for you. If you annotate a <code>static</code> method, the annotation locks on a static field named <code>$LOCK</code> instead.
+ </p><p>
+ If you want, you can create these locks yourself. The <code>$lock</code> and <code>$LOCK</code> fields will of course not be generated if you already created them yourself. You can also choose to lock on another field, by specifying it as parameter to the <code>@Synchronized</code> annotation. In this usage variant, the fields will not be created automatically, and you must explicitly create them yourself, or an error will be emitted.
+ </p><p>
+ Locking on <code>this</code> or your own class object can have unfortunate side-effects, as other code not under your control can lock on these objects as well, which can cause race conditions and other nasty threading-related bugs.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="Synchronized" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.synchronized.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Synchronized</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ If <code>$lock</code> and/or <code>$LOCK</code> are auto-generated, the fields are initialized with an empty <code>Object[]</code> array, and not just a <code>new Object()</code> as most snippets showing this pattern in action use. Lombok does this because a new object is <em>NOT</em> serializable, but 0-size array is. Therefore, using <code>@Synchronized</code> will not prevent your object from being serialized.
+ </p><p>
+ Having at least one <code>@Synchronized</code> method in your class means there will be a lock field, but if you later remove all such methods, there will no longer be a lock field. That means your predetermined <code>serialVersionUID</code> changes. We suggest you <em>always</em> add a <code>serialVersionUID</code> to your classes if you intend to store them long-term via java's serialization mechanism. If you do so, removing all <code>@Synchronized</code> annotations from your method will not break serialization.
+ </p><p>
+ If you'd like to know why a field is not automatically generated when you choose your own name for the lock object: Because otherwise making a typo in the field name will result in a <em>very</em> hard to find bug!
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/ToString.html b/website/templates/features/ToString.html
new file mode 100644
index 00000000..6f230561
--- /dev/null
+++ b/website/templates/features/ToString.html
@@ -0,0 +1,54 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@ToString" logline="No need to start a debugger to see your fields: Just let lombok generate a <code>toString</code> for you!">
+ <@f.overview>
+ <p>
+ Any class definition may be annotated with <code>@ToString</code> to let lombok generate an implementation of the <code>toString()</code> method. By default, it'll print your class name, along with each field, in order, separated by commas.
+ </p><p>
+ By setting the <code>includeFieldNames</code> parameter to <em>true</em> you can add some clarity (but also quite some length) to the output of the <code>toString()</code> method.
+ </p><p>
+ By default, all non-static fields will be printed. If you want to skip some fields, you can name them in the <code>exclude</code> parameter; each named field will not be printed at all. Alternatively, you can specify exactly which fields you wish to be used by naming them in the <code>of</code> parameter.
+ </p><p>
+ By setting <code>callSuper</code> to <em>true</em>, you can include the output of the superclass implementation of <code>toString</code> to the output. Be aware that the default implementation of <code>toString()</code> in <code>java.lang.Object</code> is pretty much meaningless, so you probably don't want to do this unless you are extending another class.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="ToString" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.toString.includeFieldNames</code> = [<code>true</code> | <code>false</code>] (default: true)
+ </dt><dd>
+ Normally lombok generates a fragment of the toString response for each field in the form of <code>fieldName = fieldValue</code>. If this setting is set to <code>false</code>, lombok will omit the name of the field and simply deploy a comma-separated list of all the field values. The annotation parameter '<code>includeFieldNames</code>', if explicitly specified, takes precedence over this setting.
+ </dd><dt>
+ <code>lombok.toString.doNotUseGetters</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, lombok will access fields directly instead of using getters (if available) when generating <code>toString</code> methods. The annotation parameter '<code>doNotUseGetters</code>', if explicitly specified, takes precedence over this setting.
+ </dd><dt>
+ <code>lombok.toString.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@ToString</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ If there is <em>any</em> method named <code>toString</code> with no arguments, regardless of return type, no method will be generated, and instead a warning is emitted explaining that your <code>@ToString</code> annotation is doing nothing. You can mark any method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
+ </p><p>
+ Arrays are printed via <code>Arrays.deepToString</code>, which means that arrays that contain themselves will result in <code>StackOverflowError</code>s. However, this behaviour is no different from e.g. <code>ArrayList</code>.
+ </p><p>
+ Attempting to exclude fields that don't exist or would have been excluded anyway (because they are static) results in warnings on the named fields. You therefore don't have to worry about typos.
+ </p><p>
+ Having both <code>exclude</code> and <code>of</code> generates a warning; the <code>exclude</code> parameter will be ignored in that case.
+ </p><p>
+ We don't promise to keep the output of the generated <code>toString()</code> methods the same between lombok versions. You should never design your API so that other code is forced to parse your <code>toString()</code> output anyway!
+ </p><p>
+ By default, any variables that start with a $ symbol are excluded automatically. You can only include them by using the 'of' parameter.
+ </p><p>
+ If a getter exists for a field to be included, it is called instead of using a direct field reference. This behaviour can be suppressed:<br />
+ <code>@ToString(doNotUseGetters = true)</code>
+ </p><p>
+ <code>@ToString</code> can also be used on an enum definition.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/Value.html b/website/templates/features/Value.html
new file mode 100644
index 00000000..fdad0e12
--- /dev/null
+++ b/website/templates/features/Value.html
@@ -0,0 +1,50 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Value" logline="Immutable classes made very easy.">
+ <@f.history>
+ <p>
+ <code>@Value</code> was introduced as experimental feature in lombok v0.11.4.
+ </p><p>
+ <code>@Value</code> no longer implies <code>@Wither</code> since lombok v0.11.8.
+ </p><p>
+ <code>@Value</code> promoted to the main <code>lombok</code> package since lombok v0.12.0.
+ </p>
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ <code>@Value</code> is the immutable variant of <a href="/features/Data"><code>@Data</code></a>; all fields are made <code>private</code> and <code>final</code> by default, and setters are not generated. The class itself is also made <code>final</code> by default, because immutability is not something that can be forced onto a subclass. Like <code>@Data</code>, useful <code>toString()</code>, <code>equals()</code> and <code>hashCode()</code> methods are also generated, each field gets a getter method, and a constructor that covers every argument (except <code>final</code> fields that are initialized in the field declaration) is also generated.
+ </p><p>
+ In practice, <code>@Value</code> is shorthand for: <code>final @ToString @EqualsAndHashCode @AllArgsConstructor @FieldDefaults(makeFinal = true, level = AccessLevel.PRIVATE) @Getter</code>, except that explicitly including an implementation of any of the relevant methods simply means that part won't be generated and no warning will be emitted. For example, if you write your own <code>toString</code>, no error occurs, and lombok will not generate a <code>toString</code>. Also, <em>any</em> explicit constructor, no matter the arguments list, implies lombok will not generate a constructor. If you do want lombok to generate the all-args constructor, add <code>@AllArgsConstructor</code> to the class. You can mark any constructor or method with <code>@lombok.experimental.Tolerate</code> to hide them from lombok.
+ </p><p>
+ It is possible to override the final-by-default and private-by-default behavior using either an explicit access level on a field, or by using the <code>@NonFinal</code> or <code>@PackagePrivate</code> annotations.<br />
+ It is possible to override any default behavior for any of the 'parts' that make up <code>@Value</code> by explicitly using that annotation.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="Value" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.value.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Value</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.val.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>val</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Look for the documentation on the 'parts' of <code>@Value</code>: <a href="/features/ToString"><code>@ToString</code></a>, <a href="/features/EqualsAndHashCode"><code>@EqualsAndHashCode</code></a>, <a href="/features/Constructor"><code>@AllArgsConstructor</code></a>, <a href="/features/experimental/FieldDefaults"><code>@FieldDefaults</code></a>, and <a href="/features/GetterSetter"><code>@Getter</code></a>.
+ </p><p>
+ For classes with generics, it's useful to have a static method which serves as a constructor, because inference of generic parameters via static methods works in java6 and avoids having to use the diamond operator. While you can force this by applying an explicit <code>@AllArgsConstructor(staticConstructor="of")</code> annotation, there's also the <code>@Value(staticConstructor="of")</code> feature, which will make the generated all-arguments constructor private, and generates a public static method named <code>of</code> which is a wrapper around this private constructor.
+ </p><p>
+ <code>@Value</code> was an experimental feature from v0.11.4 to v0.11.9 (as <code>@lombok.experimental.Value</code>). It has since been moved into the core package. The old annotation is still around (and is an alias). It will eventually be removed in a future version, though.
+ </p><p>
+ It is not possible to use <code>@FieldDefaults</code> to 'undo' the private-by-default and final-by-default aspect of fields in the annotated class. Use <code>@NonFinal</code> and <code>@PackagePrivate</code> on the fields in the class to override this behaviour.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/_features.html b/website/templates/features/_features.html
new file mode 100644
index 00000000..f602b95b
--- /dev/null
+++ b/website/templates/features/_features.html
@@ -0,0 +1,79 @@
+<#import "/_scaffold.html" as main>
+
+<#macro featureSection>
+ <div class="row">
+ <#nested>
+ </div>
+</#macro>
+
+<#macro history>
+ <div class="row">
+ <#nested>
+ </div>
+</#macro>
+
+<#macro overview>
+ <div class="row">
+ <@main.h3 title="Overview" />
+ <#nested>
+ </div>
+</#macro>
+
+<#macro experimental>
+ <div class="row">
+ <@main.h3 title="Experimental" />
+
+ Experimental because:
+ <#nested>
+ </div>
+</#macro>
+
+<#macro snippets name>
+ <div class="row container-fluid">
+ <div class="snippet-col first-snippet">
+ <@main.h3 title="With Lombok" />
+
+ <div class="snippet">${usages.pre(name)?no_esc}</div>
+ </div>
+ <div class="sep"></div>
+ <div class="snippet-col second-snippet">
+ <@main.h3 title="Vanilla Java" />
+
+ <div class="snippet">${usages.post(name)?no_esc}</div>
+ </div>
+ </div>
+</#macro>
+
+<#macro confKeys>
+ <div class="row">
+ <@main.h3 title="Supported configuration keys:" />
+ <dl>
+ <#nested>
+ </dl>
+ </div>
+</#macro>
+
+<#macro smallPrint>
+ <div class="row">
+ <@main.h3 title="Small print" />
+
+ <div class="smallprint">
+ <#nested>
+ </div>
+ </div>
+</#macro>
+
+<#macro scaffold title logline load=[]>
+ <@main.scaffold load title>
+ <div class="page-header top5" id="featureContent">
+ <div class="row text-center">
+ <div class="header-group">
+ <@main.h1 title="${title}" />
+
+ <@main.h3 title="${logline?no_esc}" />
+ </div>
+ </div>
+ <#nested>
+ </div>
+ </@main.scaffold>
+</#macro>
diff --git a/website/templates/features/configuration.html b/website/templates/features/configuration.html
new file mode 100644
index 00000000..4f861287
--- /dev/null
+++ b/website/templates/features/configuration.html
@@ -0,0 +1,114 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="Configuration system" logline="Lombok, made to order: Configure lombok features in one place for your entire project or even your workspace.">
+ <@f.history>
+ The configuration system was introduced in lombok 1.14.
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ You can create <code>lombok.config</code> files in any directory and put configuration directives in it. These apply to all source files in this directory and all child directories.<br />
+ The configuration system is particularly useful for configurable aspects of lombok which tend to be the same across an entire project, such as the name of your log variable. The configuration system can also be used to tell lombok to flag any usage of some lombok feature you don't like as a warning or even an error.
+ </p><p>
+ Usually, a user of lombok puts a <code>lombok.config</code> file with their preferences in a workspace or project root directory, with the special <code>config.stopBubbling = true</code> key to tell lombok this is your root directory. You can then create <code>lombok.config</code> files in any subdirectories (generally representing projects or source packages) with different settings.
+ </p><p>
+ An up to date list of all configuration keys supported by your version of lombok can be generated by running:
+ <div class="snippet example">
+ <code>java -jar lombok.jar config -g --verbose</code>
+ </div>
+ The output of the <em>config</em> tool is itself a valid <code>lombok.config</code> file.<br />
+ The <em>config</em> tool can also be used to display the complete lombok configuration used for any given directory or source file by supplying these as arguments.
+ </p><p>
+ A sample of available configuration options (see the feature pages of the lombok features for their related config keys, as well as <code>java -jar lombok.jar config -g</code> for the complete list):
+ <dl>
+ <dt>
+ <code>lombok.accessors.chain</code>
+ </dt><dd>
+ If set to <code>true</code>, generated setters will 'chain' by default (They will return <code>this</code> instead of having a <code>void</code> return type).
+ </dd><dt>
+ <code>lombok.accessors.fluent</code>
+ </dt><dd>
+ If set to <code>true</code>, generated setters and getters will simply be named the same as the field name, without a <code>get</code> or <code>set</code> prefix.
+ </dd><dt>
+ <code>lombok.anyConstructor.suppressConstructorProperties</code>
+ </dt><dd>
+ If <code>true</code>, lombok will not generate a <code>@java.beans.ConstructorProperties</code> annotation when generating constructors. This is particularly useful for GWT and Android development.
+ </dd><dt>
+ <code>lombok.log.fieldName</code>
+ </dt><dd>
+ The name of the generated log field (default: <code>log</code>).
+ </dd><dt>
+ <code>lombok.<em>(featureName)</em>.flagUsage</code>
+ </dt><dd>
+ Allows you to forcibly stop or discourage use of a lombok feature. Legal values for this key are <code>warning</code> or <code>error</code>. Some examples of values for <em>(featureName)</em> are: "<code>experimental</code>" (flags use of any of the <a href="/features/experimental">experimental</a> features)</li>, "<a href="/features/Builder"><code>builder</code></a>", "<a
+ href="/features/SneakyThrows"><code>sneakyThrows</code></a>", or "<a href="/features/experimental/ExtensionMethod"><code>extensionMethod</code></a>".
+ </dd>
+ </dl>
+ </p><p>
+ Configuration files are hierarchical: Any configuration setting applies to all source files in that directory, and all source files in subdirectories, but configuration settings closer to the source file take precedence. For example, if you have in <code>/Users/me/projects/lombok.config</code> the following:
+ <div class="snippet example">
+ <code>lombok.log.fieldName = foobar</code>
+ </div>
+ and in <code>/Users/me/projects/MyProject/lombok.config</code> you have:
+ <div class="snippet example">
+ <code>lombok.log.fieldName = xyzzy</code>
+ </div>
+ Then the various <a ng-click="toFeature('log')"><code>@Log</code></a> annotations will use <code>foobar</code> instead of the default <code>log</code> as a field name to generate in all your projects, except for your project in <code>/Users/me/projects/MyProject</code>, where <code>xyzzy</code> is used instead.
+ </p><p>
+ To restore a configuration key set by a parent config file back to the default, the <code>clear</code> option can be used. For example, if a parent configuration file has configured all use of <code>val</code> to emit a warning, you can turn off the warnings for a subdirectory by including in it a <code>lombok.config</code> file with:
+ <div class="snippet example">
+ <code>clear lombok.val.flagUsage</code>
+ </div>
+ </p><p>
+ Some configuration keys take lists. For lists, use <code>+=</code> to add an entry. You can remove a single item from the list (useful to undo a parent configuration file's setting) with <code>-=</code>. For example:
+ <div class="snippet example">
+ <code>lombok.accessors.prefix += m_</code>
+ </div>
+ </p><p>
+ Comments can be included in <code>lombok.config</code> files; any line that starts with <code>#</code> is considered a comment.
+ </p>
+ </@f.overview>
+
+ <@f.featureSection>
+ <@f.main.h3 title="Global config keys" />
+
+ <p>
+ To stop lombok from looking at parent directories for more configuration files, the special key:
+ <div class="snippet example">
+ <code>config.stopBubbling = true</code>
+ </div>
+ can be included. We suggest you put this in the root of your workspace directory.
+ </p><p>
+ Lombok can add <code>@javax.annotation.Generated</code> annotations to all generated nodes where possible. You can enable this with:
+ <div class="snippet example">
+ <code>lombok.addJavaxGeneratedAnnotation = true</code>
+ </div>
+ We advise against this; JDK9 breaks this annotation, and it's unlikely to ever get fixed.<br />
+ <em>NB:</em> Until Lombok v2.0.0, this setting defaulted to <code>true</code>.
+ </p><p>
+ Lombok can be configured to add <code>@lombok.Generated</code> annotations to all generated nodes where possible; useful for JaCoCo (which has built in support),
+ or other style checkers and code coverage tools:
+ <div class="snippet example">
+ <code>lombok.addLombokGeneratedAnnotation = true</code>
+ </div>
+ </p><p>
+ Lombok can add the <code>@SuppressFBWarnings</code> annotation which is useful if you want to run <a href="http://findbugs.sourceforge.net/">FindBugs</a> on your class files. To enable this feature, make sure findbugs is on the classpath when you compile, and add the following config key:
+ <div class="snippet example">
+ <code>lombok.extern.findbugs.addSuppressFBWarnings = true</code>
+ </div>
+ </p>
+ </@f.featureSection>
+
+ <@f.featureSection>
+ <@f.main.h3 title="Config keys that can affect any source file" />
+
+ <p>
+ These config keys can make lombok affect source files even if they have 0 lombok annotations in them.<br />
+ <div class="snippet example">
+ <code>lombok.fieldDefaults.defaultPrivate = true</code><br />
+ <code>lombok.fieldDefaults.defaultFinal = true</code>
+ </div>
+ Turning either of these options on means lombok will make <em>every</em> field in <em>every</em> source file final and/or private unless it has an explicit access modifier or annotation to suppress this. <a href="experimental/FieldDefaults">See the <code>@FieldDefaults</code> documentation for more</a>.
+ </p>
+ </@f.featureSection>
+</@f.scaffold>
diff --git a/website/templates/features/constructor.html b/website/templates/features/constructor.html
new file mode 100644
index 00000000..716efe5a
--- /dev/null
+++ b/website/templates/features/constructor.html
@@ -0,0 +1,57 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@NoArgsConstructor, @RequiredArgsConstructor, @AllArgsConstructor"
+ logline="Constructors made to order: Generates constructors that take no arguments, one argument per final / non-null field, or one argument for every field.">
+
+ <@f.overview>
+ <p>
+ This set of 3 annotations generate a constructor that will accept 1 parameter for certain fields, and simply assigns this parameter to the field.
+ </p><p>
+ <code>@NoArgsConstructor</code> will generate a constructor with no parameters. If this is not possible (because of final fields), a compiler error will result instead, unless <code>@NoArgsConstructor(force = true)</code> is used, then all final fields are initialized with <code>0</code> / <code>false</code> / <code>null</code>. For fields with constraints, such as <code>@NonNull</code> fields, <em>no</em> check is generated,so be aware that these constraints will generally not be fulfilled until those fields are properly initialized later. Certain java constructs, such as hibernate and the Service Provider Interface require a no-args constructor. This annotation is useful primarily in combination with either <code>@Data</code> or one of the other constructor generating annotations.
+ </p><p>
+ <code>@RequiredArgsConstructor</code> generates a constructor with 1 parameter for each field that requires special handling. All non-initialized <code>final</code> fields get a parameter, as well as any fields that are marked as <code>@NonNull</code> that aren't initialized where they are declared. For those fields marked with <code>@NonNull</code>, an explicit null check is also generated. The constructor will throw a <code>NullPointerException</code> if any of the parameters intended for the fields marked with <code>@NonNull</code> contain <code>null</code>. The order of the parameters match the order in which the fields appear in your class.
+ </p><p>
+ <code>@AllArgsConstructor</code> generates a constructor with 1 parameter for each field in your class. Fields marked with <code>@NonNull</code> result in null checks on those parameters.
+ </p><p>
+ Each of these annotations allows an alternate form, where the generated constructor is always private, and an additional static factory method that wraps around the private constructor is generated. This mode is enabled by supplying the <code>staticName</code> value for the annotation, like so: <code>@RequiredArgsConstructor(staticName="of")</code>. Such a static factory method will infer generics, unlike a normal constructor. This means your API users get write <code>MapEntry.of("foo", 5)</code> instead of the much longer <code>new MapEntry&lt;String, Integer&gt;("foo", 5)</code>.
+ </p><p>
+ To put annotations on the generated constructor, you can use <code>onConstructor=@__({@AnnotationsHere})</code>, but be careful; this is an experimental feature. For more details see the documentation on the <a href="/features/experimental/onX">onX</a> feature.
+ </p><p>
+ Static fields are skipped by these annotations. Also, a <code>@java.beans.ConstructorProperties</code> annotation is added for all constructors with at least 1 argument, which allows bean editor tools to call the generated constructors. <code>@ConstructorProperties</code> is new in Java 1.6, which means that if your code is intended for compilation on Java 1.5, a compiler error will occur. <em>Running</em> on a JVM 1.5 should be no problem (the annotation will be ignored). To suppress the generation of the <code>@ConstructorProperties</code> annotation, add a parameter to your annotation: <code>@AllArgsConstructor(suppressConstructorProperties=true)</code>. However, as java 1.5, which has already been end-of-lifed, fades into obscurity, this parameter will eventually be removed. It has also been marked deprecated for this reason.
+ </p><p>
+ Unlike most other lombok annotations, the existence of an explicit constructor does not stop these annotations from generating their own constructor. This means you can write your own specialized constructor, and let lombok generate the boilerplate ones as well. If a conflict arises (one of your constructors ends up with the same signature as one that lombok generates), a compiler error will occur.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="Constructor" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.anyConstructor.suppressConstructorProperties</code> = [<code>true</code> | <code>false</code>] (default: <code>false</code>)
+ </dt><dd>
+ If set to <code>true</code>, then lombok will skip adding a <code>@java.beans.ConstructorProperties</code> to generated constructors. This is useful in android and GWT development where that annotation is not usually available.
+ </dd><dt>
+ <code>lombok.</code>[<code>allArgsConstructor</code>|<code>requiredArgsConstructor</code>|<code>noArgsConstructor</code>]<code>.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of the relevant annotation (<code>@AllArgsConstructor</code>, <code>@RequiredArgsConstructor</code> or <code>@NoArgsConstructor</code>) as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.anyConstructor.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of any of the 3 constructor-generating annotations as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Even if a field is explicitly initialized with <code>null</code>, lombok will consider the requirement to avoid null as fulfilled, and will <em>NOT</em> consider the field as a 'required' argument. The assumption is that if you explicitly assign <code>null</code> to a field that you've also marked as <code>@NonNull</code> signals you must know what you're doing.
+ </p><p>
+ The <code>@java.beans.ConstructorProperties</code> annotation is never generated for a constructor with no arguments. This also explains why <code>@NoArgsConstructor</code> lacks the <code>suppressConstructorProperties</code> annotation method. The generated static factory methods also do not get <code>@ConstructorProperties</code>, as this annotation can only be added to real constructors.
+ </p><p>
+ <code>@XArgsConstructor</code> can also be used on an enum definition. The generated constructor will always be private, because non-private constructors aren't legal in enums. You don't have to specify <code>AccessLevel.PRIVATE</code>.
+ </p><p>
+ While <code>suppressConstructorProperties</code> has been marked deprecated in anticipation of a world where all java environments have the <code>@ConstructorProperties</code> annotation available, first GWT 2.2 and Android 2.3.3, which do not (yet) have this annotation, will have to be ancient history before this annotation parameter will be removed.
+ </p><p>
+ The <code>flagUsage</code> configuration keys do not trigger when a constructor is generated by <code>@Data</code>, <code>@Value</code> or any other lombok annotation.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/delombok.html b/website/templates/features/delombok.html
new file mode 100644
index 00000000..6f41fc46
--- /dev/null
+++ b/website/templates/features/delombok.html
@@ -0,0 +1,61 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="Delombok" logline="">
+ <@f.overview>
+ <p>
+ Normally, lombok adds support for all the lombok features directly to your IDE and compiler by plugging into them.<br />
+ However, lombok doesn't cover all tools. For example, lombok cannot plug into javadoc, nor can it plug into the Google Widget Toolkit, both of which run on java sources. Delombok still allows you to use lombok with these tools by preprocessing your java code into java code with all of lombok's transformations already applied.
+ </p><p>
+ Delombok can of course also help understand what's happening with your source by letting you look at exactly what lombok is doing 'under the hood'.
+ </p><p>
+ Delombok's standard mode of operation is that it copies an entire directory into another directory, recursively, skipping class files, and applying lombok transformations to any java source files it encounters.
+ </p><p>
+ Delombok's output format can be configured with command line options (use <code>--format-help</code> for a complete list). A few such options are automatically scanned from input if possible (such as indent). If delombok's formatting is not conforming to your preferred code style, have a look!
+ </p>
+
+ <@f.main.h3 title="Running delombok on the command line" />
+
+ <p>
+ Delombok is included in <code>lombok.jar</code>. To use it, all you need to run on the command line is:
+ <div class="snippet">
+ <pre>java -jar lombok.jar delombok src -d src-delomboked</pre>
+ </div><br />
+ Which will duplicate the contents of the <code>src</code> directory into the <code>src-delomboked</code> directory, which will be created if it doesn't already exist, but delomboked of course. Delombok on the command line has a few more options; use the <code>--help</code> parameter to see more options.
+ </p><p>
+ To let delombok print the transformation result of a single java file directly to standard output, you can use:
+ <div class="snippet">
+ <pre>java -jar lombok.jar delombok -p MyJavaFile.java</pre>
+ </div>
+ </p>
+
+ <@f.main.h3 title="Running delombok in ant" />
+
+ <p>
+ <code>lombok.jar</code> includes an ant task which can apply delombok for you. For example, to create javadoc for your project, your <code>build.xml</code> file would look something like:
+ <div class="snippet"><pre>&lt;target name="javadoc"&gt;
+&lt;taskdef classname="lombok.delombok.ant.Tasks$Delombok" classpath="lib/lombok.jar" name="delombok" /&gt;
+&lt;mkdir dir="build/src-delomboked" /&gt;
+<strong>&lt;delombok verbose="true" encoding="UTF-8" to="build/src-delomboked" from="src"&gt;</strong>
+ <strong>&lt;format value="suppressWarnings:skip" /&gt;</strong>
+<strong>&lt;/delombok&gt;</strong>
+&lt;mkdir dir="build/api" /&gt;
+&lt;javadoc sourcepath="build/src-delomboked" defaultexcludes="yes" destdir="build/api" /&gt;
+&lt;/target&gt;</pre>
+ </div><br />
+ Instead of a <code>from</code> attribute, you can also nest <code>&lt;fileset&gt;</code> nodes.
+ </p>
+
+ <@f.main.h3 title="Running delombok in maven" />
+
+ <p>
+ Anthony Whitford has written a <a href="https://github.com/awhitford/lombok.maven">maven plugin</a> for delomboking your source code.
+ </p>
+
+ <@f.main.h3 title="Limitations" />
+
+ <p>
+ Delombok tries to preserve your code as much as it can, but comments may move around a little bit, especially comments that are in the middle of a syntax node. For example, any comments appearing in the middle of a list of method modifiers, such as <code>public /*comment*/ static ...</code> will move towards the front of the list of modifiers. In practice, any java source parsing tool will not be affected.<br />
+ To keep any changes to your code style to a minimum, delombok just copies a source file directly without changing any of it if the source file contains no lombok transformations.
+ </p>
+ </@f.overview>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/Accessors.html b/website/templates/features/experimental/Accessors.html
new file mode 100644
index 00000000..97017dc6
--- /dev/null
+++ b/website/templates/features/experimental/Accessors.html
@@ -0,0 +1,75 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@Accessors" logline="A more fluent API for getters and setters.">
+ <@f.history>
+ <p>
+ <code>@Accessors</code> was introduced as experimental feature in lombok v0.11.0.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ We may want to roll these features into a more complete property support concept.
+ </li><li>
+ New feature – community feedback requested.
+ </li>
+ </ul>
+ Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ The <code>@Accessors</code> annotation is used to configure how lombok generates and looks for getters and setters.
+ </p><p>
+ By default, lombok follows the <em>bean specification</em> for getters and setters: The getter for a field named <code>pepper</code> is <code>getPepper</code> for example. However, some might like to break with the <em>bean specification</em> in order to end up with nicer looking APIs. <code>@Accessors</code> lets you do this.
+ </p><p>
+ Some programmers like to use a prefix for their fields, i.e. they write <code>fPepper</code> instead of <code>pepper</code>. We <em>strongly</em> discourage doing this, as you can't unit test the validity of your prefixes, and refactor scripts may turn fields into local variables or method names. Furthermore, your tools (such as your editor) can take care of rendering the identifier in a certain way if you want this information to be instantly visible. Nevertheless, you can list the prefixes that your project uses via <code>@Accessors</code> as well.
+ </p><p>
+ <code>@Accessors</code> therefore has 3 options:
+ <ul>
+ <li>
+ <code>fluent</code> – A boolean. If <em>true</em>, the getter for <code>pepper</code> is just <code>pepper()</code>, and the setter is <code>pepper(T newValue)</code>. Furthermore, unless specified, <code>chain</code> defaults to <em>true</em>. <br />
+ Default: <em>false</em>.
+ </li><li>
+ <code>chain</code> – A boolean. If <em>true</em>, generated setters return <code>this</code> instead of <code>void</code>.<br />
+ Default: <em>false</em>, unless <code>fluent=true</code>, then Default: <em>true</em>.
+ </li><li>
+ <code>prefix</code> – A list of strings. If present, fields must be prefixed with any of these prefixes. Each field name is compared to each prefix in the list in turn, and if a match is found, the prefix is stripped out to create the base name for the field. It is legal to include an empty string in the list, which will always match. For characters which are letters, the character following the prefix must not be a lowercase letter, i.e. <code>pepper</code> is not a match even to prefix <code>p</code>, but <code>pEpper</code> would be (and would mean the base name of this field is <code>epper</code>).
+ </li>
+ </ul>
+ <p><p>
+ The <code>@Accessors</code> annotation is legal on types and fields; the annotation that applies is the one on the field if present, otherwise the one on the class. When a <code>@Accessors</code> annotation on a field is present, any <code>@Accessors</code> annotation also present on that field's type is ignored.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/Accessors" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.accessors.chain</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, any class that either doesn't have an <code>@Accessors</code> annotation, or it does, but that annotation does not have an explicit value for the <code>chain</code> parameter, will act as if <code>@Accessors(chain = true)</code> is present.
+ </dd><dt>
+ <code>lombok.accessors.fluent</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ If set to <code>true</code>, any class that either doesn't have an <code>@Accessors</code> annotation, or it does, but that annotation does not have an explicit value for the <code>fluent</code> parameter, will act as if <code>@Accessors(fluent = true)</code> is present.
+ </dd><dt>
+ <code>lombok.accessors.prefix</code> += <em>a field prefix</em> (default: empty list)
+ </dt><dd>
+ This is a list property; entries can be added with the <code>+=</code> operator. Inherited prefixes from parent config files can be removed with the <code>-=</code> operator. Any class that either doesn't have an <code>@Accessors</code> annotation, or it does, but that annotation does not have an explicit value for the <code>prefix</code> parameter, will act as if <code>@Accessors(prefix = {<em>prefixes listed in configuration</em>})</code> is present.
+ </dd><dt>
+ <code>lombok.accessors.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Accessors</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ The nearest <code>@Accessors</code> annotation is also used for the various methods in lombok that look for getters, such as <code>@EqualsAndHashCode</code>.
+ </p><p>
+ If a prefix list is provided and a field does not start with one of them, that field is skipped entirely by lombok, and a warning will be generated.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/Delegate.html b/website/templates/features/experimental/Delegate.html
new file mode 100644
index 00000000..265c754a
--- /dev/null
+++ b/website/templates/features/experimental/Delegate.html
@@ -0,0 +1,59 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@Delegate" logline="Don't lose your composition.">
+ <@f.history>
+ <p>
+ <code>@Delegate</code> was introduced as feature in lombok v0.10 (the experimental package did not exist yet).<br />
+ It was moved to the experimental package in lombok v1.14; the old version from the main lombok package is now deprecated.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ Not used that much.
+ </li><li>
+ Difficult to support for edge cases, such as recursive delegation.
+ </li><li>
+ API is rather unfriendly; it would be a lot nicer if you can simply implement some methods and let <code>@Delegate</code> generate delegates for whatever you didn't manually implement, but due to issues with generics erasure this also can't be made to work without caveats.
+ </li>
+ </ul>
+ Current status: <em>negative</em> - Currently we feel this feature will not move out of experimental status anytime soon, and support for this feature may be dropped if future versions of javac or ecj make it difficult to continue to maintain the feature.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ Any field or no-argument method can be annotated with <code>@Delegate</code> to let lombok generate delegate methods that forward the call to this field (or the result of invoking this method).
+ </p><p>
+ Lombok delegates all <code>public</code> methods of the field's type (or method's return type), as well as those of its supertypes except for all methods declared in <code>java.lang.Object</code>.
+ </p><p>
+ You can pass any number of classes into the <code>@Delegate</code> annotation's <code>types</code> parameter. If you do that, then lombok will delegate all <code>public</code> methods in those types (and their supertypes, except <code>java.lang.Object</code>) instead of looking at the field/method's type.
+ </p><p>
+ All public non-<code>Object</code> methods that are part of the calculated type(s) are copied, whether or not you also wrote implementations for those methods. That would thus result in duplicate method errors. You can avoid these by using the <code>@Delegate(excludes=SomeType.class)</code> parameter to exclude all public methods in the excluded type(s), and their supertypes.
+ </p><p>
+ To have very precise control over what is delegated and what isn't, write private inner interfaces with method signatures, then specify these private inner interfaces as types in <code>@Delegate(types=PrivateInnerInterfaceWithIncludesList.class, excludes=SameForExcludes.class)</code>.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/Delegate" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.delegate.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Delegate</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ When passing classes to the annotation's <code>types</code> or <code>excludes</code> parameter, you cannot include generics. This is a limitation of java. Use private inner interfaces or classes that extend the intended type including the generics parameter to work around this problem.
+ </p><p>
+ When passing classes to the annotation, these classes do not need to be supertypes of the field. See the example.
+ </p><p>
+ <code>@Delegate</code> cannot be used on static fields or methods.
+ </p><p>
+ <code>@Delegate</code> cannot be used when the calculated type(s) to delegate / exclude themselves contain <code>@Delegate</code> annotations; in other words, <code>@Delegate</code> will error if you attempt to use it recursively.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/ExtensionMethod.html b/website/templates/features/experimental/ExtensionMethod.html
new file mode 100644
index 00000000..f1d8b084
--- /dev/null
+++ b/website/templates/features/experimental/ExtensionMethod.html
@@ -0,0 +1,67 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@ExtensionMethod" logline="Annoying API? Fix it yourself: Add new methods to existing types!">
+ <@f.history>
+ <p>
+ <code>@ExtensionMethod</code> was introduced as experimental feature in lombok v0.11.2.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ High-impact on code style.
+ </li><li>
+ Really would like to ship with utility methods to expand common classes, but so far lombok doesn't have a good distribution method for such runtime dependencies.
+ </li><li>
+ Affects quite a bit of eclipse, and auto-complete e.d. do not work yet in netbeans.
+ </li><li>
+ Should @ExtensionMethod be legal on methods? Should it be legal on packages?
+ </li><li>
+ This feature has more bugs associated with it than we would like, and it is a large maintenance burden.
+ </li>
+ </ul>
+ Current status: <em>hold</em> - Currently we feel this feature will not move out of experimental status anytime soon, but it will not significantly change and support for it is unlikely to be removed in future versions of lombok either.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ You can make a class containing a bunch of <code>public</code>, <code>static</code> methods which all take at least 1 parameter. These methods will extend the type of the first parameter, as if they were instance methods, using the <code>@ExtensionMethod</code> feature.
+ </p><p>
+ For example, if you create <code>public static String toTitleCase(String in) { ... }</code>, you can use the <code>@ExtensionMethod</code> feature to make it look like the <code>java.lang.String</code> class has a method named <code>toTitleCase</code>, which has no arguments. The first argument of the static method fills the role of <code>this</code> in instance methods.
+ </p><p>
+ All methods that are <code>public</code>, <code>static</code>, and have at least 1 argument whose type is not primitive, are considered extension methods, and each will be injected into the namespace of the type of the first parameter as if they were instance methods. As in the above example, a call that looks like: <code>foo.toTitleCase()</code> is replaced with <code>ClassContainingYourExtensionMethod.toTitleCase(foo);</code>. Note that it is actually not an instant <code>NullPointerException</code> if <code>foo</code> is null - it is passed like any other parameter.
+ </p><p>
+ You can pass any number of classes to the <code>@ExtensionMethod</code> annotation; they will all be searched for extension methods. These extension methods apply for any code that is in the annotated class.
+ </p><p>
+ Lombok does not (currently) have any runtime dependencies which means lombok does not (currently) ship with any useful extension methods so you'll have to make your own. However, here's one that might spark your imagination: <br />
+ <pre>public class ObjectExtensions {
+ public static &lt;T&gt; T or(T object, T ifNull) {
+ return object != null ? object : ifNull;
+ }
+}</pre><br />
+ With the above class, if you add <code>@ExtensionMethod(ObjectExtensions.class)</code> to your class definition, you can write:<br />
+ <pre>String x = null;
+System.out.println(x.or("Hello, World!"));</pre><br />
+ The above code will not fail with a <code>NullPointerException</code>; it will actually output <code>Hello, World!</code>
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/ExtensionMethod" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.extensionMethod.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@ExtensionMethod</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Calls are rewritten to a call to the extension method; the static method itself is not inlined. Therefore, the extension method must be present both at compile and at runtime.
+ </p><p>
+ Generics is fully applied to figure out extension methods. i.e. if the first parameter of your extension method is <code>List&lt;? extends String&gt;</code>, then any expression that is compatible with that will have your extension method, but other kinds of lists won't. So, a <code>List&lt;Object&gt;</code> won't get it, but a <code>List&lt;String&gt;</code> will.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/FieldDefaults.html b/website/templates/features/experimental/FieldDefaults.html
new file mode 100644
index 00000000..c0d3db96
--- /dev/null
+++ b/website/templates/features/experimental/FieldDefaults.html
@@ -0,0 +1,56 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@FieldDefaults" logline="New default field modifiers for the 21st century.">
+ <@f.history>
+ <p>
+ @FieldDefaults was introduced as experimental feature in lombok v0.11.4.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ New feature; unsure if this busts enough boilerplate.
+ </li><li>
+ Would be nice if you could stick this on the package-info.java package to set the default for all classes in that package.
+ </li><li>
+ Part of the work on @Value, which is experimental.
+ </li>
+ </ul>
+ Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ The <code>@FieldDefaults</code> annotation can add an access modifier (<code>public</code>, <code>private</code>, or <code>protected</code>) to each field in the annotated class or enum. It can also add <code>final</code> to each field in the annotated class or enum.
+ </p><p>
+ To add <code>final</code> to each (instance) field, use <code>@FieldDefaults(makeFinal=true)</code>. Any non-final field which must remain nonfinal can be annotated with <code>@NonFinal</code> (also in the <code>lombok.experimental</code> package).
+ </p><p>
+ To add an access modifier to each (instance) field, use <code>@FieldDefaults(level=AccessLevel.PRIVATE)</code>. Any field that does not already have an access modifier (i.e. any field that looks like package private access) is changed to have the appropriate access modifier. Any package private field which must remain package private can be annotated with <code>@PackagePrivate</code> (also in the <code>lombok.experimental</code> package).
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/FieldDefaults" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.fieldDefaults.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@FieldDefaults</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.fieldDefaults.defaultPrivate</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ (Since 1.16.8) If set to <code>true</code>, <em>every</em> field in <em>every</em> class or enum anywhere in the sources being compiled will be marked as <code>private</code> unless it has an explicit access modifier or the <code>@PackagePrivate</code> annotation, or an explicit <code>@FieldDefaults</code> annotation is present to override this config key.
+ </dd><dt>
+ <code>lombok.fieldDefaults.defaultFinal</code> = [<code>true</code> | <code>false</code>] (default: false)
+ </dt><dd>
+ (Since 1.16.8) If set to <code>true</code>, <em>every</em> field in <em>every</em> class or enum anywhere in the sources being compiled will be marked as <code>final</code> unless it has the <code>@NonFinal</code> annotation, or an explicit <code>@FieldDefaults</code> annotation is present to override this config key.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Like other lombok handlers that touch fields, any field whose name starts with a dollar (<code>$</code>) symbol is skipped entirely. Such a field will not be modified at all.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/Helper.html b/website/templates/features/experimental/Helper.html
new file mode 100644
index 00000000..93b6e2b4
--- /dev/null
+++ b/website/templates/features/experimental/Helper.html
@@ -0,0 +1,52 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@Helper" logline="With a little help from my friends... Helper methods for java.">
+ <@f.history>
+ <p>
+ <code>@Helper</code> was introduced as an experimental feature in lombok v1.16.6.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ Lambdas with general function types offer an alternative strategy.
+ </li><li>
+ Perhaps a way to make helper methods with less boilerplate is possible, making this feature obsolete.
+ </li>
+ </ul>
+ Current status: <em>unknown</em> - We don't have enough experience with this feature to make predictions on its future.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ This annotation lets you put methods in methods. You might not know this, but you can declare classes inside methods, and the methods in this class can access any (effectively) final local variable or parameter defined and set before the declaration. Unfortunately, to actually call any methods you'd have to make an instance of this method local class first, but that's where <code>@Helper</code> comes in and helps you out! Annotate a method local class with <code>@Helper</code> and it's as if all the methods in that helper class are methods that you can call directly, just as if java had allowed methods to exist inside methods.
+ </p><p>
+ Normally you'd have to declare an instance of your helper, for example: <code>HelperClass h = new HelperClass();</code> directly after declaring your helper class, and then call methods in your helper class with <code>h.helperMethod();</code>. With <code>@Helper</code>, both of these things are no longer needed: You do not need to waste a line of code declaring an instance of the helper, and you don't need to prefix all your calls to helper methods with <code>nameOfHelperInstance.</code>
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/Helper" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.helper.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Helper</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ <code>@Helper</code> requires that the helper class has a no-args constructor. A compiler error will be generated if this is not the case.
+ </p><p>
+ Currently, the instance of your helper that's made under the hood is called <code>$Foo</code>, where <code>Foo</code> is the name of your helper. We might change this in the future; please don't rely on this variable existing. We might even replace this later with a sibling method instead.
+ </p><p>
+ Please don't rely on <code>this</code> making any sense in the helper method code. You can refer to the real 'this' by using the syntax <code>NameOfMyClass.this</code>.
+ </p><p>
+ <em>ANY</em> unqualified method call in code that exists <em>below</em> the declaration of the helper method with the same name as any method in the helper is assumed to be a call to the helper. If the arguments don't end up being compatible, you get a compiler error.
+ </p><p>
+ Unless you're using JDK8 or higher (which introduced the concept of 'effectively final'), you'll have to declare local variables and parameters as <code>final</code> if you wish to refer to them in your method local class. This is a java limitation, not something specific to lombok's <code>@Helper</code>.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/UtilityClass.html b/website/templates/features/experimental/UtilityClass.html
new file mode 100644
index 00000000..4cee3657
--- /dev/null
+++ b/website/templates/features/experimental/UtilityClass.html
@@ -0,0 +1,44 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@UtilityClass" logline="Utility, metility, wetility! Utility classes for the masses.">
+ <@f.history>
+ <p>
+ <code>@UtilityClass</code> was introduced as an experimental feature in lombok v1.16.2.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ Some debate as to whether its common enough to count as boilerplate.
+ </li>
+ </ul>
+ Current status: <em>positive</em> - Currently we feel this feature may move out of experimental status with no or minor changes soon.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ A utility class is a class that is just a namespace for functions. No instances of it can exist, and all its members are static. For example, <code>java.lang.Math</code> and <code>java.util.Collections</code> are well known utility classes. This annotation automatically turns the annotated class into one.
+ </p><p>
+ A utility class cannot be instantiated. By marking your class with <code>@UtilityClass</code>, lombok will automatically generate a private constructor that throws an exception, flags as error any explicit constructors you add, and marks the class <code>final</code>. If the class is an inner class, the class is also marked <code>static</code>.
+ </p><p>
+ <em>All</em> members of a utility class are automatically marked as <code>static</code>. Even fields and inner classes.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/UtilityClass" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.utilityClass.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@UtilityClass</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ There isn't currently any way to create non-static members, or to define your own constructor. If you want to instantiate the utility class, even only as an internal implementation detail, <code>@UtilityClass</code> cannot be used.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/Wither.html b/website/templates/features/experimental/Wither.html
new file mode 100644
index 00000000..9642458b
--- /dev/null
+++ b/website/templates/features/experimental/Wither.html
@@ -0,0 +1,66 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="@Wither" logline="Immutable 'setters' - methods that create a clone but with one changed field.">
+ <@f.history>
+ <p>
+ @Wither was introduced as experimental feature in lombok v0.11.4.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ Still not sure that <code>@Wither</code> is an appropriate name for this feature.
+ </li><li>
+ Should there be an option to supply a way of cloning the input somehow?
+ </li><li>
+ Should the way that the clone is created by configurable?
+ </li><li>
+ Should we replace @Wither entirely with a builder class?
+ </li>
+ </ul>
+ Current status: <em>neutral</em> - More feedback requires on the items in the above list before promotion to the main package is warranted.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ The next best alternative to a setter for an immutable property is to construct a clone of the object, but with a new value for this one field. A method to generate this clone is precisely what <code>@Wither</code> generates: a <code>withFieldName(newValue)</code> method which produces a clone except for the new value for the associated field.
+ </p><p>
+ For example, if you create <code>public class Point { private final int x, y; }</code>, setters make no sense because the fields are final. <code>@Wither</code> can generate a <code>withX(int newXValue)</code> method for you which will return a new point with the supplied value for <code>x</code> and the same value for <code>y</code>.
+ </p><p>
+ Like <a href="/features/GetterSetter"><code>@Setter</code></a>, you can specify an access level in case you want the generated wither to be something other than <code>public</code>:<br /> <code>@Wither(level = AccessLevel.PROTECTED)</code>. Also like <a href="/features/GetterSetter"><code>@Setter</code></a>, you can also put a <code>@Wither</code> annotation on a type, which means a 'wither' is generated for each field (even non-final fields).
+ </p><p>
+ To put annotations on the generated method, you can use <code>onMethod=@__({@AnnotationsHere})</code>; to put annotations on the only parameter of a generated wither method, you can use <code>onParam=@__({@AnnotationsHere})</code>. Be careful though! This is an experimental feature. For more details see the documentation on the <a href="/features/experimental/onX">onX</a> feature.
+ </p><p>
+ <em>NEW in lombok v1.12.0:</em> javadoc on the field will now be copied to generated withers. Normally, all text is copied, and <code>@param</code> is <em>moved</em> to the wither, whilst <code>@return</code> lines are stripped from the wither's javadoc. Moved means: Deleted from the field's javadoc. It is also possible to define unique text for the wither's javadoc. To do that, you create a 'section' named <code>WITHER</code>. A section is a line in your javadoc containing 2 or more dashes, then the text 'WITHER', followed by 2 or more dashes, and nothing else on the line. If you use sections, <code>@return</code> and <code>@param</code> stripping / copying for that section is no longer done (move the <code>@param</code> line into the section).
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/Wither" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.wither.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@Wither</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ Withers cannot be generated for static fields because that makes no sense.
+ </p><p>
+ Withers can be generated for abstract classes, but this generates an abstract method with the appropriate signature.
+ </p><p>
+ When applying <code>@Wither</code> to a type, static fields and fields whose name start with a $ are skipped.
+ </p><p>
+ For generating the method names, the first character of the field, if it is a lowercase character, is title-cased, otherwise, it is left unmodified. Then, <code>with</code> is prefixed.
+ </p><p>
+ No method is generated if any method already exists with the same name (case insensitive) and same parameter count. For example, <code>withX(int x)</code> will not be generated if there's already a method <code>withX(String... x)</code> even though it is technically possible to make the method. This caveat exists to prevent confusion. If the generation of a method is skipped for this reason, a warning is emitted instead. Varargs count as 0 to N parameters.
+ </p><p>
+ For <code>boolean</code> fields that start with <code>is</code> immediately followed by a title-case letter, nothing is prefixed to generate the wither name.
+ </p><p>
+ Any annotations named <code>@NonNull</code> (case insensitive) on the field are interpreted as: This field must not ever hold <em>null</em>. Therefore, these annotations result in an explicit null check in the generated wither. Also, these annotations (as well as any annotation named <code>@Nullable</code> or <code>@CheckForNull</code>) are copied to wither parameter.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/experimental/index.html b/website/templates/features/experimental/index.html
new file mode 100644
index 00000000..21e8fceb
--- /dev/null
+++ b/website/templates/features/experimental/index.html
@@ -0,0 +1,87 @@
+<#import "../../_scaffold.html" as main>
+<#import "../_features.html" as f>
+
+<@main.scaffold title="Experimental">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <@main.h1 title="Lombok experimental features" />
+ </div>
+ <div class="row">
+ The <a href="/api/">Lombok javadoc</a> is available, but we advise these pages.
+
+ <p>
+ Experimental features are available in your normal lombok installation, but are not as robustly supported as lombok's main features. In particular, experimental features:
+ <ul>
+ <li>
+ Are not tested as well as the core features.
+ </li><li>
+ Do not get bugs fixed as quickly as core features.
+ </li><li>
+ May have APIs that will change, possibly drastically if we find a different, better way to solve the same problem.
+ </li><li>
+ May disappear entirely if the feature is too difficult to support or doesn't bust enough boilerplate.
+ </li>
+ </ul>
+ </p><p>
+ Features that receive positive community feedback and which seem to produce clean, flexible code will eventually become accepted as a core feature and move out of the experimental package.
+ </p>
+ </div>
+ <div class="row">
+ <@main.feature title="var" href="var">
+ Modifiable local variables with a type inferred by assigning value.
+ </@main.feature>
+
+ <@main.feature title="@Accessors" href="Accessors">
+ A more fluent API for getters and setters.
+ </@main.feature>
+
+ <@main.feature title="@ExtensionMethod" href="ExtensionMethod">
+ Annoying API? Fix it yourself: Add new methods to existing types!
+ </@main.feature>
+
+ <@main.feature title="@FieldDefaults" href="FieldDefaults">
+ New default field modifiers for the 21st century.
+ </@main.feature>
+
+ <@main.feature title="@Delegate" href="Delegate">
+ Don't lose your composition.
+ </@main.feature>
+
+ <@main.feature title="@Wither" href="Wither">
+ Immutable 'setters' - methods that create a clone but with one changed field.
+ </@main.feature>
+
+ <@main.feature title="onMethod= / onConstructor= / onParam=" href="onX">
+ Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you're annotating.
+ </@main.feature>
+
+ <@main.feature title="@UtilityClass" href="UtilityClass">
+ Utility, metility, wetility! Utility classes for the masses.
+ </@main.feature>
+
+ <@main.feature title="@Helper" href="Helper">
+ With a little help from my friends... Helper methods for java.
+ </@main.feature>
+ </div>
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.experimental.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of any of the features listed here as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <div class="row">
+ <h3 class="text-center">Putting the "Ex" in "Experimental": promoted or deleted experimental features.</h3>
+ <div class="row">
+ <@main.feature title="@Value: promoted" href="/features/Value">
+ <code>@Value</code> has proven its value and has been moved to the main package.
+ </@main.feature>
+ <@main.feature title="@Builder: promoted" href="/features/Builder">
+ <code>@Builder</code> is a solid base to build APIs on, and has been moved to the main package.
+ </@main.feature>
+ </div>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/features/experimental/onX.html b/website/templates/features/experimental/onX.html
new file mode 100644
index 00000000..fd2e7b58
--- /dev/null
+++ b/website/templates/features/experimental/onX.html
@@ -0,0 +1,62 @@
+<#import "../_features.html" as f>
+
+<@f.scaffold title="onX" logline="Sup dawg, we heard you like annotations, so we put annotations in your annotations so you can annotate while you're annotating.">
+ <@f.history>
+ <p>
+ onX was introduced as experimental feature in lombok v0.11.8.
+ </p>
+ </@f.history>
+
+ <@f.experimental>
+ <ul>
+ <li>
+ Ugly syntax. The syntax of this feature is not optimal, but it is the least convoluted syntax that could possibly work (for now!)
+ </li><li>
+ Possibly java 9 will offer (much) better ways of supporting this feature.
+ </li><li>
+ Uncertainty: Future versions of javac may break this feature, and we may not be able to restore it.
+ </li>
+ </ul>
+ Current status: <em>uncertain</em> - Currently we feel this feature cannot move out of experimental status.
+ </@f.experimental>
+
+ <@f.overview>
+ <p>
+ <strong>This feature is considered 'workaround status' - it exists in order to allow users of lombok that cannot work without this feature to have access to it anyway. If we find a better way to implement this feature, or some future java version introduces an alternative strategy, this feature can disappear without a reasonable deprecation period. Also, this feature may not work in future versions of javac. Use at your own discretion.</strong>
+ </p><p>
+ Most annotations that make lombok generate methods or constructors can be configured to also make lombok put custom annotations on elements in the generated code.
+ </p><p>
+ <code>@Getter</code>, <code>@Setter</code>, and <code>@Wither</code> support the <code>onMethod</code> option, which will put the listed annotations on the generated method.
+ </p><p>
+ <code>@AllArgsConstructor</code>, <code>@NoArgsConstructor</code>, and <code>@RequiredArgsConstructor</code> support the <code>onConstructor</code> option which will put the listed annotations on the generated constructor.
+ </p><p>
+ <code>@Setter</code> and <code>@Wither</code> support <code>onParam</code> in addition to <code>onMethod</code>; annotations listed will be put on the only parameter that the generated method has. <code>@EqualsAndHashCode</code> also supports <code>onParam</code>; the listed annotation(s) will be placed on the single parameter of the generated <code>equals</code> method, as well as any generated <code>canEqual</code> method.
+ </p><p>
+ The syntax is a little strange and depends on the javac you are using.<br />
+ On javac7, to use any of the 3 <code>onX</code> features, you must wrap the annotations to be applied to the constructor / method / parameter in <code>@__(@AnnotationGoesHere)</code>. To apply multiple annotations, use <code>@__({@Annotation1, @Annotation2})</code>. The annotations can themselves obviously have parameters as well.<br />
+ On javac8 and up, you add an underscore after <code>onMethod</code>, <code>onParam</code>, or <code>onConstructor</code>.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="experimental/onX" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.onX.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>onX</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ The reason of the weird syntax is to make this feature work in javac 7 compilers; the <code>@__</code> type is an annotation reference to the annotation type <code>__</code> (double underscore) which doesn't actually exist; this makes javac 7 delay aborting the compilation process due to an error because it is possible an annotation processor will later create the <code>__</code> type. Instead, lombok applies the annotations and removes the references so that the error will never actually occur. The point is: The <code>__</code> type <em>must not exist</em>, otherwise the feature does not work. In the rare case that the <code>__</code> type does exist (and is imported or in the package), you can simply add more underscores. Technically any non-existent type would work, but to maintain consistency and readability and catch erroneous use, lombok considers it an error if the 'wrapper' annotation is anything but a series of underscores.
+ </p><p>
+ In javac8, the above feature should work but due to a bug in javac8 it does not. However, starting in javac8, if the parameter name does not exist in the annotation type, compilation proceeds to a phase where lombok can fix it.
+ </p><p>
+ To reiterate: This feature can disappear at any time; if you use this feature, be prepared to adjust your code when we find a nicer way of implementing this feature, or, if a future version of javac forces us to remove this feature entirely with no alternative.
+ </p><p>
+ The <code>onX</code> parameter is not legal on any type-wide variant. For example, a <code>@Getter</code> annotation on a class does not support <code>onMethod</code>.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/index.html b/website/templates/features/index.html
new file mode 100644
index 00000000..cd4c9e26
--- /dev/null
+++ b/website/templates/features/index.html
@@ -0,0 +1,97 @@
+<#import "../_scaffold.html" as main>
+
+<@main.scaffold title="Stable">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <@main.h1 title="Lombok features" />
+ </div>
+ <div class="row">
+ The <a href="/api/">Lombok javadoc</a> is available, but we advise these pages.
+
+ <@main.feature title="val" href="val">
+ Finally! Hassle-free final local variables.
+ </@main.feature>
+
+ <@main.feature title="var" href="var">
+ Mutably! Hassle-free local variables.
+ </@main.feature>
+
+ <@main.feature title="@NonNull" href="NonNull">
+ or: How I learned to stop worrying and love the NullPointerException.
+ </@main.feature>
+
+ <@main.feature title="@Cleanup" href="Cleanup">
+ Automatic resource management: Call your <code>close()</code> methods safely with no hassle.
+ </@main.feature>
+
+ <@main.feature title="@Getter/@Setter" href="GetterSetter">
+ Never write <code>public int getFoo() {return foo;}</code> again.
+ </@main.feature>
+
+ <@main.feature title="@ToString" href="ToString">
+ No need to start a debugger to see your fields: Just let lombok generate a <code>toString</code> for
+ you!
+ </@main.feature>
+
+ <@main.feature title="@EqualsAndHashCode" href="EqualsAndHashCode">
+ Equality made easy: Generates <code>hashCode</code> and <code>equals</code> implementations from the
+ fields of your object..
+ </@main.feature>
+
+ <@main.feature title="@NoArgsConstructor, @RequiredArgsConstructor and @AllArgsConstructor" href="constructor">
+ Constructors made to order: Generates constructors that take no arguments, one argument per final /
+ non-nullfield, or one argument for every field.
+ </@main.feature>
+
+ <@main.feature title="@Data" href="Data">
+ All together now: A shortcut for <code>@ToString</code>, <code>@EqualsAndHashCode</code>,
+ <code>@Getter</code> on all fields, and <code>@Setter</code> on all non-final fields, and
+ <code>@RequiredArgsConstructor</code>!
+ </@main.feature>
+
+ <@main.feature title="@Value" href="Value">
+ Immutable classes made very easy.
+ </@main.feature>
+
+ <@main.feature title="@Builder" href="Builder">
+ ... and Bob's your uncle: No-hassle fancy-pants APIs for object creation!
+ </@main.feature>
+
+ <@main.feature title="@SneakyThrows" href="SneakyThrows">
+ To boldly throw checked exceptions where no one has thrown them before!
+ </@main.feature>
+
+ <@main.feature title="@Synchronized" href="Synchronized">
+ <code>synchronized</code> done right: Don't expose your locks.
+ </@main.feature>
+
+ <@main.feature title="@Getter(lazy=true)" href="GetterLazy">
+ Laziness is a virtue!
+ </@main.feature>
+
+ <@main.feature title="@Log" href="log">
+ Captain's Log, stardate 24435.7: &quot;What was that line again?&quot;
+ </@main.feature>
+
+ <@main.feature title="experimental" href="/features/experimental/all">
+ Head to the lab: The new stuff we're working on.
+ </@main.feature>
+ </div>
+
+ <div class="row">
+ <@main.h1 title="Configuration system" />
+
+ <div class="text-center">
+ Lombok, made to order: <a href="configuration">Configure lombok features</a> in one place for your entire project or even your workspace.
+ </div>
+ </div>
+
+ <div class="row">
+ <@main.h1 title="Running delombok" />
+
+ <div>
+ Delombok copies your source files to another directory, replacing all lombok annotations with their desugared form. So, it'll turn <code>@Getter</code> back into the actual getter. It then removes the annotation. This is useful for all sorts of reasons; you can check out what's happening under the hood, if the unthinkable happens and you want to stop using lombok, you can easily remove all traces of it in your source, and you can use delombok to preprocess your source files for source-level tools such as javadoc and GWT. More information about how to run delombok, including instructions for build tools can be found at the <a href="delombok">delombok page</a>.
+ </div>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/features/log.html b/website/templates/features/log.html
new file mode 100644
index 00000000..2854e896
--- /dev/null
+++ b/website/templates/features/log.html
@@ -0,0 +1,106 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="@Log (and friends)" logline="Captain's Log, stardate 24435.7: &quot;What was that line again?&quot;">
+ <@f.history>
+ <p>
+ The various <code>@Log</code> variants were added in lombok v0.10.
+ <em>NEW in lombok 0.10: </em>You can annotate any class with a log annotation to let lombok generate a logger field.<br/>
+ The logger is named <code>log</code> and the field's type depends on which logger you have selected.
+ </p>
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ You put the variant of <code>@Log</code> on your class (whichever one applies to the logging system you use); you then have a static final <code>log</code> field, initialized to the name of your class, which you can then use to write log statements.
+ </p><p>
+ There are several choices available:<br />
+ <dl>
+ <dt>
+ <code>@CommonsLog</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="https://commons.apache.org/logging/apidocs/org/apache/commons/logging/Log.html">org.apache.commons.logging.Log</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="https://commons.apache.org/logging/apidocs/org/apache/commons/logging/LogFactory.html#getLog(java.lang.Class)">org.apache.commons.logging.LogFactory.getLog</a>(LogExample.<span class="keyword">class</span>);</code>
+ </dd><dt>
+ <code>@JBossLog</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html">org.jboss.logging.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://docs.jboss.org/jbosslogging/latest/org/jboss/logging/Logger.html#getLogger(java.lang.Class)">org.jboss.logging.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>);</code>
+ </dd><dt>
+ <code>@Log</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://download.oracle.com/javase/6/docs/api/java/util/logging/Logger.html">java.util.logging.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://download.oracle.com/javase/6/docs/api/java/util/logging/Logger.html#getLogger(java.lang.String)">java.util.logging.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>.getName());</code>
+ </dd><dt>
+ <code>@Log4j</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html">org.apache.log4j.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="https://logging.apache.org/log4j/1.2/apidocs/org/apache/log4j/Logger.html#getLogger(java.lang.Class)">org.apache.log4j.Logger.getLogger</a>(LogExample.<span class="keyword">class</span>);</code>
+ </dd><dt>
+ <code>@Log4j2</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="https://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/Logger.html">org.apache.logging.log4j.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="https://logging.apache.org/log4j/2.0/log4j-api/apidocs/org/apache/logging/log4j/LogManager.html#getLogger(java.lang.Class)">org.apache.logging.log4j.LogManager.getLogger</a>(LogExample.<span class="keyword">class</span>);</code>
+ </dd><dt>
+ <code>@Slf4j</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://www.slf4j.org/api/org/slf4j/Logger.html">org.slf4j.Logger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://www.slf4j.org/apidocs/org/slf4j/LoggerFactory.html#getLogger(java.lang.Class)">org.slf4j.LoggerFactory.getLogger</a>(LogExample.<span class="keyword">class</span>);</code>
+ </dd><dt>
+ <code>@XSlf4j</code>
+ </dt><dd>
+ Creates <code><span class="keyword">private&nbsp;static&nbsp;final&nbsp;</span><a href="http://www.slf4j.org/api/org/slf4j/ext/XLogger.html">org.slf4j.ext.XLogger</a>&nbsp;<span class="staticfield">log</span>&nbsp;=&nbsp;<a href="http://www.slf4j.org/apidocs/org/slf4j/ext/XLoggerFactory.html#getXLogger(java.lang.Class)">org.slf4j.ext.XLoggerFactory.getXLogger</a>(LogExample.<span class="keyword">class</span>);</code>
+ </dd>
+ </dl>
+ </p><p>
+ By default, the topic (or name) of the logger will be the class name of the class annotated with the <code>@Log</code> annotation. This can be customised by specifying the <code>topic</code> parameter. For example: <code>@XSlf4j(topic="reporting")</code>.
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="Log" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.log.fieldName</code> = <em>an identifier</em> (default: <code>log</code>).
+ </dt><dd>
+ The generated logger fieldname is by default '<code>log</code>', but you can change it to a different name with this setting.
+ </dd><dt>
+ <code>lombok.log.fieldIsStatic</code> = [<code>true</code> | <code>false</code>] (default: true)
+ </dt><dd>
+ Normally the generated logger is a <code>static</code> field. By setting this key to <code>false</code>, the generated field will be an instance field instead.
+ </dd><dt>
+ <code>lombok.log.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of any of the various log annotations as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.apacheCommons.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.apachecommons.CommonsLog</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.javaUtilLogging.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.java.Log</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.jbosslog.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.jbosslog.JBossLog</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.log4j.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.log4j.Log4j</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.log4j2.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.log4j.Log4j2</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.slf4j.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.slf4j.Slf4j</code> as a warning or error if configured.
+ </dd><dt>
+ <code>lombok.log.xslf4j.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>@lombok.extern.slf4j.XSlf4j</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ If a field called <code>log</code> already exists, a warning will be emitted and no code will be generated.
+ </p><p>
+ A future feature of lombok's diverse log annotations is to find calls to the logger field and, if the chosen logging framework supports it and the log level can be compile-time determined from the log call, guard it with an <code>if</code> statement. This way if the log statement ends up being ignored, the potentially expensive calculation of the log string is avoided entirely. This does mean that you should <em>NOT</em> put any side-effects in the expression that you log.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/val.html b/website/templates/features/val.html
new file mode 100644
index 00000000..32a8ffdf
--- /dev/null
+++ b/website/templates/features/val.html
@@ -0,0 +1,36 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="val" logline="Finally! Hassle-free final local variables.">
+ <@f.history>
+ <p>
+ <code>val</code> was introduced in lombok 0.10.
+ </p>
+ </@f.history>
+ <@f.overview>
+ <p>
+ You can use <code>val</code> as the type of a local variable declaration instead of actually writing the type. When you do this, the type will be inferred from the initializer expression. The local variable will also be made final. This feature works on local variables and on foreach loops only, not on fields. The initializer expression is required.
+ </p><p>
+ <code>val</code> is actually a 'type' of sorts, and exists as a real class in the <code>lombok</code> package. You must import it for val to work (or use <code>lombok.val</code> as the type). The existence of this type on a local variable declaration triggers both the adding of the <code>final</code> keyword as well as copying the type of the initializing expression which overwrites the 'fake' <code>val</code> type.
+ </p><p>
+ <em>WARNING: This feature does not currently work in NetBeans.</em>
+ </p>
+ </@f.overview>
+
+ <@f.snippets name="val" />
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.val.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>val</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+
+ <@f.smallPrint>
+ <p>
+ For compound types, the most common superclass is inferred, not any shared interfaces. For example, <code>bool ? new HashSet() : new ArrayList()</code> is an expression with a compound type: The result is both <code>AbstractCollection</code> as well as <code>Serializable</code>. The type inferred will be <code>AbstractCollection</code>, as that is a class, whereas <code>Serializable</code> is an interface.
+ </p><p>
+ In ambiguous cases, such as when the initializer expression is <code>null</code>, <code>java.lang.Object</code> is inferred.
+ </p>
+ </@f.smallPrint>
+</@f.scaffold>
diff --git a/website/templates/features/var.html b/website/templates/features/var.html
new file mode 100644
index 00000000..60e24914
--- /dev/null
+++ b/website/templates/features/var.html
@@ -0,0 +1,27 @@
+<#import "_features.html" as f>
+
+<@f.scaffold title="var" logline="Mutably! Hassle-free local variables.">
+ <@f.history>
+ <p><ul>
+ <li><code>var</code> was promoted to the main package in lombok 2.0.0; given that <a href="http://openjdk.java.net/jeps/286">JEP 286</a> establishes expectations, and lombok's take on <code>var</code> follows these, we've decided to promote <code>var</code> eventhough the feature remains controversial.</li>
+ <li><code>var</code> was introduced in lombok 1.16.12 as experimental feature.</li>
+ </ul></p>
+ </@f.history>
+
+ <@f.overview>
+ <p>
+ <code>var</code> works exactly like <a href="/features/val"><code>val</code></a>, except the local variable is <em>not</em> marked as <code>final</code>.
+ </p><p>
+ The type is still entirely derived from the mandatory initializer expression, and any further assignments, while now legal (because the variable is no longer <code>final</code>), aren't looked at to determine the appropriate type.<br />
+ For example, <code>var x = "Hello"; x = Color.RED;</code> does <em>not</em> work; the type of x will be inferred to be <code>java.lang.String</code> and thus, the <code>x = Color.RED</code> assignment will fail. If the type of <code>x</code> was inferred to be <code>java.lang.Object</code> this code would have compiled, but that's not how<code>var</code> works.
+ </p>
+ </@f.overview>
+
+ <@f.confKeys>
+ <dt>
+ <code>lombok.var.flagUsage</code> = [<code>warning</code> | <code>error</code>] (default: not set)
+ </dt><dd>
+ Lombok will flag any usage of <code>var</code> as a warning or error if configured.
+ </dd>
+ </@f.confKeys>
+</@f.scaffold>
diff --git a/website/templates/main.html b/website/templates/main.html
new file mode 100644
index 00000000..25098758
--- /dev/null
+++ b/website/templates/main.html
@@ -0,0 +1,44 @@
+<#import "/_scaffold.html" as main>
+<@main.scaffold load=["/js/supporters.js"]>
+ <div class="page-header top5">
+ <div class="row text-center">
+ <@main.h1 title="Project Lombok" />
+ <p>
+ Project Lombok is a java library that automatically plugs into your editor and build tools, spicing up your java.<br />
+ Never write another getter or equals method again. Early access to future java features such as <code>val</code>, and much more.
+ </p>
+ </div>
+ <div class="video text-center">
+ <div id="clickForVideo"><span class="clickToTap">Click</span> to watch a 4 minute demo to learn more.</div>
+ <video id="demoVideo" hidden="hidden" width="800" height="480" poster="/img/poster.png" controls="controls" preload="none">
+ <source src="https://projectlombok.org/videos/lombok.ogv" type="video/ogg" />
+ <source src="https://projectlombok.org/videos/lombok.mp4" type="video/mp4" />
+ <source src="https://projectlombok.org/videos/lombok-iPhone.m4v" type="video/mp4" />
+ <@main.h1 title="Can't watch the video?" />
+ <p>
+ <a href="https://www.youtube.com/watch?v=y6zMyM-YTgg">See it on Youtube instead</a>.
+ </p><p>
+ Or, download the video:<br/>
+ <a href="/videos/lombok.mp4">MPEG4 / H.264 (Windows / Mac)</a> |
+ <a href="/videos/lombok.ogv">Ogg Theora &amp; Vorbis ".ogv" (Linux)</a>
+ </p>
+ </video>
+ <div class="row">
+ <div class="text-center">
+ <a href="http://jnb.ociweb.com/jnb/jnbJan2010.html">Show me a text and images based explanation and tutorial instead!</a>
+ </div>
+ </div>
+ </div>
+ <div class="row text-center">
+ <@main.h2 title="Upcoming presentations" />
+ <p>
+ We're talking to NL-JUG to give a presentation soon in the The Hague (The Netherlands) area.<br />
+ Want us to present at your JUG or conference? Feel free to contact us, via email (<code>info@</code>) or twitter: <a href="https://twitter.com/project_lombok">@project_lombok</a>.
+ </p>
+ </div>
+ <div class="row text-center supporterBar">
+ <h2 class="introText" hidden="hidden">Project Lombok is <a href="/supporters">powered by</a>:</h2>
+ <div class="supporterFooter" hidden="hidden"><a class="buttonLike" href="/order-license-info">I want to support Project Lombok too!</a></div>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/order-license-info.html b/website/templates/order-license-info.html
new file mode 100644
index 00000000..3572ad0f
--- /dev/null
+++ b/website/templates/order-license-info.html
@@ -0,0 +1,31 @@
+<#import "/_scaffold.html" as main>
+
+<@main.scaffold title="Order / Donate">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <h2>Order a professional or enterprise license</h2>
+ </div>
+ <div class="row">
+ <p>
+ Lombok is open source. We offer three licenses for using lombok. The standard license is free. Here you can order a professional or enterprise license.
+ </p><p>
+ <a class="buttonLike orderButton" href="/order-license">Order a professional or enterprise license</a><br />
+ <a class="buttonLike orderButton" href="https://www.patreon.com/lombok">For individuals: Become a patreon</a>
+ </p>
+ <div class="row text-center">
+ <h2>Benefits of becoming a licensee</h2>
+ </div>
+ <p>
+ Lombok is and will remain a free, open source product. However, we ask you to consider becoming a licensee. Licensees will be <a href="/supporters">listed</a> on the <code>projectlombok.org</code> website, we'll send you some stickers, and an official license. You'll be supporting the development of Project Lombok.
+ </p>
+ <div class="row text-center">
+ <h2>Small print</h2>
+ </div>
+ <p class="deemphasize">
+ As part of being a professional or enterprise licensee, we will put your name, a logo, and possibly a link on our ‘supporters and licensees’ page. We'll also put (at random) some supporters and licensees on our front page. You may of course opt out of this offer. We may, at our discretion, opt not to list you. If we elect not to do so, you will be notified at the email address you fill in on our form, and you are as always free to cancel your license at any time.
+ </p><p class="deemphasize">
+ Project Lombok is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed, even for professional and enterprise license holders. In no event shall the copyright holder or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.
+ </p>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/order-license.html b/website/templates/order-license.html
new file mode 100644
index 00000000..818c27f3
--- /dev/null
+++ b/website/templates/order-license.html
@@ -0,0 +1,151 @@
+<#import "/_scaffold.html" as main>
+
+<@main.scaffold load=["/js/order-license.js"] title="Order a license">
+ <div class="page-header top5 order-license">
+ <div class="row text-center">
+ <h2>Order a professional or enterprise license</h2>
+ </div>
+ <div class="row">
+ <form>
+ <fieldset class="form-group">
+ <legend>Basic information</legend>
+ <div class="form-group">
+ <label for="companyName">Company name</label>
+ <input type="text" class="form-control" aria-describedby="companyNameHelp" id="companyName" placeholder="license holder name" />
+ <div id="companyNameErr" class="formErr" hidden="hidden">Company name is a required field.</div>
+ <small id="companyNameHelp" class="form-text text-muted">If applying for an individual license, fill in your own name.</small>
+ </div>
+ <div class="form-group">
+ <label for="email">Email</label>
+ <input type="email" class="form-control" aria-describedby="emailHelp" id="email" placeholder="email of contact / holder" />
+ <div id="emailErr" class="formErr" hidden="hidden">Your email address is required; we will send the bill to this email address.</div>
+ <small id="emailHelp" class="form-text text-muted">We will never share this email with any third parties; we'll email you the invoice at this email address.</small>
+ </div>
+ </fieldset>
+ <fieldset class="form-group">
+ <legend>Type of license</legend>
+ <div class="form-group">
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input licenseType" name="licenseType" value="professional" checked="checked" />
+ Professional (€2,- per developer per month; ~ $2.50).
+ </label>
+ </div>
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input licenseType" name="licenseType" value="enterprise" />
+ Enterprise (€5,- per developer per month; ~ $6.10).
+ </label>
+ </div>
+ </div>
+ <div id="licenseTypeErr" class="formErr" hidden="hidden">License type is a required field.</div>
+ <div class="form-group">
+ <label for="seats"># of developers using lombok</label>
+ <input type="number" placeholder="# of developers" class="form-control" id="seats" />
+ <div id="seatsErr" class="formErr" hidden="hidden">We need to know the # of developers to determine the license price.</div>
+ </div>
+ </fieldset>
+ <fieldset class="form-group">
+ <legend>Payment</legend>
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input paymentType" name="paymentType" value="yearly" checked="checked" />
+ Yearly
+ </label>
+ </div>
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input paymentType" name="paymentType" value="monthly" />
+ Monthly<span id="onlyYearlyWarning" hidden="hidden" class="warning">The total license cost is sufficiently low that we'll bill you yearly.</span>
+ </label>
+ </div>
+ <div id="paymentTypeErr" class="formErr" hidden="hidden">Payment type is a required field.</div>
+ <div class="form-group" hidden="hidden" id="costIndicator">
+ </div>
+ </fieldset>
+ <fieldset class="form-group">
+ <legend>Mention</legend>
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="checkbox" class="form-check-input" id="mentionMe" name="mentionMe" checked="checked" />
+ Mention me on the <em>supporters / licensees</em> page.
+ </label>
+ </div>
+ <div class="form-group">
+ <label for="companyUrl">Company URL (optional)</label>
+ <input type="url" class="form-control" id="companyUrl" placeholder="URL of your company website" />
+ </div>
+ <div class="form-group">
+ <label for="logo">Company Logo (optional)</label>
+ <input type="file" style="display: none;" id="logo" name="logo" />
+ <button class="form-control" id="companyLogo">Upload a logo</button>
+ <div id="logoCnt" style="display: none;"></div>
+ <button class="form-control" id="deleteCompanyLogo" style="display: none;">Remove logo</button>
+ </div>
+ </fieldset>
+ <fieldset class="form-group">
+ <legend>Location and VAT</legend>
+ <div class="form-group">
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input locationType" name="locationType" value="eu" checked="checked" />
+ We are based in the Europe
+ </label>
+ </div>
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input locationType" name="locationType" value="usa" />
+ We are based in the USA
+ </label>
+ </div>
+ <div class="form-check">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input locationType" name="locationType" value="other" />
+ We are based elsewhere
+ </label>
+ </div>
+ <div id="locationTypeErr" class="formErr" hidden="hidden">Location (continent) is a required field.</div>
+ </div>
+ <div class="form-group" id="locationType_eu">
+ <label for="euVat">EU VAT number</label>
+ <input type="text" class="form-control" id="euVat" placeholder="EU VAT number" />
+ <div id="euVatErr" class="formErr" hidden="hidden">EU VAT is a required field. If you are an individual and you have no EU VAT number, consider giving us a <a href="https://www.patreon.com/lombok">patreon</a> donation.</div>
+ </div>
+ <div class="form-group" hidden="hidden" id="locationType_usa">
+ Please <a href="/W8BEN_lombok.pdf">download our W-8BEN form</a> for your tax records.
+ </div>
+ <div class="form-group" hidden="hidden" id="locationType_other">
+ Please make sure you fulfill any local tax obligations for buying software from other countries.
+ </div>
+ </fieldset>
+ <fieldset class="form-group">
+ <legend>Payment method</legend>
+ <div class="form-group">
+ <div class="form-check" id="paymentMethod_iban">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input" name="paymentMethod" value="iban" checked="checked" />
+ Pay via IBAN (european bank transfer)
+ </label>
+ </div>
+ <div class="form-check" hidden="hidden" id="paymentMethod_intl">
+ <label class="form-check-label">
+ <input type="radio" class="form-check-input" name="paymentMethod" value="intl" />
+ Pay via international bank transfer
+ </label>
+ </div>
+ <div class="form-check">
+ <label class="form-check-label" id="paymentMethod_payoneer">
+ <input type="radio" class="form-check-input" name="paymentMethod" value="payoneer" />
+ Pay with Payoneer
+ </label>
+ </div>
+ <div id="paymentMethodErr" class="formErr" hidden="hidden">Payment method is a required field.</div>
+ </div>
+ </fieldset>
+ <button type="submit" id="submit" class="btn btn-primary">Submit order</button>
+ <div id="orderHelp">If you run into issues with the order form, or you have any other questions, please send us an email at <a href="mailto:orders@projectlombok.org"><code>orders@projectlombok.org</code></a>. You can cancel your subscription at any time.</div>
+ <div class="orderDetails">Our EU VAT number: NL858105378B01</div>
+ </p>
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/templates/setup/_setup.html b/website/templates/setup/_setup.html
new file mode 100644
index 00000000..166891ce
--- /dev/null
+++ b/website/templates/setup/_setup.html
@@ -0,0 +1,28 @@
+<#import "/_scaffold.html" as main>
+
+<#macro introduction>
+ <div class="row">
+ <#nested>
+ </div>
+</#macro>
+
+<#macro section title>
+ <div class="row">
+ <@main.h3 title="${title}" />
+
+ <#nested>
+ </div>
+</#macro>
+
+<#macro scaffold title load=[]>
+ <@main.scaffold load title>
+ <div class="page-header top5" id="featureContent">
+ <div class="row text-center">
+ <div class="header-group">
+ <@main.h1 title="${title}" />
+ </div>
+ </div>
+ <#nested>
+ </div>
+ </@main.scaffold>
+</#macro>
diff --git a/website/templates/setup/android.html b/website/templates/setup/android.html
new file mode 100644
index 00000000..19e92a58
--- /dev/null
+++ b/website/templates/setup/android.html
@@ -0,0 +1,84 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Android">
+ <@s.introduction>
+ <p>
+ Android development with lombok is easy and won't make your android application any 'heavier' because lombok is a compile-time only library. It is important to configure your android project properly to make sure lombok doesn't end up in your application and waste precious space on android devices.
+ </p><p>
+ The instructions listed below are excerpts from <a href="https://github.com/excilys/androidannotations/wiki/Cookbook">The
+ AndroidAnnotations project cookbook</a>. You may wish to refer to that documentation for complete instructions; lombok is just
+ the equivalent to <code>androidannotations-VERSION.jar</code>; there is no <code>-api</code> aspect.
+ </p>
+ </@s.introduction>
+
+ <@s.section title="Gradle">
+ <p>
+ <ul><li>
+ Make sure that the version of your android plugin is <code>&gt;= 0.4.3</code>
+ </li><li>
+ Use the <a href="https://github.com/franzbecker/gradle-lombok">gradle-lombok</a> plugin.
+ </li><li>
+ If you don't want to use the plugin, add Lombok to your application's <code>dependencies</code> block (requires Gradle v2.12 or newer):<br /><br />
+<pre>
+dependencies {
+ compileOnly "org.projectlombok:lombok:${version}"
+}</pre>
+ </li></ul>
+ </p>
+ </@s.section>
+
+ <@s.section title="Android Studio">
+ <p>
+ Follow the previous instructions (<em>Gradle</em>). In addition to setting up your gradle project correctly, you need to add the <a href="https://plugins.jetbrains.com/plugin/6317">Lombok IntelliJ plugin</a> to add lombok support to Android Studio:
+ <ul><li>
+ Go to <code>File &gt; Settings &gt; Plugins</code>
+ </li><li>
+ Click on <code>Browse repositories...</code>
+ </li><li>
+ Search for <code>Lombok Plugin</code>
+ </li><li>
+ Click on <code>Install plugin</code>
+ </li><li>
+ Restart Android Studio
+ </li></ul>
+ </p>
+ <p>
+ Modify your application's <code>dependencies</code> block:
+<pre>
+dependencies {
+ compileOnly 'org.projectlombok:lombok:${version}'
+ annotationProcessor 'org.projectlombok:lombok:${version}'
+}</pre>
+ </@s.section>
+
+ <@s.section title="Eclipse">
+ <p>
+ In eclipse, create a 'lightweight' lombok jar that contains only the annotations by running:<br /><br />
+ <pre>
+java -jar lombok.jar publicApi</pre>
+ Then, add the <code>lombok-api.jar</code> file created by running this command to your android project instead of the complete <code>lombok.jar</code>, and, as usual, install lombok into eclipse by double-clicking <code>lombok.jar</code>.
+ </p>
+ </@s.section>
+
+ <@s.section title="Maven">
+ <p>
+ You should be able to just follow the normal <a href="maven">integrate lombok with maven instructions</a>.<br />
+ Note that if you use android, eclipse, and maven together you may have to replace <code>lombok.jar</code> in your eclipse android project's build path (which you can modify in that project's properties page) with <code>lombok-api.jar</code>, as produced in the procedure explained for <em>Eclipse</em>, above.
+ </p>
+ </@s.section>
+
+ <@s.section title="Ant">
+ <p>
+ <ul><li>
+ Find <code>build.xml</code> in <code>${r"${ANDROID_SDK_ROOT}"}/tools/ant/build.xml</code> and copy the <code>-compile</code> target into the paste buffer.
+ </li><li>
+ Copy this to the <code>build.xml</code> of your own project, right before the <code>&lt;import file="${r"${sdk.dir}"}/tools/ant/build.xml"&gt;</code> line.
+ </li><li>
+ Create a <code>compile-libs</code> directory in your own project and copy the complete <code>lombok.jar</code> to it.
+ </li><li>
+ Now modify the <code>&lt;classpath&gt;</code> entry inside the <code>&lt;javac&gt;</code> task in the <code>-compile</code> target you just copied:<br />
+ add <code>&lt;fileset dir="compile-libs" includes="*.jar" /&gt;</code> to it.
+ </li></ul>
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/ant.html b/website/templates/setup/ant.html
new file mode 100644
index 00000000..3781e01d
--- /dev/null
+++ b/website/templates/setup/ant.html
@@ -0,0 +1,29 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Ant+ivy">
+ <@s.introduction>
+ <p>
+ This page explains how to compile your code when you use the <a href="https://ant.apache.org/">Apache Ant</a> build tool. We suggest you use <a href="http://ant.apache.org/ivy/">ivy</a>, the ant add-on that lets you fetch dependencies from the internet automatically.
+ </p><p>
+ Lombok just needs to be on the classpath when you compile your code to do its work, so all you have to ensure, is that lombok is on the classpath in your <code>&lt;javac&gt;</code> task.
+ </p>
+ </@s.introduction>
+
+ <@s.section title="Just ant">
+ <p>
+ Assuming that you've put <code>lombok.jar</code> in a <code>lib</code> dir, your javac task would have to look like:<pre>
+&lt;javac srcdir="src" destdir="build" source="1.8"&gt;
+ &lt;classpath location="lib/lombok.jar" /&gt;
+&lt;/javac&gt;</pre>
+ </p>
+ </@s.section>
+
+ <@s.section title="Ant with Ivy">
+ <p>
+ Lombok is available in Maven Central, so you can tell ivy to fetch lombok like so (assuming you have a configuration named <code>build</code>:<pre>
+&lt;dependencies&gt;
+ &lt;dependency org="org.projectlombok" name="lombok" rev="${version}" conf="build->master" /&gt;
+&lt;/dependencies&gt;</pre>
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/ecj.html b/website/templates/setup/ecj.html
new file mode 100644
index 00000000..9d56a085
--- /dev/null
+++ b/website/templates/setup/ecj.html
@@ -0,0 +1,31 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="ecj">
+ <@s.introduction>
+ <p>
+ ecj (the eclipse standalone compiler) is compatible with lombok. Use the following command line to enable lombok with ecj:
+ <pre>java <strong>-javaagent:lombok.jar=ECJ</strong> -jar ecj.jar -cp lombok.jar -source 1.8 <em class="note">(rest of arguments)</em></pre>
+ </p><p>
+ You may have to add the following VM argument, if you're using an older version of lombok or java:
+ <pre><strong>-Xbootclasspath/p:lombok.jar</strong></pre>
+ </p><p>
+ If you're using a tool based on ecj, adding these VM arguments and adding lombok.jar to the classpath should work.
+ </p>
+ </@s.introduction>
+
+ <@s.section title="Maven">
+ <p>
+ It is possible to <a href="/files/pom.xml">configure</a> <code>maven-compiler-plugin</code> with <code>maven-dependency-plugin</code> and <code>plexus-compiler-eclipse</code>.
+ </p><p>
+ Before the <code>compile</code> phase, you will have to set your <code>MAVEN_OPTS</code> environment variable to include the <code>javaagent</code> argument. In the example below, <code>target</code> is your <code>${r"${project.build.directory}"}</code>.
+ </p><p>
+ Use the following commands in sequence to enable lombok with ecj in your Maven build:
+<pre>
+mvn clean <strong>dependency:copy@get-lombok</strong>
+set MAVEN_OPTS=<strong>-javaagent:target/lombok.jar=ECJ</strong> <em class="note">(or your OS's equivalent)</em>
+mvn install
+set MAVEN_OPTS= <em class="note">(or your OS's equivalent)</em>
+</pre>
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/eclipse.html b/website/templates/setup/eclipse.html
new file mode 100644
index 00000000..85304c83
--- /dev/null
+++ b/website/templates/setup/eclipse.html
@@ -0,0 +1,26 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Eclipse, Spring Tool Suite, (Red Hat) JBoss Developer Studio, MyEclipse">
+ <@s.introduction>
+ <p>
+ The <a href="https://eclipse.org/">Eclipse</a> editor is compatible with lombok. Eclipse offshoots are also compatible with lombok, specifically:
+ <ul><li>
+ <a href="https://www.genuitec.com/products/myeclipse/">MyEclipse</a>
+ </li><li>
+ <a href="https://developers.redhat.com/products/devstudio/overview/">Red Hat JBoss Developer Studio</a>
+ </li><li>
+ <a href="https://tools.jboss.org/downloads/devstudio/">JBoss Developer Studio (JBDS)</a>
+ </li><li>
+ <a href="https://spring.io/tools">Spring Tools Suite (STS)</a>
+ </li></ul>
+ </p><p>
+ Double-click lombok.jar (downloadable from this site, or from your maven repository; it's the same jar). This starts the eclipse installer which will find eclipse (and eclipse variants as listed above), and offers to install lombok into these eclipse installations. The same tool can also uninstall lombok: <br />
+
+ <img src="/img/lombok-installer.png" />
+ </p><p>
+ You can check if your eclipse installation is lombok-enabled in eclipse's about dialog. The lombok version will be listed at the end of the copyright text:<br /><br />
+
+ <img src="/img/eclipse-about.png" />
+ </p>
+ </@s.introduction>
+</@s.scaffold>
diff --git a/website/templates/setup/gradle.html b/website/templates/setup/gradle.html
new file mode 100644
index 00000000..7cb4af0d
--- /dev/null
+++ b/website/templates/setup/gradle.html
@@ -0,0 +1,65 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Gradle">
+ <@s.introduction>
+ <p>
+ To set up lombok with any build tool, you have to specify that the lombok dependency is required to compile your source code, but does not need to be present when running/testing/jarring/otherwise deploying your code. Generally this is called a 'provided' dependency. This page explains how to integrate lombok with the <a href="https://gradle.org/">Gradle build tool</a>.
+ </p><p>
+ Lombok is available in maven central, so telling Gradle to download lombok is easy.
+ </p>
+ </@s.introduction>
+
+ <@s.section title="The Lombok Gradle Plugin">
+ <p>
+ There is a plugin for gradle that we recommend you use; it makes deployment a breeze, works around shortcomings of gradle prior to v2.12, and makes it easy to do additional tasks, such as running the lombok eclipse installer or delomboking. The plugin is open source. Read more <a href="https://github.com/franzbecker/gradle-lombok">about the gradle-lombok plugin</a>.
+ </p><p>
+ Note, to tell the <code>gradle-lombok</code> plugin to use the latest version of lombok, you need to explicitly tell it about the latest version number and the SHA-256. For our current latest version, put this in your <code>build.gradle</code> file:<pre>
+lombok {
+ version = ${version}
+ sha256 = ""
+}</pre>
+ </p>
+ </@s.section>
+
+ <@s.section title="Gradle v2.12 and up">
+ <p>
+ If you don't want to use the plugin, gradle has the built-in <code>compileOnly</code> scope, which can be used to tell gradle to add lombok only during compilation. Your <code>build.gradle</code> will look like:<pre>
+repositories {
+ mavenCentral()
+}
+
+plugins {
+ id 'net.ltgt.apt' version '0.10'
+}
+
+dependencies {
+ compileOnly 'org.projectlombok:lombok:${version}'
+
+ apt "org.projectlombok:lombok:${version}"
+}</pre>
+ </p><p>
+ Remember that you still have to download <code>lombok.jar</code> (or find it in gradle's caches) and run it as a jarfile, if you wish to program in eclipse. The plugin makes that part easier.
+ </p>
+ </@s.section>
+ <@s.section title="Gradle prior to v2.12">
+ <p>
+ If you don't want to use the plugin and you're on gradle prior to v2.12, there's a bit of problem: Gradle didn't introduce the 'provided' concept until v2.12. The concept is added by a few well known plugins: The gradle <code>war</code> plugin has the <code>providedCompile</code> scope, and the <a href="https://github.com/nebula-plugins/gradle-extra-configurations-plugin">Gradle Extra Configurations Plugin</a> supports the <code>provided</code> scope. With these plugins, your <code>build.gradle</code> file will look something like this:<pre>
+apply plugin: 'java'
+apply plugin: 'nebula.provided-base'
+
+repositories {
+ mavenCentral()
+}
+
+dependencies {
+ provided 'org.projectlombok:lombok:${version}'
+}</pre>
+ </p>
+ </@s.section>
+
+ <@s.section title="Android development">
+ <p>
+ Complete instructions for integrating lombok with your android development is available on our <a href="android">Using lombok for android development</a> page.
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/gwt.html b/website/templates/setup/gwt.html
new file mode 100644
index 00000000..142362ac
--- /dev/null
+++ b/website/templates/setup/gwt.html
@@ -0,0 +1,16 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="GWT">
+ <@s.introduction>
+ <p>
+ <a href="http://www.gwtproject.org/">GWT (Google Web Toolkit)</a> is compatible with lombok.
+ </p><p>
+ Edit your <code>proj-debug</code> and <code>proj-compile</code> batch scripts to add the following VM arguments:
+<pre>
+java <strong>-javaagent:lombok.jar=ECJ</strong> <em>(rest of arguments)</em>
+</pre>
+ </p><p>
+ Thanks to Stephen Haberman for figuring this out.
+ </p>
+ </@s.introduction>
+</@s.scaffold>
diff --git a/website/templates/setup/intellij.html b/website/templates/setup/intellij.html
new file mode 100644
index 00000000..331a7bcd
--- /dev/null
+++ b/website/templates/setup/intellij.html
@@ -0,0 +1,22 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="IntelliJ IDEA">
+ <@s.introduction>
+ <p>
+ The <a href="https://www.jetbrains.com/idea/">Jetbrains IntelliJ IDEA</a> editor is compatible with lombok.
+ </p><p>
+ Add the <a href="https://plugins.jetbrains.com/plugin/6317">Lombok IntelliJ plugin</a> to add lombok support for IntelliJ:
+ <ul><li>
+ Go to <code>File &gt; Settings &gt; Plugins</code>
+ </li><li>
+ Click on <code>Browse repositories...</code>
+ </li><li>
+ Search for <code>Lombok Plugin</code>
+ </li><li>
+ Click on <code>Install plugin</code>
+ </li><li>
+ Restart IntelliJ IDEA
+ </li></ul>
+ </p>
+ </@s.introduction>
+</@s.scaffold>
diff --git a/website/templates/setup/javac.html b/website/templates/setup/javac.html
new file mode 100644
index 00000000..48b0ebcf
--- /dev/null
+++ b/website/templates/setup/javac.html
@@ -0,0 +1,25 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="JavaC">
+ <@s.introduction>
+ <p>
+ Just put lombok on the classpath when compiling with any javac (version 1.6 - 1.8): <code>javac -cp lombok.jar ....</code>
+ </p>
+ </@s.introduction>
+
+ <@s.section title="JDK 9">
+ <p>
+ Support for JDK9, if you haven't modularized your own projects yet (no <code>module-info.java</code> yet), is included in lombok starting with version 1.16.20. Just use lombok as normal: <code> javac -cp lombok.jar ...</code>
+ </p><p>
+ Support for JDK9 if you did modularize your own projects (you've written a <code>module-info.java</code> file) is available in the <a href="/download-edge">edge release</a>. To use it: <code>javac -cp lombok.jar -p lombok.jar ...</code><br />
+ Note that you will have to add lombok to your <code>module-info.java</code> file:<pre>
+module <em>myapp</em> {
+ requires static lombok;
+}</pre>
+ </p><p>
+ The 'static' part ensures that you won't need lombok to be present at runtime.
+ </p><p>
+ Feedback about JDK9 module-info support can be given at <a href="https://github.com/rzwitserloot/lombok/issues/985">github issue #985</a>.
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/kobalt.html b/website/templates/setup/kobalt.html
new file mode 100644
index 00000000..26adf23d
--- /dev/null
+++ b/website/templates/setup/kobalt.html
@@ -0,0 +1,20 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Kobalt">
+ <@s.introduction>
+ <p>
+ To set up lombok with any build tool, you have to specify that the lombok dependency is required to compile your source code, but does not need to be present when running/testing/jarring/otherwise deploying your code. Generally this is called a 'provided' dependency. This page explains how to integrate lombok with the <a href="http://beust.com/kobalt/home/index.html">Kobalt</a> buid tool.
+ </p><p>
+ Lombok is available in maven central, so telling Kobalt to download lombok is easy.
+ </p>
+ </@s.introduction>
+
+ <@s.section title="Configuring Kobalt">
+ <p>
+ To add lombok as a 'provided' dependency to your project, write your <code>Built.kt</code> like so:<pre>
+dependencies {
+ provided("org.projectlombok:lombok:${version}")
+}</pre>
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/main.html b/website/templates/setup/main.html
new file mode 100644
index 00000000..8c874a55
--- /dev/null
+++ b/website/templates/setup/main.html
@@ -0,0 +1,14 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Using lombok">
+ <@s.introduction>
+ <#list s.main.setupTargets as cat, tgtList>
+ <h3 class="listHeader">${cat}</h3>
+ <ul>
+ <#list tgtList as name, url>
+ <li class="target"><a href="/setup/${url}">${name}</a></li>
+ </#list>
+ </ul>
+ </#list>
+ </@s.introduction>
+</@s.scaffold>
diff --git a/website/templates/setup/maven.html b/website/templates/setup/maven.html
new file mode 100644
index 00000000..5ca09126
--- /dev/null
+++ b/website/templates/setup/maven.html
@@ -0,0 +1,32 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Maven">
+ <@s.introduction>
+ <p>
+ To set up lombok with any build tool, you have to specify that the lombok dependency is required to compile your source code, but does not need to be present when running/testing/jarring/otherwise deploying your code. Generally this is called a 'provided' dependency. This page explains how to integrate lombok with the <a href="https://maven.apache.org/">Apache Maven</a> build tool.
+ </p><p>
+ Lombok is available in maven central, so telling Maven to download lombok is easy.
+ </p>
+ </@s.introduction>
+
+ <@s.section title="Adding lombok to your pom file">
+ <p>
+ To include lombok as a 'provided' dependency, add it to your <code>&lt;dependencies&gt;</code> block like so:<pre>
+&lt;dependencies&gt;
+ &lt;dependency&gt;
+ &lt;groupId&gt;org.projectlombok&lt;/groupId&gt;
+ &lt;artifactId&gt;lombok&lt;/artifactId&gt;
+ &lt;version&gt;${version}&lt;/version&gt;
+ &lt;scope&gt;provided&lt;/scope&gt;
+ &lt;/dependency&gt;
+&lt;/dependencies&gt;
+</pre>
+ </p>
+ </@s.section>
+
+ <@s.section title="Delomboking: The Lombok Maven Plugin">
+ <p>
+ There is a plugin for Maven that we recommend you use if you want to delombok via maven. Useful if you want to run source analysis tools on your source <em>after</em> lombok has been applied, or if you want to generate javadoc. The plugin is open source. Read more <a href="http://awhitford.github.io/lombok.maven/lombok-maven-plugin/">about the lombok maven plugin</a>.
+ </p>
+ </@s.section>
+</@s.scaffold>
diff --git a/website/templates/setup/netbeans.html b/website/templates/setup/netbeans.html
new file mode 100644
index 00000000..eccd9e93
--- /dev/null
+++ b/website/templates/setup/netbeans.html
@@ -0,0 +1,16 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Netbeans">
+ <@s.introduction>
+ <p>
+ The <a href="https://netbeans.org/">Netbeans</a> editor is compatible with lombok.
+ <ol><li>
+ Add <code>lombok.jar</code> to the project libraries.
+ </li><li>
+ In the project properties, in the section <code>Build &ndash; Compiling</code>, check the <code>&#39;Enable Annotation Processing in Editor&#39;</code> checkbox.
+ </li></ol>
+
+ <img src="/img/netbeans-enable-annotation-processing-in-editor.png" />
+ </p>
+ </@s.introduction>
+</@s.scaffold>
diff --git a/website/templates/setup/vscode.html b/website/templates/setup/vscode.html
new file mode 100644
index 00000000..bf9c3e58
--- /dev/null
+++ b/website/templates/setup/vscode.html
@@ -0,0 +1,18 @@
+<#import "_setup.html" as s>
+
+<@s.scaffold title="Microsoft Visual Studio Code">
+ <@s.introduction>
+ <p>
+ The <a href="https://code.visualstudio.com/">Microsoft Visual Studio Code</a> editor is compatible with lombok.
+ </p><p>
+ Add the <a href="https://marketplace.visualstudio.com/items?itemName=GabrielBB.vscode-lombok">vscode-lombok</a> plugin to your Visual Studio Code IDE to add lombok support.
+ <ul><li>
+ press <code>Ctrl + Shift + X</code> to open the extension manager.
+ </li><li>
+ Type <code>lombok</code> to find the plugin, and click <code>install</code>.
+ </li><li>
+ Reload VS Code when asked.
+ </li></ul>
+ </p>
+ </@s.introduction>
+</@s.scaffold>
diff --git a/website/templates/supporters.html b/website/templates/supporters.html
new file mode 100644
index 00000000..9facb090
--- /dev/null
+++ b/website/templates/supporters.html
@@ -0,0 +1,10 @@
+<#import "/_scaffold.html" as main>
+
+<@main.scaffold load=["js/supporters.js"] title="Supporters">
+ <div class="page-header top5">
+ <div class="row text-center">
+ <h1>Project Lombok supporters</h1>
+ </div><div class="row supporters">
+ </div>
+ </div>
+</@main.scaffold>
diff --git a/website/unknown_person.gif b/website/unknown_person.gif
deleted file mode 100644
index c5ec6b89..00000000
--- a/website/unknown_person.gif
+++ /dev/null
Binary files differ
diff --git a/website/usageExamples/BuilderExample_post.jpage b/website/usageExamples/BuilderExample_post.jpage
new file mode 100644
index 00000000..54b064d7
--- /dev/null
+++ b/website/usageExamples/BuilderExample_post.jpage
@@ -0,0 +1,74 @@
+import java.util.Set;
+
+public class BuilderExample {
+ private String name;
+ private int age;
+ private Set<String> occupations;
+
+ BuilderExample(String name, int age, Set<String> occupations) {
+ this.name = name;
+ this.age = age;
+ this.occupations = occupations;
+ }
+
+ public static BuilderExampleBuilder builder() {
+ return new BuilderExampleBuilder();
+ }
+
+ public static class BuilderExampleBuilder {
+ private String name;
+ private int age;
+ private java.util.ArrayList<String> occupations;
+
+ BuilderExampleBuilder() {
+ }
+
+ public BuilderExampleBuilder name(String name) {
+ this.name = name;
+ return this;
+ }
+
+ public BuilderExampleBuilder age(int age) {
+ this.age = age;
+ return this;
+ }
+
+ public BuilderExampleBuilder occupation(String occupation) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.add(occupation);
+ return this;
+ }
+
+ public BuilderExampleBuilder occupations(Collection<? extends String> occupations) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.addAll(occupations);
+ return this;
+ }
+
+ public BuilderExampleBuilder clearOccupations() {
+ if (this.occupations != null) {
+ this.occupations.clear();
+ }
+
+ return this;
+ }
+
+ public BuilderExample build() {
+ // complicated switch statement to produce a compact properly sized immutable set omitted.
+ // go to https://projectlombok.org/features/Singular-snippet.html to see it.
+ Set<String> occupations = ...;
+ return new BuilderExample(name, age, occupations);
+ }
+
+ @java.lang.Override
+ public String toString() {
+ return "BuilderExample.BuilderExampleBuilder(name = " + this.name + ", age = " + this.age + ", occupations = " + this.occupations + ")";
+ }
+ }
+} \ No newline at end of file
diff --git a/website/usageExamples/BuilderExample_pre.jpage b/website/usageExamples/BuilderExample_pre.jpage
new file mode 100644
index 00000000..1557fff4
--- /dev/null
+++ b/website/usageExamples/BuilderExample_pre.jpage
@@ -0,0 +1,10 @@
+import lombok.Builder;
+import lombok.Singular;
+import java.util.Set;
+
+@Builder
+public class BuilderExample {
+ private String name;
+ private int age;
+ @Singular private Set<String> occupations;
+}
diff --git a/website/usageExamples/CleanupExample_post.jpage b/website/usageExamples/CleanupExample_post.jpage
new file mode 100644
index 00000000..7e87c153
--- /dev/null
+++ b/website/usageExamples/CleanupExample_post.jpage
@@ -0,0 +1,26 @@
+import java.io.*;
+
+public class CleanupExample {
+ public static void main(String[] args) throws IOException {
+ InputStream in = new FileInputStream(args[0]);
+ try {
+ OutputStream out = new FileOutputStream(args[1]);
+ try {
+ byte[] b = new byte[10000];
+ while (true) {
+ int r = in.read(b);
+ if (r == -1) break;
+ out.write(b, 0, r);
+ }
+ } finally {
+ if (out != null) {
+ out.close();
+ }
+ }
+ } finally {
+ if (in != null) {
+ in.close();
+ }
+ }
+ }
+}
diff --git a/website/usageExamples/CleanupExample_pre.jpage b/website/usageExamples/CleanupExample_pre.jpage
new file mode 100644
index 00000000..9f639171
--- /dev/null
+++ b/website/usageExamples/CleanupExample_pre.jpage
@@ -0,0 +1,15 @@
+import lombok.Cleanup;
+import java.io.*;
+
+public class CleanupExample {
+ public static void main(String[] args) throws IOException {
+ @Cleanup InputStream in = new FileInputStream(args[0]);
+ @Cleanup OutputStream out = new FileOutputStream(args[1]);
+ byte[] b = new byte[10000];
+ while (true) {
+ int r = in.read(b);
+ if (r == -1) break;
+ out.write(b, 0, r);
+ }
+ }
+}
diff --git a/website/usageExamples/ConstructorExample_post.jpage b/website/usageExamples/ConstructorExample_post.jpage
new file mode 100644
index 00000000..8a2d5069
--- /dev/null
+++ b/website/usageExamples/ConstructorExample_post.jpage
@@ -0,0 +1,28 @@
+public class ConstructorExample<T> {
+ private int x, y;
+ @NonNull private T description;
+
+ private ConstructorExample(T description) {
+ if (description == null) throw new NullPointerException("description");
+ this.description = description;
+ }
+
+ public static <T> ConstructorExample<T> of(T description) {
+ return new ConstructorExample<T>(description);
+ }
+
+ @java.beans.ConstructorProperties({"x", "y", "description"})
+ protected ConstructorExample(int x, int y, T description) {
+ if (description == null) throw new NullPointerException("description");
+ this.x = x;
+ this.y = y;
+ this.description = description;
+ }
+
+ public static class NoArgsExample {
+ @NonNull private String field;
+
+ public NoArgsExample() {
+ }
+ }
+}
diff --git a/website/usageExamples/ConstructorExample_pre.jpage b/website/usageExamples/ConstructorExample_pre.jpage
new file mode 100644
index 00000000..ac0d3c28
--- /dev/null
+++ b/website/usageExamples/ConstructorExample_pre.jpage
@@ -0,0 +1,16 @@
+import lombok.AccessLevel;
+import lombok.RequiredArgsConstructor;
+import lombok.AllArgsConstructor;
+import lombok.NonNull;
+
+@RequiredArgsConstructor(staticName = "of")
+@AllArgsConstructor(access = AccessLevel.PROTECTED)
+public class ConstructorExample<T> {
+ private int x, y;
+ @NonNull private T description;
+
+ @NoArgsConstructor
+ public static class NoArgsExample {
+ @NonNull private String field;
+ }
+}
diff --git a/website/usageExamples/DataExample_post.jpage b/website/usageExamples/DataExample_post.jpage
new file mode 100644
index 00000000..bef0a0f1
--- /dev/null
+++ b/website/usageExamples/DataExample_post.jpage
@@ -0,0 +1,119 @@
+import java.util.Arrays;
+
+public class DataExample {
+ private final String name;
+ private int age;
+ private double score;
+ private String[] tags;
+
+ public DataExample(String name) {
+ this.name = name;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ void setAge(int age) {
+ this.age = age;
+ }
+
+ public int getAge() {
+ return this.age;
+ }
+
+ public void setScore(double score) {
+ this.score = score;
+ }
+
+ public double getScore() {
+ return this.score;
+ }
+
+ public String[] getTags() {
+ return this.tags;
+ }
+
+ public void setTags(String[] tags) {
+ this.tags = tags;
+ }
+
+ @Override public String toString() {
+ return "DataExample(" + this.getName() + ", " + this.getAge() + ", " + this.getScore() + ", " + Arrays.deepToString(this.getTags()) + ")";
+ }
+
+ protected boolean canEqual(Object other) {
+ return other instanceof DataExample;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof DataExample)) return false;
+ DataExample other = (DataExample) o;
+ if (!other.canEqual((Object)this)) return false;
+ if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
+ if (this.getAge() != other.getAge()) return false;
+ if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
+ if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
+ return true;
+ }
+
+ @Override public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final long temp1 = Double.doubleToLongBits(this.getScore());
+ result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
+ result = (result*PRIME) + this.getAge();
+ result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
+ result = (result*PRIME) + Arrays.deepHashCode(this.getTags());
+ return result;
+ }
+
+ public static class Exercise<T> {
+ private final String name;
+ private final T value;
+
+ private Exercise(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public static <T> Exercise<T> of(String name, T value) {
+ return new Exercise<T>(name, value);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public T getValue() {
+ return this.value;
+ }
+
+ @Override public String toString() {
+ return "Exercise(name=" + this.getName() + ", value=" + this.getValue() + ")";
+ }
+
+ protected boolean canEqual(Object other) {
+ return other instanceof Exercise;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof Exercise)) return false;
+ Exercise<?> other = (Exercise<?>) o;
+ if (!other.canEqual((Object)this)) return false;
+ if (this.getName() == null ? other.getValue() != null : !this.getName().equals(other.getName())) return false;
+ if (this.getValue() == null ? other.getValue() != null : !this.getValue().equals(other.getValue())) return false;
+ return true;
+ }
+
+ @Override public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = (result*PRIME) + (this.getName() == null ? 43 : this.getName().hashCode());
+ result = (result*PRIME) + (this.getValue() == null ? 43 : this.getValue().hashCode());
+ return result;
+ }
+ }
+}
diff --git a/website/usageExamples/DataExample_pre.jpage b/website/usageExamples/DataExample_pre.jpage
new file mode 100644
index 00000000..404d3458
--- /dev/null
+++ b/website/usageExamples/DataExample_pre.jpage
@@ -0,0 +1,18 @@
+import lombok.AccessLevel;
+import lombok.Setter;
+import lombok.Data;
+import lombok.ToString;
+
+@Data public class DataExample {
+ private final String name;
+ @Setter(AccessLevel.PACKAGE) private int age;
+ private double score;
+ private String[] tags;
+
+ @ToString(includeFieldNames=true)
+ @Data(staticConstructor="of")
+ public static class Exercise<T> {
+ private final String name;
+ private final T value;
+ }
+}
diff --git a/website/usageExamples/EqualsAndHashCodeExample_post.jpage b/website/usageExamples/EqualsAndHashCodeExample_post.jpage
new file mode 100644
index 00000000..91e78250
--- /dev/null
+++ b/website/usageExamples/EqualsAndHashCodeExample_post.jpage
@@ -0,0 +1,72 @@
+import java.util.Arrays;
+
+public class EqualsAndHashCodeExample {
+ private transient int transientVar = 10;
+ private String name;
+ private double score;
+ private Shape shape = new Square(5, 10);
+ private String[] tags;
+ private int id;
+
+ public String getName() {
+ return this.name;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof EqualsAndHashCodeExample)) return false;
+ EqualsAndHashCodeExample other = (EqualsAndHashCodeExample) o;
+ if (!other.canEqual((Object)this)) return false;
+ if (this.getName() == null ? other.getName() != null : !this.getName().equals(other.getName())) return false;
+ if (Double.compare(this.score, other.score) != 0) return false;
+ if (!Arrays.deepEquals(this.tags, other.tags)) return false;
+ return true;
+ }
+
+ @Override public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final long temp1 = Double.doubleToLongBits(this.score);
+ result = (result*PRIME) + (this.name == null ? 43 : this.name.hashCode());
+ result = (result*PRIME) + (int)(temp1 ^ (temp1 >>> 32));
+ result = (result*PRIME) + Arrays.deepHashCode(this.tags);
+ return result;
+ }
+
+ protected boolean canEqual(Object other) {
+ return other instanceof EqualsAndHashCodeExample;
+ }
+
+ public static class Square extends Shape {
+ private final int width, height;
+
+ public Square(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof Square)) return false;
+ Square other = (Square) o;
+ if (!other.canEqual((Object)this)) return false;
+ if (!super.equals(o)) return false;
+ if (this.width != other.width) return false;
+ if (this.height != other.height) return false;
+ return true;
+ }
+
+ @Override public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ result = (result*PRIME) + super.hashCode();
+ result = (result*PRIME) + this.width;
+ result = (result*PRIME) + this.height;
+ return result;
+ }
+
+ protected boolean canEqual(Object other) {
+ return other instanceof Square;
+ }
+ }
+}
diff --git a/website/usageExamples/EqualsAndHashCodeExample_pre.jpage b/website/usageExamples/EqualsAndHashCodeExample_pre.jpage
new file mode 100644
index 00000000..64faf59f
--- /dev/null
+++ b/website/usageExamples/EqualsAndHashCodeExample_pre.jpage
@@ -0,0 +1,25 @@
+import lombok.EqualsAndHashCode;
+
+@EqualsAndHashCode(exclude={"id", "shape"})
+public class EqualsAndHashCodeExample {
+ private transient int transientVar = 10;
+ private String name;
+ private double score;
+ private Shape shape = new Square(5, 10);
+ private String[] tags;
+ private int id;
+
+ public String getName() {
+ return this.name;
+ }
+
+ @EqualsAndHashCode(callSuper=true)
+ public static class Square extends Shape {
+ private final int width, height;
+
+ public Square(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+ }
+}
diff --git a/website/usageExamples/GetterLazyExample_post.jpage b/website/usageExamples/GetterLazyExample_post.jpage
new file mode 100644
index 00000000..5f34c43e
--- /dev/null
+++ b/website/usageExamples/GetterLazyExample_post.jpage
@@ -0,0 +1,26 @@
+public class GetterLazyExample {
+ private final java.util.concurrent.AtomicReference<java.lang.Object> cached = new java.util.concurrent.AtomicReference<java.lang.Object>();
+
+ public double[] getCached() {
+ java.lang.Object value = this.cached.get();
+ if (value == null) {
+ synchronized(this.cached) {
+ value = this.cached.get();
+ if (value == null) {
+ final double[] actualValue = expensive();
+ value = actualValue == null ? this.cached : actualValue;
+ this.cached.set(value);
+ }
+ }
+ }
+ return (double[])(value == this.cached ? null : value);
+ }
+
+ private double[] expensive() {
+ double[] result = new double[1000000];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = Math.asin(i);
+ }
+ return result;
+ }
+}
diff --git a/website/usageExamples/GetterLazyExample_pre.jpage b/website/usageExamples/GetterLazyExample_pre.jpage
new file mode 100644
index 00000000..ca6c9d58
--- /dev/null
+++ b/website/usageExamples/GetterLazyExample_pre.jpage
@@ -0,0 +1,13 @@
+import lombok.Getter;
+
+public class GetterLazyExample {
+ @Getter(lazy=true) private final double[] cached = expensive();
+
+ private double[] expensive() {
+ double[] result = new double[1000000];
+ for (int i = 0; i < result.length; i++) {
+ result[i] = Math.asin(i);
+ }
+ return result;
+ }
+}
diff --git a/website/usageExamples/GetterSetterExample_post.jpage b/website/usageExamples/GetterSetterExample_post.jpage
new file mode 100644
index 00000000..241a3a4e
--- /dev/null
+++ b/website/usageExamples/GetterSetterExample_post.jpage
@@ -0,0 +1,42 @@
+public class GetterSetterExample {
+ /**
+ * Age of the person. Water is wet.
+ */
+ private int age = 10;
+
+ /**
+ * Name of the person.
+ */
+ private String name;
+
+ @Override public String toString() {
+ return String.format("%s (age: %d)", name, age);
+ }
+
+ /**
+ * Age of the person. Water is wet.
+ *
+ * @return The current value of this person's age. Circles are round.
+ */
+ public int getAge() {
+ return age;
+ }
+
+ /**
+ * Age of the person. Water is wet.
+ *
+ * @param age New value for this person's age. Sky is blue.
+ */
+ public void setAge(int age) {
+ this.age = age;
+ }
+
+ /**
+ * Changes the name of this person.
+ *
+ * @param name The new value.
+ */
+ protected void setName(String name) {
+ this.name = name;
+ }
+}
diff --git a/website/usageExamples/GetterSetterExample_pre.jpage b/website/usageExamples/GetterSetterExample_pre.jpage
new file mode 100644
index 00000000..4183aa5d
--- /dev/null
+++ b/website/usageExamples/GetterSetterExample_pre.jpage
@@ -0,0 +1,26 @@
+import lombok.AccessLevel;
+import lombok.Getter;
+import lombok.Setter;
+
+public class GetterSetterExample {
+ /**
+ * Age of the person. Water is wet.
+ *
+ * @param age New value for this person's age. Sky is blue.
+ * @return The current value of this person's age. Circles are round.
+ */
+ @Getter @Setter private int age = 10;
+
+ /**
+ * Name of the person.
+ * -- SETTER --
+ * Changes the name of this person.
+ *
+ * @param name The new value.
+ */
+ @Setter(AccessLevel.PROTECTED) private String name;
+
+ @Override public String toString() {
+ return String.format("%s (age: %d)", name, age);
+ }
+}
diff --git a/website/usageExamples/LogExample_post.jpage b/website/usageExamples/LogExample_post.jpage
new file mode 100644
index 00000000..eab3b046
--- /dev/null
+++ b/website/usageExamples/LogExample_post.jpage
@@ -0,0 +1,23 @@
+public class LogExample {
+ private static final java.util.logging.Logger log = java.util.logging.Logger.getLogger(LogExample.class.getName());
+
+ public static void main(String... args) {
+ log.error("Something's wrong here");
+ }
+}
+
+public class LogExampleOther {
+ private static final org.slf4j.Logger log = org.slf4j.LoggerFactory.getLogger(LogExampleOther.class);
+
+ public static void main(String... args) {
+ log.error("Something else is wrong here");
+ }
+}
+
+public class LogExampleCategory {
+ private static final org.apache.commons.logging.Log log = org.apache.commons.logging.LogFactory.getLog("CounterLog");
+
+ public static void main(String... args) {
+ log.error("Calling the 'CounterLog' with a message");
+ }
+}
diff --git a/website/usageExamples/LogExample_pre.jpage b/website/usageExamples/LogExample_pre.jpage
new file mode 100644
index 00000000..ba27dd27
--- /dev/null
+++ b/website/usageExamples/LogExample_pre.jpage
@@ -0,0 +1,26 @@
+import lombok.extern.java.Log;
+import lombok.extern.slf4j.Slf4j;
+
+@Log
+public class LogExample {
+
+ public static void main(String... args) {
+ log.error("Something's wrong here");
+ }
+}
+
+@Slf4j
+public class LogExampleOther {
+
+ public static void main(String... args) {
+ log.error("Something else is wrong here");
+ }
+}
+
+@CommonsLog(topic="CounterLog")
+public class LogExampleCategory {
+
+ public static void main(String... args) {
+ log.error("Calling the 'CounterLog' with a message");
+ }
+}
diff --git a/website/usageExamples/NonNullExample_post.jpage b/website/usageExamples/NonNullExample_post.jpage
new file mode 100644
index 00000000..24175e06
--- /dev/null
+++ b/website/usageExamples/NonNullExample_post.jpage
@@ -0,0 +1,13 @@
+import lombok.NonNull;
+
+public class NonNullExample extends Something {
+ private String name;
+
+ public NonNullExample(@NonNull Person person) {
+ super("Hello");
+ if (person == null) {
+ throw new NullPointerException("person");
+ }
+ this.name = person.getName();
+ }
+}
diff --git a/website/usageExamples/NonNullExample_pre.jpage b/website/usageExamples/NonNullExample_pre.jpage
new file mode 100644
index 00000000..47556ce7
--- /dev/null
+++ b/website/usageExamples/NonNullExample_pre.jpage
@@ -0,0 +1,10 @@
+import lombok.NonNull;
+
+public class NonNullExample extends Something {
+ private String name;
+
+ public NonNullExample(@NonNull Person person) {
+ super("Hello");
+ this.name = person.getName();
+ }
+}
diff --git a/website/usageExamples/Singular-snippetExample_post.jpage b/website/usageExamples/Singular-snippetExample_post.jpage
new file mode 100644
index 00000000..4e2b0460
--- /dev/null
+++ b/website/usageExamples/Singular-snippetExample_post.jpage
@@ -0,0 +1,160 @@
+import java.util.Collection;
+import java.util.Set;
+import java.util.SortedMap;
+import com.google.common.collect.ImmutableList;
+
+public class SingularExample<T extends Number> {
+ private Set<String> occupations;
+ private ImmutableList<String> axes;
+ private SortedMap<Integer, T> elves;
+ private Collection<?> minutiae;
+
+ SingularExample(Set<String> occupations, ImmutableList<String> axes, SortedMap<Integer, T> elves, Collection<?> minutiae) {
+ this.occupations = occupations;
+ this.axes = axes;
+ this.elves = elves;
+ this.minutiae = minutiae;
+ }
+
+ public static class SingularExampleBuilder<T extends Number> {
+ private java.util.ArrayList<String> occupations;
+ private com.google.common.collect.ImmutableList.Builder<String> axes;
+ private java.util.ArrayList<Integer> elves$key;
+ private java.util.ArrayList<T> elves$value;
+ private java.util.ArrayList<java.lang.Object> minutiae;
+
+ SingularExampleBuilder() {
+ }
+
+ public SingularExampleBuilder<T> occupation(String occupation) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.add(occupation);
+ return this;
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public SingularExampleBuilder<T> occupations(java.util.Collection<? extends String> occupations) {
+ if (this.occupations == null) {
+ this.occupations = new java.util.ArrayList<String>();
+ }
+
+ this.occupations.addAll(occupations);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> axis(String axis) {
+ if (this.axes == null) {
+ this.axes = com.google.common.collect.ImmutableList.builder();
+ }
+
+ this.axes.add(axis);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> axes(java.lang.Iterable<? extends String> axes) {
+ if (this.axes == null) {
+ this.axes = com.google.common.collect.ImmutableList.builder();
+ }
+
+ this.axes.addAll(axes);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> elf(Integer elfKey, T elfValue) {
+ if (this.elves$key == null) {
+ this.elves$key = new java.util.ArrayList<Integer>();
+ this.elves$value = new java.util.ArrayList<T>();
+ }
+
+ this.elves$key.add(elfKey);
+ this.elves$value.add(elfValue);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> elves(java.util.Map<? extends Integer, ? extends T> elves) {
+ if (this.elves$key == null) {
+ this.elves$key = new java.util.ArrayList<Integer>();
+ this.elves$value = new java.util.ArrayList<T>();
+ }
+
+ for (java.util.Map.Entry<? extends Integer, ? extends T> $lombokEntry : elves.entrySet()) {
+ this.elves$key.add($lombokEntry.getKey());
+ this.elves$value.add($lombokEntry.getValue());
+ }
+ return this;
+ }
+
+ public SingularExampleBuilder<T> minutia(java.lang.Object minutia) {
+ if (this.minutiae == null) {
+ this.minutiae = new java.util.ArrayList<java.lang.Object>();
+ }
+
+ this.minutiae.add(minutia);
+ return this;
+ }
+
+ public SingularExampleBuilder<T> minutiae(java.util.Collection<?> minutiae) {
+ if (this.minutiae == null) {
+ this.minutiae = new java.util.ArrayList<java.lang.Object>();
+ }
+
+ this.minutiae.addAll(minutiae);
+ return this;
+ }
+
+ public SingularExample<T> build() {
+ java.util.Set<String> occupations;
+ switch (this.occupations == null ? 0 : this.occupations.size()) {
+ case 0:
+ occupations = java.util.Collections.emptySet();
+ break;
+
+ case 1:
+ occupations = java.util.Collections.singleton(this.occupations.get(0));
+ break;
+
+ default:
+ occupations = new java.util.LinkedHashSet<String>(this.occupations.size() < 1073741824 ? 1 + this.occupations.size() + (this.occupations.size() - 3) / 3 : java.lang.Integer.MAX_VALUE);
+ occupations.addAll(this.occupations);
+ occupations = java.util.Collections.unmodifiableSet(occupations);
+
+ }
+
+ com.google.common.collect.ImmutableList<String> axes = this.axes == null ? com.google.common.collect.ImmutableList.<String>of() : this.axes.build();
+
+ java.util.SortedMap<Integer, T> elves = new java.util.TreeMap<Integer, T>();
+ if (this.elves$key != null) for (int $i = 0; $i < (this.elves$key == null ? 0 : this.elves$key.size()); $i++) elves.put(this.elves$key.get($i), this.elves$value.get($i));
+ elves = java.util.Collections.unmodifiableSortedMap(elves);
+
+ java.util.Collection<java.lang.Object> minutiae;
+ switch (this.minutiae == null ? 0 : this.minutiae.size()) {
+ case 0:
+ minutiae = java.util.Collections.emptyList();
+ break;
+
+ case 1:
+ minutiae = java.util.Collections.singletonList(this.minutiae.get(0));
+ break;
+
+ default:
+ minutiae = java.util.Collections.unmodifiableList(new java.util.ArrayList<java.lang.Object>(this.minutiae));
+
+ }
+
+ return new SingularExample<T>(occupations, axes, elves, minutiae);
+ }
+
+ @java.lang.Override
+ public java.lang.String toString() {
+ return "SingularExample.SingularExampleBuilder(occupations=" + this.occupations + ", axes=" + this.axes + ", elves$key=" + this.elves$key + ", elves$value=" + this.elves$value + ", minutiae=" + this.minutiae + ")";
+ }
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public static <T extends Number> SingularExampleBuilder<T> builder() {
+ return new SingularExampleBuilder<T>();
+ }
+}
diff --git a/website/usageExamples/Singular-snippetExample_pre.jpage b/website/usageExamples/Singular-snippetExample_pre.jpage
new file mode 100644
index 00000000..65f6bbc8
--- /dev/null
+++ b/website/usageExamples/Singular-snippetExample_pre.jpage
@@ -0,0 +1,14 @@
+import lombok.Builder;
+import lombok.Singular;
+import java.util.Collection;
+import java.util.Set;
+import java.util.SortedMap;
+import com.google.common.collect.ImmutableList;
+
+@Builder
+public class SingularExample<T extends Number> {
+ private @Singular Set<String> occupations;
+ private @Singular("axis") ImmutableList<String> axes;
+ private @Singular SortedMap<Integer, T> elves;
+ private @Singular Collection<?> minutiae;
+}
diff --git a/website/usageExamples/SneakyThrowsExample_post.jpage b/website/usageExamples/SneakyThrowsExample_post.jpage
new file mode 100644
index 00000000..916d94f0
--- /dev/null
+++ b/website/usageExamples/SneakyThrowsExample_post.jpage
@@ -0,0 +1,19 @@
+import lombok.Lombok;
+
+public class SneakyThrowsExample implements Runnable {
+ public String utf8ToString(byte[] bytes) {
+ try {
+ return new String(bytes, "UTF-8");
+ } catch (UnsupportedEncodingException e) {
+ throw Lombok.sneakyThrow(e);
+ }
+ }
+
+ public void run() {
+ try {
+ throw new Throwable();
+ } catch (Throwable t) {
+ throw Lombok.sneakyThrow(t);
+ }
+ }
+}
diff --git a/website/usageExamples/SneakyThrowsExample_pre.jpage b/website/usageExamples/SneakyThrowsExample_pre.jpage
new file mode 100644
index 00000000..be6d72d5
--- /dev/null
+++ b/website/usageExamples/SneakyThrowsExample_pre.jpage
@@ -0,0 +1,13 @@
+import lombok.SneakyThrows;
+
+public class SneakyThrowsExample implements Runnable {
+ @SneakyThrows(UnsupportedEncodingException.class)
+ public String utf8ToString(byte[] bytes) {
+ return new String(bytes, "UTF-8");
+ }
+
+ @SneakyThrows
+ public void run() {
+ throw new Throwable();
+ }
+}
diff --git a/website/usageExamples/SynchronizedExample_post.jpage b/website/usageExamples/SynchronizedExample_post.jpage
new file mode 100644
index 00000000..219ab88a
--- /dev/null
+++ b/website/usageExamples/SynchronizedExample_post.jpage
@@ -0,0 +1,23 @@
+public class SynchronizedExample {
+ private static final Object $LOCK = new Object[0];
+ private final Object $lock = new Object[0];
+ private final Object readLock = new Object();
+
+ public static void hello() {
+ synchronized($LOCK) {
+ System.out.println("world");
+ }
+ }
+
+ public int answerToLife() {
+ synchronized($lock) {
+ return 42;
+ }
+ }
+
+ public void foo() {
+ synchronized(readLock) {
+ System.out.println("bar");
+ }
+ }
+}
diff --git a/website/usageExamples/SynchronizedExample_pre.jpage b/website/usageExamples/SynchronizedExample_pre.jpage
new file mode 100644
index 00000000..ace39f85
--- /dev/null
+++ b/website/usageExamples/SynchronizedExample_pre.jpage
@@ -0,0 +1,20 @@
+import lombok.Synchronized;
+
+public class SynchronizedExample {
+ private final Object readLock = new Object();
+
+ @Synchronized
+ public static void hello() {
+ System.out.println("world");
+ }
+
+ @Synchronized
+ public int answerToLife() {
+ return 42;
+ }
+
+ @Synchronized("readLock")
+ public void foo() {
+ System.out.println("bar");
+ }
+}
diff --git a/website/usageExamples/ToStringExample_post.jpage b/website/usageExamples/ToStringExample_post.jpage
new file mode 100644
index 00000000..67e78f20
--- /dev/null
+++ b/website/usageExamples/ToStringExample_post.jpage
@@ -0,0 +1,30 @@
+import java.util.Arrays;
+
+public class ToStringExample {
+ private static final int STATIC_VAR = 10;
+ private String name;
+ private Shape shape = new Square(5, 10);
+ private String[] tags;
+ private int id;
+
+ public String getName() {
+ return this.getName();
+ }
+
+ public static class Square extends Shape {
+ private final int width, height;
+
+ public Square(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+
+ @Override public String toString() {
+ return "Square(super=" + super.toString() + ", width=" + this.width + ", height=" + this.height + ")";
+ }
+ }
+
+ @Override public String toString() {
+ return "ToStringExample(" + this.getName() + ", " + this.shape + ", " + Arrays.deepToString(this.tags) + ")";
+ }
+}
diff --git a/website/usageExamples/ToStringExample_pre.jpage b/website/usageExamples/ToStringExample_pre.jpage
new file mode 100644
index 00000000..a15fb944
--- /dev/null
+++ b/website/usageExamples/ToStringExample_pre.jpage
@@ -0,0 +1,24 @@
+import lombok.ToString;
+
+@ToString(exclude="id")
+public class ToStringExample {
+ private static final int STATIC_VAR = 10;
+ private String name;
+ private Shape shape = new Square(5, 10);
+ private String[] tags;
+ private int id;
+
+ public String getName() {
+ return this.getName();
+ }
+
+ @ToString(callSuper=true, includeFieldNames=true)
+ public static class Square extends Shape {
+ private final int width, height;
+
+ public Square(int width, int height) {
+ this.width = width;
+ this.height = height;
+ }
+ }
+}
diff --git a/website/usageExamples/ValueExample_post.jpage b/website/usageExamples/ValueExample_post.jpage
new file mode 100644
index 00000000..8a5d4836
--- /dev/null
+++ b/website/usageExamples/ValueExample_post.jpage
@@ -0,0 +1,120 @@
+import java.util.Arrays;
+
+public final class ValueExample {
+ private final String name;
+ private int age;
+ private final double score;
+ protected final String[] tags;
+
+ @java.beans.ConstructorProperties({"name", "age", "score", "tags"})
+ public ValueExample(String name, int age, double score, String[] tags) {
+ this.name = name;
+ this.age = age;
+ this.score = score;
+ this.tags = tags;
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public int getAge() {
+ return this.age;
+ }
+
+ public double getScore() {
+ return this.score;
+ }
+
+ public String[] getTags() {
+ return this.tags;
+ }
+
+ @java.lang.Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof ValueExample)) return false;
+ final ValueExample other = (ValueExample)o;
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
+ if (this.getAge() != other.getAge()) return false;
+ if (Double.compare(this.getScore(), other.getScore()) != 0) return false;
+ if (!Arrays.deepEquals(this.getTags(), other.getTags())) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
+ result = result * PRIME + this.getAge();
+ final long $score = Double.doubleToLongBits(this.getScore());
+ result = result * PRIME + (int)($score >>> 32 ^ $score);
+ result = result * PRIME + Arrays.deepHashCode(this.getTags());
+ return result;
+ }
+
+ @java.lang.Override
+ public String toString() {
+ return "ValueExample(name=" + getName() + ", age=" + getAge() + ", score=" + getScore() + ", tags=" + Arrays.deepToString(getTags()) + ")";
+ }
+
+ ValueExample withAge(int age) {
+ return this.age == age ? this : new ValueExample(name, age, score, tags);
+ }
+
+ public static final class Exercise<T> {
+ private final String name;
+ private final T value;
+
+ private Exercise(String name, T value) {
+ this.name = name;
+ this.value = value;
+ }
+
+ public static <T> Exercise<T> of(String name, T value) {
+ return new Exercise<T>(name, value);
+ }
+
+ public String getName() {
+ return this.name;
+ }
+
+ public T getValue() {
+ return this.value;
+ }
+
+ @java.lang.Override
+ public boolean equals(Object o) {
+ if (o == this) return true;
+ if (!(o instanceof ValueExample.Exercise)) return false;
+ final Exercise<?> other = (Exercise<?>)o;
+ final Object this$name = this.getName();
+ final Object other$name = other.getName();
+ if (this$name == null ? other$name != null : !this$name.equals(other$name)) return false;
+ final Object this$value = this.getValue();
+ final Object other$value = other.getValue();
+ if (this$value == null ? other$value != null : !this$value.equals(other$value)) return false;
+ return true;
+ }
+
+ @java.lang.Override
+ public int hashCode() {
+ final int PRIME = 59;
+ int result = 1;
+ final Object $name = this.getName();
+ result = result * PRIME + ($name == null ? 43 : $name.hashCode());
+ final Object $value = this.getValue();
+ result = result * PRIME + ($value == null ? 43 : $value.hashCode());
+ return result;
+ }
+
+ @java.lang.Override
+ public String toString() {
+ return "ValueExample.Exercise(name=" + getName() + ", value=" + getValue() + ")";
+ }
+ }
+} \ No newline at end of file
diff --git a/website/usageExamples/ValueExample_pre.jpage b/website/usageExamples/ValueExample_pre.jpage
new file mode 100644
index 00000000..d9550c25
--- /dev/null
+++ b/website/usageExamples/ValueExample_pre.jpage
@@ -0,0 +1,19 @@
+import lombok.AccessLevel;
+import lombok.experimental.NonFinal;
+import lombok.experimental.Value;
+import lombok.experimental.Wither;
+import lombok.ToString;
+
+@Value public class ValueExample {
+ String name;
+ @Wither(AccessLevel.PACKAGE) @NonFinal int age;
+ double score;
+ protected String[] tags;
+
+ @ToString(includeFieldNames=true)
+ @Value(staticConstructor="of")
+ public static class Exercise<T> {
+ String name;
+ T value;
+ }
+}
diff --git a/website/usageExamples/experimental/AccessorsExample_post.jpage b/website/usageExamples/experimental/AccessorsExample_post.jpage
new file mode 100644
index 00000000..ae5a39db
--- /dev/null
+++ b/website/usageExamples/experimental/AccessorsExample_post.jpage
@@ -0,0 +1,20 @@
+public class AccessorsExample {
+ private int age = 10;
+
+ public int age() {
+ return this.age;
+ }
+
+ public AccessorsExample age(final int age) {
+ this.age = age;
+ return this;
+ }
+}
+
+class PrefixExample {
+ private String fName = "Hello, World!";
+
+ public String getName() {
+ return this.fName;
+ }
+}
diff --git a/website/usageExamples/experimental/AccessorsExample_pre.jpage b/website/usageExamples/experimental/AccessorsExample_pre.jpage
new file mode 100644
index 00000000..f1591aba
--- /dev/null
+++ b/website/usageExamples/experimental/AccessorsExample_pre.jpage
@@ -0,0 +1,14 @@
+import lombok.experimental.Accessors;
+import lombok.Getter;
+import lombok.Setter;
+
+@Accessors(fluent = true)
+public class AccessorsExample {
+ @Getter @Setter
+ private int age = 10;
+}
+
+class PrefixExample {
+ @Accessors(prefix = "f") @Getter
+ private String fName = "Hello, World!";
+}
diff --git a/website/usageExamples/experimental/DelegateExample_post.jpage b/website/usageExamples/experimental/DelegateExample_post.jpage
new file mode 100644
index 00000000..1c5239f1
--- /dev/null
+++ b/website/usageExamples/experimental/DelegateExample_post.jpage
@@ -0,0 +1,97 @@
+import java.util.ArrayList;
+import java.util.Collection;
+
+public class DelegationExample {
+ private interface SimpleCollection {
+ boolean add(String item);
+ boolean remove(Object item);
+ }
+
+ private final Collection<String> collection = new ArrayList<String>();
+
+ @java.lang.SuppressWarnings("all")
+ public boolean add(final java.lang.String item) {
+ return this.collection.add(item);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean remove(final java.lang.Object item) {
+ return this.collection.remove(item);
+ }
+}
+
+class ExcludesDelegateExample {
+ long counter = 0L;
+
+ private interface Add {
+ boolean add(String x);
+ boolean addAll(Collection<? extends String> x);
+ }
+
+ private final Collection<String> collection = new ArrayList<String>();
+
+ public boolean add(String item) {
+ counter++;
+ return collection.add(item);
+ }
+
+ public boolean addAll(Collection<? extends String> col) {
+ counter += col.size();
+ return collection.addAll(col);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public int size() {
+ return this.collection.size();
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean isEmpty() {
+ return this.collection.isEmpty();
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean contains(final java.lang.Object arg0) {
+ return this.collection.contains(arg0);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public java.util.Iterator<java.lang.String> iterator() {
+ return this.collection.iterator();
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public java.lang.Object[] toArray() {
+ return this.collection.toArray();
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public <T extends .java.lang.Object>T[] toArray(final T[] arg0) {
+ return this.collection.<T>toArray(arg0);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean remove(final java.lang.Object arg0) {
+ return this.collection.remove(arg0);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean containsAll(final java.util.Collection<?> arg0) {
+ return this.collection.containsAll(arg0);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean removeAll(final java.util.Collection<?> arg0) {
+ return this.collection.removeAll(arg0);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public boolean retainAll(final java.util.Collection<?> arg0) {
+ return this.collection.retainAll(arg0);
+ }
+
+ @java.lang.SuppressWarnings("all")
+ public void clear() {
+ this.collection.clear();
+ }
+}
diff --git a/website/usageExamples/experimental/DelegateExample_pre.jpage b/website/usageExamples/experimental/DelegateExample_pre.jpage
new file mode 100644
index 00000000..885ab3a8
--- /dev/null
+++ b/website/usageExamples/experimental/DelegateExample_pre.jpage
@@ -0,0 +1,37 @@
+import java.util.ArrayList;
+import java.util.Collection;
+
+import lombok.experimental.Delegate;
+
+public class DelegationExample {
+ private interface SimpleCollection {
+ boolean add(String item);
+ boolean remove(Object item);
+ }
+
+ @Delegate(types=SimpleCollection.class)
+ private final Collection<String> collection = new ArrayList<String>();
+}
+
+
+class ExcludesDelegateExample {
+ long counter = 0L;
+
+ private interface Add {
+ boolean add(String x);
+ boolean addAll(Collection<? extends String> x);
+ }
+
+ @Delegate(excludes=Add.class)
+ private final Collection<String> collection = new ArrayList<String>();
+
+ public boolean add(String item) {
+ counter++;
+ return collection.add(item);
+ }
+
+ public boolean addAll(Collection<? extends String> col) {
+ counter += col.size();
+ return collection.addAll(col);
+ }
+}
diff --git a/website/usageExamples/experimental/ExtensionMethodExample_post.jpage b/website/usageExamples/experimental/ExtensionMethodExample_post.jpage
new file mode 100644
index 00000000..de46d776
--- /dev/null
+++ b/website/usageExamples/experimental/ExtensionMethodExample_post.jpage
@@ -0,0 +1,21 @@
+public class ExtensionMethodExample {
+ public String test() {
+ int[] intArray = {5, 3, 8, 2};
+ java.util.Arrays.sort(intArray);
+
+ String iAmNull = null;
+ return Extensions.or(iAmNull, Extensions.toTitleCase("hELlO, WORlD!"));
+ }
+}
+
+class Extensions {
+ public static <T> T or(T obj, T ifNull) {
+ return obj != null ? obj : ifNull;
+ }
+
+ public static String toTitleCase(String in) {
+ if (in.isEmpty()) return in;
+ return "" + Character.toTitleCase(in.charAt(0)) +
+ in.substring(1).toLowerCase();
+ }
+}
diff --git a/website/usageExamples/experimental/ExtensionMethodExample_pre.jpage b/website/usageExamples/experimental/ExtensionMethodExample_pre.jpage
new file mode 100644
index 00000000..b3b9f1fa
--- /dev/null
+++ b/website/usageExamples/experimental/ExtensionMethodExample_pre.jpage
@@ -0,0 +1,24 @@
+import lombok.experimental.ExtensionMethod;
+
+@ExtensionMethod({java.util.Arrays.class, Extensions.class})
+public class ExtensionMethodExample {
+ public String test() {
+ int[] intArray = {5, 3, 8, 2};
+ intArray.sort();
+
+ String iAmNull = null;
+ return iAmNull.or("hELlO, WORlD!".toTitleCase());
+ }
+}
+
+class Extensions {
+ public static <T> T or(T obj, T ifNull) {
+ return obj != null ? obj : ifNull;
+ }
+
+ public static String toTitleCase(String in) {
+ if (in.isEmpty()) return in;
+ return "" + Character.toTitleCase(in.charAt(0)) +
+ in.substring(1).toLowerCase();
+ }
+}
diff --git a/website/usageExamples/experimental/FieldDefaultsExample_post.jpage b/website/usageExamples/experimental/FieldDefaultsExample_post.jpage
new file mode 100644
index 00000000..95c17a4b
--- /dev/null
+++ b/website/usageExamples/experimental/FieldDefaultsExample_post.jpage
@@ -0,0 +1,12 @@
+public class FieldDefaultsExample {
+ public final int a;
+ private final int b;
+ private int c;
+ final int d;
+
+ FieldDefaultsExample() {
+ a = 0;
+ b = 0;
+ d = 0;
+ }
+}
diff --git a/website/usageExamples/experimental/FieldDefaultsExample_pre.jpage b/website/usageExamples/experimental/FieldDefaultsExample_pre.jpage
new file mode 100644
index 00000000..c8335832
--- /dev/null
+++ b/website/usageExamples/experimental/FieldDefaultsExample_pre.jpage
@@ -0,0 +1,18 @@
+import lombok.AccessLevel;
+import lombok.experimental.FieldDefaults;
+import lombok.experimental.NonFinal;
+import lombok.experimental.PackagePrivate;
+
+@FieldDefaults(makeFinal=true, level=AccessLevel.PRIVATE)
+public class FieldDefaultsExample {
+ public final int a;
+ int b;
+ @NonFinal int c;
+ @PackagePrivate int d;
+
+ FieldDefaultsExample() {
+ a = 0;
+ b = 0;
+ d = 0;
+ }
+}
diff --git a/website/usageExamples/experimental/HelperExample_post.jpage b/website/usageExamples/experimental/HelperExample_post.jpage
new file mode 100644
index 00000000..04a97b9f
--- /dev/null
+++ b/website/usageExamples/experimental/HelperExample_post.jpage
@@ -0,0 +1,14 @@
+public class HelperExample {
+ int someMethod(int arg1) {
+ int localVar = 5;
+
+ class Helpers {
+ int helperMethod(int arg) {
+ return arg + localVar;
+ }
+ }
+ Helpers $Helpers = new Helpers();
+
+ return $Helpers.helperMethod(10);
+ }
+}
diff --git a/website/usageExamples/experimental/HelperExample_pre.jpage b/website/usageExamples/experimental/HelperExample_pre.jpage
new file mode 100644
index 00000000..cd86ef3c
--- /dev/null
+++ b/website/usageExamples/experimental/HelperExample_pre.jpage
@@ -0,0 +1,15 @@
+import lombok.experimental.Helper;
+
+public class HelperExample {
+ int someMethod(int arg1) {
+ int localVar = 5;
+
+ @Helper class Helpers {
+ int helperMethod(int arg) {
+ return arg + localVar;
+ }
+ }
+
+ return helperMethod(10);
+ }
+}
diff --git a/website/usageExamples/experimental/UtilityClassExample_post.jpage b/website/usageExamples/experimental/UtilityClassExample_post.jpage
new file mode 100644
index 00000000..70810230
--- /dev/null
+++ b/website/usageExamples/experimental/UtilityClassExample_post.jpage
@@ -0,0 +1,11 @@
+public final class UtilityClassExample {
+ private static final int CONSTANT = 5;
+
+ private UtilityClassExample() {
+ throw new java.lang.UnsupportedOperationException("This is a utility class and cannot be instantiated");
+ }
+
+ public static void addSomething(int in) {
+ return in + CONSTANT;
+ }
+}
diff --git a/website/usageExamples/experimental/UtilityClassExample_pre.jpage b/website/usageExamples/experimental/UtilityClassExample_pre.jpage
new file mode 100644
index 00000000..85731b81
--- /dev/null
+++ b/website/usageExamples/experimental/UtilityClassExample_pre.jpage
@@ -0,0 +1,10 @@
+import lombok.experimental.UtilityClass;
+
+@UtilityClass
+public class UtilityClassExample {
+ private final int CONSTANT = 5;
+
+ public void addSomething(int in) {
+ return in + CONSTANT;
+ }
+}
diff --git a/website/usageExamples/experimental/WitherExample_post.jpage b/website/usageExamples/experimental/WitherExample_post.jpage
new file mode 100644
index 00000000..3447192a
--- /dev/null
+++ b/website/usageExamples/experimental/WitherExample_post.jpage
@@ -0,0 +1,21 @@
+import lombok.NonNull;
+
+public class WitherExample {
+ private final int age;
+ private @NonNull final String name;
+
+ public WitherExample(String name, int age) {
+ if (name == null) throw new NullPointerException();
+ this.name = name;
+ this.age = age;
+ }
+
+ public WitherExample withAge(int age) {
+ return this.age == age ? this : new WitherExample(name, age);
+ }
+
+ protected WitherExample withName(@NonNull String name) {
+ if (name == null) throw new java.lang.NullPointerException("name");
+ return this.name == name ? this : new WitherExample(name, age);
+ }
+} \ No newline at end of file
diff --git a/website/usageExamples/experimental/WitherExample_pre.jpage b/website/usageExamples/experimental/WitherExample_pre.jpage
new file mode 100644
index 00000000..5db799fc
--- /dev/null
+++ b/website/usageExamples/experimental/WitherExample_pre.jpage
@@ -0,0 +1,14 @@
+import lombok.AccessLevel;
+import lombok.NonNull;
+import lombok.experimental.Wither;
+
+public class WitherExample {
+ @Wither private final int age;
+ @Wither(AccessLevel.PROTECTED) @NonNull private final String name;
+
+ public WitherExample(String name, int age) {
+ if (name == null) throw new NullPointerException();
+ this.name = name;
+ this.age = age;
+ }
+}
diff --git a/website/usageExamples/experimental/onXExample_post.jpage b/website/usageExamples/experimental/onXExample_post.jpage
new file mode 100644
index 00000000..1be94f2a
--- /dev/null
+++ b/website/usageExamples/experimental/onXExample_post.jpage
@@ -0,0 +1,22 @@
+import javax.inject.Inject;
+import javax.persistence.Id;
+import javax.persistence.Column;
+import javax.validation.constraints.Max;
+
+public class OnXExample {
+ private long unid;
+
+ @Inject
+ public OnXExample(long unid) {
+ this.unid = unid;
+ }
+
+ @Id @Column(name="unique-id")
+ public long getUnid() {
+ return unid;
+ }
+
+ public void setUnid(@Max(10000) long unid) {
+ this.unid = unid;
+ }
+}
diff --git a/website/usageExamples/experimental/onXExample_pre.jpage b/website/usageExamples/experimental/onXExample_pre.jpage
new file mode 100644
index 00000000..f8fcb435
--- /dev/null
+++ b/website/usageExamples/experimental/onXExample_pre.jpage
@@ -0,0 +1,15 @@
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.inject.Inject;
+import javax.persistence.Id;
+import javax.persistence.Column;
+import javax.validation.constraints.Max;
+
+@AllArgsConstructor(onConstructor=@__(@Inject))
+public class OnXExample {
+ @Getter(onMethod=@__({@Id, @Column(name="unique-id")}))
+ @Setter(onParam=@__(@Max(10000)))
+ private long unid;
+}
diff --git a/website/usageExamples/valExample_post.jpage b/website/usageExamples/valExample_post.jpage
new file mode 100644
index 00000000..fa2e852e
--- /dev/null
+++ b/website/usageExamples/valExample_post.jpage
@@ -0,0 +1,21 @@
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+public class ValExample {
+ public String example() {
+ final ArrayList<String> example = new ArrayList<String>();
+ example.add("Hello, World!");
+ final String foo = example.get(0);
+ return foo.toLowerCase();
+ }
+
+ public void example2() {
+ final HashMap<Integer, String> map = new HashMap<Integer, String>();
+ map.put(0, "zero");
+ map.put(5, "five");
+ for (final Map.Entry<Integer, String> entry : map.entrySet()) {
+ System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
+ }
+ }
+}
diff --git a/website/usageExamples/valExample_pre.jpage b/website/usageExamples/valExample_pre.jpage
new file mode 100644
index 00000000..a621640f
--- /dev/null
+++ b/website/usageExamples/valExample_pre.jpage
@@ -0,0 +1,21 @@
+import java.util.ArrayList;
+import java.util.HashMap;
+import lombok.val;
+
+public class ValExample {
+ public String example() {
+ val example = new ArrayList<String>();
+ example.add("Hello, World!");
+ val foo = example.get(0);
+ return foo.toLowerCase();
+ }
+
+ public void example2() {
+ val map = new HashMap<Integer, String>();
+ map.put(0, "zero");
+ map.put(5, "five");
+ for (val entry : map.entrySet()) {
+ System.out.printf("%d: %s\n", entry.getKey(), entry.getValue());
+ }
+ }
+}
diff --git a/website/videos/expressInstall.swf b/website/videos/expressInstall.swf
deleted file mode 100644
index 0fbf8fca..00000000
--- a/website/videos/expressInstall.swf
+++ /dev/null
Binary files differ
diff --git a/website/videos/lombok-iPhone.m4v b/website/videos/lombok-iPhone.m4v
deleted file mode 100644
index 19487ebd..00000000
--- a/website/videos/lombok-iPhone.m4v
+++ /dev/null
Binary files differ
diff --git a/website/videos/lombok.mp4 b/website/videos/lombok.mp4
deleted file mode 100644
index b6f2107b..00000000
--- a/website/videos/lombok.mp4
+++ /dev/null
Binary files differ
diff --git a/website/videos/lombok.ogv b/website/videos/lombok.ogv
deleted file mode 100644
index 70e20225..00000000
--- a/website/videos/lombok.ogv
+++ /dev/null
Binary files differ
diff --git a/website/videos/player.swf b/website/videos/player.swf
deleted file mode 100644
index 1f655a26..00000000
--- a/website/videos/player.swf
+++ /dev/null
Binary files differ
diff --git a/website/videos/poster.png b/website/videos/poster.png
deleted file mode 100644
index 4911408f..00000000
--- a/website/videos/poster.png
+++ /dev/null
Binary files differ
diff --git a/website/videos/swfobject.js b/website/videos/swfobject.js
deleted file mode 100644
index 8eafe9dd..00000000
--- a/website/videos/swfobject.js
+++ /dev/null
@@ -1,4 +0,0 @@
-/* SWFObject v2.2 <http://code.google.com/p/swfobject/>
- is released under the MIT License <http://www.opensource.org/licenses/mit-license.php>
-*/
-var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}(); \ No newline at end of file