]>
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 | * John Kaplan, johnkaplantech@gmail.com - 108071 [code templates] template for body of newly created class | |
11 | *******************************************************************************/ | |
12 | package org.eclipse.jdt.internal.corext.codemanipulation; | |
13 | ||
14 | import java.io.IOException; | |
15 | import java.lang.reflect.Modifier; | |
16 | import java.util.AbstractList; | |
17 | import java.util.ArrayList; | |
18 | import java.util.Collection; | |
19 | import java.util.Collections; | |
20 | import java.util.HashSet; | |
21 | import java.util.LinkedHashSet; | |
22 | import java.util.List; | |
23 | import java.util.Set; | |
24 | import java.util.StringTokenizer; | |
25 | ||
26 | import org.eclipse.core.runtime.CoreException; | |
27 | import org.eclipse.core.runtime.IStatus; | |
28 | import org.eclipse.core.runtime.Platform; | |
29 | import org.eclipse.core.runtime.Status; | |
30 | import org.eclipse.core.runtime.preferences.IScopeContext; | |
31 | import org.eclipse.core.runtime.preferences.InstanceScope; | |
32 | ||
33 | import org.eclipse.core.resources.IProject; | |
34 | import org.eclipse.core.resources.ProjectScope; | |
35 | ||
36 | import org.eclipse.text.edits.DeleteEdit; | |
37 | import org.eclipse.text.edits.MalformedTreeException; | |
38 | import org.eclipse.text.edits.MultiTextEdit; | |
39 | ||
40 | import org.eclipse.jface.text.BadLocationException; | |
41 | import org.eclipse.jface.text.Document; | |
42 | import org.eclipse.jface.text.IDocument; | |
43 | import org.eclipse.jface.text.IRegion; | |
44 | import org.eclipse.jface.text.templates.Template; | |
45 | import org.eclipse.jface.text.templates.TemplateBuffer; | |
46 | import org.eclipse.jface.text.templates.TemplateException; | |
47 | import org.eclipse.jface.text.templates.TemplateVariable; | |
48 | import org.eclipse.jface.text.templates.persistence.TemplatePersistenceData; | |
49 | import org.eclipse.jface.text.templates.persistence.TemplateStore; | |
50 | ||
51 | import org.eclipse.jdt.core.Flags; | |
52 | import org.eclipse.jdt.core.IBuffer; | |
53 | import org.eclipse.jdt.core.ICompilationUnit; | |
54 | import org.eclipse.jdt.core.IField; | |
55 | import org.eclipse.jdt.core.IJavaElement; | |
56 | import org.eclipse.jdt.core.IJavaProject; | |
57 | import org.eclipse.jdt.core.IMethod; | |
58 | import org.eclipse.jdt.core.IOpenable; | |
59 | import org.eclipse.jdt.core.IPackageFragment; | |
60 | import org.eclipse.jdt.core.IParent; | |
61 | import org.eclipse.jdt.core.ISourceReference; | |
62 | import org.eclipse.jdt.core.IType; | |
63 | import org.eclipse.jdt.core.ITypeParameter; | |
64 | import org.eclipse.jdt.core.ITypeRoot; | |
65 | import org.eclipse.jdt.core.JavaCore; | |
66 | import org.eclipse.jdt.core.JavaModelException; | |
67 | import org.eclipse.jdt.core.NamingConventions; | |
68 | import org.eclipse.jdt.core.Signature; | |
69 | import org.eclipse.jdt.core.dom.AST; | |
70 | import org.eclipse.jdt.core.dom.ASTNode; | |
71 | import org.eclipse.jdt.core.dom.ASTParser; | |
72 | import org.eclipse.jdt.core.dom.AbstractTypeDeclaration; | |
73 | import org.eclipse.jdt.core.dom.ArrayType; | |
74 | import org.eclipse.jdt.core.dom.CastExpression; | |
75 | import org.eclipse.jdt.core.dom.ClassInstanceCreation; | |
76 | import org.eclipse.jdt.core.dom.CompilationUnit; | |
77 | import org.eclipse.jdt.core.dom.ConstructorInvocation; | |
78 | import org.eclipse.jdt.core.dom.Expression; | |
79 | import org.eclipse.jdt.core.dom.FieldAccess; | |
80 | import org.eclipse.jdt.core.dom.IBinding; | |
81 | import org.eclipse.jdt.core.dom.IMethodBinding; | |
82 | import org.eclipse.jdt.core.dom.ITypeBinding; | |
83 | import org.eclipse.jdt.core.dom.IVariableBinding; | |
84 | import org.eclipse.jdt.core.dom.MethodDeclaration; | |
85 | import org.eclipse.jdt.core.dom.MethodInvocation; | |
86 | import org.eclipse.jdt.core.dom.Name; | |
87 | import org.eclipse.jdt.core.dom.NumberLiteral; | |
88 | import org.eclipse.jdt.core.dom.ParameterizedType; | |
89 | import org.eclipse.jdt.core.dom.SingleVariableDeclaration; | |
90 | import org.eclipse.jdt.core.dom.StringLiteral; | |
91 | import org.eclipse.jdt.core.dom.StructuralPropertyDescriptor; | |
92 | import org.eclipse.jdt.core.dom.SuperConstructorInvocation; | |
93 | import org.eclipse.jdt.core.dom.SuperMethodInvocation; | |
94 | import org.eclipse.jdt.core.dom.Type; | |
95 | import org.eclipse.jdt.core.dom.TypeParameter; | |
96 | import org.eclipse.jdt.core.dom.rewrite.ImportRewrite; | |
97 | import org.eclipse.jdt.core.formatter.IndentManipulation; | |
98 | ||
99 | import org.eclipse.jdt.internal.corext.dom.ASTNodes; | |
100 | import org.eclipse.jdt.internal.corext.dom.Bindings; | |
101 | import org.eclipse.jdt.internal.corext.template.java.CodeTemplateContext; | |
102 | import org.eclipse.jdt.internal.corext.template.java.CodeTemplateContextType; | |
103 | import org.eclipse.jdt.internal.corext.util.Strings; | |
104 | ||
105 | import org.eclipse.jdt.ui.CodeStyleConfiguration; | |
106 | import org.eclipse.jdt.ui.PreferenceConstants; | |
107 | ||
108 | import org.eclipse.jdt.internal.ui.JavaPlugin; | |
109 | import org.eclipse.jdt.internal.ui.JavaUIStatus; | |
110 | import org.eclipse.jdt.internal.ui.javaeditor.ASTProvider; | |
111 | import org.eclipse.jdt.internal.ui.text.correction.ASTResolving; | |
112 | import org.eclipse.jdt.internal.ui.viewsupport.ProjectTemplateStore; | |
113 | ||
114 | public class StubUtility { | |
115 | ||
116 | private static final String[] EMPTY= new String[0]; | |
117 | ||
118 | private static final Set<String> VALID_TYPE_BODY_TEMPLATES; | |
119 | static { | |
120 | VALID_TYPE_BODY_TEMPLATES= new HashSet<String>(); | |
121 | VALID_TYPE_BODY_TEMPLATES.add(CodeTemplateContextType.CLASSBODY_ID); | |
122 | VALID_TYPE_BODY_TEMPLATES.add(CodeTemplateContextType.INTERFACEBODY_ID); | |
123 | VALID_TYPE_BODY_TEMPLATES.add(CodeTemplateContextType.ENUMBODY_ID); | |
124 | VALID_TYPE_BODY_TEMPLATES.add(CodeTemplateContextType.ANNOTATIONBODY_ID); | |
125 | } | |
126 | ||
127 | /* | |
128 | * Don't use this method directly, use CodeGeneration. | |
129 | */ | |
130 | public static String getMethodBodyContent(boolean isConstructor, IJavaProject project, String destTypeName, String methodName, String bodyStatement, String lineDelimiter) throws CoreException { | |
131 | String templateName= isConstructor ? CodeTemplateContextType.CONSTRUCTORSTUB_ID : CodeTemplateContextType.METHODSTUB_ID; | |
132 | Template template= getCodeTemplate(templateName, project); | |
133 | if (template == null) { | |
134 | return bodyStatement; | |
135 | } | |
136 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); | |
137 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); | |
138 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, destTypeName); | |
139 | context.setVariable(CodeTemplateContextType.BODY_STATEMENT, bodyStatement); | |
140 | String str= evaluateTemplate(context, template, new String[] { CodeTemplateContextType.BODY_STATEMENT }); | |
141 | if (str == null && !Strings.containsOnlyWhitespaces(bodyStatement)) { | |
142 | return bodyStatement; | |
143 | } | |
144 | return str; | |
145 | } | |
146 | ||
147 | /* | |
148 | * Don't use this method directly, use CodeGeneration. | |
149 | */ | |
150 | public static String getGetterMethodBodyContent(IJavaProject project, String destTypeName, String methodName, String fieldName, String lineDelimiter) throws CoreException { | |
151 | String templateName= CodeTemplateContextType.GETTERSTUB_ID; | |
152 | Template template= getCodeTemplate(templateName, project); | |
153 | if (template == null) { | |
154 | return null; | |
155 | } | |
156 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); | |
157 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); | |
158 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, destTypeName); | |
159 | context.setVariable(CodeTemplateContextType.FIELD, fieldName); | |
160 | ||
161 | return evaluateTemplate(context, template); | |
162 | } | |
163 | ||
164 | /* | |
165 | * Don't use this method directly, use CodeGeneration. | |
166 | */ | |
167 | public static String getSetterMethodBodyContent(IJavaProject project, String destTypeName, String methodName, String fieldName, String paramName, String lineDelimiter) throws CoreException { | |
168 | String templateName= CodeTemplateContextType.SETTERSTUB_ID; | |
169 | Template template= getCodeTemplate(templateName, project); | |
170 | if (template == null) { | |
171 | return null; | |
172 | } | |
173 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); | |
174 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); | |
175 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, destTypeName); | |
176 | context.setVariable(CodeTemplateContextType.FIELD, fieldName); | |
177 | context.setVariable(CodeTemplateContextType.FIELD_TYPE, fieldName); | |
178 | context.setVariable(CodeTemplateContextType.PARAM, paramName); | |
179 | ||
180 | return evaluateTemplate(context, template); | |
181 | } | |
182 | ||
183 | public static String getCatchBodyContent(ICompilationUnit cu, String exceptionType, String variableName, ASTNode locationInAST, String lineDelimiter) throws CoreException { | |
184 | String enclosingType= ""; //$NON-NLS-1$ | |
185 | String enclosingMethod= ""; //$NON-NLS-1$ | |
186 | ||
187 | if (locationInAST != null) { | |
188 | MethodDeclaration parentMethod= ASTResolving.findParentMethodDeclaration(locationInAST); | |
189 | if (parentMethod != null) { | |
190 | enclosingMethod= parentMethod.getName().getIdentifier(); | |
191 | locationInAST= parentMethod; | |
192 | } | |
193 | ASTNode parentType= ASTResolving.findParentType(locationInAST); | |
194 | if (parentType instanceof AbstractTypeDeclaration) { | |
195 | enclosingType= ((AbstractTypeDeclaration)parentType).getName().getIdentifier(); | |
196 | } | |
197 | } | |
198 | return getCatchBodyContent(cu, exceptionType, variableName, enclosingType, enclosingMethod, lineDelimiter); | |
199 | } | |
200 | ||
201 | ||
202 | public static String getCatchBodyContent(ICompilationUnit cu, String exceptionType, String variableName, String enclosingType, String enclosingMethod, String lineDelimiter) throws CoreException { | |
203 | Template template= getCodeTemplate(CodeTemplateContextType.CATCHBLOCK_ID, cu.getJavaProject()); | |
204 | if (template == null) { | |
205 | return null; | |
206 | } | |
207 | ||
208 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelimiter); | |
209 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, enclosingType); | |
210 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, enclosingMethod); | |
211 | context.setVariable(CodeTemplateContextType.EXCEPTION_TYPE, exceptionType); | |
212 | context.setVariable(CodeTemplateContextType.EXCEPTION_VAR, variableName); | |
213 | return evaluateTemplate(context, template); | |
214 | } | |
215 | ||
216 | /* | |
217 | * Don't use this method directly, use CodeGeneration. | |
218 | * @see org.eclipse.jdt.ui.CodeGeneration#getCompilationUnitContent(ICompilationUnit, String, String, String, String) | |
219 | */ | |
220 | public static String getCompilationUnitContent(ICompilationUnit cu, String fileComment, String typeComment, String typeContent, String lineDelimiter) throws CoreException { | |
221 | IPackageFragment pack= (IPackageFragment)cu.getParent(); | |
222 | String packDecl= pack.isDefaultPackage() ? "" : "package " + pack.getElementName() + ';'; //$NON-NLS-1$ //$NON-NLS-2$ | |
223 | return getCompilationUnitContent(cu, packDecl, fileComment, typeComment, typeContent, lineDelimiter); | |
224 | } | |
225 | ||
226 | public static String getCompilationUnitContent(ICompilationUnit cu, String packDecl, String fileComment, String typeComment, String typeContent, String lineDelimiter) throws CoreException { | |
227 | Template template= getCodeTemplate(CodeTemplateContextType.NEWTYPE_ID, cu.getJavaProject()); | |
228 | if (template == null) { | |
229 | return null; | |
230 | } | |
231 | ||
232 | IJavaProject project= cu.getJavaProject(); | |
233 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); | |
234 | context.setCompilationUnitVariables(cu); | |
235 | context.setVariable(CodeTemplateContextType.PACKAGE_DECLARATION, packDecl); | |
236 | context.setVariable(CodeTemplateContextType.TYPE_COMMENT, typeComment != null ? typeComment : ""); //$NON-NLS-1$ | |
237 | context.setVariable(CodeTemplateContextType.FILE_COMMENT, fileComment != null ? fileComment : ""); //$NON-NLS-1$ | |
238 | context.setVariable(CodeTemplateContextType.TYPE_DECLARATION, typeContent); | |
239 | context.setVariable(CodeTemplateContextType.TYPENAME, JavaCore.removeJavaLikeExtension(cu.getElementName())); | |
240 | ||
241 | String[] fullLine= { CodeTemplateContextType.PACKAGE_DECLARATION, CodeTemplateContextType.FILE_COMMENT, CodeTemplateContextType.TYPE_COMMENT }; | |
242 | return evaluateTemplate(context, template, fullLine); | |
243 | } | |
244 | ||
245 | ||
246 | /* | |
247 | * Don't use this method directly, use CodeGeneration. | |
248 | * @see org.eclipse.jdt.ui.CodeGeneration#getFileComment(ICompilationUnit, String) | |
249 | */ | |
250 | public static String getFileComment(ICompilationUnit cu, String lineDelimiter) throws CoreException { | |
251 | Template template= getCodeTemplate(CodeTemplateContextType.FILECOMMENT_ID, cu.getJavaProject()); | |
252 | if (template == null) { | |
253 | return null; | |
254 | } | |
255 | ||
256 | IJavaProject project= cu.getJavaProject(); | |
257 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), project, lineDelimiter); | |
258 | context.setCompilationUnitVariables(cu); | |
259 | context.setVariable(CodeTemplateContextType.TYPENAME, JavaCore.removeJavaLikeExtension(cu.getElementName())); | |
260 | return evaluateTemplate(context, template); | |
261 | } | |
262 | ||
263 | /* | |
264 | * Don't use this method directly, use CodeGeneration. | |
265 | * @see org.eclipse.jdt.ui.CodeGeneration#getTypeComment(ICompilationUnit, String, String[], String) | |
266 | */ | |
267 | public static String getTypeComment(ICompilationUnit cu, String typeQualifiedName, String[] typeParameterNames, String lineDelim) throws CoreException { | |
268 | Template template= getCodeTemplate(CodeTemplateContextType.TYPECOMMENT_ID, cu.getJavaProject()); | |
269 | if (template == null) { | |
270 | return null; | |
271 | } | |
272 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelim); | |
273 | context.setCompilationUnitVariables(cu); | |
274 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, Signature.getQualifier(typeQualifiedName)); | |
275 | context.setVariable(CodeTemplateContextType.TYPENAME, Signature.getSimpleName(typeQualifiedName)); | |
276 | ||
277 | TemplateBuffer buffer; | |
278 | try { | |
279 | buffer= context.evaluate(template); | |
280 | } catch (BadLocationException e) { | |
281 | throw new CoreException(Status.CANCEL_STATUS); | |
282 | } catch (TemplateException e) { | |
283 | throw new CoreException(Status.CANCEL_STATUS); | |
284 | } | |
285 | String str= buffer.getString(); | |
286 | if (Strings.containsOnlyWhitespaces(str)) { | |
287 | return null; | |
288 | } | |
289 | ||
290 | TemplateVariable position= findVariable(buffer, CodeTemplateContextType.TAGS); // look if Javadoc tags have to be added | |
291 | if (position == null) { | |
292 | return str; | |
293 | } | |
294 | ||
295 | IDocument document= new Document(str); | |
296 | int[] tagOffsets= position.getOffsets(); | |
297 | for (int i= tagOffsets.length - 1; i >= 0; i--) { // from last to first | |
298 | try { | |
299 | insertTag(document, tagOffsets[i], position.getLength(), EMPTY, EMPTY, null, typeParameterNames, false, lineDelim); | |
300 | } catch (BadLocationException e) { | |
301 | throw new CoreException(JavaUIStatus.createError(IStatus.ERROR, e)); | |
302 | } | |
303 | } | |
304 | return document.get(); | |
305 | } | |
306 | ||
307 | /* | |
308 | * Returns the parameters type names used in see tags. Currently, these are always fully qualified. | |
309 | */ | |
310 | public static String[] getParameterTypeNamesForSeeTag(IMethodBinding binding) { | |
311 | ITypeBinding[] typeBindings= binding.getParameterTypes(); | |
312 | String[] result= new String[typeBindings.length]; | |
313 | for (int i= 0; i < result.length; i++) { | |
314 | ITypeBinding curr= typeBindings[i]; | |
315 | if (curr.isTypeVariable()) { | |
316 | curr= curr.getErasure(); // in Javadoc only use type variable erasure | |
317 | } | |
318 | curr= curr.getTypeDeclaration(); // no parameterized types | |
319 | result[i]= curr.getQualifiedName(); | |
320 | } | |
321 | return result; | |
322 | } | |
323 | ||
324 | /* | |
325 | * Returns the parameters type names used in see tags. Currently, these are always fully qualified. | |
326 | */ | |
327 | private static String[] getParameterTypeNamesForSeeTag(IMethod overridden) { | |
328 | try { | |
329 | ASTParser parser= ASTParser.newParser(ASTProvider.SHARED_AST_LEVEL); | |
330 | parser.setProject(overridden.getJavaProject()); | |
331 | IBinding[] bindings= parser.createBindings(new IJavaElement[] { overridden }, null); | |
332 | if (bindings.length == 1 && bindings[0] instanceof IMethodBinding) { | |
333 | return getParameterTypeNamesForSeeTag((IMethodBinding)bindings[0]); | |
334 | } | |
335 | } catch (IllegalStateException e) { | |
336 | // method does not exist | |
337 | } | |
338 | // fall back code. Not good for generic methods! | |
339 | String[] paramTypes= overridden.getParameterTypes(); | |
340 | String[] paramTypeNames= new String[paramTypes.length]; | |
341 | for (int i= 0; i < paramTypes.length; i++) { | |
342 | paramTypeNames[i]= Signature.toString(Signature.getTypeErasure(paramTypes[i])); | |
343 | } | |
344 | return paramTypeNames; | |
345 | } | |
346 | ||
347 | private static String getSeeTag(String declaringClassQualifiedName, String methodName, String[] parameterTypesQualifiedNames) { | |
348 | StringBuffer buf= new StringBuffer(); | |
349 | buf.append("@see "); //$NON-NLS-1$ | |
350 | buf.append(declaringClassQualifiedName); | |
351 | buf.append('#'); | |
352 | buf.append(methodName); | |
353 | buf.append('('); | |
354 | for (int i= 0; i < parameterTypesQualifiedNames.length; i++) { | |
355 | if (i > 0) { | |
356 | buf.append(", "); //$NON-NLS-1$ | |
357 | } | |
358 | buf.append(parameterTypesQualifiedNames[i]); | |
359 | } | |
360 | buf.append(')'); | |
361 | return buf.toString(); | |
362 | } | |
363 | ||
364 | public static String[] getTypeParameterNames(ITypeParameter[] typeParameters) { | |
365 | String[] typeParametersNames= new String[typeParameters.length]; | |
366 | for (int i= 0; i < typeParameters.length; i++) { | |
367 | typeParametersNames[i]= typeParameters[i].getElementName(); | |
368 | } | |
369 | return typeParametersNames; | |
370 | } | |
371 | ||
372 | /** | |
373 | * Don't use this method directly, use CodeGeneration. | |
374 | * | |
375 | * @param templateID the template id of the type body to get. Valid id's are | |
376 | * {@link CodeTemplateContextType#CLASSBODY_ID}, | |
377 | * {@link CodeTemplateContextType#INTERFACEBODY_ID}, | |
378 | * {@link CodeTemplateContextType#ENUMBODY_ID}, | |
379 | * {@link CodeTemplateContextType#ANNOTATIONBODY_ID}, | |
380 | * @param cu the compilation unit to which the template is added | |
381 | * @param typeName the type name | |
382 | * @param lineDelim the line delimiter to use | |
383 | * @return return the type body template or <code>null</code> | |
384 | * @throws CoreException thrown if the template could not be evaluated | |
385 | * @see org.eclipse.jdt.ui.CodeGeneration#getTypeBody(String, ICompilationUnit, String, String) | |
386 | */ | |
387 | public static String getTypeBody(String templateID, ICompilationUnit cu, String typeName, String lineDelim) throws CoreException { | |
388 | if (!VALID_TYPE_BODY_TEMPLATES.contains(templateID)) { | |
389 | throw new IllegalArgumentException("Invalid code template ID: " + templateID); //$NON-NLS-1$ | |
390 | } | |
391 | ||
392 | Template template= getCodeTemplate(templateID, cu.getJavaProject()); | |
393 | if (template == null) { | |
394 | return null; | |
395 | } | |
396 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelim); | |
397 | context.setCompilationUnitVariables(cu); | |
398 | context.setVariable(CodeTemplateContextType.TYPENAME, typeName); | |
399 | ||
400 | return evaluateTemplate(context, template); | |
401 | } | |
402 | ||
403 | /* | |
404 | * Don't use this method directly, use CodeGeneration. | |
405 | * @see org.eclipse.jdt.ui.CodeGeneration#getMethodComment(ICompilationUnit, String, String, String[], String[], String, String[], IMethod, String) | |
406 | */ | |
407 | public static String getMethodComment(ICompilationUnit cu, String typeName, String methodName, String[] paramNames, String[] excTypeSig, String retTypeSig, String[] typeParameterNames, | |
408 | IMethod target, boolean delegate, String lineDelimiter) throws CoreException { | |
409 | String templateName= CodeTemplateContextType.METHODCOMMENT_ID; | |
410 | if (retTypeSig == null) { | |
411 | templateName= CodeTemplateContextType.CONSTRUCTORCOMMENT_ID; | |
412 | } else if (target != null) { | |
413 | if (delegate) | |
414 | templateName= CodeTemplateContextType.DELEGATECOMMENT_ID; | |
415 | else | |
416 | templateName= CodeTemplateContextType.OVERRIDECOMMENT_ID; | |
417 | } | |
418 | Template template= getCodeTemplate(templateName, cu.getJavaProject()); | |
419 | if (template == null) { | |
420 | return null; | |
421 | } | |
422 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelimiter); | |
423 | context.setCompilationUnitVariables(cu); | |
424 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName); | |
425 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); | |
426 | ||
427 | if (retTypeSig != null) { | |
428 | context.setVariable(CodeTemplateContextType.RETURN_TYPE, Signature.toString(retTypeSig)); | |
429 | } | |
430 | if (target != null) { | |
431 | String targetTypeName= target.getDeclaringType().getFullyQualifiedName('.'); | |
432 | String[] targetParamTypeNames= getParameterTypeNamesForSeeTag(target); | |
433 | if (delegate) | |
434 | context.setVariable(CodeTemplateContextType.SEE_TO_TARGET_TAG, getSeeTag(targetTypeName, methodName, targetParamTypeNames)); | |
435 | else | |
436 | context.setVariable(CodeTemplateContextType.SEE_TO_OVERRIDDEN_TAG, getSeeTag(targetTypeName, methodName, targetParamTypeNames)); | |
437 | } | |
438 | TemplateBuffer buffer; | |
439 | try { | |
440 | buffer= context.evaluate(template); | |
441 | } catch (BadLocationException e) { | |
442 | throw new CoreException(Status.CANCEL_STATUS); | |
443 | } catch (TemplateException e) { | |
444 | throw new CoreException(Status.CANCEL_STATUS); | |
445 | } | |
446 | if (buffer == null) { | |
447 | return null; | |
448 | } | |
449 | ||
450 | String str= buffer.getString(); | |
451 | if (Strings.containsOnlyWhitespaces(str)) { | |
452 | return null; | |
453 | } | |
454 | TemplateVariable position= findVariable(buffer, CodeTemplateContextType.TAGS); // look if Javadoc tags have to be added | |
455 | if (position == null) { | |
456 | return str; | |
457 | } | |
458 | ||
459 | IDocument document= new Document(str); | |
460 | String[] exceptionNames= new String[excTypeSig.length]; | |
461 | for (int i= 0; i < excTypeSig.length; i++) { | |
462 | exceptionNames[i]= Signature.toString(excTypeSig[i]); | |
463 | } | |
464 | String returnType= retTypeSig != null ? Signature.toString(retTypeSig) : null; | |
465 | int[] tagOffsets= position.getOffsets(); | |
466 | for (int i= tagOffsets.length - 1; i >= 0; i--) { // from last to first | |
467 | try { | |
468 | insertTag(document, tagOffsets[i], position.getLength(), paramNames, exceptionNames, returnType, typeParameterNames, false, lineDelimiter); | |
469 | } catch (BadLocationException e) { | |
470 | throw new CoreException(JavaUIStatus.createError(IStatus.ERROR, e)); | |
471 | } | |
472 | } | |
473 | return document.get(); | |
474 | } | |
475 | ||
476 | // remove lines for empty variables | |
477 | private static String fixEmptyVariables(TemplateBuffer buffer, String[] variables) throws MalformedTreeException, BadLocationException { | |
478 | IDocument doc= new Document(buffer.getString()); | |
479 | int nLines= doc.getNumberOfLines(); | |
480 | MultiTextEdit edit= new MultiTextEdit(); | |
481 | HashSet<Integer> removedLines= new HashSet<Integer>(); | |
482 | for (int i= 0; i < variables.length; i++) { | |
483 | TemplateVariable position= findVariable(buffer, variables[i]); // look if Javadoc tags have to be added | |
484 | if (position == null || position.getLength() > 0) { | |
485 | continue; | |
486 | } | |
487 | int[] offsets= position.getOffsets(); | |
488 | for (int k= 0; k < offsets.length; k++) { | |
489 | int line= doc.getLineOfOffset(offsets[k]); | |
490 | IRegion lineInfo= doc.getLineInformation(line); | |
491 | int offset= lineInfo.getOffset(); | |
492 | String str= doc.get(offset, lineInfo.getLength()); | |
493 | if (Strings.containsOnlyWhitespaces(str) && nLines > line + 1 && removedLines.add(new Integer(line))) { | |
494 | int nextStart= doc.getLineOffset(line + 1); | |
495 | edit.addChild(new DeleteEdit(offset, nextStart - offset)); | |
496 | } | |
497 | } | |
498 | } | |
499 | edit.apply(doc, 0); | |
500 | return doc.get(); | |
501 | } | |
502 | ||
503 | /* | |
504 | * Don't use this method directly, use CodeGeneration. | |
505 | */ | |
506 | public static String getFieldComment(ICompilationUnit cu, String typeName, String fieldName, String lineDelimiter) throws CoreException { | |
507 | Template template= getCodeTemplate(CodeTemplateContextType.FIELDCOMMENT_ID, cu.getJavaProject()); | |
508 | if (template == null) { | |
509 | return null; | |
510 | } | |
511 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelimiter); | |
512 | context.setCompilationUnitVariables(cu); | |
513 | context.setVariable(CodeTemplateContextType.FIELD_TYPE, typeName); | |
514 | context.setVariable(CodeTemplateContextType.FIELD, fieldName); | |
515 | ||
516 | return evaluateTemplate(context, template); | |
517 | } | |
518 | ||
519 | ||
520 | /* | |
521 | * Don't use this method directly, use CodeGeneration. | |
522 | * @see org.eclipse.jdt.ui.CodeGeneration#getSetterComment(ICompilationUnit, String, String, String, String, String, String, String) | |
523 | */ | |
524 | public static String getSetterComment(ICompilationUnit cu, String typeName, String methodName, String fieldName, String fieldType, String paramName, String bareFieldName, String lineDelimiter) | |
525 | throws CoreException { | |
526 | String templateName= CodeTemplateContextType.SETTERCOMMENT_ID; | |
527 | Template template= getCodeTemplate(templateName, cu.getJavaProject()); | |
528 | if (template == null) { | |
529 | return null; | |
530 | } | |
531 | ||
532 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelimiter); | |
533 | context.setCompilationUnitVariables(cu); | |
534 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName); | |
535 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); | |
536 | context.setVariable(CodeTemplateContextType.FIELD, fieldName); | |
537 | context.setVariable(CodeTemplateContextType.FIELD_TYPE, fieldType); | |
538 | context.setVariable(CodeTemplateContextType.BARE_FIELD_NAME, bareFieldName); | |
539 | context.setVariable(CodeTemplateContextType.PARAM, paramName); | |
540 | ||
541 | return evaluateTemplate(context, template); | |
542 | } | |
543 | ||
544 | /* | |
545 | * Don't use this method directly, use CodeGeneration. | |
546 | * @see org.eclipse.jdt.ui.CodeGeneration#getGetterComment(ICompilationUnit, String, String, String, String, String, String) | |
547 | */ | |
548 | public static String getGetterComment(ICompilationUnit cu, String typeName, String methodName, String fieldName, String fieldType, String bareFieldName, String lineDelimiter) throws CoreException { | |
549 | String templateName= CodeTemplateContextType.GETTERCOMMENT_ID; | |
550 | Template template= getCodeTemplate(templateName, cu.getJavaProject()); | |
551 | if (template == null) { | |
552 | return null; | |
553 | } | |
554 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelimiter); | |
555 | context.setCompilationUnitVariables(cu); | |
556 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName); | |
557 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, methodName); | |
558 | context.setVariable(CodeTemplateContextType.FIELD, fieldName); | |
559 | context.setVariable(CodeTemplateContextType.FIELD_TYPE, fieldType); | |
560 | context.setVariable(CodeTemplateContextType.BARE_FIELD_NAME, bareFieldName); | |
561 | ||
562 | return evaluateTemplate(context, template); | |
563 | } | |
564 | ||
565 | private static String evaluateTemplate(CodeTemplateContext context, Template template) throws CoreException { | |
566 | TemplateBuffer buffer; | |
567 | try { | |
568 | buffer= context.evaluate(template); | |
569 | } catch (BadLocationException e) { | |
570 | throw new CoreException(Status.CANCEL_STATUS); | |
571 | } catch (TemplateException e) { | |
572 | throw new CoreException(Status.CANCEL_STATUS); | |
573 | } | |
574 | if (buffer == null) | |
575 | return null; | |
576 | String str= buffer.getString(); | |
577 | if (Strings.containsOnlyWhitespaces(str)) { | |
578 | return null; | |
579 | } | |
580 | return str; | |
581 | } | |
582 | ||
583 | private static String evaluateTemplate(CodeTemplateContext context, Template template, String[] fullLineVariables) throws CoreException { | |
584 | TemplateBuffer buffer; | |
585 | try { | |
586 | buffer= context.evaluate(template); | |
587 | if (buffer == null) | |
588 | return null; | |
589 | String str= fixEmptyVariables(buffer, fullLineVariables); | |
590 | if (Strings.containsOnlyWhitespaces(str)) { | |
591 | return null; | |
592 | } | |
593 | return str; | |
594 | } catch (BadLocationException e) { | |
595 | throw new CoreException(Status.CANCEL_STATUS); | |
596 | } catch (TemplateException e) { | |
597 | throw new CoreException(Status.CANCEL_STATUS); | |
598 | } | |
599 | } | |
600 | ||
601 | ||
602 | /* | |
603 | * Don't use this method directly, use CodeGeneration. | |
604 | * @see org.eclipse.jdt.ui.CodeGeneration#getMethodComment(ICompilationUnit, String, MethodDeclaration, boolean, String, String[], String) | |
605 | */ | |
606 | public static String getMethodComment(ICompilationUnit cu, String typeName, MethodDeclaration decl, boolean isDeprecated, String targetName, String targetMethodDeclaringTypeName, | |
607 | String[] targetMethodParameterTypeNames, boolean delegate, String lineDelimiter) throws CoreException { | |
608 | boolean needsTarget= targetMethodDeclaringTypeName != null && targetMethodParameterTypeNames != null; | |
609 | String templateName= CodeTemplateContextType.METHODCOMMENT_ID; | |
610 | if (decl.isConstructor()) { | |
611 | templateName= CodeTemplateContextType.CONSTRUCTORCOMMENT_ID; | |
612 | } else if (needsTarget) { | |
613 | if (delegate) | |
614 | templateName= CodeTemplateContextType.DELEGATECOMMENT_ID; | |
615 | else | |
616 | templateName= CodeTemplateContextType.OVERRIDECOMMENT_ID; | |
617 | } | |
618 | Template template= getCodeTemplate(templateName, cu.getJavaProject()); | |
619 | if (template == null) { | |
620 | return null; | |
621 | } | |
622 | CodeTemplateContext context= new CodeTemplateContext(template.getContextTypeId(), cu.getJavaProject(), lineDelimiter); | |
623 | context.setCompilationUnitVariables(cu); | |
624 | context.setVariable(CodeTemplateContextType.ENCLOSING_TYPE, typeName); | |
625 | context.setVariable(CodeTemplateContextType.ENCLOSING_METHOD, decl.getName().getIdentifier()); | |
626 | if (!decl.isConstructor()) { | |
627 | context.setVariable(CodeTemplateContextType.RETURN_TYPE, ASTNodes.asString(getReturnType(decl))); | |
628 | } | |
629 | if (needsTarget) { | |
630 | if (delegate) | |
631 | context.setVariable(CodeTemplateContextType.SEE_TO_TARGET_TAG, getSeeTag(targetMethodDeclaringTypeName, targetName, targetMethodParameterTypeNames)); | |
632 | else | |
633 | context.setVariable(CodeTemplateContextType.SEE_TO_OVERRIDDEN_TAG, getSeeTag(targetMethodDeclaringTypeName, targetName, targetMethodParameterTypeNames)); | |
634 | } | |
635 | ||
636 | TemplateBuffer buffer; | |
637 | try { | |
638 | buffer= context.evaluate(template); | |
639 | } catch (BadLocationException e) { | |
640 | throw new CoreException(Status.CANCEL_STATUS); | |
641 | } catch (TemplateException e) { | |
642 | throw new CoreException(Status.CANCEL_STATUS); | |
643 | } | |
644 | if (buffer == null) | |
645 | return null; | |
646 | String str= buffer.getString(); | |
647 | if (Strings.containsOnlyWhitespaces(str)) { | |
648 | return null; | |
649 | } | |
650 | TemplateVariable position= findVariable(buffer, CodeTemplateContextType.TAGS); // look if Javadoc tags have to be added | |
651 | if (position == null) { | |
652 | return str; | |
653 | } | |
654 | ||
655 | IDocument textBuffer= new Document(str); | |
656 | List<TypeParameter> typeParams= shouldGenerateMethodTypeParameterTags(cu.getJavaProject()) ? decl.typeParameters() : Collections.emptyList(); | |
657 | String[] typeParamNames= new String[typeParams.size()]; | |
658 | for (int i= 0; i < typeParamNames.length; i++) { | |
659 | TypeParameter elem= typeParams.get(i); | |
660 | typeParamNames[i]= elem.getName().getIdentifier(); | |
661 | } | |
662 | List<SingleVariableDeclaration> params= decl.parameters(); | |
663 | String[] paramNames= new String[params.size()]; | |
664 | for (int i= 0; i < paramNames.length; i++) { | |
665 | SingleVariableDeclaration elem= params.get(i); | |
666 | paramNames[i]= elem.getName().getIdentifier(); | |
667 | } | |
668 | List<Name> exceptions= decl.thrownExceptions(); | |
669 | String[] exceptionNames= new String[exceptions.size()]; | |
670 | for (int i= 0; i < exceptionNames.length; i++) { | |
671 | exceptionNames[i]= ASTNodes.getSimpleNameIdentifier(exceptions.get(i)); | |
672 | } | |
673 | ||
674 | String returnType= null; | |
675 | if (!decl.isConstructor()) { | |
676 | returnType= ASTNodes.asString(getReturnType(decl)); | |
677 | } | |
678 | int[] tagOffsets= position.getOffsets(); | |
679 | for (int i= tagOffsets.length - 1; i >= 0; i--) { // from last to first | |
680 | try { | |
681 | insertTag(textBuffer, tagOffsets[i], position.getLength(), paramNames, exceptionNames, returnType, typeParamNames, isDeprecated, lineDelimiter); | |
682 | } catch (BadLocationException e) { | |
683 | throw new CoreException(JavaUIStatus.createError(IStatus.ERROR, e)); | |
684 | } | |
685 | } | |
686 | return textBuffer.get(); | |
687 | } | |
688 | ||
689 | public static boolean shouldGenerateMethodTypeParameterTags(IJavaProject project) { | |
690 | return JavaCore.ENABLED.equals(project.getOption(JavaCore.COMPILER_PB_MISSING_JAVADOC_TAGS_METHOD_TYPE_PARAMETERS, true)); | |
691 | } | |
692 | ||
693 | /** | |
694 | * @param decl the method declaration | |
695 | * @return the return type | |
696 | * @deprecated Deprecated to avoid deprecated warnings | |
697 | */ | |
698 | private static ASTNode getReturnType(MethodDeclaration decl) { | |
699 | // used from API, can't eliminate | |
700 | return decl.getAST().apiLevel() == AST.JLS2 ? decl.getReturnType() : decl.getReturnType2(); | |
701 | } | |
702 | ||
703 | ||
704 | private static TemplateVariable findVariable(TemplateBuffer buffer, String variable) { | |
705 | TemplateVariable[] positions= buffer.getVariables(); | |
706 | for (int i= 0; i < positions.length; i++) { | |
707 | TemplateVariable curr= positions[i]; | |
708 | if (variable.equals(curr.getType())) { | |
709 | return curr; | |
710 | } | |
711 | } | |
712 | return null; | |
713 | } | |
714 | ||
715 | private static void insertTag(IDocument textBuffer, int offset, int length, String[] paramNames, String[] exceptionNames, String returnType, String[] typeParameterNames, boolean isDeprecated, | |
716 | String lineDelimiter) throws BadLocationException { | |
717 | IRegion region= textBuffer.getLineInformationOfOffset(offset); | |
718 | if (region == null) { | |
719 | return; | |
720 | } | |
721 | String lineStart= textBuffer.get(region.getOffset(), offset - region.getOffset()); | |
722 | ||
723 | StringBuffer buf= new StringBuffer(); | |
724 | for (int i= 0; i < typeParameterNames.length; i++) { | |
725 | if (buf.length() > 0) { | |
726 | buf.append(lineDelimiter).append(lineStart); | |
727 | } | |
728 | buf.append("@param <").append(typeParameterNames[i]).append('>'); //$NON-NLS-1$ | |
729 | } | |
730 | for (int i= 0; i < paramNames.length; i++) { | |
731 | if (buf.length() > 0) { | |
732 | buf.append(lineDelimiter).append(lineStart); | |
733 | } | |
734 | buf.append("@param ").append(paramNames[i]); //$NON-NLS-1$ | |
735 | } | |
736 | if (returnType != null && !returnType.equals("void")) { //$NON-NLS-1$ | |
737 | if (buf.length() > 0) { | |
738 | buf.append(lineDelimiter).append(lineStart); | |
739 | } | |
740 | buf.append("@return"); //$NON-NLS-1$ | |
741 | } | |
742 | if (exceptionNames != null) { | |
743 | for (int i= 0; i < exceptionNames.length; i++) { | |
744 | if (buf.length() > 0) { | |
745 | buf.append(lineDelimiter).append(lineStart); | |
746 | } | |
747 | buf.append("@throws ").append(exceptionNames[i]); //$NON-NLS-1$ | |
748 | } | |
749 | } | |
750 | if (isDeprecated) { | |
751 | if (buf.length() > 0) { | |
752 | buf.append(lineDelimiter).append(lineStart); | |
753 | } | |
754 | buf.append("@deprecated"); //$NON-NLS-1$ | |
755 | } | |
756 | if (buf.length() == 0 && isAllCommentWhitespace(lineStart)) { | |
757 | int prevLine= textBuffer.getLineOfOffset(offset) - 1; | |
758 | if (prevLine > 0) { | |
759 | IRegion prevRegion= textBuffer.getLineInformation(prevLine); | |
760 | int prevLineEnd= prevRegion.getOffset() + prevRegion.getLength(); | |
761 | // clear full line | |
762 | textBuffer.replace(prevLineEnd, offset + length - prevLineEnd, ""); //$NON-NLS-1$ | |
763 | return; | |
764 | } | |
765 | } | |
766 | textBuffer.replace(offset, length, buf.toString()); | |
767 | } | |
768 | ||
769 | private static boolean isAllCommentWhitespace(String lineStart) { | |
770 | for (int i= 0; i < lineStart.length(); i++) { | |
771 | char ch= lineStart.charAt(i); | |
772 | if (!Character.isWhitespace(ch) && ch != '*') { | |
773 | return false; | |
774 | } | |
775 | } | |
776 | return true; | |
777 | } | |
778 | ||
779 | /** | |
780 | * Returns the line delimiter which is used in the specified project. | |
781 | * | |
782 | * @param project the java project, or <code>null</code> | |
783 | * @return the used line delimiter | |
784 | */ | |
785 | public static String getLineDelimiterUsed(IJavaProject project) { | |
786 | return getProjectLineDelimiter(project); | |
787 | } | |
788 | ||
789 | private static String getProjectLineDelimiter(IJavaProject javaProject) { | |
790 | IProject project= null; | |
791 | if (javaProject != null) | |
792 | project= javaProject.getProject(); | |
793 | ||
794 | String lineDelimiter= getLineDelimiterPreference(project); | |
795 | if (lineDelimiter != null) | |
796 | return lineDelimiter; | |
797 | ||
798 | return System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ | |
799 | } | |
800 | ||
801 | public static String getLineDelimiterPreference(IProject project) { | |
802 | IScopeContext[] scopeContext; | |
803 | if (project != null) { | |
804 | // project preference | |
805 | scopeContext= new IScopeContext[] { new ProjectScope(project) }; | |
806 | String lineDelimiter= Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, null, scopeContext); | |
807 | if (lineDelimiter != null) | |
808 | return lineDelimiter; | |
809 | } | |
810 | // workspace preference | |
811 | scopeContext= new IScopeContext[] { InstanceScope.INSTANCE }; | |
812 | String platformDefault= System.getProperty("line.separator", "\n"); //$NON-NLS-1$ //$NON-NLS-2$ | |
813 | return Platform.getPreferencesService().getString(Platform.PI_RUNTIME, Platform.PREF_LINE_SEPARATOR, platformDefault, scopeContext); | |
814 | } | |
815 | ||
816 | /** | |
817 | * Examines a string and returns the first line delimiter found. | |
818 | * | |
819 | * @param elem the element | |
820 | * @return the line delimiter used for the element | |
821 | */ | |
822 | public static String getLineDelimiterUsed(IJavaElement elem) { | |
823 | IOpenable openable= elem.getOpenable(); | |
824 | if (openable instanceof ITypeRoot) { | |
825 | try { | |
826 | return openable.findRecommendedLineSeparator(); | |
827 | } catch (JavaModelException exception) { | |
828 | // Use project setting | |
829 | } | |
830 | } | |
831 | IJavaProject project= elem.getJavaProject(); | |
832 | return getProjectLineDelimiter(project.exists() ? project : null); | |
833 | } | |
834 | ||
835 | /** | |
836 | * Evaluates the indentation used by a Java element. (in tabulators) | |
837 | * | |
838 | * @param elem the element to get the indent of | |
839 | * @return return the indent unit | |
840 | * @throws JavaModelException thrown if the element could not be accessed | |
841 | */ | |
842 | public static int getIndentUsed(IJavaElement elem) throws JavaModelException { | |
843 | IOpenable openable= elem.getOpenable(); | |
844 | if (openable instanceof ITypeRoot) { | |
845 | IBuffer buf= openable.getBuffer(); | |
846 | if (buf != null) { | |
847 | int offset= ((ISourceReference)elem).getSourceRange().getOffset(); | |
848 | return getIndentUsed(buf, offset, elem.getJavaProject()); | |
849 | } | |
850 | } | |
851 | return 0; | |
852 | } | |
853 | ||
854 | public static int getIndentUsed(IBuffer buffer, int offset, IJavaProject project) { | |
855 | int i= offset; | |
856 | // find beginning of line | |
857 | while (i > 0 && !IndentManipulation.isLineDelimiterChar(buffer.getChar(i - 1))) { | |
858 | i--; | |
859 | } | |
860 | return Strings.computeIndentUnits(buffer.getText(i, offset - i), project); | |
861 | } | |
862 | ||
863 | ||
864 | ||
865 | /** | |
866 | * Returns the element after the give element. | |
867 | * | |
868 | * @param member a Java element | |
869 | * @return the next sibling of the given element or <code>null</code> | |
870 | * @throws JavaModelException thrown if the element could not be accessed | |
871 | */ | |
872 | public static IJavaElement findNextSibling(IJavaElement member) throws JavaModelException { | |
873 | IJavaElement parent= member.getParent(); | |
874 | if (parent instanceof IParent) { | |
875 | IJavaElement[] elements= ((IParent)parent).getChildren(); | |
876 | for (int i= elements.length - 2; i >= 0; i--) { | |
877 | if (member.equals(elements[i])) { | |
878 | return elements[i + 1]; | |
879 | } | |
880 | } | |
881 | } | |
882 | return null; | |
883 | } | |
884 | ||
885 | public static String getTodoTaskTag(IJavaProject project) { | |
886 | String markers= null; | |
887 | if (project == null) { | |
888 | markers= JavaCore.getOption(JavaCore.COMPILER_TASK_TAGS); | |
889 | } else { | |
890 | markers= project.getOption(JavaCore.COMPILER_TASK_TAGS, true); | |
891 | } | |
892 | ||
893 | if (markers != null && markers.length() > 0) { | |
894 | int idx= markers.indexOf(','); | |
895 | if (idx == -1) { | |
896 | return markers; | |
897 | } else { | |
898 | return markers.substring(0, idx); | |
899 | } | |
900 | } | |
901 | return null; | |
902 | } | |
903 | ||
904 | private static String removeTypeArguments(String baseName) { | |
905 | int idx= baseName.indexOf('<'); | |
906 | if (idx != -1) { | |
907 | return baseName.substring(0, idx); | |
908 | } | |
909 | return baseName; | |
910 | } | |
911 | ||
912 | ||
913 | // --------------------------- name suggestions -------------------------- | |
914 | ||
915 | public static String[] getVariableNameSuggestions(int variableKind, IJavaProject project, ITypeBinding expectedType, Expression assignedExpression, Collection<String> excluded) { | |
916 | LinkedHashSet<String> res= new LinkedHashSet<String>(); // avoid duplicates but keep order | |
917 | ||
918 | if (assignedExpression != null) { | |
919 | String nameFromExpression= getBaseNameFromExpression(project, assignedExpression, variableKind); | |
920 | if (nameFromExpression != null) { | |
921 | add(getVariableNameSuggestions(variableKind, project, nameFromExpression, 0, excluded, false), res); // pass 0 as dimension, base name already contains plural. | |
922 | } | |
923 | ||
924 | String nameFromParent= getBaseNameFromLocationInParent(assignedExpression); | |
925 | if (nameFromParent != null) { | |
926 | add(getVariableNameSuggestions(variableKind, project, nameFromParent, 0, excluded, false), res); // pass 0 as dimension, base name already contains plural. | |
927 | } | |
928 | } | |
929 | if (expectedType != null) { | |
930 | expectedType= Bindings.normalizeTypeBinding(expectedType); | |
931 | if (expectedType != null) { | |
932 | int dim= 0; | |
933 | if (expectedType.isArray()) { | |
934 | dim= expectedType.getDimensions(); | |
935 | expectedType= expectedType.getElementType(); | |
936 | } | |
937 | if (expectedType.isParameterizedType()) { | |
938 | expectedType= expectedType.getTypeDeclaration(); | |
939 | } | |
940 | String typeName= expectedType.getName(); | |
941 | if (typeName.length() > 0) { | |
942 | add(getVariableNameSuggestions(variableKind, project, typeName, dim, excluded, false), res); | |
943 | } | |
944 | } | |
945 | } | |
946 | if (res.isEmpty()) { | |
947 | return getDefaultVariableNameSuggestions(variableKind, excluded); | |
948 | } | |
949 | return res.toArray(new String[res.size()]); | |
950 | } | |
951 | ||
952 | public static String[] getVariableNameSuggestions(int variableKind, IJavaProject project, Type expectedType, Expression assignedExpression, Collection<String> excluded) { | |
953 | LinkedHashSet<String> res= new LinkedHashSet<String>(); // avoid duplicates but keep order | |
954 | ||
955 | if (assignedExpression != null) { | |
956 | String nameFromExpression= getBaseNameFromExpression(project, assignedExpression, variableKind); | |
957 | if (nameFromExpression != null) { | |
958 | add(getVariableNameSuggestions(variableKind, project, nameFromExpression, 0, excluded, false), res); // pass 0 as dimension, base name already contains plural. | |
959 | } | |
960 | ||
961 | String nameFromParent= getBaseNameFromLocationInParent(assignedExpression); | |
962 | if (nameFromParent != null) { | |
963 | add(getVariableNameSuggestions(variableKind, project, nameFromParent, 0, excluded, false), res); // pass 0 as dimension, base name already contains plural. | |
964 | } | |
965 | } | |
966 | if (expectedType != null) { | |
967 | String[] names= getVariableNameSuggestions(variableKind, project, expectedType, excluded, false); | |
968 | for (int i= 0; i < names.length; i++) { | |
969 | res.add(names[i]); | |
970 | } | |
971 | } | |
972 | if (res.isEmpty()) { | |
973 | return getDefaultVariableNameSuggestions(variableKind, excluded); | |
974 | } | |
975 | return res.toArray(new String[res.size()]); | |
976 | } | |
977 | ||
978 | private static String[] getVariableNameSuggestions(int variableKind, IJavaProject project, Type expectedType, Collection<String> excluded, boolean evaluateDefault) { | |
979 | int dim= 0; | |
980 | if (expectedType.isArrayType()) { | |
981 | ArrayType arrayType= (ArrayType)expectedType; | |
982 | dim= arrayType.getDimensions(); | |
983 | expectedType= arrayType.getElementType(); | |
984 | } | |
985 | if (expectedType.isParameterizedType()) { | |
986 | expectedType= ((ParameterizedType)expectedType).getType(); | |
987 | } | |
988 | String typeName= ASTNodes.getTypeName(expectedType); | |
989 | ||
990 | if (typeName.length() > 0) { | |
991 | return getVariableNameSuggestions(variableKind, project, typeName, dim, excluded, evaluateDefault); | |
992 | } | |
993 | return EMPTY; | |
994 | } | |
995 | ||
996 | private static String[] getDefaultVariableNameSuggestions(int variableKind, Collection<String> excluded) { | |
997 | String prop= variableKind == NamingConventions.VK_STATIC_FINAL_FIELD ? "X" : "x"; //$NON-NLS-1$//$NON-NLS-2$ | |
998 | String name= prop; | |
999 | int i= 1; | |
1000 | while (excluded.contains(name)) { | |
1001 | name= prop + i++; | |
1002 | } | |
1003 | return new String[] { name }; | |
1004 | } | |
1005 | ||
1006 | /** | |
1007 | * Returns variable name suggestions for the given base name. This is a layer over the JDT.Core | |
1008 | * NamingConventions API to fix its shortcomings. JDT UI code should only use this API. | |
1009 | * | |
1010 | * @param variableKind specifies what type the variable is: {@link NamingConventions#VK_LOCAL}, | |
1011 | * {@link NamingConventions#VK_PARAMETER}, {@link NamingConventions#VK_STATIC_FIELD}, | |
1012 | * {@link NamingConventions#VK_INSTANCE_FIELD}, or | |
1013 | * {@link NamingConventions#VK_STATIC_FINAL_FIELD}. | |
1014 | * @param project the current project | |
1015 | * @param baseName the base name to make a suggestion on. The base name is expected to be a name | |
1016 | * without any pre- or suffixes in singular form. Type name are accepted as well. | |
1017 | * @param dimensions if greater than 0, the resulting name will be in plural form | |
1018 | * @param excluded a collection containing all excluded names or <code>null</code> if no names | |
1019 | * are excluded | |
1020 | * @param evaluateDefault if set, the result is guaranteed to contain at least one result. If | |
1021 | * not, the result can be an empty array. | |
1022 | * | |
1023 | * @return the name suggestions sorted by relevance (best proposal first). If | |
1024 | * <code>evaluateDefault</code> is set to true, the returned array is never empty. If | |
1025 | * <code>evaluateDefault</code> is set to false, an empty array is returned if there is | |
1026 | * no good suggestion for the given base name. | |
1027 | */ | |
1028 | public static String[] getVariableNameSuggestions(int variableKind, IJavaProject project, String baseName, int dimensions, Collection<String> excluded, boolean evaluateDefault) { | |
1029 | return NamingConventions.suggestVariableNames(variableKind, NamingConventions.BK_TYPE_NAME, removeTypeArguments(baseName), project, dimensions, getExcludedArray(excluded), evaluateDefault); | |
1030 | } | |
1031 | ||
1032 | private static String[] getExcludedArray(Collection<String> excluded) { | |
1033 | if (excluded == null) { | |
1034 | return null; | |
1035 | } else if (excluded instanceof ExcludedCollection) { | |
1036 | return ((ExcludedCollection)excluded).getExcludedArray(); | |
1037 | } | |
1038 | return excluded.toArray(new String[excluded.size()]); | |
1039 | } | |
1040 | ||
1041 | ||
1042 | private static final String[] KNOWN_METHOD_NAME_PREFIXES= { "get", "is", "to" }; //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-1$ | |
1043 | ||
1044 | ||
1045 | private static void add(String[] names, Set<String> result) { | |
1046 | for (int i= 0; i < names.length; i++) { | |
1047 | result.add(names[i]); | |
1048 | } | |
1049 | } | |
1050 | ||
1051 | private static String getBaseNameFromExpression(IJavaProject project, Expression assignedExpression, int variableKind) { | |
1052 | String name= null; | |
1053 | if (assignedExpression instanceof CastExpression) { | |
1054 | assignedExpression= ((CastExpression)assignedExpression).getExpression(); | |
1055 | } | |
1056 | if (assignedExpression instanceof Name) { | |
1057 | Name simpleNode= (Name)assignedExpression; | |
1058 | IBinding binding= simpleNode.resolveBinding(); | |
1059 | if (binding instanceof IVariableBinding) | |
1060 | return getBaseName((IVariableBinding)binding, project); | |
1061 | ||
1062 | return ASTNodes.getSimpleNameIdentifier(simpleNode); | |
1063 | } else if (assignedExpression instanceof MethodInvocation) { | |
1064 | name= ((MethodInvocation)assignedExpression).getName().getIdentifier(); | |
1065 | } else if (assignedExpression instanceof SuperMethodInvocation) { | |
1066 | name= ((SuperMethodInvocation)assignedExpression).getName().getIdentifier(); | |
1067 | } else if (assignedExpression instanceof FieldAccess) { | |
1068 | return ((FieldAccess)assignedExpression).getName().getIdentifier(); | |
1069 | } else if (variableKind == NamingConventions.VK_STATIC_FINAL_FIELD && (assignedExpression instanceof StringLiteral || assignedExpression instanceof NumberLiteral)) { | |
1070 | String string= assignedExpression instanceof StringLiteral ? ((StringLiteral)assignedExpression).getLiteralValue() : ((NumberLiteral)assignedExpression).getToken(); | |
1071 | StringBuffer res= new StringBuffer(); | |
1072 | boolean needsUnderscore= false; | |
1073 | for (int i= 0; i < string.length(); i++) { | |
1074 | char ch= string.charAt(i); | |
1075 | if (Character.isJavaIdentifierPart(ch)) { | |
1076 | if (res.length() == 0 && !Character.isJavaIdentifierStart(ch) || needsUnderscore) { | |
1077 | res.append('_'); | |
1078 | } | |
1079 | res.append(ch); | |
1080 | needsUnderscore= false; | |
1081 | } else { | |
1082 | needsUnderscore= res.length() > 0; | |
1083 | } | |
1084 | } | |
1085 | if (res.length() > 0) { | |
1086 | return res.toString(); | |
1087 | } | |
1088 | } | |
1089 | if (name != null) { | |
1090 | for (int i= 0; i < KNOWN_METHOD_NAME_PREFIXES.length; i++) { | |
1091 | String curr= KNOWN_METHOD_NAME_PREFIXES[i]; | |
1092 | if (name.startsWith(curr)) { | |
1093 | if (name.equals(curr)) { | |
1094 | return null; // don't suggest 'get' as variable name | |
1095 | } else if (Character.isUpperCase(name.charAt(curr.length()))) { | |
1096 | return name.substring(curr.length()); | |
1097 | } | |
1098 | } | |
1099 | } | |
1100 | } | |
1101 | return name; | |
1102 | } | |
1103 | ||
1104 | private static String getBaseNameFromLocationInParent(Expression assignedExpression, List<Expression> arguments, IMethodBinding binding) { | |
1105 | if (binding == null) | |
1106 | return null; | |
1107 | ||
1108 | ITypeBinding[] parameterTypes= binding.getParameterTypes(); | |
1109 | if (parameterTypes.length != arguments.size()) // beware of guessed method bindings | |
1110 | return null; | |
1111 | ||
1112 | int index= arguments.indexOf(assignedExpression); | |
1113 | if (index == -1) | |
1114 | return null; | |
1115 | ||
1116 | ITypeBinding expressionBinding= assignedExpression.resolveTypeBinding(); | |
1117 | if (expressionBinding != null && !expressionBinding.isAssignmentCompatible(parameterTypes[index])) | |
1118 | return null; | |
1119 | ||
1120 | try { | |
1121 | IJavaElement javaElement= binding.getJavaElement(); | |
1122 | if (javaElement instanceof IMethod) { | |
1123 | IMethod method= (IMethod)javaElement; | |
1124 | if (method.getOpenable().getBuffer() != null) { // avoid dummy names and lookup from Javadoc | |
1125 | String[] parameterNames= method.getParameterNames(); | |
1126 | if (index < parameterNames.length) { | |
1127 | return NamingConventions.getBaseName(NamingConventions.VK_PARAMETER, parameterNames[index], method.getJavaProject()); | |
1128 | } | |
1129 | } | |
1130 | } | |
1131 | } catch (JavaModelException e) { | |
1132 | // ignore | |
1133 | } | |
1134 | return null; | |
1135 | } | |
1136 | ||
1137 | ||
1138 | private static String getBaseNameFromLocationInParent(Expression assignedExpression) { | |
1139 | StructuralPropertyDescriptor location= assignedExpression.getLocationInParent(); | |
1140 | if (location == MethodInvocation.ARGUMENTS_PROPERTY) { | |
1141 | MethodInvocation parent= (MethodInvocation)assignedExpression.getParent(); | |
1142 | return getBaseNameFromLocationInParent(assignedExpression, parent.arguments(), parent.resolveMethodBinding()); | |
1143 | } else if (location == ClassInstanceCreation.ARGUMENTS_PROPERTY) { | |
1144 | ClassInstanceCreation parent= (ClassInstanceCreation)assignedExpression.getParent(); | |
1145 | return getBaseNameFromLocationInParent(assignedExpression, parent.arguments(), parent.resolveConstructorBinding()); | |
1146 | } else if (location == SuperMethodInvocation.ARGUMENTS_PROPERTY) { | |
1147 | SuperMethodInvocation parent= (SuperMethodInvocation)assignedExpression.getParent(); | |
1148 | return getBaseNameFromLocationInParent(assignedExpression, parent.arguments(), parent.resolveMethodBinding()); | |
1149 | } else if (location == ConstructorInvocation.ARGUMENTS_PROPERTY) { | |
1150 | ConstructorInvocation parent= (ConstructorInvocation)assignedExpression.getParent(); | |
1151 | return getBaseNameFromLocationInParent(assignedExpression, parent.arguments(), parent.resolveConstructorBinding()); | |
1152 | } else if (location == SuperConstructorInvocation.ARGUMENTS_PROPERTY) { | |
1153 | SuperConstructorInvocation parent= (SuperConstructorInvocation)assignedExpression.getParent(); | |
1154 | return getBaseNameFromLocationInParent(assignedExpression, parent.arguments(), parent.resolveConstructorBinding()); | |
1155 | } | |
1156 | return null; | |
1157 | } | |
1158 | ||
1159 | public static String[] getArgumentNameSuggestions(IType type, String[] excluded) { | |
1160 | return getVariableNameSuggestions(NamingConventions.VK_PARAMETER, type.getJavaProject(), type.getElementName(), 0, new ExcludedCollection(excluded), true); | |
1161 | } | |
1162 | ||
1163 | public static String[] getArgumentNameSuggestions(IJavaProject project, Type type, String[] excluded) { | |
1164 | return getVariableNameSuggestions(NamingConventions.VK_PARAMETER, project, type, new ExcludedCollection(excluded), true); | |
1165 | } | |
1166 | ||
1167 | public static String[] getArgumentNameSuggestions(IJavaProject project, ITypeBinding binding, String[] excluded) { | |
1168 | return getVariableNameSuggestions(NamingConventions.VK_PARAMETER, project, binding, null, new ExcludedCollection(excluded)); | |
1169 | } | |
1170 | ||
1171 | public static String[] getArgumentNameSuggestions(IJavaProject project, String baseName, int dimensions, String[] excluded) { | |
1172 | return getVariableNameSuggestions(NamingConventions.VK_PARAMETER, project, baseName, dimensions, new ExcludedCollection(excluded), true); | |
1173 | } | |
1174 | ||
1175 | public static String[] getFieldNameSuggestions(IType type, int fieldModifiers, String[] excluded) { | |
1176 | return getFieldNameSuggestions(type.getJavaProject(), type.getElementName(), 0, fieldModifiers, excluded); | |
1177 | } | |
1178 | ||
1179 | public static String[] getFieldNameSuggestions(IJavaProject project, String baseName, int dimensions, int modifiers, String[] excluded) { | |
1180 | if (Flags.isFinal(modifiers) && Flags.isStatic(modifiers)) { | |
1181 | return getVariableNameSuggestions(NamingConventions.VK_STATIC_FINAL_FIELD, project, baseName, dimensions, new ExcludedCollection(excluded), true); | |
1182 | } else if (Flags.isStatic(modifiers)) { | |
1183 | return getVariableNameSuggestions(NamingConventions.VK_STATIC_FIELD, project, baseName, dimensions, new ExcludedCollection(excluded), true); | |
1184 | } | |
1185 | return getVariableNameSuggestions(NamingConventions.VK_INSTANCE_FIELD, project, baseName, dimensions, new ExcludedCollection(excluded), true); | |
1186 | } | |
1187 | ||
1188 | public static String[] getLocalNameSuggestions(IJavaProject project, String baseName, int dimensions, String[] excluded) { | |
1189 | return getVariableNameSuggestions(NamingConventions.VK_LOCAL, project, baseName, dimensions, new ExcludedCollection(excluded), true); | |
1190 | } | |
1191 | ||
1192 | public static String suggestArgumentName(IJavaProject project, String baseName, String[] excluded) { | |
1193 | return suggestVariableName(NamingConventions.VK_PARAMETER, project, baseName, 0, excluded); | |
1194 | } | |
1195 | ||
1196 | private static String suggestVariableName(int varKind, IJavaProject project, String baseName, int dimension, String[] excluded) { | |
1197 | return getVariableNameSuggestions(varKind, project, baseName, dimension, new ExcludedCollection(excluded), true)[0]; | |
1198 | } | |
1199 | ||
1200 | ||
1201 | public static String[][] suggestArgumentNamesWithProposals(IJavaProject project, String[] paramNames) { | |
1202 | String[][] newNames= new String[paramNames.length][]; | |
1203 | ArrayList<String> takenNames= new ArrayList<String>(); | |
1204 | ||
1205 | // Ensure that the code generation preferences are respected | |
1206 | for (int i= 0; i < paramNames.length; i++) { | |
1207 | String curr= paramNames[i]; | |
1208 | String baseName= NamingConventions.getBaseName(NamingConventions.VK_PARAMETER, curr, project); | |
1209 | ||
1210 | String[] proposedNames= getVariableNameSuggestions(NamingConventions.VK_PARAMETER, project, curr, 0, takenNames, true); | |
1211 | if (!curr.equals(baseName)) { | |
1212 | // make the existing name to favorite | |
1213 | LinkedHashSet<String> updatedNames= new LinkedHashSet<String>(); | |
1214 | updatedNames.add(curr); | |
1215 | for (int k= 0; k < proposedNames.length; k++) { | |
1216 | updatedNames.add(proposedNames[k]); | |
1217 | } | |
1218 | proposedNames= updatedNames.toArray(new String[updatedNames.size()]); | |
1219 | } | |
1220 | newNames[i]= proposedNames; | |
1221 | takenNames.add(proposedNames[0]); | |
1222 | } | |
1223 | return newNames; | |
1224 | } | |
1225 | ||
1226 | public static String[][] suggestArgumentNamesWithProposals(IJavaProject project, IMethodBinding binding) { | |
1227 | int nParams= binding.getParameterTypes().length; | |
1228 | if (nParams > 0) { | |
1229 | try { | |
1230 | IMethod method= (IMethod)binding.getMethodDeclaration().getJavaElement(); | |
1231 | if (method != null) { | |
1232 | String[] parameterNames= method.getParameterNames(); | |
1233 | if (parameterNames.length == nParams) { | |
1234 | return suggestArgumentNamesWithProposals(project, parameterNames); | |
1235 | } | |
1236 | } | |
1237 | } catch (JavaModelException e) { | |
1238 | // ignore | |
1239 | } | |
1240 | } | |
1241 | String[][] names= new String[nParams][]; | |
1242 | for (int i= 0; i < names.length; i++) { | |
1243 | names[i]= new String[] { "arg" + i }; //$NON-NLS-1$ | |
1244 | } | |
1245 | return names; | |
1246 | } | |
1247 | ||
1248 | ||
1249 | public static String[] suggestArgumentNames(IJavaProject project, IMethodBinding binding) { | |
1250 | int nParams= binding.getParameterTypes().length; | |
1251 | ||
1252 | if (nParams > 0) { | |
1253 | try { | |
1254 | IMethod method= (IMethod)binding.getMethodDeclaration().getJavaElement(); | |
1255 | if (method != null) { | |
1256 | String[] paramNames= method.getParameterNames(); | |
1257 | if (paramNames.length == nParams) { | |
1258 | String[] namesArray= EMPTY; | |
1259 | ArrayList<String> newNames= new ArrayList<String>(paramNames.length); | |
1260 | // Ensure that the code generation preferences are respected | |
1261 | for (int i= 0; i < paramNames.length; i++) { | |
1262 | String curr= paramNames[i]; | |
1263 | String baseName= NamingConventions.getBaseName(NamingConventions.VK_PARAMETER, curr, method.getJavaProject()); | |
1264 | if (!curr.equals(baseName)) { | |
1265 | // make the existing name the favorite | |
1266 | newNames.add(curr); | |
1267 | } else { | |
1268 | newNames.add(suggestArgumentName(project, curr, namesArray)); | |
1269 | } | |
1270 | namesArray= newNames.toArray(new String[newNames.size()]); | |
1271 | } | |
1272 | return namesArray; | |
1273 | } | |
1274 | } | |
1275 | } catch (JavaModelException e) { | |
1276 | // ignore | |
1277 | } | |
1278 | } | |
1279 | String[] names= new String[nParams]; | |
1280 | for (int i= 0; i < names.length; i++) { | |
1281 | names[i]= "arg" + i; //$NON-NLS-1$ | |
1282 | } | |
1283 | return names; | |
1284 | } | |
1285 | ||
1286 | public static String getBaseName(IField field) throws JavaModelException { | |
1287 | return NamingConventions.getBaseName(getFieldKind(field.getFlags()), field.getElementName(), field.getJavaProject()); | |
1288 | } | |
1289 | ||
1290 | public static String getBaseName(IVariableBinding binding, IJavaProject project) { | |
1291 | return NamingConventions.getBaseName(getKind(binding), binding.getName(), project); | |
1292 | } | |
1293 | ||
1294 | /** | |
1295 | * Returns the kind of the given binding. | |
1296 | * | |
1297 | * @param binding variable binding | |
1298 | * @return one of the <code>NamingConventions.VK_*</code> constants | |
1299 | * @since 3.5 | |
1300 | */ | |
1301 | private static int getKind(IVariableBinding binding) { | |
1302 | if (binding.isField()) | |
1303 | return getFieldKind(binding.getModifiers()); | |
1304 | ||
1305 | if (binding.isParameter()) | |
1306 | return NamingConventions.VK_PARAMETER; | |
1307 | ||
1308 | return NamingConventions.VK_LOCAL; | |
1309 | } | |
1310 | ||
1311 | private static int getFieldKind(int modifiers) { | |
1312 | if (!Modifier.isStatic(modifiers)) | |
1313 | return NamingConventions.VK_INSTANCE_FIELD; | |
1314 | ||
1315 | if (!Modifier.isFinal(modifiers)) | |
1316 | return NamingConventions.VK_STATIC_FIELD; | |
1317 | ||
1318 | return NamingConventions.VK_STATIC_FINAL_FIELD; | |
1319 | } | |
1320 | ||
1321 | private static class ExcludedCollection extends AbstractList<String> { | |
1322 | private String[] fExcluded; | |
1323 | ||
1324 | public ExcludedCollection(String[] excluded) { | |
1325 | fExcluded= excluded; | |
1326 | } | |
1327 | ||
1328 | public String[] getExcludedArray() { | |
1329 | return fExcluded; | |
1330 | } | |
1331 | ||
1332 | @Override | |
1333 | public int size() { | |
1334 | return fExcluded.length; | |
1335 | } | |
1336 | ||
1337 | @Override | |
1338 | public String get(int index) { | |
1339 | return fExcluded[index]; | |
1340 | } | |
1341 | ||
1342 | @Override | |
1343 | public int indexOf(Object o) { | |
1344 | if (o instanceof String) { | |
1345 | for (int i= 0; i < fExcluded.length; i++) { | |
1346 | if (o.equals(fExcluded[i])) | |
1347 | return i; | |
1348 | } | |
1349 | } | |
1350 | return -1; | |
1351 | } | |
1352 | ||
1353 | @Override | |
1354 | public boolean contains(Object o) { | |
1355 | return indexOf(o) != -1; | |
1356 | } | |
1357 | } | |
1358 | ||
1359 | ||
1360 | public static boolean hasFieldName(IJavaProject project, String name) { | |
1361 | String prefixes= project.getOption(JavaCore.CODEASSIST_FIELD_PREFIXES, true); | |
1362 | String suffixes= project.getOption(JavaCore.CODEASSIST_FIELD_SUFFIXES, true); | |
1363 | String staticPrefixes= project.getOption(JavaCore.CODEASSIST_STATIC_FIELD_PREFIXES, true); | |
1364 | String staticSuffixes= project.getOption(JavaCore.CODEASSIST_STATIC_FIELD_SUFFIXES, true); | |
1365 | ||
1366 | ||
1367 | return hasPrefixOrSuffix(prefixes, suffixes, name) | |
1368 | || hasPrefixOrSuffix(staticPrefixes, staticSuffixes, name); | |
1369 | } | |
1370 | ||
1371 | public static boolean hasParameterName(IJavaProject project, String name) { | |
1372 | String prefixes= project.getOption(JavaCore.CODEASSIST_ARGUMENT_PREFIXES, true); | |
1373 | String suffixes= project.getOption(JavaCore.CODEASSIST_ARGUMENT_SUFFIXES, true); | |
1374 | return hasPrefixOrSuffix(prefixes, suffixes, name); | |
1375 | } | |
1376 | ||
1377 | public static boolean hasLocalVariableName(IJavaProject project, String name) { | |
1378 | String prefixes= project.getOption(JavaCore.CODEASSIST_LOCAL_PREFIXES, true); | |
1379 | String suffixes= project.getOption(JavaCore.CODEASSIST_LOCAL_SUFFIXES, true); | |
1380 | return hasPrefixOrSuffix(prefixes, suffixes, name); | |
1381 | } | |
1382 | ||
1383 | public static boolean hasConstantName(IJavaProject project, String name) { | |
1384 | if (Character.isUpperCase(name.charAt(0))) | |
1385 | return true; | |
1386 | String prefixes= project.getOption(JavaCore.CODEASSIST_STATIC_FINAL_FIELD_PREFIXES, true); | |
1387 | String suffixes= project.getOption(JavaCore.CODEASSIST_STATIC_FINAL_FIELD_SUFFIXES, true); | |
1388 | return hasPrefixOrSuffix(prefixes, suffixes, name); | |
1389 | } | |
1390 | ||
1391 | ||
1392 | private static boolean hasPrefixOrSuffix(String prefixes, String suffixes, String name) { | |
1393 | final String listSeparartor= ","; //$NON-NLS-1$ | |
1394 | ||
1395 | StringTokenizer tok= new StringTokenizer(prefixes, listSeparartor); | |
1396 | while (tok.hasMoreTokens()) { | |
1397 | String curr= tok.nextToken(); | |
1398 | if (name.startsWith(curr)) { | |
1399 | return true; | |
1400 | } | |
1401 | } | |
1402 | ||
1403 | tok= new StringTokenizer(suffixes, listSeparartor); | |
1404 | while (tok.hasMoreTokens()) { | |
1405 | String curr= tok.nextToken(); | |
1406 | if (name.endsWith(curr)) { | |
1407 | return true; | |
1408 | } | |
1409 | } | |
1410 | return false; | |
1411 | } | |
1412 | ||
1413 | // -------------------- preference access ----------------------- | |
1414 | ||
1415 | public static boolean useThisForFieldAccess(IJavaProject project) { | |
1416 | return Boolean.valueOf(PreferenceConstants.getPreference(PreferenceConstants.CODEGEN_KEYWORD_THIS, project)).booleanValue(); | |
1417 | } | |
1418 | ||
1419 | public static boolean useIsForBooleanGetters(IJavaProject project) { | |
1420 | return Boolean.valueOf(PreferenceConstants.getPreference(PreferenceConstants.CODEGEN_IS_FOR_GETTERS, project)).booleanValue(); | |
1421 | } | |
1422 | ||
1423 | public static String getExceptionVariableName(IJavaProject project) { | |
1424 | return PreferenceConstants.getPreference(PreferenceConstants.CODEGEN_EXCEPTION_VAR_NAME, project); | |
1425 | } | |
1426 | ||
1427 | public static boolean doAddComments(IJavaProject project) { | |
1428 | return Boolean.valueOf(PreferenceConstants.getPreference(PreferenceConstants.CODEGEN_ADD_COMMENTS, project)).booleanValue(); | |
1429 | } | |
1430 | ||
1431 | /** | |
1432 | * Only to be used by tests | |
1433 | * | |
1434 | * @param templateId the template id | |
1435 | * @param pattern the new pattern | |
1436 | * @param project not used | |
1437 | */ | |
1438 | public static void setCodeTemplate(String templateId, String pattern, IJavaProject project) { | |
1439 | TemplateStore codeTemplateStore= JavaPlugin.getDefault().getCodeTemplateStore(); | |
1440 | TemplatePersistenceData data= codeTemplateStore.getTemplateData(templateId); | |
1441 | Template orig= data.getTemplate(); | |
1442 | Template copy= new Template(orig.getName(), orig.getDescription(), orig.getContextTypeId(), pattern, true); | |
1443 | data.setTemplate(copy); | |
1444 | } | |
1445 | ||
1446 | public static Template getCodeTemplate(String id, IJavaProject project) { | |
1447 | if (project == null) | |
1448 | return JavaPlugin.getDefault().getCodeTemplateStore().findTemplateById(id); | |
1449 | ProjectTemplateStore projectStore= new ProjectTemplateStore(project.getProject()); | |
1450 | try { | |
1451 | projectStore.load(); | |
1452 | } catch (IOException e) { | |
1453 | JavaPlugin.log(e); | |
1454 | } | |
1455 | return projectStore.findTemplateById(id); | |
1456 | } | |
1457 | ||
1458 | ||
1459 | public static ImportRewrite createImportRewrite(ICompilationUnit cu, boolean restoreExistingImports) throws JavaModelException { | |
1460 | return CodeStyleConfiguration.createImportRewrite(cu, restoreExistingImports); | |
1461 | } | |
1462 | ||
1463 | /** | |
1464 | * Returns a {@link ImportRewrite} using {@link ImportRewrite#create(CompilationUnit, boolean)} and | |
1465 | * configures the rewriter with the settings as specified in the JDT UI preferences. | |
1466 | * <p> | |
1467 | * This method sets {@link ImportRewrite#setUseContextToFilterImplicitImports(boolean)} to <code>true</code> | |
1468 | * iff the given AST has been resolved with bindings. Clients should always supply a context | |
1469 | * when they call one of the <code>addImport(...)</code> methods. | |
1470 | * </p> | |
1471 | * | |
1472 | * @param astRoot the AST root to create the rewriter on | |
1473 | * @param restoreExistingImports specifies if the existing imports should be kept or removed. | |
1474 | * @return the new rewriter configured with the settings as specified in the JDT UI preferences. | |
1475 | * | |
1476 | * @see ImportRewrite#create(CompilationUnit, boolean) | |
1477 | */ | |
1478 | public static ImportRewrite createImportRewrite(CompilationUnit astRoot, boolean restoreExistingImports) { | |
1479 | ImportRewrite rewrite= CodeStyleConfiguration.createImportRewrite(astRoot, restoreExistingImports); | |
1480 | if (astRoot.getAST().hasResolvedBindings()) { | |
1481 | rewrite.setUseContextToFilterImplicitImports(true); | |
1482 | } | |
1483 | return rewrite; | |
1484 | } | |
1485 | ||
1486 | } |