2
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER.
4
* Copyright 1997-2007 Sun Microsystems, Inc. All rights reserved.
6
* The contents of this file are subject to the terms of either the GNU
7
* General Public License Version 2 only ("GPL") or the Common
8
* Development and Distribution License("CDDL") (collectively, the
9
* "License"). You may not use this file except in compliance with the
10
* License. You can obtain a copy of the License at
11
* http://www.netbeans.org/cddl-gplv2.html
12
* or nbbuild/licenses/CDDL-GPL-2-CP. See the License for the
13
* specific language governing permissions and limitations under the
14
* License. When distributing the software, include this License Header
15
* Notice in each file and include the License file at
16
* nbbuild/licenses/CDDL-GPL-2-CP. Sun designates this
17
* particular file as subject to the "Classpath" exception as provided
18
* by Sun in the GPL Version 2 section of the License file that
19
* accompanied this code. If applicable, add the following below the
20
* License Header, with the fields enclosed by brackets [] replaced by
21
* your own identifying information:
22
* "Portions Copyrighted [year] [name of copyright owner]"
26
* The Original Software is NetBeans. The Initial Developer of the Original
27
* Software is Sun Microsystems, Inc. Portions Copyright 1997-2006 Sun
28
* Microsystems, Inc. All Rights Reserved.
30
* If you wish your version of this file to be governed by only the CDDL
31
* or only the GPL Version 2, indicate your decision by adding
32
* "[Contributor] elects to include this software in this distribution
33
* under the [CDDL or GPL Version 2] license." If you do not indicate a
34
* single choice of license, a recipient has the option to distribute
35
* your version of this file under either the CDDL, the GPL Version 2 or
36
* to extend the choice of license to its licensees as provided above.
37
* However, if you add GPL Version 2 code and therefore, elected the GPL
38
* Version 2 license, then the option applies only if the new code is
39
* made subject to such option by the copyright holder.
42
package org.netbeans.modules.j2ee.common.method;
44
import com.sun.source.tree.BlockTree;
45
import javax.lang.model.type.ArrayType;
46
import org.netbeans.api.java.source.CompilationController;
47
import com.sun.source.tree.ExpressionTree;
48
import com.sun.source.tree.MethodTree;
49
import com.sun.source.tree.Tree;
50
import com.sun.source.tree.TypeParameterTree;
51
import com.sun.source.tree.VariableTree;
52
import java.util.ArrayList;
53
import java.util.Collections;
54
import java.util.List;
55
import javax.lang.model.element.Element;
56
import javax.lang.model.element.ExecutableElement;
57
import javax.lang.model.element.Modifier;
58
import javax.lang.model.element.TypeElement;
59
import javax.lang.model.element.VariableElement;
60
import javax.lang.model.type.TypeKind;
61
import javax.lang.model.type.TypeMirror;
62
import org.netbeans.api.java.source.GeneratorUtilities;
63
import org.netbeans.api.java.source.TreeMaker;
64
import org.netbeans.api.java.source.WorkingCopy;
65
import org.openide.util.Parameters;
68
* Support class for {@link MethodModel} providing some factory and conversion methods.
70
* @author Martin Adamek
72
public final class MethodModelSupport {
74
private MethodModelSupport() {}
77
* Creates new instance of method model. None of the parameters can be null.
78
* This method must be called from within javac context.
80
* @param workingCopy controller from javac context
81
* @param method method for which the model is to be created
82
* @throws NullPointerException if any of the parameters is <code>null</code>.
83
* @return immutable model of method
85
public static MethodModel createMethodModel(CompilationController controller, ExecutableElement method) {
86
Parameters.notNull("controller", controller); // NOI18N
87
Parameters.notNull("method", method); // NOI18N
88
List<MethodModel.Variable> parameters = new ArrayList<MethodModel.Variable>();
89
for (VariableElement variableElement : method.getParameters()) {
90
String type = getTypeName(controller, variableElement.asType());
91
String name = variableElement.getSimpleName().toString();
92
parameters.add(MethodModel.Variable.create(type, name));
94
List<String> exceptions = new ArrayList<String>();
95
for (TypeMirror typeMirror : method.getThrownTypes()) {
96
exceptions.add(getTypeName(controller, typeMirror));
98
return MethodModel.create(
99
method.getSimpleName().toString(),
100
getTypeName(controller, method.getReturnType()),
101
//TODO: RETOUCHE get body of method
105
method.getModifiers()
110
* Creates new instance of model of class variable or method parameter
111
* This method must be called from within javac context.
113
* @param workingCopy controller from javac context
114
* @param variableElement variable or method parameter for which the model is to be created
115
* @throws NullPointerException if any of the parameters is <code>null</code>.
116
* @return immutable model of variable or method parameter
118
public static MethodModel.Variable createVariable(CompilationController controller, VariableElement variableElement) {
119
Parameters.notNull("controller", controller); //NOI18N
120
Parameters.notNull("variableElement", variableElement); //NOI18N
121
return MethodModel.Variable.create(
122
getTypeName(controller, variableElement.asType()),
123
variableElement.getSimpleName().toString(),
124
variableElement.getModifiers().contains(Modifier.FINAL)
129
* Creates {@link MethodTree} represented by methodModel in given javac context.
131
* @param workingCopy controller from javac context
132
* @param methodModel model of method
133
* @throws NullPointerException if any of the parameters is <code>null</code>.
134
* @return tree representing methodModel
136
public static MethodTree createMethodTree(WorkingCopy workingCopy, MethodModel methodModel) {
137
return createMethodTree(workingCopy, methodModel, false);
141
* Creates {@link MethodTree} represented by methodModel in given javac context.
143
* @param workingCopy controller from javac context
144
* @param methodModel model of method
145
* @param generateDefaultBody if true and body on methodModel is null or empty string, default return statement will be generated
146
* @throws NullPointerException if any of the parameters is <code>null</code>.
147
* @return tree representing methodModel
149
public static MethodTree createMethodTree(WorkingCopy workingCopy, MethodModel methodModel, boolean generateDefaultBody) {
150
Parameters.notNull("workingCopy", workingCopy); //NOI18N
151
Parameters.notNull("methodModel", methodModel); //NOI18N
152
TreeMaker treeMaker = workingCopy.getTreeMaker();
153
List<VariableTree> paramsList = new ArrayList<VariableTree>();
154
if (methodModel.getParameters() != null) {
155
for (MethodModel.Variable parameter : methodModel.getParameters()) {
156
VariableTree variableTree = treeMaker.Variable(
157
treeMaker.Modifiers(parameter.getFinalModifier() ? Collections.<Modifier>singleton(Modifier.FINAL) : Collections.<Modifier>emptySet()),
159
getTypeTree(workingCopy, parameter.getType()),
162
paramsList.add(variableTree);
165
List<ExpressionTree> throwsList = new ArrayList<ExpressionTree>();
166
for (String exceptionName : methodModel.getExceptions()) {
167
throwsList.add(createQualIdent(workingCopy, exceptionName));
170
String body = methodModel.getBody();
171
// if passed body is null, generate default return statement (if return type is not void)
172
if (generateDefaultBody && (body == null || "".equals(body.trim()))) {
173
String generatedBody = getDefaultReturnValue(workingCopy, methodModel.getReturnType());
174
body = generatedBody == null ? "" : "return " + generatedBody + ";";
177
result = treeMaker.Method(
178
treeMaker.Modifiers(methodModel.getModifiers()),
179
methodModel.getName(),
180
getTypeTree(workingCopy, methodModel.getReturnType()),
181
Collections.<TypeParameterTree>emptyList(),
188
result = treeMaker.Method(
189
treeMaker.Modifiers(methodModel.getModifiers()),
190
methodModel.getName(),
191
getTypeTree(workingCopy, methodModel.getReturnType()),
192
Collections.<TypeParameterTree>emptyList(),
199
return (MethodTree) GeneratorUtilities.get(workingCopy).importFQNs(result);
203
* Checks if signature of {@link ExecutableElement} is represented by {@link MethodModel} methodModel
204
* in given javac context.
206
* @param compilationInfo controller from javac context
207
* @param method method existing in given javac context
208
* @param methodModel model of method
209
* @throws NullPointerException if any of the parameters is <code>null</code>.
210
* @return true if method and methodModel have same signature, false otherwise
212
public static boolean isSameMethod(CompilationController controller, ExecutableElement method, MethodModel methodModel) {
213
//TODO: RETOUCHE fix this method, see #90505
214
Parameters.notNull("compilationInfo", controller); // NOI18N
215
Parameters.notNull("method", method); // NOI18N
216
Parameters.notNull("methodModel", methodModel); // NOI18N
217
if (!method.getSimpleName().contentEquals(methodModel.getName())) {
220
List<? extends VariableElement> methodParams = method.getParameters();
221
if (methodParams.size() != methodModel.getParameters().size()) {
224
for (int i = 0; i < methodParams.size(); i++) {
225
VariableElement variableElement = methodParams.get(i);
226
String variableElementType = getTypeName(controller, variableElement.asType());
227
MethodModel.Variable variable = methodModel.getParameters().get(i);
228
if (!variableElementType.equals(variable.getType())) {
236
* Generates default value for provided type
238
* @param workingCopy workingCopy
239
* @param typeName fully-qualified type name or primitive type name or "void"
240
* @return values according to JLS '4.5.5 Initial Values of Variables'
241
* with exception for "char" where it returns "c"
243
public static String getDefaultReturnValue(WorkingCopy workingCopy, String typeName) {
244
if ("boolean".equals(typeName)) { // NOI18N
245
return "false"; // NOI18N
246
} else if ("byte".equals(typeName)) { // NOI18N
247
return "0"; // NOI18N
248
} else if ("short".equals(typeName)) { // NOI18N
249
return "0"; // NOI18N
250
} else if ("int".equals(typeName)) { // NOI18N
251
return "0"; // NOI18N
252
} else if ("long".equals(typeName)) { // NOI18N
253
return "0L"; // NOI18N
254
} else if ("char".equals(typeName)) { // NOI18N
255
// should be '\u0000' which is null character, but we cannot return that
256
return "'c'"; // NOI18N
257
} else if ("float".equals(typeName)) { // NOI18N
258
return "0.0f"; // NOI18N
259
} else if ("double".equals(typeName)) { // NOI18N
260
return "0.0d"; // NOI18N
261
} else if ("void".equals(typeName)) { // NOI18N
264
return "null"; // NOI18N
268
//TODO: RETOUCHE move/reuse to GenerationUtil, this one has also void type
269
private static Tree getTypeTree(WorkingCopy workingCopy, String typeName) {
270
TreeMaker make = workingCopy.getTreeMaker();
271
TypeKind primitiveTypeKind = null;
272
if ("boolean".equals(typeName)) { // NOI18N
273
primitiveTypeKind = TypeKind.BOOLEAN;
274
} else if ("byte".equals(typeName)) { // NOI18N
275
primitiveTypeKind = TypeKind.BYTE;
276
} else if ("short".equals(typeName)) { // NOI18N
277
primitiveTypeKind = TypeKind.SHORT;
278
} else if ("int".equals(typeName)) { // NOI18N
279
primitiveTypeKind = TypeKind.INT;
280
} else if ("long".equals(typeName)) { // NOI18N
281
primitiveTypeKind = TypeKind.LONG;
282
} else if ("char".equals(typeName)) { // NOI18N
283
primitiveTypeKind = TypeKind.CHAR;
284
} else if ("float".equals(typeName)) { // NOI18N
285
primitiveTypeKind = TypeKind.FLOAT;
286
} else if ("double".equals(typeName)) { // NOI18N
287
primitiveTypeKind = TypeKind.DOUBLE;
288
} else if ("void".equals(typeName)) { // NOI18N
289
primitiveTypeKind = TypeKind.VOID;
291
if (primitiveTypeKind != null) {
292
return make.PrimitiveType(primitiveTypeKind);
294
return createQualIdent(workingCopy, typeName);
298
//TODO: RETOUCHE move/reuse to GenerationUtil
299
private static ExpressionTree createQualIdent(WorkingCopy workingCopy, String typeName) {
300
TypeElement typeElement = workingCopy.getElements().getTypeElement(typeName);
301
if (typeElement == null) {
302
typeElement = workingCopy.getElements().getTypeElement("java.lang." + typeName);
303
if (typeElement == null) {
304
return workingCopy.getTreeMaker().Identifier(typeName);
307
return workingCopy.getTreeMaker().QualIdent(typeElement);
310
//TODO: RETOUCHE move/reuse in SourceUtil, or best - get from java/source!
311
// package private only for unit test
313
static String getTypeName(CompilationController controller, TypeMirror typeMirror) {
314
TypeKind typeKind = typeMirror.getKind();
316
case BOOLEAN : return "boolean"; // NOI18N
317
case BYTE : return "byte"; // NOI18N
318
case CHAR : return "char"; // NOI18N
319
case DOUBLE : return "double"; // NOI18N
320
case FLOAT : return "float"; // NOI18N
321
case INT : return "int"; // NOI18N
322
case LONG : return "long"; // NOI18N
323
case SHORT : return "short"; // NOI18N
324
case VOID : return "void"; // NOI18N
326
Element element = controller.getTypes().asElement(typeMirror);
327
return ((TypeElement) element).getQualifiedName().toString();
329
ArrayType arrayType = (ArrayType) typeMirror;
330
TypeMirror componentType = arrayType.getComponentType();
331
return getTypeName(controller, componentType) + "[]";