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