• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2007-2010 Júlio Vilmar Gesser.
3  * Copyright (C) 2011, 2013-2017 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.AllFieldsConstructor;
25 import com.github.javaparser.ast.Modifier;
26 import com.github.javaparser.ast.Node;
27 import com.github.javaparser.ast.NodeList;
28 import com.github.javaparser.ast.expr.AnnotationExpr;
29 import com.github.javaparser.ast.expr.SimpleName;
30 import com.github.javaparser.ast.nodeTypes.*;
31 import com.github.javaparser.ast.nodeTypes.modifiers.*;
32 import com.github.javaparser.ast.observer.ObservableProperty;
33 import com.github.javaparser.ast.type.ArrayType;
34 import com.github.javaparser.ast.type.ReferenceType;
35 import com.github.javaparser.ast.type.Type;
36 import com.github.javaparser.ast.type.TypeParameter;
37 import com.github.javaparser.ast.visitor.CloneVisitor;
38 import com.github.javaparser.metamodel.CallableDeclarationMetaModel;
39 import com.github.javaparser.metamodel.JavaParserMetaModel;
40 import com.github.javaparser.metamodel.OptionalProperty;
41 import javax.annotation.Generated;
42 import java.util.EnumSet;
43 import java.util.List;
44 import static com.github.javaparser.utils.Utils.assertNotNull;
45 import static java.util.stream.Collectors.joining;
46 import static java.util.stream.Collectors.toList;
47 import java.util.Optional;
48 import java.util.function.Consumer;
49 
50 /**
51  * Represents a declaration which is callable eg. a method or a constructor.
52  */
53 public abstract class CallableDeclaration<T extends CallableDeclaration<?>> extends BodyDeclaration<T> implements NodeWithAccessModifiers<T>, NodeWithDeclaration, NodeWithSimpleName<T>, NodeWithParameters<T>, NodeWithThrownExceptions<T>, NodeWithTypeParameters<T>, NodeWithJavadoc<T>, NodeWithAbstractModifier<T>, NodeWithStaticModifier<T>, NodeWithFinalModifier<T>, NodeWithStrictfpModifier<T> {
54 
55     private EnumSet<Modifier> modifiers;
56 
57     private NodeList<TypeParameter> typeParameters;
58 
59     private SimpleName name;
60 
61     private NodeList<Parameter> parameters;
62 
63     private NodeList<ReferenceType> thrownExceptions;
64 
65     @OptionalProperty
66     private ReceiverParameter receiverParameter;
67 
68     @AllFieldsConstructor
CallableDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter)69     CallableDeclaration(EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter) {
70         this(null, modifiers, annotations, typeParameters, name, parameters, thrownExceptions, receiverParameter);
71     }
72 
73     /**
74      * This constructor is used by the parser and is considered private.
75      */
76     @Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator")
CallableDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter)77     public CallableDeclaration(TokenRange tokenRange, EnumSet<Modifier> modifiers, NodeList<AnnotationExpr> annotations, NodeList<TypeParameter> typeParameters, SimpleName name, NodeList<Parameter> parameters, NodeList<ReferenceType> thrownExceptions, ReceiverParameter receiverParameter) {
78         super(tokenRange, annotations);
79         setModifiers(modifiers);
80         setTypeParameters(typeParameters);
81         setName(name);
82         setParameters(parameters);
83         setThrownExceptions(thrownExceptions);
84         setReceiverParameter(receiverParameter);
85         customInitialization();
86     }
87 
88     /**
89      * Return the modifiers of this member declaration.
90      *
91      * @return modifiers
92      * @see Modifier
93      */
94     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
getModifiers()95     public EnumSet<Modifier> getModifiers() {
96         return modifiers;
97     }
98 
99     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
100     @SuppressWarnings("unchecked")
setModifiers(final EnumSet<Modifier> modifiers)101     public T setModifiers(final EnumSet<Modifier> modifiers) {
102         assertNotNull(modifiers);
103         if (modifiers == this.modifiers) {
104             return (T) this;
105         }
106         notifyPropertyChange(ObservableProperty.MODIFIERS, this.modifiers, modifiers);
107         this.modifiers = modifiers;
108         return (T) this;
109     }
110 
111     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
getName()112     public SimpleName getName() {
113         return name;
114     }
115 
116     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
117     @SuppressWarnings("unchecked")
setName(final SimpleName name)118     public T setName(final SimpleName name) {
119         assertNotNull(name);
120         if (name == this.name) {
121             return (T) this;
122         }
123         notifyPropertyChange(ObservableProperty.NAME, this.name, name);
124         if (this.name != null)
125             this.name.setParentNode(null);
126         this.name = name;
127         setAsParentNodeOf(name);
128         return (T) this;
129     }
130 
131     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
getParameters()132     public NodeList<Parameter> getParameters() {
133         return parameters;
134     }
135 
136     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
137     @SuppressWarnings("unchecked")
setParameters(final NodeList<Parameter> parameters)138     public T setParameters(final NodeList<Parameter> parameters) {
139         assertNotNull(parameters);
140         if (parameters == this.parameters) {
141             return (T) this;
142         }
143         notifyPropertyChange(ObservableProperty.PARAMETERS, this.parameters, parameters);
144         if (this.parameters != null)
145             this.parameters.setParentNode(null);
146         this.parameters = parameters;
147         setAsParentNodeOf(parameters);
148         return (T) this;
149     }
150 
151     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
getThrownExceptions()152     public NodeList<ReferenceType> getThrownExceptions() {
153         return thrownExceptions;
154     }
155 
156     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
157     @SuppressWarnings("unchecked")
setThrownExceptions(final NodeList<ReferenceType> thrownExceptions)158     public T setThrownExceptions(final NodeList<ReferenceType> thrownExceptions) {
159         assertNotNull(thrownExceptions);
160         if (thrownExceptions == this.thrownExceptions) {
161             return (T) this;
162         }
163         notifyPropertyChange(ObservableProperty.THROWN_EXCEPTIONS, this.thrownExceptions, thrownExceptions);
164         if (this.thrownExceptions != null)
165             this.thrownExceptions.setParentNode(null);
166         this.thrownExceptions = thrownExceptions;
167         setAsParentNodeOf(thrownExceptions);
168         return (T) this;
169     }
170 
171     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
getTypeParameters()172     public NodeList<TypeParameter> getTypeParameters() {
173         return typeParameters;
174     }
175 
176     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
177     @SuppressWarnings("unchecked")
setTypeParameters(final NodeList<TypeParameter> typeParameters)178     public T setTypeParameters(final NodeList<TypeParameter> typeParameters) {
179         assertNotNull(typeParameters);
180         if (typeParameters == this.typeParameters) {
181             return (T) this;
182         }
183         notifyPropertyChange(ObservableProperty.TYPE_PARAMETERS, this.typeParameters, typeParameters);
184         if (this.typeParameters != null)
185             this.typeParameters.setParentNode(null);
186         this.typeParameters = typeParameters;
187         setAsParentNodeOf(typeParameters);
188         return (T) this;
189     }
190 
getDeclarationAsString(boolean includingModifiers, boolean includingThrows)191     public String getDeclarationAsString(boolean includingModifiers, boolean includingThrows) {
192         return getDeclarationAsString(includingModifiers, includingThrows, true);
193     }
194 
getDeclarationAsString()195     public String getDeclarationAsString() {
196         return getDeclarationAsString(true, true, true);
197     }
198 
getDeclarationAsString(boolean includingModifiers, boolean includingThrows, boolean includingParameterName)199     public abstract String getDeclarationAsString(boolean includingModifiers, boolean includingThrows, boolean includingParameterName);
200 
appendThrowsIfRequested(boolean includingThrows)201     protected String appendThrowsIfRequested(boolean includingThrows) {
202         StringBuilder sb = new StringBuilder();
203         if (includingThrows) {
204             boolean firstThrow = true;
205             for (ReferenceType thr : getThrownExceptions()) {
206                 if (firstThrow) {
207                     firstThrow = false;
208                     sb.append(" throws ");
209                 } else {
210                     sb.append(", ");
211                 }
212                 sb.append(thr.toString(prettyPrinterNoCommentsConfiguration));
213             }
214         }
215         return sb.toString();
216     }
217 
218     @Override
219     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
remove(Node node)220     public boolean remove(Node node) {
221         if (node == null)
222             return false;
223         for (int i = 0; i < parameters.size(); i++) {
224             if (parameters.get(i) == node) {
225                 parameters.remove(i);
226                 return true;
227             }
228         }
229         if (receiverParameter != null) {
230             if (node == receiverParameter) {
231                 removeReceiverParameter();
232                 return true;
233             }
234         }
235         for (int i = 0; i < thrownExceptions.size(); i++) {
236             if (thrownExceptions.get(i) == node) {
237                 thrownExceptions.remove(i);
238                 return true;
239             }
240         }
241         for (int i = 0; i < typeParameters.size(); i++) {
242             if (typeParameters.get(i) == node) {
243                 typeParameters.remove(i);
244                 return true;
245             }
246         }
247         return super.remove(node);
248     }
249 
250     /**
251      * A method or constructor signature.
252      * <p/>Note that since JavaParser has no real knowledge of types - only the text found in the source file - using
253      * this will fail in some cases. (java.util.String != String for example, and generics are not taken into account.)
254      */
255     public static class Signature {
256 
257         private final String name;
258 
259         private final List<Type> parameterTypes;
260 
Signature(String name, List<Type> parameterTypes)261         private Signature(String name, List<Type> parameterTypes) {
262             this.name = name;
263             this.parameterTypes = parameterTypes;
264         }
265 
getName()266         public String getName() {
267             return name;
268         }
269 
getParameterTypes()270         public List<Type> getParameterTypes() {
271             return parameterTypes;
272         }
273 
274         @Override
equals(Object o)275         public boolean equals(Object o) {
276             if (this == o)
277                 return true;
278             if (o == null || getClass() != o.getClass())
279                 return false;
280             Signature signature = (Signature) o;
281             if (!name.equals(signature.name))
282                 return false;
283             if (!parameterTypes.equals(signature.parameterTypes))
284                 return false;
285             return true;
286         }
287 
288         @Override
hashCode()289         public int hashCode() {
290             int result = name.hashCode();
291             result = 31 * result + parameterTypes.hashCode();
292             return result;
293         }
294 
asString()295         public String asString() {
296             return parameterTypes.stream().map(Type::asString).collect(joining(", ", name + "(", ")"));
297         }
298 
299         @Override
toString()300         public String toString() {
301             return asString();
302         }
303     }
304 
getSignature()305     public Signature getSignature() {
306         return new Signature(getName().getIdentifier(), getParameters().stream().map(this::getTypeWithVarargsAsArray).map(this::stripGenerics).map(this::stripAnnotations).collect(toList()));
307     }
308 
stripAnnotations(Type type)309     private Type stripAnnotations(Type type) {
310         if (type instanceof NodeWithAnnotations) {
311             ((NodeWithAnnotations) type).setAnnotations(new NodeList<>());
312         }
313         return type;
314     }
315 
stripGenerics(Type type)316     private Type stripGenerics(Type type) {
317         if (type instanceof NodeWithTypeArguments) {
318             ((NodeWithTypeArguments) type).setTypeArguments((NodeList<Type>) null);
319         }
320         return type;
321     }
322 
getTypeWithVarargsAsArray(Parameter p)323     private Type getTypeWithVarargsAsArray(Parameter p) {
324         /* A signature includes the varargs ellipsis.
325          This is a field on parameter which we lose when we only get the type,
326          so we represent it as an additional [] on the type. */
327         Type t = p.getType().clone();
328         if (p.isVarArgs()) {
329             t = new ArrayType(t);
330         }
331         return t;
332     }
333 
334     @Override
335     @Generated("com.github.javaparser.generator.core.node.CloneGenerator")
clone()336     public CallableDeclaration<?> clone() {
337         return (CallableDeclaration<?>) accept(new CloneVisitor(), null);
338     }
339 
340     @Override
341     @Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator")
getMetaModel()342     public CallableDeclarationMetaModel getMetaModel() {
343         return JavaParserMetaModel.callableDeclarationMetaModel;
344     }
345 
346     @Override
347     @Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator")
replace(Node node, Node replacementNode)348     public boolean replace(Node node, Node replacementNode) {
349         if (node == null)
350             return false;
351         if (node == name) {
352             setName((SimpleName) replacementNode);
353             return true;
354         }
355         for (int i = 0; i < parameters.size(); i++) {
356             if (parameters.get(i) == node) {
357                 parameters.set(i, (Parameter) replacementNode);
358                 return true;
359             }
360         }
361         if (receiverParameter != null) {
362             if (node == receiverParameter) {
363                 setReceiverParameter((ReceiverParameter) replacementNode);
364                 return true;
365             }
366         }
367         for (int i = 0; i < thrownExceptions.size(); i++) {
368             if (thrownExceptions.get(i) == node) {
369                 thrownExceptions.set(i, (ReferenceType) replacementNode);
370                 return true;
371             }
372         }
373         for (int i = 0; i < typeParameters.size(); i++) {
374             if (typeParameters.get(i) == node) {
375                 typeParameters.set(i, (TypeParameter) replacementNode);
376                 return true;
377             }
378         }
379         return super.replace(node, replacementNode);
380     }
381 
382     @Override
383     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
isCallableDeclaration()384     public boolean isCallableDeclaration() {
385         return true;
386     }
387 
388     @Override
389     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
asCallableDeclaration()390     public CallableDeclaration asCallableDeclaration() {
391         return this;
392     }
393 
394     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
ifCallableDeclaration(Consumer<CallableDeclaration> action)395     public void ifCallableDeclaration(Consumer<CallableDeclaration> action) {
396         action.accept(this);
397     }
398 
399     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
getReceiverParameter()400     public Optional<ReceiverParameter> getReceiverParameter() {
401         return Optional.ofNullable(receiverParameter);
402     }
403 
404     @Generated("com.github.javaparser.generator.core.node.PropertyGenerator")
405     @SuppressWarnings("unchecked")
setReceiverParameter(final ReceiverParameter receiverParameter)406     public T setReceiverParameter(final ReceiverParameter receiverParameter) {
407         if (receiverParameter == this.receiverParameter) {
408             return (T) this;
409         }
410         notifyPropertyChange(ObservableProperty.RECEIVER_PARAMETER, this.receiverParameter, receiverParameter);
411         if (this.receiverParameter != null)
412             this.receiverParameter.setParentNode(null);
413         this.receiverParameter = receiverParameter;
414         setAsParentNodeOf(receiverParameter);
415         return (T) this;
416     }
417 
418     @Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator")
removeReceiverParameter()419     public CallableDeclaration removeReceiverParameter() {
420         return setReceiverParameter((ReceiverParameter) null);
421     }
422 
423     @Override
424     @Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator")
toCallableDeclaration()425     public Optional<CallableDeclaration> toCallableDeclaration() {
426         return Optional.of(this);
427     }
428 }
429