blob: 37e96d2ad819f481eca752f586dc1507843f3a36 [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2000, 2015 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.core.filebuffers.manipulation;
import java.util.Map;
import org.eclipse.core.internal.filebuffers.FileBuffersPlugin;
import org.eclipse.core.internal.filebuffers.Progress;
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.OperationCanceledException;
import org.eclipse.core.runtime.Status;
import org.eclipse.core.filebuffers.IFileBuffer;
import org.eclipse.core.filebuffers.IFileBufferStatusCodes;
import org.eclipse.core.filebuffers.ITextFileBuffer;
import org.eclipse.text.edits.TextEdit;
import org.eclipse.jface.text.BadLocationException;
import org.eclipse.jface.text.DocumentRewriteSession;
import org.eclipse.jface.text.DocumentRewriteSessionType;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentExtension4;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.TextUtilities;
/**
* Abstraction for a file buffer operation that works on text file buffers.
* Subclasses have to override the <code>computeTextEdits</code> method in
* order to provide a sequence of {@link org.eclipse.text.edits.TextEdit}
* objects.
*
* @since 3.1
*/
public abstract class TextFileBufferOperation implements IFileBufferOperation {
/**
* Computes and returns a text edit. Subclasses have to provide that method.
*
* @param textFileBuffer the text file buffer to manipulate
* @param progressMonitor the progress monitor
* @return the text edits describing the content manipulation
* @throws CoreException in case the computation failed
* @throws OperationCanceledException in case the progress monitor has been set to canceled
*/
protected abstract MultiTextEditWithProgress computeTextEdit(ITextFileBuffer textFileBuffer, IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException;
/**
* Returns the rewrite session type that corresponds to the text edit sequence.
*
* @return the rewrite session type
*/
protected abstract DocumentRewriteSessionType getDocumentRewriteSessionType();
private String fOperationName;
private DocumentRewriteSession fDocumentRewriteSession;
/**
* Creates a new operation with the given name.
*
* @param operationName the name of the operation
*/
protected TextFileBufferOperation(String operationName) {
fOperationName= operationName;
}
@Override
public String getOperationName() {
return fOperationName;
}
@Override
public void run(IFileBuffer fileBuffer, IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
if (fileBuffer instanceof ITextFileBuffer) {
ITextFileBuffer textFileBuffer= (ITextFileBuffer) fileBuffer;
IPath path= textFileBuffer.getLocation();
String taskName= path == null ? getOperationName() : path.lastSegment();
progressMonitor= Progress.getMonitor(progressMonitor);
progressMonitor.beginTask(taskName, 100);
try {
IProgressMonitor subMonitor= Progress.getSubMonitor(progressMonitor, 10);
MultiTextEditWithProgress edit= computeTextEdit(textFileBuffer, subMonitor);
subMonitor.done();
if (edit != null) {
Map<String, IDocumentPartitioner> stateData= startRewriteSession(textFileBuffer);
try {
subMonitor= Progress.getSubMonitor(progressMonitor, 90);
applyTextEdit(textFileBuffer, edit, subMonitor);
subMonitor.done();
} finally {
stopRewriteSession(textFileBuffer, stateData);
}
}
} finally {
progressMonitor.done();
}
}
}
private Map<String, IDocumentPartitioner> startRewriteSession(ITextFileBuffer fileBuffer) {
Map<String, IDocumentPartitioner> stateData= null;
IDocument document= fileBuffer.getDocument();
if (document instanceof IDocumentExtension4) {
IDocumentExtension4 extension= (IDocumentExtension4) document;
fDocumentRewriteSession= extension.startRewriteSession(getDocumentRewriteSessionType());
} else
stateData= TextUtilities.removeDocumentPartitioners(document);
return stateData;
}
private void stopRewriteSession(ITextFileBuffer fileBuffer, Map<String, IDocumentPartitioner> stateData) {
IDocument document= fileBuffer.getDocument();
if (document instanceof IDocumentExtension4) {
IDocumentExtension4 extension= (IDocumentExtension4) document;
extension.stopRewriteSession(fDocumentRewriteSession);
fDocumentRewriteSession= null;
} else if (stateData != null)
TextUtilities.addDocumentPartitioners(document, stateData);
}
private void applyTextEdit(ITextFileBuffer fileBuffer, MultiTextEditWithProgress textEdit, IProgressMonitor progressMonitor) throws CoreException, OperationCanceledException {
try {
textEdit.apply(fileBuffer.getDocument(), TextEdit.NONE, progressMonitor);
} catch (BadLocationException x) {
throw new CoreException(new Status(IStatus.ERROR, FileBuffersPlugin.PLUGIN_ID, IFileBufferStatusCodes.CONTENT_CHANGE_FAILED, "", x)); //$NON-NLS-1$
}
}
}