blob: 8ffc692c32f8d378200911db73bfbf33fc3cc43a [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2005 IBM Corporation and others.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* IBM Corporation - initial API and implementation
*******************************************************************************/
package org.eclipse.jdt.internal.corext.codemanipulation;
import org.eclipse.text.edits.InsertEdit;
import org.eclipse.text.edits.MultiTextEdit;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IPath;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.NullProgressMonitor;
import org.eclipse.core.runtime.OperationCanceledException;
import org.eclipse.core.runtime.SubProgressMonitor;
import org.eclipse.core.runtime.jobs.ISchedulingRule;
import org.eclipse.core.filebuffers.FileBuffers;
import org.eclipse.core.filebuffers.ITextFileBufferManager;
import org.eclipse.core.resources.IWorkspaceRunnable;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IRegion;
import org.eclipse.jface.text.TextUtilities;
import org.eclipse.jdt.core.ICompilationUnit;
import org.eclipse.jdt.core.IField;
import org.eclipse.jdt.core.IJavaElement;
import org.eclipse.jdt.core.IJavaProject;
import org.eclipse.jdt.core.IMember;
import org.eclipse.jdt.core.IMethod;
import org.eclipse.jdt.core.IType;
import org.eclipse.jdt.core.ITypeHierarchy;
import org.eclipse.jdt.core.JavaModelException;
import org.eclipse.jdt.core.Signature;
import org.eclipse.jdt.internal.corext.dom.TokenScanner;
import org.eclipse.jdt.internal.corext.util.MethodOverrideTester;
import org.eclipse.jdt.internal.corext.util.Strings;
import org.eclipse.jdt.internal.corext.util.SuperTypeHierarchyCache;
import org.eclipse.jdt.ui.CodeGeneration;
import org.eclipse.jdt.internal.ui.JavaUIStatus;
/**
* Add javadoc stubs to members. All members must belong to the same compilation unit.
* If the parent type is open in an editor, be sure to pass over its working copy.
*/
public class AddJavaDocStubOperation implements IWorkspaceRunnable {
private IMember[] fMembers;
public AddJavaDocStubOperation(IMember[] members) {
super();
fMembers= members;
}
private String createTypeComment(IType type, String lineDelimiter) throws CoreException {
String[] typeParameterNames= StubUtility.getTypeParameterNames(type.getTypeParameters());
return CodeGeneration.getTypeComment(type.getCompilationUnit(), type.getTypeQualifiedName('.'), typeParameterNames, lineDelimiter);
}
private String createMethodComment(IMethod meth, String lineDelimiter) throws CoreException {
IType declaringType= meth.getDeclaringType();
IMethod overridden= null;
if (!meth.isConstructor()) {
ITypeHierarchy hierarchy= SuperTypeHierarchyCache.getTypeHierarchy(declaringType);
MethodOverrideTester tester= new MethodOverrideTester(declaringType, hierarchy);
overridden= tester.findOverriddenMethod(meth, true);
}
return CodeGeneration.getMethodComment(meth, overridden, lineDelimiter);
}
private String createFieldComment(IField field, String lineDelimiter) throws JavaModelException, CoreException {
String typeName= Signature.toString(field.getTypeSignature());
String fieldName= field.getElementName();
return CodeGeneration.getFieldComment(field.getCompilationUnit(), typeName, fieldName, lineDelimiter);
}
/**
* @return Returns the scheduling rule for this operation
*/
public ISchedulingRule getScheduleRule() {
return ResourcesPlugin.getWorkspace().getRoot();
}
/**
* Runs the operation.
* @throws OperationCanceledException Runtime error thrown when operation is cancelled.
*/
public void run(IProgressMonitor monitor) throws CoreException, OperationCanceledException {
if (monitor == null) {
monitor= new NullProgressMonitor();
}
if (fMembers.length == 0) {
return;
}
try {
monitor.beginTask(CodeGenerationMessages.AddJavaDocStubOperation_description, fMembers.length + 2);
addJavadocComments(monitor);
} finally {
monitor.done();
}
}
private void addJavadocComments(IProgressMonitor monitor) throws CoreException {
ICompilationUnit cu= fMembers[0].getCompilationUnit();
ITextFileBufferManager manager= FileBuffers.getTextFileBufferManager();
IPath path= cu.getPath();
manager.connect(path, new SubProgressMonitor(monitor, 1));
try {
IDocument document= manager.getTextFileBuffer(path).getDocument();
String lineDelim= TextUtilities.getDefaultLineDelimiter(document);
MultiTextEdit edit= new MultiTextEdit();
for (int i= 0; i < fMembers.length; i++) {
IMember curr= fMembers[i];
int memberStartOffset= getMemberStartOffset(curr, document);
String comment= null;
switch (curr.getElementType()) {
case IJavaElement.TYPE:
comment= createTypeComment((IType) curr, lineDelim);
break;
case IJavaElement.FIELD:
comment= createFieldComment((IField) curr, lineDelim);
break;
case IJavaElement.METHOD:
comment= createMethodComment((IMethod) curr, lineDelim);
break;
}
if (comment == null) {
StringBuffer buf= new StringBuffer();
buf.append("/**").append(lineDelim); //$NON-NLS-1$
buf.append(" *").append(lineDelim); //$NON-NLS-1$
buf.append(" */").append(lineDelim); //$NON-NLS-1$
comment= buf.toString();
} else {
if (!comment.endsWith(lineDelim)) {
comment= comment + lineDelim;
}
}
final IJavaProject project= cu.getJavaProject();
IRegion region= document.getLineInformationOfOffset(memberStartOffset);
String line= document.get(region.getOffset(), region.getLength());
String indentString= Strings.getIndentString(line, project);
String indentedComment= Strings.changeIndent(comment, 0, project, indentString, lineDelim);
edit.addChild(new InsertEdit(memberStartOffset, indentedComment));
monitor.worked(1);
}
edit.apply(document); // apply all edits
} catch (BadLocationException e) {
throw new CoreException(JavaUIStatus.createError(IStatus.ERROR, e));
} finally {
manager.disconnect(path, new SubProgressMonitor(monitor, 1));
}
}
private int getMemberStartOffset(IMember curr, IDocument document) throws JavaModelException {
int offset= curr.getSourceRange().getOffset();
TokenScanner scanner= new TokenScanner(document);
try {
return scanner.getNextStartOffset(offset, true); // read to the first real non comment token
} catch (CoreException e) {
// ignore
}
return offset;
}
}