1 /*******************************************************************************
2  * Copyright (c) 2020 Fabrice TIERCELIN and others.
3  *
4  * This program and the accompanying materials
5  * are made available under the terms of the Eclipse Public License 2.0
6  * which accompanies this distribution, and is available at
7  * https://www.eclipse.org/legal/epl-2.0/
8  *
9  * SPDX-License-Identifier: EPL-2.0
10  *
11  * Contributors:
12  *     Fabrice TIERCELIN - initial API and implementation
13  *******************************************************************************/
14 package org.eclipse.jdt.internal.ui.fix;
15 
16 import java.util.ArrayList;
17 import java.util.Collections;
18 import java.util.List;
19 import java.util.Map;
20 
21 import org.eclipse.core.runtime.CoreException;
22 
23 import org.eclipse.jdt.core.ICompilationUnit;
24 import org.eclipse.jdt.core.dom.AST;
25 import org.eclipse.jdt.core.dom.ASTNode;
26 import org.eclipse.jdt.core.dom.ASTVisitor;
27 import org.eclipse.jdt.core.dom.Block;
28 import org.eclipse.jdt.core.dom.ClassInstanceCreation;
29 import org.eclipse.jdt.core.dom.CompilationUnit;
30 import org.eclipse.jdt.core.dom.CreationReference;
31 import org.eclipse.jdt.core.dom.Expression;
32 import org.eclipse.jdt.core.dom.ExpressionMethodReference;
33 import org.eclipse.jdt.core.dom.FieldAccess;
34 import org.eclipse.jdt.core.dom.IMethodBinding;
35 import org.eclipse.jdt.core.dom.ITypeBinding;
36 import org.eclipse.jdt.core.dom.LambdaExpression;
37 import org.eclipse.jdt.core.dom.MethodInvocation;
38 import org.eclipse.jdt.core.dom.Modifier;
39 import org.eclipse.jdt.core.dom.NumberLiteral;
40 import org.eclipse.jdt.core.dom.ReturnStatement;
41 import org.eclipse.jdt.core.dom.SimpleName;
42 import org.eclipse.jdt.core.dom.Statement;
43 import org.eclipse.jdt.core.dom.StringLiteral;
44 import org.eclipse.jdt.core.dom.SuperFieldAccess;
45 import org.eclipse.jdt.core.dom.SuperMethodInvocation;
46 import org.eclipse.jdt.core.dom.SuperMethodReference;
47 import org.eclipse.jdt.core.dom.ThisExpression;
48 import org.eclipse.jdt.core.dom.Type;
49 import org.eclipse.jdt.core.dom.TypeMethodReference;
50 import org.eclipse.jdt.core.dom.VariableDeclarationFragment;
51 import org.eclipse.jdt.core.dom.rewrite.ASTRewrite;
52 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite;
53 import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext;
54 
55 import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext;
56 import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory;
57 import org.eclipse.jdt.internal.corext.dom.ASTNodes;
58 import org.eclipse.jdt.internal.corext.dom.Bindings;
59 import org.eclipse.jdt.internal.corext.fix.CleanUpConstants;
60 import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix;
61 import org.eclipse.jdt.internal.corext.fix.CompilationUnitRewriteOperationsFix.CompilationUnitRewriteOperation;
62 import org.eclipse.jdt.internal.corext.fix.LinkedProposalModel;
63 import org.eclipse.jdt.internal.corext.refactoring.structure.CompilationUnitRewrite;
64 import org.eclipse.jdt.internal.corext.util.JavaModelUtil;
65 
66 import org.eclipse.jdt.ui.cleanup.CleanUpRequirements;
67 import org.eclipse.jdt.ui.cleanup.ICleanUpFix;
68 import org.eclipse.jdt.ui.text.java.IProblemLocation;
69 
70 /**
71  * A fix that simplifies the lambda expression and the method reference syntax:
72  * <ul>
73  * <li>Parenthesis are not needed for a single untyped parameter,</li>
74  * <li>Return statement is not needed for a single expression,</li>
75  * <li>Brackets are not needed for a single statement,</li>
76  * <li>A lambda expression can be replaced by a creation or a method reference in some cases.</li>
77  * </ul>
78  */
79 public class LambdaExpressionAndMethodRefCleanUp extends AbstractMultiFix {
LambdaExpressionAndMethodRefCleanUp()80 	public LambdaExpressionAndMethodRefCleanUp() {
81 		this(Collections.emptyMap());
82 	}
83 
LambdaExpressionAndMethodRefCleanUp(Map<String, String> options)84 	public LambdaExpressionAndMethodRefCleanUp(Map<String, String> options) {
85 		super(options);
86 	}
87 
88 	@Override
getRequirements()89 	public CleanUpRequirements getRequirements() {
90 		boolean requireAST= isEnabled(CleanUpConstants.SIMPLIFY_LAMBDA_EXPRESSION_AND_METHOD_REF);
91 		Map<String, String> requiredOptions= null;
92 		return new CleanUpRequirements(requireAST, false, false, requiredOptions);
93 	}
94 
95 	@Override
getStepDescriptions()96 	public String[] getStepDescriptions() {
97 		if (isEnabled(CleanUpConstants.SIMPLIFY_LAMBDA_EXPRESSION_AND_METHOD_REF)) {
98 			return new String[] { MultiFixMessages.LambdaExpressionAndMethodRefCleanUp_description };
99 		}
100 		return new String[0];
101 	}
102 
103 	@Override
getPreview()104 	public String getPreview() {
105 		StringBuilder bld= new StringBuilder();
106 
107 		if (isEnabled(CleanUpConstants.SIMPLIFY_LAMBDA_EXPRESSION_AND_METHOD_REF)) {
108 			bld.append("someString -> someString.trim().toLowerCase();\n"); //$NON-NLS-1$
109 			bld.append("someString -> someString.trim().toLowerCase();\n"); //$NON-NLS-1$
110 			bld.append("someString -> (someString.trim().toLowerCase() + \"bar\");\n"); //$NON-NLS-1$
111 			bld.append("ArrayList::new;\n"); //$NON-NLS-1$
112 			bld.append("Date::getTime;\n"); //$NON-NLS-1$
113 		} else {
114 			bld.append("(someString) -> someString.trim().toLowerCase();\n"); //$NON-NLS-1$
115 			bld.append("someString -> {return someString.trim().toLowerCase();};\n"); //$NON-NLS-1$
116 			bld.append("someString -> {return someString.trim().toLowerCase() + \"bar\";};\n"); //$NON-NLS-1$
117 			bld.append("() -> new ArrayList<>();\n"); //$NON-NLS-1$
118 			bld.append("date -> date.getTime();\n"); //$NON-NLS-1$
119 		}
120 
121 		return bld.toString();
122 	}
123 
124 	@Override
createFix(CompilationUnit unit)125 	protected ICleanUpFix createFix(CompilationUnit unit) throws CoreException {
126 		if (!isEnabled(CleanUpConstants.SIMPLIFY_LAMBDA_EXPRESSION_AND_METHOD_REF) || !JavaModelUtil.is18OrHigher(unit.getJavaElement().getJavaProject())) {
127 			return null;
128 		}
129 
130 		final List<CompilationUnitRewriteOperation> rewriteOperations= new ArrayList<>();
131 
132 		unit.accept(new ASTVisitor() {
133 			@Override
134 			public boolean visit(final LambdaExpression node) {
135 				if (node.hasParentheses() && node.parameters().size() == 1
136 						&& node.parameters().get(0) instanceof VariableDeclarationFragment) {
137 					rewriteOperations.add(new RemoveParamParenthesesOperation(node));
138 					return false;
139 				} else if (node.getBody() instanceof Block) {
140 					List<Statement> statements= ((Block) node.getBody()).statements();
141 
142 					if (statements.size() == 1 && statements.get(0) instanceof ReturnStatement) {
143 						rewriteOperations.add(new RemoveReturnAndBracketsOperation(node, statements));
144 						return false;
145 					}
146 				} else if (node.getBody() instanceof ClassInstanceCreation) {
147 					ClassInstanceCreation ci= (ClassInstanceCreation) node.getBody();
148 
149 					List<Expression> arguments= ci.arguments();
150 					if (node.parameters().size() == arguments.size()
151 							&& areSameIdentifiers(node, arguments)
152 							&& ci.getAnonymousClassDeclaration() == null) {
153 						rewriteOperations.add(new ReplaceByCreationReferenceOperation(node, ci));
154 						return false;
155 					}
156 				} else if (node.getBody() instanceof SuperMethodInvocation) {
157 					SuperMethodInvocation smi= (SuperMethodInvocation) node.getBody();
158 					List<Expression> arguments= smi.arguments();
159 
160 					if (node.parameters().size() == arguments.size() && areSameIdentifiers(node, arguments)) {
161 						rewriteOperations.add(new ReplaceBySuperMethodReferenceOperation(node, smi));
162 						return false;
163 					}
164 				} else if (node.getBody() instanceof MethodInvocation) {
165 					MethodInvocation methodInvocation= (MethodInvocation) node.getBody();
166 					Expression calledExpression= methodInvocation.getExpression();
167 					List<Expression> arguments= methodInvocation.arguments();
168 
169 					if (node.parameters().size() == arguments.size()) {
170 						if (!areSameIdentifiers(node, arguments)) {
171 							return true;
172 						}
173 
174 						IMethodBinding methodBinding= methodInvocation.resolveMethodBinding();
175 
176 						if (Boolean.TRUE.equals(ASTNodes.isStatic(methodInvocation))) {
177 							if (methodBinding == null || methodBinding.getDeclaringClass() == null) {
178 								return true;
179 							}
180 
181 							ITypeBinding calledType= methodBinding.getDeclaringClass();
182 
183 							if (!arguments.isEmpty()) {
184 								String[] remainingParams= new String[arguments.size() - 1];
185 
186 								for (int i= 0; i < arguments.size() - 1; i++) {
187 									ITypeBinding resolveTypeBinding= arguments.get(i + 1).resolveTypeBinding();
188 
189 									if (resolveTypeBinding == null) {
190 										return true;
191 									}
192 
193 									remainingParams[i]= resolveTypeBinding.getQualifiedName();
194 								}
195 
196 								for (IMethodBinding declaredMethodBinding : calledType.getDeclaredMethods()) {
197 									if ((declaredMethodBinding.getModifiers() & Modifier.STATIC) == 0 && ASTNodes.usesGivenSignature(declaredMethodBinding,
198 											calledType.getQualifiedName(), methodInvocation.getName().getIdentifier(), remainingParams)) {
199 										return true;
200 									}
201 								}
202 							}
203 
204 							rewriteOperations.add(new ReplaceByTypeReferenceOperation(node, methodInvocation, calledType));
205 							return false;
206 						}
207 
208 						if (calledExpression == null) {
209 							if (methodBinding != null) {
210 								ITypeBinding calledType= methodBinding.getDeclaringClass();
211 								ITypeBinding enclosingType= Bindings.getBindingOfParentType(node);
212 
213 								if (calledType != null && Bindings.isSuperType(calledType, enclosingType)) {
214 									rewriteOperations.add(new ReplaceByMethodReferenceOperation(node, methodInvocation));
215 									return false;
216 								}
217 							}
218 						} else if (calledExpression instanceof StringLiteral || calledExpression instanceof NumberLiteral
219 								|| calledExpression instanceof ThisExpression) {
220 							rewriteOperations.add(new ReplaceByMethodReferenceOperation(node, methodInvocation));
221 							return false;
222 						} else if (calledExpression instanceof FieldAccess) {
223 							FieldAccess fieldAccess= (FieldAccess) calledExpression;
224 
225 							if (fieldAccess.resolveFieldBinding() != null && fieldAccess.resolveFieldBinding().isEffectivelyFinal()) {
226 								rewriteOperations.add(new ReplaceByMethodReferenceOperation(node, methodInvocation));
227 								return false;
228 							}
229 						} else if (calledExpression instanceof SuperFieldAccess) {
230 							SuperFieldAccess fieldAccess= (SuperFieldAccess) calledExpression;
231 
232 							if (fieldAccess.resolveFieldBinding() != null && fieldAccess.resolveFieldBinding().isEffectivelyFinal()) {
233 								rewriteOperations.add(new ReplaceByMethodReferenceOperation(node, methodInvocation));
234 								return false;
235 							}
236 						}
237 					} else if (calledExpression instanceof SimpleName && node.parameters().size() == arguments.size() + 1) {
238 						SimpleName calledObject= (SimpleName) calledExpression;
239 
240 						if (isSameIdentifier(node, 0, calledObject)) {
241 							for (int i= 0; i < arguments.size(); i++) {
242 								ASTNode expression= ASTNodes.getUnparenthesedExpression(arguments.get(i));
243 
244 								if (!(expression instanceof SimpleName) || !isSameIdentifier(node, i + 1, (SimpleName) expression)) {
245 									return true;
246 								}
247 							}
248 
249 							ITypeBinding clazz= null;
250 							if (calledExpression.resolveTypeBinding() != null) {
251 								clazz= calledExpression.resolveTypeBinding();
252 							} else if (methodInvocation.resolveMethodBinding() != null && methodInvocation.resolveMethodBinding().getDeclaringClass() != null) {
253 								clazz= methodInvocation.resolveMethodBinding().getDeclaringClass();
254 							} else {
255 								return true;
256 							}
257 
258 							String[] cumulativeParams= new String[arguments.size() + 1];
259 							cumulativeParams[0]= clazz.getQualifiedName();
260 
261 							for (int i= 0; i < arguments.size(); i++) {
262 								ITypeBinding resolveTypeBinding= arguments.get(i).resolveTypeBinding();
263 
264 								if (resolveTypeBinding == null) {
265 									return true;
266 								}
267 
268 								cumulativeParams[i + 1]= resolveTypeBinding.getQualifiedName();
269 							}
270 
271 							for (IMethodBinding declaredMethodBinding : clazz.getDeclaredMethods()) {
272 								if ((declaredMethodBinding.getModifiers() & Modifier.STATIC) > 0 && ASTNodes.usesGivenSignature(declaredMethodBinding,
273 										clazz.getQualifiedName(), methodInvocation.getName().getIdentifier(), cumulativeParams)) {
274 									return true;
275 								}
276 							}
277 
278 							rewriteOperations.add(new ReplaceByTypeReferenceOperation(node, methodInvocation, clazz));
279 							return false;
280 						}
281 					}
282 				}
283 
284 				return true;
285 			}
286 
287 			/**
288 			 * In order to make parameters implicit, those ones should be the same in the same
289 			 * order.
290 			 *
291 			 * @param node the lambda expression
292 			 * @param arguments The arguments in the expression
293 			 * @return true if the parameters are obvious
294 			 */
295 			private boolean areSameIdentifiers(LambdaExpression node, List<Expression> arguments) {
296 				for (int i= 0; i < node.parameters().size(); i++) {
297 					Expression expression= ASTNodes.getUnparenthesedExpression(arguments.get(i));
298 
299 					if (!(expression instanceof SimpleName) || !isSameIdentifier(node, i, (SimpleName) expression)) {
300 						return false;
301 					}
302 				}
303 
304 				return true;
305 			}
306 
307 			private boolean isSameIdentifier(final LambdaExpression node, final int i, final SimpleName argument) {
308 				Object param0= node.parameters().get(i);
309 
310 				if (param0 instanceof VariableDeclarationFragment) {
311 					VariableDeclarationFragment vdf= (VariableDeclarationFragment) param0;
312 					return vdf.getName().getIdentifier().equals(argument.getIdentifier());
313 				}
314 
315 				return false;
316 			}
317 		});
318 
319 		if (rewriteOperations.isEmpty()) {
320 			return null;
321 		}
322 
323 		return new CompilationUnitRewriteOperationsFix(MultiFixMessages.LambdaExpressionAndMethodRefCleanUp_description, unit,
324 				rewriteOperations.toArray(new CompilationUnitRewriteOperation[rewriteOperations.size()]));
325 	}
326 
327 	@Override
canFix(ICompilationUnit compilationUnit, IProblemLocation problem)328 	public boolean canFix(ICompilationUnit compilationUnit, IProblemLocation problem) {
329 		return false;
330 	}
331 
332 	@Override
createFix(CompilationUnit unit, IProblemLocation[] problems)333 	protected ICleanUpFix createFix(CompilationUnit unit, IProblemLocation[] problems) throws CoreException {
334 		return null;
335 	}
336 
337 	private static class RemoveParamParenthesesOperation extends CompilationUnitRewriteOperation {
338 		private final LambdaExpression node;
339 
RemoveParamParenthesesOperation(final LambdaExpression node)340 		public RemoveParamParenthesesOperation(final LambdaExpression node) {
341 			this.node= node;
342 		}
343 
344 		@Override
rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel)345 		public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
346 			ASTRewrite rewrite= cuRewrite.getASTRewrite();
347 			AST ast= cuRewrite.getRoot().getAST();
348 
349 			LambdaExpression copyOfLambdaExpression= ast.newLambdaExpression();
350 			ASTNode copyOfParameter= rewrite.createCopyTarget((ASTNode) node.parameters().get(0));
351 			copyOfLambdaExpression.parameters().add(copyOfParameter);
352 			copyOfLambdaExpression.setBody(rewrite.createCopyTarget(node.getBody()));
353 			copyOfLambdaExpression.setParentheses(false);
354 			rewrite.replace(node, copyOfLambdaExpression, null);
355 		}
356 	}
357 
358 	private static class RemoveReturnAndBracketsOperation extends CompilationUnitRewriteOperation {
359 		private final LambdaExpression node;
360 
361 		private final List<Statement> statements;
362 
RemoveReturnAndBracketsOperation(final LambdaExpression node, final List<Statement> statements)363 		public RemoveReturnAndBracketsOperation(final LambdaExpression node, final List<Statement> statements) {
364 			this.node= node;
365 			this.statements= statements;
366 		}
367 
368 		@Override
rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel)369 		public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
370 			ASTRewrite rewrite= cuRewrite.getASTRewrite();
371 			AST ast= cuRewrite.getRoot().getAST();
372 
373 			ReturnStatement returnStatement= (ReturnStatement) statements.get(0);
374 			Expression copyOfExpression= (Expression) rewrite.createCopyTarget(returnStatement.getExpression());
375 			rewrite.replace(node.getBody(), ASTNodeFactory.parenthesizeIfNeeded(ast, copyOfExpression), null);
376 		}
377 	}
378 
379 	private static class ReplaceByCreationReferenceOperation extends CompilationUnitRewriteOperation {
380 		private final LambdaExpression node;
381 
382 		private final ClassInstanceCreation classInstanceCreation;
383 
ReplaceByCreationReferenceOperation(final LambdaExpression node, final ClassInstanceCreation classInstanceCreation)384 		public ReplaceByCreationReferenceOperation(final LambdaExpression node, final ClassInstanceCreation classInstanceCreation) {
385 			this.node= node;
386 			this.classInstanceCreation= classInstanceCreation;
387 		}
388 
389 		@Override
rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel)390 		public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
391 			ASTRewrite rewrite= cuRewrite.getASTRewrite();
392 			AST ast= cuRewrite.getRoot().getAST();
393 
394 			CreationReference creationRef= ast.newCreationReference();
395 			creationRef.setType(copyType(cuRewrite, ast, classInstanceCreation, classInstanceCreation.resolveTypeBinding()));
396 			rewrite.replace(node, creationRef, null);
397 		}
398 	}
399 
400 	private static class ReplaceBySuperMethodReferenceOperation extends CompilationUnitRewriteOperation {
401 		private final LambdaExpression node;
402 
403 		private final SuperMethodInvocation superMethodInvocation;
404 
ReplaceBySuperMethodReferenceOperation(final LambdaExpression node, final SuperMethodInvocation superMethodInvocation)405 		public ReplaceBySuperMethodReferenceOperation(final LambdaExpression node, final SuperMethodInvocation superMethodInvocation) {
406 			this.node= node;
407 			this.superMethodInvocation= superMethodInvocation;
408 		}
409 
410 		@Override
rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel)411 		public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
412 			ASTRewrite rewrite= cuRewrite.getASTRewrite();
413 			AST ast= cuRewrite.getRoot().getAST();
414 
415 			SuperMethodReference creationRef= ast.newSuperMethodReference();
416 			creationRef.setName((SimpleName) rewrite.createCopyTarget(superMethodInvocation.getName()));
417 			rewrite.replace(node, creationRef, null);
418 		}
419 	}
420 
421 	private static class ReplaceByTypeReferenceOperation extends CompilationUnitRewriteOperation {
422 		private final LambdaExpression node;
423 		private final MethodInvocation methodInvocation;
424 
425 		private final ITypeBinding type;
426 
ReplaceByTypeReferenceOperation(LambdaExpression node, MethodInvocation methodInvocation, ITypeBinding type)427 		public ReplaceByTypeReferenceOperation(LambdaExpression node, MethodInvocation methodInvocation, ITypeBinding type) {
428 			this.node= node;
429 			this.methodInvocation= methodInvocation;
430 			this.type= type;
431 		}
432 
433 		@Override
rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel)434 		public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
435 			ASTRewrite rewrite= cuRewrite.getASTRewrite();
436 			AST ast= cuRewrite.getRoot().getAST();
437 
438 			TypeMethodReference typeMethodRef= ast.newTypeMethodReference();
439 
440 			typeMethodRef.setType(copyType(cuRewrite, ast, methodInvocation, type));
441 			typeMethodRef.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
442 			rewrite.replace(node, typeMethodRef, null);
443 		}
444 	}
445 
446 	private static class ReplaceByMethodReferenceOperation extends CompilationUnitRewriteOperation {
447 		private final LambdaExpression node;
448 
449 		private final MethodInvocation methodInvocation;
450 
ReplaceByMethodReferenceOperation(LambdaExpression node, MethodInvocation methodInvocation)451 		public ReplaceByMethodReferenceOperation(LambdaExpression node, MethodInvocation methodInvocation) {
452 			this.node= node;
453 			this.methodInvocation= methodInvocation;
454 		}
455 
456 		@Override
rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel)457 		public void rewriteAST(final CompilationUnitRewrite cuRewrite, final LinkedProposalModel linkedModel) throws CoreException {
458 			ASTRewrite rewrite= cuRewrite.getASTRewrite();
459 			AST ast= cuRewrite.getRoot().getAST();
460 			ExpressionMethodReference typeMethodRef= ast.newExpressionMethodReference();
461 
462 			if (methodInvocation.getExpression() != null) {
463 				typeMethodRef.setExpression((Expression) rewrite.createCopyTarget(methodInvocation.getExpression()));
464 			} else {
465 				typeMethodRef.setExpression(ast.newThisExpression());
466 			}
467 
468 			typeMethodRef.setName((SimpleName) rewrite.createCopyTarget(methodInvocation.getName()));
469 			rewrite.replace(node, typeMethodRef, null);
470 		}
471 	}
472 
copyType(final CompilationUnitRewrite cuRewrite, final AST ast, final ASTNode node, final ITypeBinding typeBinding)473 	private static Type copyType(final CompilationUnitRewrite cuRewrite, final AST ast, final ASTNode node, final ITypeBinding typeBinding) {
474 		ImportRewrite importRewrite= cuRewrite.getImportRewrite();
475 		ImportRewriteContext importContext= new ContextSensitiveImportRewriteContext(node, importRewrite);
476 		ITypeBinding modifiedType;
477 
478 		if (typeBinding.getTypeParameters().length == 0) {
479 			modifiedType= typeBinding.getErasure();
480 		} else {
481 			modifiedType= typeBinding;
482 		}
483 
484 		return ASTNodeFactory.newCreationType(ast, modifiedType, importRewrite, importContext);
485 	}
486 }