1 | /* |
---|---|
2 | * Copyright (C) 2007-2010 JĂșlio Vilmar Gesser. |
3 | * Copyright (C) 2011, 2013-2020 The JavaParser Team. |
4 | * |
5 | * This file is part of JavaParser. |
6 | * |
7 | * JavaParser can be used either under the terms of |
8 | * a) the GNU Lesser General Public License as published by |
9 | * the Free Software Foundation, either version 3 of the License, or |
10 | * (at your option) any later version. |
11 | * b) the terms of the Apache License |
12 | * |
13 | * You should have received a copy of both licenses in LICENCE.LGPL and |
14 | * LICENCE.APACHE. Please refer to those files for details. |
15 | * |
16 | * JavaParser is distributed in the hope that it will be useful, |
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of |
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
19 | * GNU Lesser General Public License for more details. |
20 | */ |
21 | package com.github.javaparser.ast.body; |
22 | |
23 | import com.github.javaparser.TokenRange; |
24 | import com.github.javaparser.ast.*; |
25 | import com.github.javaparser.ast.expr.AnnotationExpr; |
26 | import com.github.javaparser.ast.expr.AssignExpr; |
27 | import com.github.javaparser.ast.expr.AssignExpr.Operator; |
28 | import com.github.javaparser.ast.expr.NameExpr; |
29 | import com.github.javaparser.ast.nodeTypes.NodeWithJavadoc; |
30 | import com.github.javaparser.ast.nodeTypes.NodeWithVariables; |
31 | import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithAccessModifiers; |
32 | import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithFinalModifier; |
33 | import com.github.javaparser.ast.nodeTypes.modifiers.NodeWithStaticModifier; |
34 | import com.github.javaparser.ast.observer.ObservableProperty; |
35 | import com.github.javaparser.ast.stmt.BlockStmt; |
36 | import com.github.javaparser.ast.stmt.ReturnStmt; |
37 | import com.github.javaparser.ast.type.Type; |
38 | import com.github.javaparser.ast.type.VoidType; |
39 | import com.github.javaparser.ast.visitor.CloneVisitor; |
40 | import com.github.javaparser.ast.visitor.GenericVisitor; |
41 | import com.github.javaparser.ast.visitor.VoidVisitor; |
42 | import com.github.javaparser.metamodel.FieldDeclarationMetaModel; |
43 | import com.github.javaparser.metamodel.JavaParserMetaModel; |
44 | import com.github.javaparser.metamodel.NonEmptyProperty; |
45 | import com.github.javaparser.resolution.Resolvable; |
46 | import com.github.javaparser.resolution.declarations.ResolvedFieldDeclaration; |
47 | import java.util.Optional; |
48 | import java.util.function.Consumer; |
49 | import static com.github.javaparser.ast.NodeList.nodeList; |
50 | import static com.github.javaparser.utils.Utils.assertNotNull; |
51 | import com.github.javaparser.ast.Node; |
52 | import com.github.javaparser.ast.Generated; |
53 | |
54 | /** |
55 | * The declaration of a field in a class. "private static int a=15*15;" in this example: {@code class X { private static |
56 | * int a=15*15; }} |
57 | * |
58 | * <br>All annotations preceding the type will be set on this object, not on the type. |
59 | * JavaParser doesn't know if it they are applicable to the method or the type. |
60 | * |
61 | * @author Julio Vilmar Gesser |
62 | */ |
63 | public class FieldDeclaration extends BodyDeclaration<FieldDeclaration> implements NodeWithJavadoc<FieldDeclaration>, NodeWithVariables<FieldDeclaration>, NodeWithAccessModifiers<FieldDeclaration>, NodeWithStaticModifier<FieldDeclaration>, NodeWithFinalModifier<FieldDeclaration>, Resolvable<ResolvedFieldDeclaration> { |
64 | |
65 | private NodeList<Modifier> modifiers; |
66 | |
67 | @NonEmptyProperty |
68 | private NodeList<VariableDeclarator> variables; |
69 | |
70 | public FieldDeclaration() { |
71 | this(null, new NodeList<>(), new NodeList<>(), new NodeList<>()); |
72 | } |
73 | |
74 | public FieldDeclaration(NodeList<Modifier> modifiers, VariableDeclarator variable) { |
75 | this(null, modifiers, new NodeList<>(), nodeList(variable)); |
76 | } |
77 | |
78 | public FieldDeclaration(NodeList<Modifier> modifiers, NodeList<VariableDeclarator> variables) { |
79 | this(null, modifiers, new NodeList<>(), variables); |
80 | } |
81 | |
82 | @AllFieldsConstructor |
83 | public FieldDeclaration(NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) { |
84 | this(null, modifiers, annotations, variables); |
85 | } |
86 | |
87 | /** |
88 | * This constructor is used by the parser and is considered private. |
89 | */ |
90 | @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator") |
91 | public FieldDeclaration(TokenRange tokenRange, NodeList<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<VariableDeclarator> variables) { |
92 | super(tokenRange, annotations); |
93 | setModifiers(modifiers); |
94 | setVariables(variables); |
95 | customInitialization(); |
96 | } |
97 | |
98 | /** |
99 | * Creates a {@link FieldDeclaration}. |
100 | * |
101 | * @param modifiers modifiers |
102 | * @param type type |
103 | * @param name field name |
104 | */ |
105 | public FieldDeclaration(NodeList<Modifier> modifiers, Type type, String name) { |
106 | this(assertNotNull(modifiers), new VariableDeclarator(type, assertNotNull(name))); |
107 | } |
108 | |
109 | @Override |
110 | @Generated("com.github.javaparser.generator.core.node.AcceptGenerator") |
111 | public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) { |
112 | return v.visit(this, arg); |
113 | } |
114 | |
115 | @Override |
116 | @Generated("com.github.javaparser.generator.core.node.AcceptGenerator") |
117 | public <A> void accept(final VoidVisitor<A> v, final A arg) { |
118 | v.visit(this, arg); |
119 | } |
120 | |
121 | /** |
122 | * Return the modifiers of this member declaration. |
123 | * |
124 | * @return modifiers |
125 | * @see Modifier |
126 | */ |
127 | @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") |
128 | public NodeList<Modifier> getModifiers() { |
129 | return modifiers; |
130 | } |
131 | |
132 | @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") |
133 | public NodeList<VariableDeclarator> getVariables() { |
134 | return variables; |
135 | } |
136 | |
137 | @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") |
138 | public FieldDeclaration setModifiers(final NodeList<Modifier> modifiers) { |
139 | assertNotNull(modifiers); |
140 | if (modifiers == this.modifiers) { |
141 | return (FieldDeclaration) this; |
142 | } |
143 | notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers); |
144 | if (this.modifiers != null) |
145 | this.modifiers.setParentNode(null); |
146 | this.modifiers = modifiers; |
147 | setAsParentNodeOf(modifiers); |
148 | return this; |
149 | } |
150 | |
151 | @Generated("com.github.javaparser.generator.core.node.PropertyGenerator") |
152 | public FieldDeclaration setVariables(final NodeList<VariableDeclarator> variables) { |
153 | assertNotNull(variables); |
154 | if (variables == this.variables) { |
155 | return (FieldDeclaration) this; |
156 | } |
157 | notifyPropertyChange(ObservableProperty.VARIABLES, this.variables, variables); |
158 | if (this.variables != null) |
159 | this.variables.setParentNode(null); |
160 | this.variables = variables; |
161 | setAsParentNodeOf(variables); |
162 | return this; |
163 | } |
164 | |
165 | /** |
166 | * Create a getter for this field, <b>will only work if this field declares only 1 identifier and if this field is |
167 | * already added to a ClassOrInterfaceDeclaration</b> |
168 | * |
169 | * @return the {@link MethodDeclaration} created |
170 | * @throws IllegalStateException if there is more than 1 variable identifier or if this field isn't attached to a |
171 | * class or enum |
172 | */ |
173 | public MethodDeclaration createGetter() { |
174 | if (getVariables().size() != 1) |
175 | throw new IllegalStateException("You can use this only when the field declares only 1 variable name"); |
176 | Optional<ClassOrInterfaceDeclaration> parentClass = findAncestor(ClassOrInterfaceDeclaration.class); |
177 | Optional<EnumDeclaration> parentEnum = findAncestor(EnumDeclaration.class); |
178 | if (!(parentClass.isPresent() || parentEnum.isPresent()) || (parentClass.isPresent() && parentClass.get().isInterface())) |
179 | throw new IllegalStateException("You can use this only when the field is attached to a class or an enum"); |
180 | VariableDeclarator variable = getVariable(0); |
181 | String fieldName = variable.getNameAsString(); |
182 | String fieldNameUpper = fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1, fieldName.length()); |
183 | final MethodDeclaration getter; |
184 | getter = parentClass.map(clazz -> clazz.addMethod("get" + fieldNameUpper, Modifier.Keyword.PUBLIC)).orElseGet(() -> parentEnum.get().addMethod("get" + fieldNameUpper, Modifier.Keyword.PUBLIC)); |
185 | getter.setType(variable.getType()); |
186 | BlockStmt blockStmt = new BlockStmt(); |
187 | getter.setBody(blockStmt); |
188 | blockStmt.addStatement(new ReturnStmt(fieldName)); |
189 | return getter; |
190 | } |
191 | |
192 | /** |
193 | * Create a setter for this field, <b>will only work if this field declares only 1 identifier and if this field is |
194 | * already added to a ClassOrInterfaceDeclaration</b> |
195 | * |
196 | * @return the {@link MethodDeclaration} created |
197 | * @throws IllegalStateException if there is more than 1 variable identifier or if this field isn't attached to a |
198 | * class or enum |
199 | */ |
200 | public MethodDeclaration createSetter() { |
201 | if (getVariables().size() != 1) |
202 | throw new IllegalStateException("You can use this only when the field declares only 1 variable name"); |
203 | Optional<ClassOrInterfaceDeclaration> parentClass = findAncestor(ClassOrInterfaceDeclaration.class); |
204 | Optional<EnumDeclaration> parentEnum = findAncestor(EnumDeclaration.class); |
205 | if (!(parentClass.isPresent() || parentEnum.isPresent()) || (parentClass.isPresent() && parentClass.get().isInterface())) |
206 | throw new IllegalStateException("You can use this only when the field is attached to a class or an enum"); |
207 | VariableDeclarator variable = getVariable(0); |
208 | String fieldName = variable.getNameAsString(); |
209 | String fieldNameUpper = fieldName.toUpperCase().substring(0, 1) + fieldName.substring(1, fieldName.length()); |
210 | final MethodDeclaration setter; |
211 | setter = parentClass.map(clazz -> clazz.addMethod("set" + fieldNameUpper, Modifier.Keyword.PUBLIC)).orElseGet(() -> parentEnum.get().addMethod("set" + fieldNameUpper, Modifier.Keyword.PUBLIC)); |
212 | setter.setType(new VoidType()); |
213 | setter.getParameters().add(new Parameter(variable.getType(), fieldName)); |
214 | BlockStmt blockStmt2 = new BlockStmt(); |
215 | setter.setBody(blockStmt2); |
216 | blockStmt2.addStatement(new AssignExpr(new NameExpr("this." + fieldName), new NameExpr(fieldName), Operator.ASSIGN)); |
217 | return setter; |
218 | } |
219 | |
220 | public boolean isTransient() { |
221 | return hasModifier(Modifier.Keyword.TRANSIENT); |
222 | } |
223 | |
224 | public boolean isVolatile() { |
225 | return hasModifier(Modifier.Keyword.VOLATILE); |
226 | } |
227 | |
228 | public FieldDeclaration setTransient(boolean set) { |
229 | return setModifier(Modifier.Keyword.TRANSIENT, set); |
230 | } |
231 | |
232 | public FieldDeclaration setVolatile(boolean set) { |
233 | return setModifier(Modifier.Keyword.VOLATILE, set); |
234 | } |
235 | |
236 | @Override |
237 | @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") |
238 | public boolean remove(Node node) { |
239 | if (node == null) |
240 | return false; |
241 | for (int i = 0; i < modifiers.size(); i++) { |
242 | if (modifiers.get(i) == node) { |
243 | modifiers.remove(i); |
244 | return true; |
245 | } |
246 | } |
247 | for (int i = 0; i < variables.size(); i++) { |
248 | if (variables.get(i) == node) { |
249 | variables.remove(i); |
250 | return true; |
251 | } |
252 | } |
253 | return super.remove(node); |
254 | } |
255 | |
256 | @Override |
257 | @Generated("com.github.javaparser.generator.core.node.CloneGenerator") |
258 | public FieldDeclaration clone() { |
259 | return (FieldDeclaration) accept(new CloneVisitor(), null); |
260 | } |
261 | |
262 | @Override |
263 | @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator") |
264 | public FieldDeclarationMetaModel getMetaModel() { |
265 | return JavaParserMetaModel.fieldDeclarationMetaModel; |
266 | } |
267 | |
268 | @Override |
269 | @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator") |
270 | public boolean replace(Node node, Node replacementNode) { |
271 | if (node == null) |
272 | return false; |
273 | for (int i = 0; i < modifiers.size(); i++) { |
274 | if (modifiers.get(i) == node) { |
275 | modifiers.set(i, (Modifier) replacementNode); |
276 | return true; |
277 | } |
278 | } |
279 | for (int i = 0; i < variables.size(); i++) { |
280 | if (variables.get(i) == node) { |
281 | variables.set(i, (VariableDeclarator) replacementNode); |
282 | return true; |
283 | } |
284 | } |
285 | return super.replace(node, replacementNode); |
286 | } |
287 | |
288 | @Override |
289 | @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
290 | public boolean isFieldDeclaration() { |
291 | return true; |
292 | } |
293 | |
294 | @Override |
295 | @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
296 | public FieldDeclaration asFieldDeclaration() { |
297 | return this; |
298 | } |
299 | |
300 | @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
301 | public void ifFieldDeclaration(Consumer<FieldDeclaration> action) { |
302 | action.accept(this); |
303 | } |
304 | |
305 | @Override |
306 | public ResolvedFieldDeclaration resolve() { |
307 | return getSymbolResolver().resolveDeclaration(this, ResolvedFieldDeclaration.class); |
308 | } |
309 | |
310 | @Override |
311 | @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
312 | public Optional<FieldDeclaration> toFieldDeclaration() { |
313 | return Optional.of(this); |
314 | } |
315 | } |
316 |
Members