]>
Commit | Line | Data |
---|---|---|
1b2798f6 EK |
1 | /******************************************************************************* |
2 | * Copyright (c) 2000, 2011 IBM Corporation and others. | |
3 | * All rights reserved. This program and the accompanying materials | |
4 | * are made available under the terms of the Eclipse Public License v1.0 | |
5 | * which accompanies this distribution, and is available at | |
6 | * http://www.eclipse.org/legal/epl-v10.html | |
7 | * | |
8 | * Contributors: | |
9 | * IBM Corporation - initial API and implementation | |
10 | *******************************************************************************/ | |
11 | ||
12 | package org.eclipse.jdt.internal.ui.text.correction.proposals; | |
13 | ||
14 | import java.util.List; | |
15 | ||
16 | import org.eclipse.swt.graphics.Image; | |
17 | ||
18 | import org.eclipse.core.runtime.CoreException; | |
19 | ||
20 | import org.eclipse.jdt.core.ICompilationUnit; | |
21 | import org.eclipse.jdt.core.dom.AST; | |
22 | import org.eclipse.jdt.core.dom.ASTNode; | |
23 | import org.eclipse.jdt.core.dom.Block; | |
24 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
25 | import org.eclipse.jdt.core.dom.Expression; | |
26 | import org.eclipse.jdt.core.dom.IMethodBinding; | |
27 | import org.eclipse.jdt.core.dom.ITypeBinding; | |
28 | import org.eclipse.jdt.core.dom.Javadoc; | |
29 | import org.eclipse.jdt.core.dom.MethodDeclaration; | |
30 | import org.eclipse.jdt.core.dom.Modifier; | |
31 | import org.eclipse.jdt.core.dom.Name; | |
32 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
33 | import org.eclipse.jdt.core.dom.SuperConstructorInvocation; | |
34 | import org.eclipse.jdt.core.dom.TypeDeclaration; | |
35 | import org.eclipse.jdt.core.dom.rewrite.ASTRewrite; | |
36 | import org.eclipse.jdt.core.dom.rewrite.ImportRewrite.ImportRewriteContext; | |
37 | ||
38 | import org.eclipse.jdt.internal.corext.codemanipulation.CodeGenerationSettings; | |
39 | import org.eclipse.jdt.internal.corext.codemanipulation.ContextSensitiveImportRewriteContext; | |
40 | import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; | |
41 | import org.eclipse.jdt.internal.corext.dom.ASTNodeFactory; | |
42 | import org.eclipse.jdt.internal.corext.dom.ASTNodes; | |
43 | import org.eclipse.jdt.internal.corext.dom.Bindings; | |
44 | import org.eclipse.jdt.internal.corext.util.Messages; | |
45 | ||
46 | import org.eclipse.jdt.ui.CodeGeneration; | |
47 | import org.eclipse.jdt.ui.JavaElementImageDescriptor; | |
48 | ||
49 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
50 | import org.eclipse.jdt.internal.ui.JavaPluginImages; | |
51 | import org.eclipse.jdt.internal.ui.preferences.JavaPreferencesSettings; | |
52 | import org.eclipse.jdt.internal.ui.text.correction.CorrectionMessages; | |
53 | import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels; | |
54 | import org.eclipse.jdt.internal.ui.viewsupport.JavaElementImageProvider; | |
55 | ||
56 | public class ConstructorFromSuperclassProposal extends LinkedCorrectionProposal { | |
57 | ||
58 | private TypeDeclaration fTypeNode; | |
59 | private IMethodBinding fSuperConstructor; | |
60 | ||
61 | public ConstructorFromSuperclassProposal(ICompilationUnit cu, TypeDeclaration typeNode, IMethodBinding superConstructor, int relevance) { | |
62 | super("", cu, null, relevance, null); //$NON-NLS-1$ | |
63 | fTypeNode= typeNode; | |
64 | fSuperConstructor= superConstructor; | |
65 | } | |
66 | ||
67 | /* (non-Javadoc) | |
68 | * @see org.eclipse.jface.text.contentassist.ICompletionProposal#getImage() | |
69 | */ | |
70 | @Override | |
71 | public Image getImage() { | |
72 | return JavaPlugin.getImageDescriptorRegistry().get( | |
73 | new JavaElementImageDescriptor(JavaPluginImages.DESC_MISC_PUBLIC, JavaElementImageDescriptor.CONSTRUCTOR, JavaElementImageProvider.SMALL_SIZE) | |
74 | ); | |
75 | } | |
76 | ||
77 | /* (non-Javadoc) | |
78 | * @see org.eclipse.jdt.internal.ui.text.correction.proposals.ChangeCorrectionProposal#getName() | |
79 | */ | |
80 | @Override | |
81 | public String getName() { | |
82 | StringBuffer buf= new StringBuffer(); | |
83 | buf.append(fTypeNode.getName().getIdentifier()); | |
84 | buf.append('('); | |
85 | if (fSuperConstructor != null) { | |
86 | ITypeBinding[] paramTypes= fSuperConstructor.getParameterTypes(); | |
87 | for (int i= 0; i < paramTypes.length; i++) { | |
88 | if (i > 0) { | |
89 | buf.append(','); | |
90 | } | |
91 | buf.append(paramTypes[i].getName()); | |
92 | } | |
93 | } | |
94 | buf.append(')'); | |
95 | return Messages.format(CorrectionMessages.ConstructorFromSuperclassProposal_description, BasicElementLabels.getJavaElementName(buf.toString())); | |
96 | } | |
97 | ||
98 | /* (non-Javadoc) | |
99 | * @see org.eclipse.jdt.internal.ui.text.correction.ASTRewriteCorrectionProposal#getRewrite() | |
100 | */ | |
101 | @Override | |
102 | protected ASTRewrite getRewrite() throws CoreException { | |
103 | AST ast= fTypeNode.getAST(); | |
104 | ||
105 | ASTRewrite rewrite= ASTRewrite.create(ast); | |
106 | ||
107 | createImportRewrite((CompilationUnit) fTypeNode.getRoot()); | |
108 | ||
109 | CodeGenerationSettings settings= JavaPreferencesSettings.getCodeGenerationSettings(getCompilationUnit().getJavaProject()); | |
110 | if (!settings.createComments) { | |
111 | settings= null; | |
112 | } | |
113 | ImportRewriteContext importRewriteContext= new ContextSensitiveImportRewriteContext(fTypeNode, getImportRewrite()); | |
114 | ||
115 | MethodDeclaration newMethodDecl= createNewMethodDeclaration(ast, fSuperConstructor, rewrite, importRewriteContext, settings); | |
116 | rewrite.getListRewrite(fTypeNode, TypeDeclaration.BODY_DECLARATIONS_PROPERTY).insertFirst(newMethodDecl, null); | |
117 | ||
118 | addLinkedRanges(rewrite, newMethodDecl); | |
119 | ||
120 | return rewrite; | |
121 | } | |
122 | ||
123 | private void addLinkedRanges(ASTRewrite rewrite, MethodDeclaration newStub) { | |
124 | List<SingleVariableDeclaration> parameters= newStub.parameters(); | |
125 | for (int i= 0; i < parameters.size(); i++) { | |
126 | SingleVariableDeclaration curr= parameters.get(i); | |
127 | String name= curr.getName().getIdentifier(); | |
128 | addLinkedPosition(rewrite.track(curr.getType()), false, "arg_type_" + name); //$NON-NLS-1$ | |
129 | addLinkedPosition(rewrite.track(curr.getName()), false, "arg_name_" + name); //$NON-NLS-1$ | |
130 | } | |
131 | } | |
132 | ||
133 | private MethodDeclaration createNewMethodDeclaration(AST ast, IMethodBinding binding, ASTRewrite rewrite, ImportRewriteContext importRewriteContext, CodeGenerationSettings commentSettings) throws CoreException { | |
134 | String name= fTypeNode.getName().getIdentifier(); | |
135 | MethodDeclaration decl= ast.newMethodDeclaration(); | |
136 | decl.setConstructor(true); | |
137 | decl.setName(ast.newSimpleName(name)); | |
138 | Block body= ast.newBlock(); | |
139 | decl.setBody(body); | |
140 | ||
141 | SuperConstructorInvocation invocation= null; | |
142 | ||
143 | List<SingleVariableDeclaration> parameters= decl.parameters(); | |
144 | String[] paramNames= getArgumentNames(binding); | |
145 | ||
146 | ITypeBinding enclosingInstance= getEnclosingInstance(); | |
147 | if (enclosingInstance != null) { | |
148 | invocation= addEnclosingInstanceAccess(rewrite, importRewriteContext, parameters, paramNames, enclosingInstance); | |
149 | } | |
150 | ||
151 | if (binding == null) { | |
152 | decl.modifiers().add(ast.newModifier(Modifier.ModifierKeyword.PUBLIC_KEYWORD)); | |
153 | } else { | |
154 | decl.modifiers().addAll(ASTNodeFactory.newModifiers(ast, binding.getModifiers())); | |
155 | ||
156 | ITypeBinding[] params= binding.getParameterTypes(); | |
157 | for (int i= 0; i < params.length; i++) { | |
158 | SingleVariableDeclaration var= ast.newSingleVariableDeclaration(); | |
159 | var.setType(getImportRewrite().addImport(params[i], ast, importRewriteContext)); | |
160 | var.setName(ast.newSimpleName(paramNames[i])); | |
161 | parameters.add(var); | |
162 | } | |
163 | ||
164 | List<Name> thrownExceptions= decl.thrownExceptions(); | |
165 | ITypeBinding[] excTypes= binding.getExceptionTypes(); | |
166 | for (int i= 0; i < excTypes.length; i++) { | |
167 | String excTypeName= getImportRewrite().addImport(excTypes[i], importRewriteContext); | |
168 | thrownExceptions.add(ASTNodeFactory.newName(ast, excTypeName)); | |
169 | } | |
170 | ||
171 | if (invocation == null) { | |
172 | invocation= ast.newSuperConstructorInvocation(); | |
173 | } | |
174 | ||
175 | List<Expression> arguments= invocation.arguments(); | |
176 | for (int i= 0; i < paramNames.length; i++) { | |
177 | Name argument= ast.newSimpleName(paramNames[i]); | |
178 | arguments.add(argument); | |
179 | addLinkedPosition(rewrite.track(argument), false, "arg_name_" + paramNames[i]); //$NON-NLS-1$ | |
180 | } | |
181 | } | |
182 | ||
183 | String bodyStatement= (invocation == null) ? "" : ASTNodes.asFormattedString(invocation, 0, String.valueOf('\n'), getCompilationUnit().getJavaProject().getOptions(true)); //$NON-NLS-1$ | |
184 | String placeHolder= CodeGeneration.getMethodBodyContent(getCompilationUnit(), name, name, true, bodyStatement, String.valueOf('\n')); | |
185 | if (placeHolder != null) { | |
186 | ASTNode todoNode= rewrite.createStringPlaceholder(placeHolder, ASTNode.RETURN_STATEMENT); | |
187 | body.statements().add(todoNode); | |
188 | } | |
189 | if (commentSettings != null) { | |
190 | String string= CodeGeneration.getMethodComment(getCompilationUnit(), name, decl, null, String.valueOf('\n')); | |
191 | if (string != null) { | |
192 | Javadoc javadoc= (Javadoc) rewrite.createStringPlaceholder(string, ASTNode.JAVADOC); | |
193 | decl.setJavadoc(javadoc); | |
194 | } | |
195 | } | |
196 | return decl; | |
197 | } | |
198 | ||
199 | private SuperConstructorInvocation addEnclosingInstanceAccess(ASTRewrite rewrite, ImportRewriteContext importRewriteContext, List<SingleVariableDeclaration> parameters, String[] paramNames, ITypeBinding enclosingInstance) { | |
200 | AST ast= rewrite.getAST(); | |
201 | SuperConstructorInvocation invocation= ast.newSuperConstructorInvocation(); | |
202 | ||
203 | SingleVariableDeclaration var= ast.newSingleVariableDeclaration(); | |
204 | var.setType(getImportRewrite().addImport(enclosingInstance, ast, importRewriteContext)); | |
205 | String[] enclosingArgNames= StubUtility.getArgumentNameSuggestions(getCompilationUnit().getJavaProject(), enclosingInstance.getTypeDeclaration().getName(), 0, paramNames); | |
206 | String firstName= enclosingArgNames[0]; | |
207 | var.setName(ast.newSimpleName(firstName)); | |
208 | parameters.add(var); | |
209 | ||
210 | Name enclosing= ast.newSimpleName(firstName); | |
211 | invocation.setExpression(enclosing); | |
212 | ||
213 | String key= "arg_name_" + firstName; //$NON-NLS-1$ | |
214 | addLinkedPosition(rewrite.track(enclosing), false, key); | |
215 | for (int i= 0; i < enclosingArgNames.length; i++) { | |
216 | addLinkedPositionProposal(key, enclosingArgNames[i], null); // alternative names | |
217 | } | |
218 | return invocation; | |
219 | } | |
220 | ||
221 | private ITypeBinding getEnclosingInstance() { | |
222 | ITypeBinding currBinding= fTypeNode.resolveBinding(); | |
223 | if (currBinding == null || Modifier.isStatic(currBinding.getModifiers())) { | |
224 | return null; | |
225 | } | |
226 | ITypeBinding superBinding= currBinding.getSuperclass(); | |
227 | if (superBinding == null || superBinding.getDeclaringClass() == null || Modifier.isStatic(superBinding.getModifiers())) { | |
228 | return null; | |
229 | } | |
230 | ITypeBinding enclosing= superBinding.getDeclaringClass(); | |
231 | ||
232 | while (currBinding != null) { | |
233 | if (Bindings.isSuperType(enclosing, currBinding)) { | |
234 | return null; // enclosing in scope | |
235 | } | |
236 | if (Modifier.isStatic(currBinding.getModifiers())) { | |
237 | return null; // no more enclosing instances | |
238 | } | |
239 | currBinding= currBinding.getDeclaringClass(); | |
240 | } | |
241 | return enclosing; | |
242 | } | |
243 | ||
244 | ||
245 | private String[] getArgumentNames(IMethodBinding binding) { | |
246 | if (binding == null) { | |
247 | return new String[0]; | |
248 | } | |
249 | return StubUtility.suggestArgumentNames(getCompilationUnit().getJavaProject(), binding); | |
250 | } | |
251 | } |