├── .gitignore
├── LICENSE.txt
├── build.xml
├── buildScripts
├── ivy-repo
│ ├── easytesting.org-fest-assert-1.3.xml
│ ├── easytesting.org-fest-util-1.1.4.xml
│ ├── eclipse.org-core.runtime-3.6.0.xml
│ ├── eclipse.org-ecj-3.6.0.xml
│ ├── eclipse.org-jdt.core-3.6.0.xml
│ ├── junit.org-junit-4.8.2.xml
│ ├── projectlombok.org-javac-1.6.0.18.xml
│ ├── projectlombok.org-lombok-0.10.0-BETA2-HEAD.xml
│ ├── projectlombok.org-lombok-test-core-0.10.0-BETA2-HEAD.xml
│ └── projectlombok.org-spi-0.2.4.xml
├── ivy.xml
└── ivysettings.xml
├── readme.txt
├── src
├── core
│ └── lombok
│ │ ├── GenerateBoundSetter.java
│ │ ├── GenerateJavaBean.java
│ │ └── core
│ │ └── util
│ │ ├── Arrays.java
│ │ ├── AstGeneration.java
│ │ ├── ErrorMessages.java
│ │ └── Names.java
├── eclipse
│ └── lombok
│ │ └── eclipse
│ │ └── handlers
│ │ ├── BoundSetterHandler.java
│ │ ├── Eclipse.java
│ │ ├── FieldBuilder.java
│ │ ├── JavaBeanHandler.java
│ │ ├── Lombok.java
│ │ ├── MemberChecks.java
│ │ └── MethodBuilder.java
└── javac
│ └── lombok
│ └── javac
│ └── handlers
│ ├── BoundSetterHandler.java
│ ├── FieldBuilder.java
│ ├── JCNoType.java
│ ├── JavaBeanHandler.java
│ ├── Lombok.java
│ ├── MemberChecks.java
│ └── MethodBuilder.java
└── test
├── core
└── lombok
│ └── core
│ └── util
│ ├── Arrays_array_Test.java
│ ├── Arrays_copy_Test.java
│ ├── Arrays_isNotEmpty_Test.java
│ ├── AstGeneration_stopAstGeneration_Test.java
│ ├── AstGeneration_stopAstGeneration_with_parameters_Test.java
│ ├── ErrorMessages_canBeUsedOnClassOnly_Test.java
│ ├── ErrorMessages_canBeUsedOnFieldOnly_Test.java
│ ├── Names_nameOfConstantBasedOnProperty_Test.java
│ └── Names_splitNameOf_Test.java
├── eclipse
└── lombok
│ └── eclipse
│ └── handlers
│ └── TestWithEcj.java
├── javac
└── lombok
│ └── javac
│ └── handlers
│ └── TestWithDelombok.java
└── transform
└── resource
├── after-delombok
├── CompleteJavaBean.java
├── GenerateJavaBeanNotInClass.java
└── SimpleJavaBean.java
├── after-ecj
├── CompleteJavaBean.java
├── GenerateJavaBeanNotInClass.java
└── SimpleJavaBean.java
├── before
├── CompleteJavaBean.java
├── GenerateJavaBeanNotInClass.java
└── SimpleJavaBean.java
├── messages-delombok
└── GenerateJavaBeanNotInClass.java.messages
└── messages-ecj
└── GenerateJavaBeanNotInClass.java.messages
/.gitignore:
--------------------------------------------------------------------------------
1 | /lib
2 | /bin
3 | /.classpath
4 | /.project
5 | /ivyCache
6 | /.settings
7 | /.factorypath
8 | /.apt_generated
9 | /build
10 | /dist
11 |
--------------------------------------------------------------------------------
/LICENSE.txt:
--------------------------------------------------------------------------------
1 |
2 | Apache License
3 | Version 2.0, January 2004
4 | http://www.apache.org/licenses/
5 |
6 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
7 |
8 | 1. Definitions.
9 |
10 | "License" shall mean the terms and conditions for use, reproduction,
11 | and distribution as defined by Sections 1 through 9 of this document.
12 |
13 | "Licensor" shall mean the copyright owner or entity authorized by
14 | the copyright owner that is granting the License.
15 |
16 | "Legal Entity" shall mean the union of the acting entity and all
17 | other entities that control, are controlled by, or are under common
18 | control with that entity. For the purposes of this definition,
19 | "control" means (i) the power, direct or indirect, to cause the
20 | direction or management of such entity, whether by contract or
21 | otherwise, or (ii) ownership of fifty percent (50%) or more of the
22 | outstanding shares, or (iii) beneficial ownership of such entity.
23 |
24 | "You" (or "Your") shall mean an individual or Legal Entity
25 | exercising permissions granted by this License.
26 |
27 | "Source" form shall mean the preferred form for making modifications,
28 | including but not limited to software source code, documentation
29 | source, and configuration files.
30 |
31 | "Object" form shall mean any form resulting from mechanical
32 | transformation or translation of a Source form, including but
33 | not limited to compiled object code, generated documentation,
34 | and conversions to other media types.
35 |
36 | "Work" shall mean the work of authorship, whether in Source or
37 | Object form, made available under the License, as indicated by a
38 | copyright notice that is included in or attached to the work
39 | (an example is provided in the Appendix below).
40 |
41 | "Derivative Works" shall mean any work, whether in Source or Object
42 | form, that is based on (or derived from) the Work and for which the
43 | editorial revisions, annotations, elaborations, or other modifications
44 | represent, as a whole, an original work of authorship. For the purposes
45 | of this License, Derivative Works shall not include works that remain
46 | separable from, or merely link (or bind by name) to the interfaces of,
47 | the Work and Derivative Works thereof.
48 |
49 | "Contribution" shall mean any work of authorship, including
50 | the original version of the Work and any modifications or additions
51 | to that Work or Derivative Works thereof, that is intentionally
52 | submitted to Licensor for inclusion in the Work by the copyright owner
53 | or by an individual or Legal Entity authorized to submit on behalf of
54 | the copyright owner. For the purposes of this definition, "submitted"
55 | means any form of electronic, verbal, or written communication sent
56 | to the Licensor or its representatives, including but not limited to
57 | communication on electronic mailing lists, source code control systems,
58 | and issue tracking systems that are managed by, or on behalf of, the
59 | Licensor for the purpose of discussing and improving the Work, but
60 | excluding communication that is conspicuously marked or otherwise
61 | designated in writing by the copyright owner as "Not a Contribution."
62 |
63 | "Contributor" shall mean Licensor and any individual or Legal Entity
64 | on behalf of whom a Contribution has been received by Licensor and
65 | subsequently incorporated within the Work.
66 |
67 | 2. Grant of Copyright License. Subject to the terms and conditions of
68 | this License, each Contributor hereby grants to You a perpetual,
69 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
70 | copyright license to reproduce, prepare Derivative Works of,
71 | publicly display, publicly perform, sublicense, and distribute the
72 | Work and such Derivative Works in Source or Object form.
73 |
74 | 3. Grant of Patent License. Subject to the terms and conditions of
75 | this License, each Contributor hereby grants to You a perpetual,
76 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable
77 | (except as stated in this section) patent license to make, have made,
78 | use, offer to sell, sell, import, and otherwise transfer the Work,
79 | where such license applies only to those patent claims licensable
80 | by such Contributor that are necessarily infringed by their
81 | Contribution(s) alone or by combination of their Contribution(s)
82 | with the Work to which such Contribution(s) was submitted. If You
83 | institute patent litigation against any entity (including a
84 | cross-claim or counterclaim in a lawsuit) alleging that the Work
85 | or a Contribution incorporated within the Work constitutes direct
86 | or contributory patent infringement, then any patent licenses
87 | granted to You under this License for that Work shall terminate
88 | as of the date such litigation is filed.
89 |
90 | 4. Redistribution. You may reproduce and distribute copies of the
91 | Work or Derivative Works thereof in any medium, with or without
92 | modifications, and in Source or Object form, provided that You
93 | meet the following conditions:
94 |
95 | (a) You must give any other recipients of the Work or
96 | Derivative Works a copy of this License; and
97 |
98 | (b) You must cause any modified files to carry prominent notices
99 | stating that You changed the files; and
100 |
101 | (c) You must retain, in the Source form of any Derivative Works
102 | that You distribute, all copyright, patent, trademark, and
103 | attribution notices from the Source form of the Work,
104 | excluding those notices that do not pertain to any part of
105 | the Derivative Works; and
106 |
107 | (d) If the Work includes a "NOTICE" text file as part of its
108 | distribution, then any Derivative Works that You distribute must
109 | include a readable copy of the attribution notices contained
110 | within such NOTICE file, excluding those notices that do not
111 | pertain to any part of the Derivative Works, in at least one
112 | of the following places: within a NOTICE text file distributed
113 | as part of the Derivative Works; within the Source form or
114 | documentation, if provided along with the Derivative Works; or,
115 | within a display generated by the Derivative Works, if and
116 | wherever such third-party notices normally appear. The contents
117 | of the NOTICE file are for informational purposes only and
118 | do not modify the License. You may add Your own attribution
119 | notices within Derivative Works that You distribute, alongside
120 | or as an addendum to the NOTICE text from the Work, provided
121 | that such additional attribution notices cannot be construed
122 | as modifying the License.
123 |
124 | You may add Your own copyright statement to Your modifications and
125 | may provide additional or different license terms and conditions
126 | for use, reproduction, or distribution of Your modifications, or
127 | for any such Derivative Works as a whole, provided Your use,
128 | reproduction, and distribution of the Work otherwise complies with
129 | the conditions stated in this License.
130 |
131 | 5. Submission of Contributions. Unless You explicitly state otherwise,
132 | any Contribution intentionally submitted for inclusion in the Work
133 | by You to the Licensor shall be under the terms and conditions of
134 | this License, without any additional terms or conditions.
135 | Notwithstanding the above, nothing herein shall supersede or modify
136 | the terms of any separate license agreement you may have executed
137 | with Licensor regarding such Contributions.
138 |
139 | 6. Trademarks. This License does not grant permission to use the trade
140 | names, trademarks, service marks, or product names of the Licensor,
141 | except as required for reasonable and customary use in describing the
142 | origin of the Work and reproducing the content of the NOTICE file.
143 |
144 | 7. Disclaimer of Warranty. Unless required by applicable law or
145 | agreed to in writing, Licensor provides the Work (and each
146 | Contributor provides its Contributions) on an "AS IS" BASIS,
147 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
148 | implied, including, without limitation, any warranties or conditions
149 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
150 | PARTICULAR PURPOSE. You are solely responsible for determining the
151 | appropriateness of using or redistributing the Work and assume any
152 | risks associated with Your exercise of permissions under this License.
153 |
154 | 8. Limitation of Liability. In no event and under no legal theory,
155 | whether in tort (including negligence), contract, or otherwise,
156 | unless required by applicable law (such as deliberate and grossly
157 | negligent acts) or agreed to in writing, shall any Contributor be
158 | liable to You for damages, including any direct, indirect, special,
159 | incidental, or consequential damages of any character arising as a
160 | result of this License or out of the use or inability to use the
161 | Work (including but not limited to damages for loss of goodwill,
162 | work stoppage, computer failure or malfunction, or any and all
163 | other commercial damages or losses), even if such Contributor
164 | has been advised of the possibility of such damages.
165 |
166 | 9. Accepting Warranty or Additional Liability. While redistributing
167 | the Work or Derivative Works thereof, You may choose to offer,
168 | and charge a fee for, acceptance of support, warranty, indemnity,
169 | or other liability obligations and/or rights consistent with this
170 | License. However, in accepting such obligations, You may act only
171 | on Your own behalf and on Your sole responsibility, not on behalf
172 | of any other Contributor, and only if You agree to indemnify,
173 | defend, and hold each Contributor harmless for any liability
174 | incurred by, or claims asserted against, such Contributor by reason
175 | of your accepting any such warranty or additional liability.
176 |
177 | END OF TERMS AND CONDITIONS
178 |
179 | APPENDIX: How to apply the Apache License to your work.
180 |
181 | To apply the Apache License to your work, attach the following
182 | boilerplate notice, with the fields enclosed by brackets "[]"
183 | replaced with your own identifying information. (Don't include
184 | the brackets!) The text should be enclosed in the appropriate
185 | comment syntax for the file format. We also recommend that a
186 | file or class name and description of purpose be included on the
187 | same "printed page" as the copyright notice for easier
188 | identification within third-party archives.
189 |
190 | Copyright [yyyy] [name of copyright owner]
191 |
192 | Licensed under the Apache License, Version 2.0 (the "License");
193 | you may not use this file except in compliance with the License.
194 | You may obtain a copy of the License at
195 |
196 | http://www.apache.org/licenses/LICENSE-2.0
197 |
198 | Unless required by applicable law or agreed to in writing, software
199 | distributed under the License is distributed on an "AS IS" BASIS,
200 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
201 | See the License for the specific language governing permissions and
202 | limitations under the License.
203 |
--------------------------------------------------------------------------------
/build.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
44 |
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
66 |
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
89 |
90 |
91 |
92 |
93 |
94 |
95 |
96 |
97 |
98 |
99 |
100 |
101 | lombok.core.AnnotationProcessor
102 |
103 |
104 |
105 |
106 |
107 |
108 |
109 |
110 |
111 |
112 |
113 |
114 |
115 |
116 |
117 |
118 |
119 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/easytesting.org-fest-assert-1.3.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/easytesting.org-fest-util-1.1.4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/eclipse.org-core.runtime-3.6.0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/eclipse.org-ecj-3.6.0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/eclipse.org-jdt.core-3.6.0.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/junit.org-junit-4.8.2.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/projectlombok.org-javac-1.6.0.18.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/projectlombok.org-lombok-0.10.0-BETA2-HEAD.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/projectlombok.org-lombok-test-core-0.10.0-BETA2-HEAD.xml:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
17 |
19 |
20 |
--------------------------------------------------------------------------------
/buildScripts/ivy-repo/projectlombok.org-spi-0.2.4.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/buildScripts/ivy.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/buildScripts/ivysettings.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
--------------------------------------------------------------------------------
/readme.txt:
--------------------------------------------------------------------------------
1 | This project contains Lombok extensions that generate JavaBeans "bound" setters.
2 | See LICENSE.txt for the project lombok license.
3 |
4 | HINT: If you'd like to develop lombok in eclipse, run 'ant eclipse' first. It creates the necessary project infrastructure and downloads dependencies.
5 |
6 | Project Author:
7 |
8 | Alex Ruiz
9 | twitter: @alexRuiz
10 | home: http://alexruiz.developerblogs.com
--------------------------------------------------------------------------------
/src/core/lombok/GenerateBoundSetter.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Nov 30, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok;
16 |
17 | import static java.lang.annotation.ElementType.FIELD;
18 | import static java.lang.annotation.RetentionPolicy.SOURCE;
19 | import static lombok.AccessLevel.PUBLIC;
20 |
21 | import java.beans.PropertyChangeSupport;
22 | import java.lang.annotation.*;
23 |
24 | import lombok.AccessLevel;
25 |
26 | /**
27 | * Instructs lombok to generate a "bound" setter for an annotated field.
28 | *
29 | * For example, given this class:
30 | *
31 | *
32 | * public class Person {
33 | *
34 | * @GenerateBoundSetter private String firstName;
35 | * }
36 | *
37 | * our lombok annotation handlers (for both javac and eclipse) will generate the AST nodes that correspond to this code:
38 | *
39 | *
55 | * Note: The handler for this annotation assumes that the class declaring the annotated field has a
56 | * field of type {@link PropertyChangeSupport} with name "propertySupport." You can either add this
57 | * expected field manually or annotate the class with {@link GenerateJavaBean} to have lombok generate it
58 | * for you.
59 | *
60 | *
61 | * @author Alex Ruiz
62 | */
63 | @Target(FIELD) @Retention(SOURCE)
64 | public @interface GenerateBoundSetter {
65 |
66 | /**
67 | * If you want your setter to be non-public, you can specify an alternate access level here.
68 | */
69 | AccessLevel value() default PUBLIC;
70 | }
71 |
--------------------------------------------------------------------------------
/src/core/lombok/GenerateJavaBean.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Nov 30, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok;
16 |
17 | import static java.lang.annotation.ElementType.*;
18 | import static java.lang.annotation.RetentionPolicy.SOURCE;
19 |
20 | import java.lang.annotation.*;
21 |
22 | /**
23 | * Instructs lombok to generate the necessary code to make an annotated Java class a JavaBean.
24 | *
25 | * For example, given this class:
26 | *
27 | *
28 | * @GenerateJavaBean
29 | * public class Person {
30 | *
31 | * }
32 | *
33 | * our lombok annotation handlers (for both javac and eclipse) will generate the AST nodes that correspond to this code:
34 | *
35 | *
49 | *
50 | *
51 | * @author Alex Ruiz
52 | */
53 | @Target(TYPE) @Retention(SOURCE)
54 | public @interface GenerateJavaBean {}
55 |
--------------------------------------------------------------------------------
/src/core/lombok/core/util/Arrays.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 6, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.core.util;
16 |
17 | import static java.util.Arrays.copyOf;
18 |
19 | /**
20 | * Utilities for arrays.
21 | *
22 | * @author Alex Ruiz
23 | */
24 | public final class Arrays {
25 |
26 | /**
27 | * Convenience method for creating arrays.
28 | * @param the type of elements of the array.
29 | * @param elements the array, in varargs form.
30 | * @return the given array in varargs form.
31 | */
32 | public static T[] array(T...elements) {
33 | return elements;
34 | }
35 |
36 | /**
37 | * Returns a copy of the given array.
38 | * @param the type of the given array.
39 | * @param array the given array.
40 | * @return a copy of the given array.
41 | */
42 | public static T[] copy(T[] array) {
43 | return copyOf(array, array.length);
44 | }
45 |
46 | /**
47 | * Indicates whether the given array has elements or not.
48 | * @param array the given array.
49 | * @return {@code true} if the given array is not {@code null} and contains at least one element; {@code false}
50 | * otherwise.
51 | */
52 | public static boolean isNotEmpty(Object[] array) {
53 | return array != null && array.length > 0;
54 | }
55 |
56 | private Arrays() {}
57 | }
58 |
--------------------------------------------------------------------------------
/src/core/lombok/core/util/AstGeneration.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 1, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.core.util;
16 |
17 | import static lombok.AccessLevel.NONE;
18 | import lombok.AccessLevel;
19 |
20 | /**
21 | * Utilities related to AST node generation.
22 | *
23 | * @author Alex Ruiz
24 | */
25 | public final class AstGeneration {
26 |
27 | /**
28 | * Indicates whether code generation should stop based on the given {@link AccessLevel}.
29 | * @param level the {@code AccessLevel} to evaluate.
30 | * @return {@code true} if the given {@code AccessLevel} is equal to {@link AccessLevel#NONE};
31 | * {@code false} otherwise.
32 | */
33 | public static boolean stopAstGeneration(AccessLevel level) {
34 | return level == NONE;
35 | }
36 |
37 | private AstGeneration() {}
38 | }
39 |
--------------------------------------------------------------------------------
/src/core/lombok/core/util/ErrorMessages.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 6, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.core.util;
16 |
17 | import java.lang.annotation.Annotation;
18 |
19 | /**
20 | * Common error messages.
21 | *
22 | * @author Alex Ruiz
23 | */
24 | public final class ErrorMessages {
25 |
26 | public static String canBeUsedOnClassOnly(Class extends Annotation> annotationType) {
27 | return errorMessage("@%s can be used on classes only", annotationType);
28 | }
29 |
30 | public static String canBeUsedOnFieldOnly(Class extends Annotation> annotationType) {
31 | return errorMessage("@%s can be used on fields only", annotationType);
32 | }
33 |
34 | private static String errorMessage(String format, Class extends Annotation> annotationType) {
35 | return String.format(format, annotationType.getName());
36 | }
37 |
38 | private ErrorMessages() {}
39 | }
40 |
--------------------------------------------------------------------------------
/src/core/lombok/core/util/Names.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Nov 30, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.core.util;
16 |
17 | import static java.lang.Character.*;
18 | import static lombok.core.util.Arrays.array;
19 |
20 | import java.beans.PropertyChangeListener;
21 | import java.beans.PropertyChangeSupport;
22 |
23 | /**
24 | * Utility methods related to names.
25 | *
26 | * @author Alex Ruiz
27 | */
28 | public final class Names {
29 |
30 | /** Name of the field of type {@link PropertyChangeSupport}. */
31 | public static final String PROPERTY_SUPPORT_FIELD_NAME = "propertySupport";
32 |
33 | /** Name of the method "firePropertyChange" in {@link PropertyChangeSupport}. */
34 | public static final String FIRE_PROPERTY_CHANGE_METHOD_NAME = "firePropertyChange";
35 |
36 | /** Name of the method argument of type {@link PropertyChangeListener}. */
37 | public static final String LISTENER_ARG_NAME = "listener";
38 |
39 | /*** Name of the variable containing the "old" value of a field before it is changed in a setter. */
40 | public static final String OLD_VALUE_VARIABLE_NAME = "old";
41 |
42 | /** Names of the "*PropertyChangeListener" methods in {@link PropertyChangeSupport}. */
43 | public static final String[] PROPERTY_CHANGE_METHOD_NAMES = array("addPropertyChangeListener",
44 | "removePropertyChangeListener");
45 |
46 | /**
47 | * Splits the name of the class using "\." as the regular expression. For example, {@code java.lang.String} will be
48 | * split into { "java", "lang", "String" }.
49 | * @param type the given class.
50 | * @return the name of the type split using "\." as the regular expression.
51 | */
52 | public static String[] splitNameOf(Class> type) {
53 | return type.getName().split("\\.");
54 | }
55 |
56 | /**
57 | * Creates the name of the constant that holds the name of a property. For example, if the name of a property is
58 | * "firstName," this method will return "PROP_FIRST_NAME."
59 | * @param propertyName the name of the property.
60 | * @return the name of the constant that holds the name of a property.
61 | */
62 | public static String nameOfConstantBasedOnProperty(String propertyName) {
63 | char[] chars = propertyName.toCharArray();
64 | StringBuilder b = new StringBuilder();
65 | b.append("PROP_");
66 | int charCount = chars.length;
67 | for (int i = 0; i < charCount; i++) {
68 | char c = chars[i];
69 | if (isUpperCase(c) && i > 0) b.append('_');
70 | if (isLowerCase(c)) c = toUpperCase(c);
71 | b.append(c);
72 | }
73 | return b.toString();
74 | }
75 |
76 | private Names() {}
77 | }
78 |
--------------------------------------------------------------------------------
/src/eclipse/lombok/eclipse/handlers/BoundSetterHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 6, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.eclipse.handlers;
16 |
17 | import static java.lang.reflect.Modifier.*;
18 | import static lombok.core.handlers.TransformationsUtil.*;
19 | import static lombok.core.util.Arrays.*;
20 | import static lombok.core.util.AstGeneration.stopAstGeneration;
21 | import static lombok.core.util.ErrorMessages.canBeUsedOnFieldOnly;
22 | import static lombok.core.util.Names.*;
23 | import static lombok.eclipse.Eclipse.*;
24 | import static lombok.eclipse.handlers.Eclipse.*;
25 | import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
26 | import static lombok.eclipse.handlers.FieldBuilder.newField;
27 | import static lombok.eclipse.handlers.Lombok.newFieldAccessor;
28 | import static lombok.eclipse.handlers.MemberChecks.*;
29 | import static lombok.eclipse.handlers.MethodBuilder.newMethod;
30 | import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccStatic;
31 |
32 | import java.beans.PropertyChangeSupport;
33 | import java.util.ArrayList;
34 | import java.util.List;
35 |
36 | import lombok.*;
37 | import lombok.core.AnnotationValues;
38 | import lombok.eclipse.EclipseAnnotationHandler;
39 | import lombok.eclipse.EclipseNode;
40 | import lombok.javac.handlers.JavaBeanHandler;
41 |
42 | import org.eclipse.jdt.internal.compiler.ast.*;
43 | import org.mangosdk.spi.ProviderFor;
44 |
45 |
46 | /**
47 | * Generates a "bound" setter for a field annotated with {@link GenerateBoundSetter}.
48 | *
49 | * For example, given this class:
50 | *
51 | *
52 | * public class Person {
53 | *
54 | * @GenerateBoundSetter private String firstName;
55 | * }
56 | *
57 | * this annotation handler will generate the AST nodes that correspond to this code:
58 | *
59 | *
75 | * Note: This annotation handler assumes that the class declaring the annotated field has a field
76 | * of type {@link PropertyChangeSupport} with name "propertySupport." You can either add this expected
77 | * field manually or annotate the class with {@link GenerateJavaBean} to have
78 | * {@link JavaBeanHandler} generate it for you.
79 | *
80 | *
81 | * @author Alex Ruiz
82 | */
83 | @ProviderFor(EclipseAnnotationHandler.class)
84 | public class BoundSetterHandler implements EclipseAnnotationHandler {
85 |
86 | private static final Class TARGET_ANNOTATION_TYPE = GenerateBoundSetter.class;
87 |
88 | /**
89 | * Called when an annotation is found that is likely to match {@link GenerateBoundSetter}. This is were
90 | * AST node generation happens.
91 | * @param annotation the actual annotation.
92 | * @param ast the Eclipse AST node representing the annotation.
93 | * @param astWrapper the lombok AST wrapper around {@code ast}.
94 | * @return {@code true} if this handler successfully handled {@code GenerateBoundSetter}; {@code false} otherwise.
95 | */
96 | @Override
97 | public boolean handle(AnnotationValues annotation, Annotation ast, EclipseNode astWrapper) {
98 | List fields = new ArrayList(astWrapper.upFromAnnotationToFields());
99 | EclipseNode mayBeField = astWrapper.up();
100 | if (mayBeField == null) return false;
101 | if (!isField(mayBeField)) {
102 | astWrapper.addError(canBeUsedOnFieldOnly(TARGET_ANNOTATION_TYPE));
103 | return true;
104 | }
105 | EclipseNode typeNode = findTypeNodeFrom(mayBeField);
106 | generateSetter(fields, annotation.getInstance(), typeNode);
107 | return true;
108 | }
109 |
110 | private EclipseNode findTypeNodeFrom(EclipseNode node) {
111 | EclipseNode n = node;
112 | while (n != null && !isTypeDeclaration(n)) n = n.up();
113 | if (!isTypeDeclaration(n)) return null;
114 | return n;
115 | }
116 |
117 | private boolean isTypeDeclaration(EclipseNode node) {
118 | return node != null && node.get() instanceof TypeDeclaration;
119 | }
120 |
121 | private void generateSetter(List fields, GenerateBoundSetter setter, EclipseNode typeNode) {
122 | for (EclipseNode fieldNode : fields) {
123 | String propertyNameFieldName = nameOfConstantBasedOnProperty(fieldNode.getName());
124 | generatePropertyNameConstant(propertyNameFieldName, fieldNode, typeNode);
125 | generateSetter(propertyNameFieldName, setter, fieldNode);
126 | }
127 | }
128 |
129 | private void generatePropertyNameConstant(String propertyNameFieldName, EclipseNode fieldNode, EclipseNode typeNode) {
130 | // generates:
131 | // public static final String PROP_FIRST_NAME = "firstName";
132 | String propertyName = fieldNode.getName();
133 | if (fieldAlreadyExists(propertyNameFieldName, fieldNode)) return;
134 | Expression propertyNameExpression = stringLiteral(propertyName, typeNode.get());
135 | FieldDeclaration fieldDecl = newField().ofType(String.class)
136 | .withName(propertyNameFieldName)
137 | .withModifiers(PUBLIC | STATIC | FINAL)
138 | .withArgs(propertyNameExpression)
139 | .buildWith(typeNode);
140 | injectField(typeNode, fieldDecl);
141 | }
142 |
143 | private void generateSetter(String propertyNameFieldName, GenerateBoundSetter setter, EclipseNode fieldNode) {
144 | AccessLevel accessLevel = setter.value();
145 | if (stopAstGeneration(accessLevel)) return;
146 | String setterName = toSetterName(fieldNode.getName());
147 | if (methodAlreadyExists(setterName, fieldNode)) return;
148 | injectMethod(fieldNode.up(), createSetterDecl(accessLevel, propertyNameFieldName, setterName, fieldNode));
149 | }
150 |
151 | private MethodDeclaration createSetterDecl(AccessLevel accessLevel, String propertyNameFieldName, String setterName,
152 | EclipseNode fieldNode) {
153 | // public void setFirstName(String value) {
154 | // final String oldValue = firstName;
155 | // firstName = value;
156 | // propertySupport.firePropertyChange(PROP_FIRST_NAME, oldValue, firstName);
157 | // }
158 | FieldDeclaration fieldDecl = (FieldDeclaration) fieldNode.get();
159 | int accessModifiers = toEclipseModifier(accessLevel)| (fieldDecl.modifiers & AccStatic);
160 | Annotation[] nonNulls = findAnnotations(fieldDecl, NON_NULL_PATTERN);
161 | return newMethod().withModifiers(accessModifiers)
162 | .withName(setterName)
163 | .withReturnType(voidType(fieldNode.get()))
164 | .withParameters(parameters(nonNulls, fieldNode))
165 | .withBody(body(propertyNameFieldName, fieldNode))
166 | .buildWith(fieldNode);
167 | }
168 |
169 | private Argument[] parameters(Annotation[] nonNulls, EclipseNode fieldNode) {
170 | FieldDeclaration fieldDecl = (FieldDeclaration) fieldNode.get();
171 | ASTNode source = fieldNode.get();
172 | Argument param = argument(fieldDecl.name, copyType(fieldDecl.type, source), 0, source);
173 | Annotation[] copied = copyAnnotations(source, nonNulls);
174 | if (isNotEmpty(copied)) param.annotations = copied;
175 | return array(param);
176 | }
177 |
178 | private Statement[] body(String propertyNameFieldName, EclipseNode fieldNode) {
179 | char[] oldValueName = OLD_VALUE_VARIABLE_NAME.toCharArray();
180 | Statement[] statements = new Statement[3];
181 | statements[0] = oldValueVariableDecl(oldValueName, fieldNode);
182 | statements[1] = assignNewValueToFieldDecl(fieldNode);
183 | statements[2] = fireChangeEventMethodDecl(propertyNameFieldName, oldValueName, fieldNode);
184 | return statements;
185 | }
186 |
187 | private Statement oldValueVariableDecl(char[] oldValueName, EclipseNode fieldNode) {
188 | FieldDeclaration varDecl = (FieldDeclaration) fieldNode.get();
189 | Expression fieldRef = newFieldAccessor(fieldNode);
190 | return localDeclaration(oldValueName, varDecl.type, fieldRef, fieldNode.get());
191 | }
192 |
193 | private Statement assignNewValueToFieldDecl(EclipseNode fieldNode) {
194 | ASTNode source = fieldNode.get();
195 | Expression fieldRef = newFieldAccessor(fieldNode);
196 | Expression name = singleNameReference(fieldNode.getName(), source);
197 | return assignment(fieldRef, name, source);
198 | }
199 |
200 | private Statement fireChangeEventMethodDecl(String propertyNameFieldName, char[] oldValueName, EclipseNode fieldNode) {
201 | ASTNode source = fieldNode.get();
202 | MessageSend fn = messageSend(source);
203 | fn.receiver = singleNameReference(PROPERTY_SUPPORT_FIELD_NAME, source);
204 | fn.selector = FIRE_PROPERTY_CHANGE_METHOD_NAME.toCharArray();
205 | List arguments = new ArrayList();
206 | arguments.add(singleNameReference(propertyNameFieldName, source));
207 | arguments.add(singleNameReference(oldValueName, source));
208 | arguments.add(newFieldAccessor(fieldNode));
209 | fn.arguments = arguments.toArray(new Expression[arguments.size()]);
210 | return fn;
211 | }
212 | }
213 |
--------------------------------------------------------------------------------
/src/eclipse/lombok/eclipse/handlers/Eclipse.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 6, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.eclipse.handlers;
16 |
17 | import static lombok.eclipse.Eclipse.*;
18 | import static org.eclipse.jdt.internal.compiler.ast.TypeReference.baseTypeReference;
19 | import static org.eclipse.jdt.internal.compiler.classfmt.ClassFileConstants.AccFinal;
20 | import static org.eclipse.jdt.internal.compiler.lookup.TypeIds.T_void;
21 |
22 | import org.eclipse.jdt.internal.compiler.CompilationResult;
23 | import org.eclipse.jdt.internal.compiler.ast.*;
24 |
25 | /**
26 | * @author Alex Ruiz
27 | */
28 | final class Eclipse {
29 |
30 | static Argument argument(char[] name, TypeReference tr, int modifiers, ASTNode source) {
31 | Argument argument = new Argument(name, posNom(source), tr, modifiers);
32 | copySourceStartAndEnt(source, argument);
33 | setGeneratedBy(argument, source);
34 | return argument;
35 | }
36 |
37 | static Assignment assignment(Expression lhs, Expression expression, ASTNode source) {
38 | Assignment assignment = new Assignment(lhs, expression, (int)posNom(source));
39 | copySourceStartAndEnt(source, assignment);
40 | setGeneratedBy(assignment, source);
41 | return assignment;
42 | }
43 |
44 | static LocalDeclaration localDeclaration(char[] name, TypeReference type, Expression initializer, ASTNode source) {
45 | LocalDeclaration decl = new LocalDeclaration(name, source.sourceStart, source.sourceEnd);
46 | decl.modifiers |= AccFinal;
47 | setGeneratedBy(decl, source);
48 | decl.type = copyType(type, source);
49 | setGeneratedBy(decl.type, source);
50 | decl.initialization = initializer;
51 | setGeneratedBy(decl.initialization, source);
52 | return decl;
53 | }
54 |
55 | static MessageSend messageSend(ASTNode source) {
56 | MessageSend messageSend = new MessageSend();
57 | copySourceStartAndEnt(source, messageSend);
58 | setGeneratedBy(messageSend, source);
59 | return messageSend;
60 | }
61 |
62 | static MethodDeclaration methodDeclaration(CompilationResult compilationResult, ASTNode source) {
63 | MethodDeclaration method = new MethodDeclaration(compilationResult);
64 | copySourceStartAndEnt(source, method);
65 | setGeneratedBy(method, source);
66 | return method;
67 | }
68 |
69 | static TypeReference qualifiedTypeReference(Class> type, ASTNode source) {
70 | long p = posNom(source);
71 | return new QualifiedTypeReference(fromQualifiedName(type.getName()), new long[] { p, p, p });
72 | }
73 |
74 | static Expression referenceForThis(ASTNode source) {
75 | return new ThisReference(source.sourceStart(), source.sourceEnd());
76 | }
77 |
78 | static Expression singleNameReference(String name, ASTNode source) {
79 | return singleNameReference(name.toCharArray(), source);
80 | }
81 |
82 | static Expression singleNameReference(char[] name, ASTNode source) {
83 | long pos = posNom(source);
84 | return singleNameReference(name, source, pos);
85 | }
86 |
87 | static Expression singleNameReference(char[] name, ASTNode source, long pos) {
88 | SingleNameReference ref = new SingleNameReference(name, pos);
89 | setGeneratedBy(ref, source);
90 | return ref;
91 | }
92 |
93 | private static long posNom(ASTNode source) {
94 | return (long) source.sourceStart << 32 | source.sourceEnd;
95 | }
96 |
97 | static Expression stringLiteral(String s, ASTNode source) {
98 | StringLiteral string = new StringLiteral(s.toCharArray(), source.sourceStart, source.sourceEnd, 0);
99 | setGeneratedBy(string, source);
100 | return string;
101 | }
102 |
103 | static TypeReference voidType(ASTNode source) {
104 | TypeReference type = baseTypeReference(T_void, 0);
105 | copySourceStartAndEnt(source, type);
106 | return type;
107 | }
108 |
109 | private static void copySourceStartAndEnt(ASTNode from, ASTNode to) {
110 | to.sourceStart = from.sourceStart;
111 | to.sourceEnd = from.sourceEnd;
112 | }
113 |
114 | private Eclipse() {}
115 | }
116 |
--------------------------------------------------------------------------------
/src/eclipse/lombok/eclipse/handlers/FieldBuilder.java:
--------------------------------------------------------------------------------
1 |
2 | /*
3 | * Created on Dec 6, 2010
4 | *
5 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
6 | * the License. You may obtain a copy of the License at
7 | *
8 | * http://www.apache.org/licenses/LICENSE-2.0
9 | *
10 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
11 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
12 | * specific language governing permissions and limitations under the License.
13 | *
14 | * Copyright @2010 the original author or authors.
15 | */
16 | package lombok.eclipse.handlers;
17 |
18 | import static lombok.core.util.Arrays.copy;
19 | import static lombok.eclipse.Eclipse.setGeneratedBy;
20 | import static lombok.eclipse.handlers.Eclipse.qualifiedTypeReference;
21 | import lombok.eclipse.EclipseNode;
22 |
23 | import org.eclipse.jdt.internal.compiler.ast.*;
24 |
25 | /**
26 | * Utility methods related to generation of fields.
27 | *
28 | * @author Alex Ruiz
29 | */
30 | final class FieldBuilder {
31 |
32 | private static final Expression[] NO_ARGS = new Expression[0];
33 |
34 | static FieldBuilder newField() {
35 | return new FieldBuilder();
36 | }
37 |
38 | private Class> type;
39 | private String name;
40 | private int modifiers;
41 | private Expression[] args = NO_ARGS;
42 |
43 | FieldBuilder ofType(Class> newType) {
44 | type = newType;
45 | return this;
46 | }
47 |
48 | FieldBuilder withName(String newName) {
49 | name = newName;
50 | return this;
51 | }
52 |
53 | FieldBuilder withModifiers(int newModifiers) {
54 | modifiers = newModifiers;
55 | return this;
56 | }
57 |
58 | FieldBuilder withArgs(Expression...newArgs) {
59 | args = copy(newArgs);
60 | return this;
61 | }
62 |
63 | FieldDeclaration buildWith(EclipseNode node) {
64 | ASTNode source = node.get();
65 | FieldDeclaration fieldDecl = new FieldDeclaration(name.toCharArray(), source.sourceStart, source.sourceEnd);
66 | setGeneratedBy(fieldDecl, source);
67 | fieldDecl.declarationSourceEnd = -1;
68 | fieldDecl.modifiers = modifiers;
69 | fieldDecl.type = qualifiedTypeReference(type, source);
70 | AllocationExpression init = new AllocationExpression();
71 | setGeneratedBy(init, source);
72 | init.type = qualifiedTypeReference(type, source);
73 | init.arguments = args;
74 | fieldDecl.initialization = init;
75 | return fieldDecl;
76 | }
77 |
78 | private FieldBuilder() {}
79 | }
80 |
--------------------------------------------------------------------------------
/src/eclipse/lombok/eclipse/handlers/JavaBeanHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 8, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.eclipse.handlers;
16 |
17 | import static java.lang.reflect.Modifier.*;
18 | import static lombok.core.util.Arrays.array;
19 | import static lombok.core.util.ErrorMessages.canBeUsedOnClassOnly;
20 | import static lombok.core.util.Names.*;
21 | import static lombok.eclipse.handlers.Eclipse.*;
22 | import static lombok.eclipse.handlers.EclipseHandlerUtil.*;
23 | import static lombok.eclipse.handlers.FieldBuilder.newField;
24 | import static lombok.eclipse.handlers.MemberChecks.*;
25 | import static lombok.eclipse.handlers.MethodBuilder.newMethod;
26 |
27 | import java.beans.*;
28 |
29 | import lombok.GenerateJavaBean;
30 | import lombok.core.AnnotationValues;
31 | import lombok.eclipse.*;
32 |
33 | import org.eclipse.jdt.internal.compiler.ast.*;
34 | import org.eclipse.jdt.internal.compiler.ast.Statement;
35 | import org.mangosdk.spi.ProviderFor;
36 |
37 |
38 | /**
39 | * Generates basic support for making a class annotated with {@link GenerateJavaBean} a JavaBean.
40 | *
41 | * "Basic" JavaBean support means:
42 | *
43 | *
Generates a field of type {@link PropertyChangeSupport} with name "propertySupport"
44 | *
Generates the public method {@code addPropertyChangeListener(PropertyChangeListener)} and
45 | * {@code removePropertyChangeListener(PropertyChangeListener)}
46 | *
47 | *
48 | *
49 | *
50 | * For example, given this class:
51 | *
52 | *
53 | * @GenerateJavaBean
54 | * public class Person {
55 | *
56 | * }
57 | *
58 | * this annotation handler will generate the AST nodes that correspond to this code:
59 | *
60 | *
81 | * Note: This annotation handler assumes that the class declaring the annotated field has a field
82 | * of type {@link PropertyChangeSupport} with name "propertySupport." You can either add this expected
83 | * field manually or annotate the class with {@link GenerateJavaBean} to have
84 | * {@link JavaBeanHandler} generate it for you.
85 | *
86 | *
87 | * @author Alex Ruiz
88 | */
89 | @ProviderFor(JavacAnnotationHandler.class)
90 | public class BoundSetterHandler implements JavacAnnotationHandler {
91 |
92 | private static final Class TARGET_ANNOTATION_TYPE = GenerateBoundSetter.class;
93 |
94 | /**
95 | * Called when an annotation is found that is likely to match {@link GenerateBoundSetter}. This is were
96 | * AST node generation happens.
97 | * @param annotation the actual annotation.
98 | * @param ast the javac AST node representing the annotation.
99 | * @param astWrapper the lombok AST wrapper around {@code ast}.
100 | * @return {@code true} if this handler successfully handled {@code GenerateBoundSetter}; {@code false} otherwise.
101 | */
102 | @Override
103 | public boolean handle(AnnotationValues annotation, JCAnnotation ast, JavacNode astWrapper) {
104 | Collection fields = astWrapper.upFromAnnotationToFields();
105 | markAnnotationAsProcessed(astWrapper, TARGET_ANNOTATION_TYPE);
106 | deleteImportFromCompilationUnit(astWrapper, AccessLevel.class.getName());
107 | JavacNode mayBeField = astWrapper.up();
108 | if (mayBeField == null) return false;
109 | if (!isField(mayBeField)) {
110 | astWrapper.addError(canBeUsedOnFieldOnly(TARGET_ANNOTATION_TYPE));
111 | return true;
112 | }
113 | JavacNode typeNode = findTypeNodeFrom(mayBeField);
114 | generateSetter(fields, annotation.getInstance(), typeNode);
115 | return true;
116 | }
117 |
118 | private JavacNode findTypeNodeFrom(JavacNode node) {
119 | JavacNode n = node;
120 | while (n != null && !isTypeDeclaration(n)) n = n.up();
121 | if (!isTypeDeclaration(n)) return null;
122 | return n;
123 | }
124 |
125 | private boolean isTypeDeclaration(JavacNode node) {
126 | return node != null && node.get() instanceof JCClassDecl;
127 | }
128 |
129 | private void generateSetter(Collection fields, GenerateBoundSetter setter, JavacNode typeNode) {
130 | for (JavacNode fieldNode : fields) {
131 | String propertyNameFieldName = nameOfConstantBasedOnProperty(fieldNode.getName());
132 | generatePropertyNameConstant(propertyNameFieldName, fieldNode, typeNode);
133 | generateSetter(propertyNameFieldName, setter, fieldNode);
134 | }
135 | }
136 |
137 | private void generatePropertyNameConstant(String propertyNameFieldName, JavacNode fieldNode, JavacNode typeNode) {
138 | // generates:
139 | // public static final String PROP_FIRST_NAME = "firstName";
140 | String propertyName = fieldNode.getName();
141 | if (fieldAlreadyExists(propertyNameFieldName, fieldNode)) return;
142 | JCExpression propertyNameExpression = fieldNode.getTreeMaker().Literal(propertyName);
143 | JCVariableDecl fieldDecl = newField().ofType(String.class)
144 | .withName(propertyNameFieldName)
145 | .withModifiers(PUBLIC | STATIC | FINAL)
146 | .withArgs(propertyNameExpression)
147 | .buildWith(typeNode);
148 | injectField(typeNode, fieldDecl);
149 | }
150 |
151 | private void generateSetter(String propertyNameFieldName, GenerateBoundSetter setter, JavacNode fieldNode) {
152 | AccessLevel accessLevel = setter.value();
153 | if (stopAstGeneration(accessLevel)) return;
154 | String setterName = toSetterName(fieldNode.getName());
155 | if (methodAlreadyExists(setterName, fieldNode)) return;
156 | injectMethod(fieldNode.up(), createSetterDecl(accessLevel, propertyNameFieldName, setterName, fieldNode));
157 | }
158 |
159 | private JCMethodDecl createSetterDecl(AccessLevel accessLevel, String propertyNameFieldName, String setterName,
160 | JavacNode fieldNode) {
161 | // public void setFirstName(String value) {
162 | // final String oldValue = firstName;
163 | // firstName = value;
164 | // propertySupport.firePropertyChange(PROP_FIRST_NAME, oldValue, firstName);
165 | // }
166 | JCVariableDecl fieldDecl = (JCVariableDecl) fieldNode.get();
167 | long accessModifiers = toJavacModifier(accessLevel) | (fieldDecl.mods.flags & STATIC);
168 | TreeMaker treeMaker = fieldNode.getTreeMaker();
169 | List nonNulls = findAnnotations(fieldNode, NON_NULL_PATTERN);
170 | return newMethod().withModifiers(accessModifiers)
171 | .withName(setterName)
172 | .withReturnType(treeMaker.Type(voidType()))
173 | .withParameters(parameters(nonNulls, fieldNode))
174 | .withBody(body(propertyNameFieldName, fieldNode))
175 | .buildWith(fieldNode);
176 | }
177 |
178 | private List parameters(List nonNulls, JavacNode fieldNode) {
179 | JCVariableDecl fieldDecl = (JCVariableDecl) fieldNode.get();
180 | TreeMaker treeMaker = fieldNode.getTreeMaker();
181 | JCVariableDecl param = treeMaker.VarDef(treeMaker.Modifiers(0, nonNulls), fieldDecl.name, fieldDecl.vartype, null);
182 | return List.of(param);
183 | }
184 |
185 | private JCBlock body(String propertyNameFieldName, JavacNode fieldNode) {
186 | Name oldValueName = fieldNode.toName(OLD_VALUE_VARIABLE_NAME);
187 | JCStatement[] statements = new JCStatement[3];
188 | statements[0] = oldValueVariableDecl(oldValueName, fieldNode);
189 | statements[1] = assignNewValueToFieldDecl(fieldNode);
190 | statements[2] = fireChangeEventMethodDecl(propertyNameFieldName, oldValueName, fieldNode);
191 | return fieldNode.getTreeMaker().Block(0, List.from(statements));
192 | }
193 |
194 | private JCStatement oldValueVariableDecl(Name oldValueName, JavacNode fieldNode) {
195 | TreeMaker treeMaker = fieldNode.getTreeMaker();
196 | JCVariableDecl varDecl = (JCVariableDecl) fieldNode.get();
197 | JCExpression init = newFieldAccessor(fieldNode);
198 | return treeMaker.VarDef(treeMaker.Modifiers(FINAL), oldValueName, varDecl.vartype, init);
199 | }
200 |
201 | private JCStatement assignNewValueToFieldDecl(JavacNode fieldNode) {
202 | JCVariableDecl fieldDecl = (JCVariableDecl) fieldNode.get();
203 | TreeMaker treeMaker = fieldNode.getTreeMaker();
204 | JCExpression fieldRef = newFieldAccessor(fieldNode);
205 | JCAssign assign = treeMaker.Assign(fieldRef, treeMaker.Ident(fieldDecl.name));
206 | return treeMaker.Exec(assign);
207 | }
208 |
209 | private JCStatement fireChangeEventMethodDecl(String propertyNameFieldName, Name oldValueName, JavacNode fieldNode) {
210 | TreeMaker treeMaker = fieldNode.getTreeMaker();
211 | JCExpression fn = chainDots(treeMaker, fieldNode, PROPERTY_SUPPORT_FIELD_NAME, FIRE_PROPERTY_CHANGE_METHOD_NAME);
212 | List args = List. of(treeMaker.Ident(fieldNode.toName(propertyNameFieldName)),
213 | treeMaker.Ident(oldValueName),
214 | newFieldAccessor(fieldNode));
215 | JCMethodInvocation m = treeMaker.Apply(List. nil(), fn, args);
216 | return treeMaker.Exec(m);
217 | }
218 |
219 | /**
220 | * Indicates whether this handler requires resolution.
221 | * @return {@code false}.
222 | */
223 | @Override public boolean isResolutionBased() {
224 | return false;
225 | }
226 | }
227 |
--------------------------------------------------------------------------------
/src/javac/lombok/javac/handlers/FieldBuilder.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Nov 30, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.javac.handlers;
16 |
17 | import static com.sun.tools.javac.util.List.nil;
18 | import static lombok.core.util.Names.splitNameOf;
19 | import static lombok.javac.handlers.JavacHandlerUtil.chainDots;
20 | import lombok.javac.JavacNode;
21 |
22 | import com.sun.tools.javac.tree.JCTree.JCExpression;
23 | import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
24 | import com.sun.tools.javac.tree.*;
25 | import com.sun.tools.javac.util.List;
26 |
27 | /**
28 | * Simplifies creation of fields.
29 | *
30 | * @author Alex Ruiz
31 | */
32 | class FieldBuilder {
33 |
34 | static FieldBuilder newField() {
35 | return new FieldBuilder();
36 | }
37 |
38 | private Class> type;
39 | private String name;
40 | private long modifiers;
41 | private List args = nil();
42 |
43 | FieldBuilder ofType(Class> newType) {
44 | type = newType;
45 | return this;
46 | }
47 |
48 | FieldBuilder withName(String newName) {
49 | name = newName;
50 | return this;
51 | }
52 |
53 | FieldBuilder withModifiers(long newModifiers) {
54 | modifiers = newModifiers;
55 | return this;
56 | }
57 |
58 | FieldBuilder withArgs(JCExpression... newArgs) {
59 | args = List.from(newArgs);
60 | return this;
61 | }
62 |
63 | JCVariableDecl buildWith(JavacNode node) {
64 | TreeMaker treeMaker = node.getTreeMaker();
65 | JCExpression classType = chainDots(treeMaker, node, splitNameOf(type));
66 | JCExpression newVar = treeMaker.NewClass(null, null, classType, args, null);
67 | return treeMaker.VarDef(treeMaker.Modifiers(modifiers), node.toName(name), classType, newVar);
68 | }
69 |
70 | private FieldBuilder() {}
71 | }
72 |
--------------------------------------------------------------------------------
/src/javac/lombok/javac/handlers/JCNoType.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 1, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.javac.handlers;
16 |
17 | import static com.sun.tools.javac.code.TypeTags.*;
18 |
19 | import javax.lang.model.type.*;
20 |
21 | import com.sun.tools.javac.code.Type;
22 |
23 | /**
24 | * A type to represent "void" and "none." Copied from Lombok.
25 | *
26 | * @author Alex Ruiz
27 | */
28 | class JCNoType extends Type implements NoType {
29 |
30 | static JCNoType voidType() {
31 | return new JCNoType(VOID);
32 | }
33 |
34 | private JCNoType(int tag) {
35 | super(tag, null);
36 | }
37 |
38 | @Override public TypeKind getKind() {
39 | if (tag == VOID) return TypeKind.VOID;
40 | if (tag == NONE) return TypeKind.NONE;
41 | throw new IllegalStateException("Unexpected tag: " + tag);
42 | }
43 |
44 | @Override public R accept(TypeVisitor v, P p) {
45 | return v.visitNoType(this, p);
46 | }
47 | }
48 |
--------------------------------------------------------------------------------
/src/javac/lombok/javac/handlers/JavaBeanHandler.java:
--------------------------------------------------------------------------------
1 | /*
2 | * Created on Dec 3, 2010
3 | *
4 | * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
5 | * the License. You may obtain a copy of the License at
6 | *
7 | * http://www.apache.org/licenses/LICENSE-2.0
8 | *
9 | * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
10 | * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
11 | * specific language governing permissions and limitations under the License.
12 | *
13 | * Copyright @2010 the original author or authors.
14 | */
15 | package lombok.javac.handlers;
16 |
17 | import static com.sun.tools.javac.code.Flags.*;
18 | import static lombok.core.util.ErrorMessages.canBeUsedOnClassOnly;
19 | import static lombok.core.util.Names.*;
20 | import static lombok.javac.handlers.FieldBuilder.newField;
21 | import static lombok.javac.handlers.JCNoType.voidType;
22 | import static lombok.javac.handlers.JavacHandlerUtil.*;
23 | import static lombok.javac.handlers.MemberChecks.*;
24 | import static lombok.javac.handlers.MethodBuilder.newMethod;
25 |
26 | import java.beans.*;
27 |
28 | import lombok.GenerateJavaBean;
29 | import lombok.core.AnnotationValues;
30 | import lombok.javac.*;
31 |
32 | import org.mangosdk.spi.ProviderFor;
33 |
34 | import com.sun.tools.javac.tree.JCTree.JCAnnotation;
35 | import com.sun.tools.javac.tree.JCTree.JCBlock;
36 | import com.sun.tools.javac.tree.JCTree.JCExpression;
37 | import com.sun.tools.javac.tree.JCTree.JCMethodDecl;
38 | import com.sun.tools.javac.tree.JCTree.JCStatement;
39 | import com.sun.tools.javac.tree.JCTree.JCVariableDecl;
40 | import com.sun.tools.javac.tree.*;
41 | import com.sun.tools.javac.util.*;
42 |
43 | /**
44 | * Generates basic support for making a class annotated with {@link GenerateJavaBean} a JavaBean.
45 | *
46 | * "Basic" JavaBean support means:
47 | *
48 | *
Generates a field of type {@link PropertyChangeSupport} with name "propertySupport"
49 | *
Generates the public method {@code addPropertyChangeListener(PropertyChangeListener)} and
50 | * {@code removePropertyChangeListener(PropertyChangeListener)}
51 | *
52 | *
53 | *
54 | *
55 | * For example, given this class:
56 | *
57 | *
58 | * @GenerateJavaBean
59 | * public class Person {
60 | *
61 | * }
62 | *
63 | * this annotation handler will generate the AST nodes that correspond to this code:
64 | *
65 | *