1 11 12 package org.eclipse.jdt.internal.ui.text.javadoc; 13 14 15 import org.eclipse.core.runtime.Assert; 16 import org.eclipse.core.runtime.CoreException; 17 18 import org.eclipse.jface.text.BadLocationException; 19 import org.eclipse.jface.text.DefaultIndentLineAutoEditStrategy; 20 import org.eclipse.jface.text.DocumentCommand; 21 import org.eclipse.jface.text.IDocument; 22 import org.eclipse.jface.text.IRegion; 23 import org.eclipse.jface.text.ITypedRegion; 24 import org.eclipse.jface.text.Region; 25 import org.eclipse.jface.text.TextUtilities; 26 27 import org.eclipse.ui.IEditorPart; 28 import org.eclipse.ui.IWorkbenchPage; 29 import org.eclipse.ui.IWorkbenchWindow; 30 import org.eclipse.ui.PlatformUI; 31 import org.eclipse.ui.texteditor.ITextEditorExtension3; 32 33 import org.eclipse.jdt.core.ICompilationUnit; 34 import org.eclipse.jdt.core.IJavaElement; 35 import org.eclipse.jdt.core.IJavaProject; 36 import org.eclipse.jdt.core.IMember; 37 import org.eclipse.jdt.core.IMethod; 38 import org.eclipse.jdt.core.ISourceRange; 39 import org.eclipse.jdt.core.IType; 40 import org.eclipse.jdt.core.JavaModelException; 41 42 import org.eclipse.jdt.internal.corext.codemanipulation.StubUtility; 43 import org.eclipse.jdt.internal.corext.util.JavaModelUtil; 44 import org.eclipse.jdt.internal.corext.util.MethodOverrideTester; 45 import org.eclipse.jdt.internal.corext.util.Strings; 46 import org.eclipse.jdt.internal.corext.util.SuperTypeHierarchyCache; 47 48 import org.eclipse.jdt.ui.CodeGeneration; 49 import org.eclipse.jdt.ui.IWorkingCopyManager; 50 import org.eclipse.jdt.ui.PreferenceConstants; 51 52 import org.eclipse.jdt.internal.ui.JavaPlugin; 53 54 55 58 public class JavaDocAutoIndentStrategy extends DefaultIndentLineAutoEditStrategy { 59 60 61 private final String fPartitioning; 62 63 68 public JavaDocAutoIndentStrategy(String partitioning) { 69 fPartitioning= partitioning; 70 } 71 72 80 private void indentAfterNewLine(IDocument d, DocumentCommand c) { 81 82 int offset= c.offset; 83 if (offset == -1 || d.getLength() == 0) 84 return; 85 86 try { 87 int p= (offset == d.getLength() ? offset - 1 : offset); 88 IRegion line= d.getLineInformationOfOffset(p); 89 90 int lineOffset= line.getOffset(); 91 int firstNonWS= findEndOfWhiteSpace(d, lineOffset, offset); 92 Assert.isTrue(firstNonWS >= lineOffset, "indentation must not be negative"); 94 StringBuffer buf= new StringBuffer (c.text); 95 IRegion prefix= findPrefixRange(d, line); 96 String indentation= d.get(prefix.getOffset(), prefix.getLength()); 97 int lengthToAdd= Math.min(offset - prefix.getOffset(), prefix.getLength()); 98 99 buf.append(indentation.substring(0, lengthToAdd)); 100 101 if (firstNonWS < offset) { 102 if (d.getChar(firstNonWS) == '/') { 103 buf.append(" * "); 106 if (isPreferenceTrue(PreferenceConstants.EDITOR_CLOSE_JAVADOCS) && isNewComment(d, offset)) { 107 c.shiftsCaret= false; 108 c.caretOffset= c.offset + buf.length(); 109 String lineDelimiter= TextUtilities.getDefaultLineDelimiter(d); 110 111 String endTag= lineDelimiter + indentation + " */"; 113 if (isPreferenceTrue(PreferenceConstants.EDITOR_ADD_JAVADOC_TAGS)) { 114 d.replace(offset, 0, endTag); 117 118 ICompilationUnit unit= getCompilationUnit(); 120 121 if (unit != null) { 122 try { 123 JavaModelUtil.reconcile(unit); 124 String string= createJavaDocTags(d, c, indentation, lineDelimiter, unit); 125 if (string != null && !string.trim().equals("*")) buf.append(string); 128 } catch (CoreException e) { 129 } 131 } 132 } else { 133 buf.append(endTag); 134 } 135 } 136 137 } 138 } 139 140 if (lengthToAdd < prefix.getLength()) 142 c.caretOffset= offset + prefix.getLength() - lengthToAdd; 143 c.text= buf.toString(); 144 145 } catch (BadLocationException excp) { 146 } 148 } 149 150 156 private boolean isPreferenceTrue(String preference) { 157 return JavaPlugin.getDefault().getPreferenceStore().getBoolean(preference); 158 } 159 160 173 private IRegion findPrefixRange(IDocument document, IRegion line) throws BadLocationException { 174 int lineOffset= line.getOffset(); 175 int lineEnd= lineOffset + line.getLength(); 176 int indentEnd= findEndOfWhiteSpace(document, lineOffset, lineEnd); 177 if (indentEnd < lineEnd && document.getChar(indentEnd) == '*') { 178 indentEnd++; 179 while (indentEnd < lineEnd && document.getChar(indentEnd) == ' ') 180 indentEnd++; 181 } 182 return new Region(lineOffset, indentEnd - lineOffset); 183 } 184 185 197 private String createJavaDocTags(IDocument document, DocumentCommand command, String indentation, String lineDelimiter, ICompilationUnit unit) 198 throws CoreException, BadLocationException 199 { 200 IJavaElement element= unit.getElementAt(command.offset); 201 if (element == null) 202 return null; 203 204 switch (element.getElementType()) { 205 case IJavaElement.TYPE: 206 return createTypeTags(document, command, indentation, lineDelimiter, (IType) element); 207 208 case IJavaElement.METHOD: 209 return createMethodTags(document, command, indentation, lineDelimiter, (IMethod) element); 210 211 default: 212 return null; 213 } 214 } 215 216 227 private String prepareTemplateComment(String comment, String indentation, IJavaProject project, String lineDelimiter) { 228 if (comment.endsWith("*/")) comment= comment.substring(0, comment.length() - 2); 231 comment= comment.trim(); 232 if (comment.startsWith("/*")) { if (comment.length() > 2 && comment.charAt(2) == '*') { 234 comment= comment.substring(3); } else { 236 comment= comment.substring(2); } 238 } 239 int nonSpace= 0; 241 int len= comment.length(); 242 while (nonSpace < len && Character.getType(comment.charAt(nonSpace)) == Character.SPACE_SEPARATOR) 243 nonSpace++; 244 comment= comment.substring(nonSpace); 245 246 return Strings.changeIndent(comment, 0, project, indentation, lineDelimiter); 247 } 248 249 private String createTypeTags(IDocument document, DocumentCommand command, String indentation, String lineDelimiter, IType type) 250 throws CoreException, BadLocationException 251 { 252 String [] typeParamNames= StubUtility.getTypeParameterNames(type.getTypeParameters()); 253 String comment= CodeGeneration.getTypeComment(type.getCompilationUnit(), type.getTypeQualifiedName('.'), typeParamNames, lineDelimiter); 254 if (comment != null) { 255 boolean javadocComment= comment.startsWith("/**"); if (!isFirstComment(document, command, type, javadocComment)) 257 return null; 258 return prepareTemplateComment(comment.trim(), indentation, type.getJavaProject(), lineDelimiter); 259 } 260 return null; 261 } 262 263 private String createMethodTags(IDocument document, DocumentCommand command, String indentation, String lineDelimiter, IMethod method) 264 throws CoreException, BadLocationException 265 { 266 IRegion partition= TextUtilities.getPartition(document, fPartitioning, command.offset, false); 267 IMethod inheritedMethod= getInheritedMethod(method); 268 String comment= CodeGeneration.getMethodComment(method, inheritedMethod, lineDelimiter); 269 if (comment != null) { 270 comment= comment.trim(); 271 boolean javadocComment= comment.startsWith("/**"); if (!isFirstComment(document, command, method, javadocComment)) 273 return null; 274 boolean isJavaDoc= partition.getLength() >= 3 && document.get(partition.getOffset(), 3).equals("/**"); if (javadocComment == isJavaDoc) { 276 return prepareTemplateComment(comment, indentation, method.getJavaProject(), lineDelimiter); 277 } 278 } 279 return null; 280 } 281 282 291 private boolean isFirstComment(IDocument document, DocumentCommand command, IMember member, boolean ignoreNonJavadoc) throws BadLocationException, JavaModelException { 292 IRegion partition= TextUtilities.getPartition(document, fPartitioning, command.offset, false); 293 ISourceRange sourceRange= member.getSourceRange(); 294 if (sourceRange == null || sourceRange.getOffset() != partition.getOffset()) 295 return false; 296 int srcOffset= sourceRange.getOffset(); 297 int srcLength= sourceRange.getLength(); 298 int nameRelativeOffset= member.getNameRange().getOffset() - srcOffset; 299 int partitionRelativeOffset= partition.getOffset() - srcOffset; 300 String token= ignoreNonJavadoc ? "/**" : "/*"; return document.get(srcOffset, srcLength).lastIndexOf(token, nameRelativeOffset) == partitionRelativeOffset; 302 } 303 304 310 private void indentAfterCommentEnd(IDocument d, DocumentCommand c) { 311 if (c.offset < 2 || d.getLength() == 0) { 312 return; 313 } 314 try { 315 if ("* ".equals(d.get(c.offset - 2, 2))) { c.length++; 318 c.offset--; 319 } 320 } catch (BadLocationException excp) { 321 } 323 } 324 325 333 private boolean isNewComment(IDocument document, int commandOffset) { 334 335 try { 336 int lineIndex= document.getLineOfOffset(commandOffset) + 1; 337 if (lineIndex >= document.getNumberOfLines()) 338 return true; 339 340 IRegion line= document.getLineInformation(lineIndex); 341 ITypedRegion partition= TextUtilities.getPartition(document, fPartitioning, commandOffset, false); 342 int partitionEnd= partition.getOffset() + partition.getLength(); 343 if (line.getOffset() >= partitionEnd) 344 return false; 345 346 if (document.getLength() == partitionEnd) 347 return true; 349 String comment= document.get(partition.getOffset(), partition.getLength()); 350 if (comment.indexOf("/*", 2) != -1) return true; 353 return false; 354 355 } catch (BadLocationException e) { 356 return false; 357 } 358 } 359 360 private boolean isSmartMode() { 361 IWorkbenchPage page= JavaPlugin.getActivePage(); 362 if (page != null) { 363 IEditorPart part= page.getActiveEditor(); 364 if (part instanceof ITextEditorExtension3) { 365 ITextEditorExtension3 extension= (ITextEditorExtension3) part; 366 return extension.getInsertMode() == ITextEditorExtension3.SMART_INSERT; 367 } 368 } 369 return false; 370 } 371 372 375 public void customizeDocumentCommand(IDocument document, DocumentCommand command) { 376 377 if (!isSmartMode()) 378 return; 379 380 if (command.text != null) { 381 if (command.length == 0) { 382 String [] lineDelimiters= document.getLegalLineDelimiters(); 383 int index= TextUtilities.endsWith(lineDelimiters, command.text); 384 if (index > -1) { 385 if (lineDelimiters[index].equals(command.text)) 387 indentAfterNewLine(document, command); 389 return; 390 } 391 } 392 393 if (command.text.equals("/")) { indentAfterCommentEnd(document, command); 395 return; 396 } 397 } 398 } 399 400 406 private static IMethod getInheritedMethod(IMethod method) throws JavaModelException { 407 IType declaringType= method.getDeclaringType(); 408 MethodOverrideTester tester= SuperTypeHierarchyCache.getMethodOverrideTester(declaringType); 409 return tester.findOverriddenMethod(method, true); 410 } 411 412 417 private static ICompilationUnit getCompilationUnit() { 418 419 IWorkbenchWindow window= PlatformUI.getWorkbench().getActiveWorkbenchWindow(); 420 if (window == null) 421 return null; 422 423 IWorkbenchPage page= window.getActivePage(); 424 if (page == null) 425 return null; 426 427 IEditorPart editor= page.getActiveEditor(); 428 if (editor == null) 429 return null; 430 431 IWorkingCopyManager manager= JavaPlugin.getDefault().getWorkingCopyManager(); 432 ICompilationUnit unit= manager.getWorkingCopy(editor.getEditorInput()); 433 if (unit == null) 434 return null; 435 436 return unit; 437 } 438 439 } 440 | Popular Tags |