1/* 2 * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26package com.sun.codemodel.internal; 27 28import java.lang.annotation.Annotation; 29import java.util.ArrayList; 30import java.util.List; 31import java.util.Set; 32import java.util.TreeSet; 33import java.util.Collections; 34import java.util.Collection; 35 36import com.sun.codemodel.internal.util.ClassNameComparator; 37 38/** 39 * Java method. 40 */ 41public class JMethod extends JGenerifiableImpl implements JDeclaration, JAnnotatable, JDocCommentable { 42 43 /** 44 * Modifiers for this method 45 */ 46 private JMods mods; 47 48 /** 49 * Return type for this method 50 */ 51 private JType type = null; 52 53 /** 54 * Name of this method 55 */ 56 private String name = null; 57 58 /** 59 * List of parameters for this method's declaration 60 */ 61 private final List<JVar> params = new ArrayList<JVar>(); 62 63 /** 64 * Set of exceptions that this method may throw. 65 * A set instance lazily created. 66 */ 67 private Set<JClass> _throws; 68 69 /** 70 * JBlock of statements that makes up the body this method 71 */ 72 private JBlock body = null; 73 74 private JDefinedClass outer; 75 76 /** 77 * javadoc comments for this JMethod 78 */ 79 private JDocComment jdoc = null; 80 81 /** 82 * Variable parameter for this method's varargs declaration 83 * introduced in J2SE 1.5 84 */ 85 private JVar varParam = null; 86 87 /** 88 * Annotations on this variable. Lazily created. 89 */ 90 private List<JAnnotationUse> annotations = null; 91 92 93 private boolean isConstructor() { 94 return type == null; 95 } 96 97 /** To set the default value for the 98 * annotation member 99 */ 100 private JExpression defaultValue = null; 101 102 103 /** 104 * JMethod constructor 105 * 106 * @param mods 107 * Modifiers for this method's declaration 108 * 109 * @param type 110 * Return type for the method 111 * 112 * @param name 113 * Name of this method 114 */ 115 JMethod(JDefinedClass outer, int mods, JType type, String name) { 116 this.mods = JMods.forMethod(mods); 117 this.type = type; 118 this.name = name; 119 this.outer = outer; 120 } 121 122 /** 123 * Constructor constructor 124 * 125 * @param mods 126 * Modifiers for this constructor's declaration 127 * 128 * @param _class 129 * JClass containing this constructor 130 */ 131 JMethod(int mods, JDefinedClass _class) { 132 this.mods = JMods.forMethod(mods); 133 this.type = null; 134 this.name = _class.name(); 135 this.outer = _class; 136 } 137 138 private Set<JClass> getThrows() { 139 if(_throws==null) 140 _throws = new TreeSet<JClass>(ClassNameComparator.theInstance); 141 return _throws; 142 } 143 144 /** 145 * Add an exception to the list of exceptions that this 146 * method may throw. 147 * 148 * @param exception 149 * Name of an exception that this method may throw 150 */ 151 public JMethod _throws(JClass exception) { 152 getThrows().add(exception); 153 return this; 154 } 155 156 public JMethod _throws(Class<? extends Throwable> exception) { 157 return _throws(outer.owner().ref(exception)); 158 } 159 160 /** 161 * Returns the list of variable of this method. 162 * 163 * @return List of parameters of this method. This list is not modifiable. 164 */ 165 public List<JVar> params() { 166 return Collections.<JVar>unmodifiableList(params); 167 } 168 169 /** 170 * Add the specified variable to the list of parameters 171 * for this method signature. 172 * 173 * @param type 174 * JType of the parameter being added 175 * 176 * @param name 177 * Name of the parameter being added 178 * 179 * @return New parameter variable 180 */ 181 public JVar param(int mods, JType type, String name) { 182 JVar v = new JVar(JMods.forVar(mods), type, name, null); 183 params.add(v); 184 return v; 185 } 186 187 public JVar param(JType type, String name) { 188 return param(JMod.NONE, type, name); 189 } 190 191 public JVar param(int mods, Class<?> type, String name) { 192 return param(mods, outer.owner()._ref(type), name); 193 } 194 195 public JVar param(Class<?> type, String name) { 196 return param(outer.owner()._ref(type), name); 197 } 198 199 /** 200 * @see #varParam(JType, String) 201 */ 202 public JVar varParam(Class<?> type, String name) { 203 return varParam(outer.owner()._ref(type),name); 204 } 205 206 /** 207 * Add the specified variable argument to the list of parameters 208 * for this method signature. 209 * 210 * @param type 211 * Type of the parameter being added. 212 * 213 * @param name 214 * Name of the parameter being added 215 * 216 * @return the variable parameter 217 * 218 * @throws IllegalStateException 219 * If this method is called twice. 220 * varargs in J2SE 1.5 can appear only once in the 221 * method signature. 222 */ 223 public JVar varParam(JType type, String name) { 224 if (!hasVarArgs()) { 225 226 varParam = 227 new JVar( 228 JMods.forVar(JMod.NONE), 229 type.array(), 230 name, 231 null); 232 return varParam; 233 } else { 234 throw new IllegalStateException( 235 "Cannot have two varargs in a method,\n" 236 + "Check if varParam method of JMethod is" 237 + " invoked more than once"); 238 239 } 240 241 } 242 243 /** 244 * Adds an annotation to this variable. 245 * @param clazz 246 * The annotation class to annotate the field with 247 */ 248 public JAnnotationUse annotate(JClass clazz){ 249 if(annotations==null) 250 annotations = new ArrayList<JAnnotationUse>(); 251 JAnnotationUse a = new JAnnotationUse(clazz); 252 annotations.add(a); 253 return a; 254 } 255 256 /** 257 * Adds an annotation to this variable. 258 * 259 * @param clazz 260 * The annotation class to annotate the field with 261 */ 262 public JAnnotationUse annotate(Class <? extends Annotation> clazz){ 263 return annotate(owner().ref(clazz)); 264 } 265 266 public <W extends JAnnotationWriter> W annotate2(Class<W> clazz) { 267 return TypedAnnotationWriter.create(clazz,this); 268 } 269 270 public boolean removeAnnotation(JAnnotationUse annotation) { 271 return this.annotations.remove(annotation); 272 } 273 274 public Collection<JAnnotationUse> annotations() { 275 if (annotations == null) 276 annotations = new ArrayList<JAnnotationUse>(); 277 return Collections.unmodifiableList(annotations); 278 } 279 280 /** 281 * Check if there are any varargs declared 282 * for this method signature. 283 */ 284 public boolean hasVarArgs() { 285 return this.varParam!=null; 286 } 287 288 public String name() { 289 return name; 290 } 291 292 /** 293 * Changes the name of the method. 294 */ 295 public void name(String n) { 296 this.name = n; 297 } 298 299 /** 300 * Returns the return type. 301 */ 302 public JType type() { 303 return type; 304 } 305 306 /** 307 * Overrides the return type. 308 */ 309 public void type(JType t) { 310 this.type = t; 311 } 312 313 /** 314 * Returns all the parameter types in an array. 315 * @return 316 * If there's no parameter, an empty array will be returned. 317 */ 318 public JType[] listParamTypes() { 319 JType[] r = new JType[params.size()]; 320 for (int i = 0; i < r.length; i++) 321 r[i] = params.get(i).type(); 322 return r; 323 } 324 325 /** 326 * Returns the varags parameter type. 327 * @return 328 * If there's no vararg parameter type, null will be returned. 329 */ 330 public JType listVarParamType() { 331 if (varParam != null) 332 return varParam.type(); 333 else 334 return null; 335 } 336 337 /** 338 * Returns all the parameters in an array. 339 * @return 340 * If there's no parameter, an empty array will be returned. 341 */ 342 public JVar[] listParams() { 343 return params.toArray(new JVar[params.size()]); 344 } 345 346 /** 347 * Returns the variable parameter 348 * @return 349 * If there's no parameter, null will be returned. 350 */ 351 public JVar listVarParam() { 352 return varParam; 353 } 354 355 /** 356 * Returns true if the method has the specified signature. 357 */ 358 public boolean hasSignature(JType[] argTypes) { 359 JVar[] p = listParams(); 360 if (p.length != argTypes.length) 361 return false; 362 363 for (int i = 0; i < p.length; i++) 364 if (!p[i].type().equals(argTypes[i])) 365 return false; 366 367 return true; 368 } 369 370 /** 371 * Get the block that makes up body of this method 372 * 373 * @return Body of method 374 */ 375 public JBlock body() { 376 if (body == null) 377 body = new JBlock(); 378 return body; 379 } 380 381 /** 382 * Specify the default value for this annotation member 383 * @param value 384 * Default value for the annotation member 385 * 386 */ 387 public void declareDefaultValue(JExpression value){ 388 this.defaultValue = value; 389 } 390 391 /** 392 * Creates, if necessary, and returns the class javadoc for this 393 * JDefinedClass 394 * 395 * @return JDocComment containing javadocs for this class 396 */ 397 public JDocComment javadoc() { 398 if (jdoc == null) 399 jdoc = new JDocComment(owner()); 400 return jdoc; 401 } 402 403 public void declare(JFormatter f) { 404 if (jdoc != null) 405 f.g(jdoc); 406 407 if (annotations != null){ 408 for (JAnnotationUse a : annotations) 409 f.g(a).nl(); 410 } 411 412 f.g(mods); 413 414 // declare the generics parameters 415 super.declare(f); 416 417 if (!isConstructor()) 418 f.g(type); 419 f.id(name).p('(').i(); 420 // when parameters are printed in new lines, we want them to be indented. 421 // there's a good chance no newlines happen, too, but just in case it does. 422 boolean first = true; 423 for (JVar var : params) { 424 if (!first) 425 f.p(','); 426 if(var.isAnnotated()) 427 f.nl(); 428 f.b(var); 429 first = false; 430 } 431 if (hasVarArgs()) { 432 if (!first) 433 f.p(','); 434 f.g(varParam.type().elementType()); 435 f.p("... "); 436 f.id(varParam.name()); 437 } 438 439 f.o().p(')'); 440 if (_throws!=null && !_throws.isEmpty()) { 441 f.nl().i().p("throws").g(_throws).nl().o(); 442 } 443 444 if (defaultValue != null) { 445 f.p("default "); 446 f.g(defaultValue); 447 } 448 if (body != null) { 449 f.s(body); 450 } else if ( 451 !outer.isInterface() && !outer.isAnnotationTypeDeclaration() && !mods.isAbstract() && !mods.isNative()) { 452 // Print an empty body for non-native, non-abstract methods 453 f.s(new JBlock()); 454 } else { 455 f.p(';').nl(); 456 } 457 } 458 459 /** 460 * @return 461 * the current modifiers of this method. 462 * Always return non-null valid object. 463 */ 464 public JMods mods() { 465 return mods; 466 } 467 468 /** 469 * @deprecated use {@link #mods()} 470 */ 471 public JMods getMods() { 472 return mods; 473 } 474 475 protected JCodeModel owner() { 476 return outer.owner(); 477 } 478} 479