blob: 836cb4436774ce491adaa69941694a864ae79c08 [file] [log] [blame]
package org.eclipse.cdt.internal.ui.editor;
/*
* (c) Copyright IBM Corp. 2000, 2001.
* All Rights Reserved.
*/
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.eclipse.cdt.core.model.CModelException;
import org.eclipse.cdt.core.model.CoreModel;
import org.eclipse.cdt.core.model.IBuffer;
import org.eclipse.cdt.core.model.IOpenable;
import org.eclipse.cdt.core.model.ITranslationUnit;
import org.eclipse.cdt.internal.core.model.IBufferFactory;
import org.eclipse.cdt.internal.core.model.IWorkingCopy;
import org.eclipse.cdt.internal.ui.CStatusConstants;
import org.eclipse.cdt.ui.CUIPlugin;
import org.eclipse.cdt.ui.IEditorInputDelegate;
import org.eclipse.core.resources.IFile;
import org.eclipse.core.resources.IResource;
import org.eclipse.core.resources.IStorage;
import org.eclipse.core.resources.ResourcesPlugin;
import org.eclipse.core.runtime.CoreException;
import org.eclipse.core.runtime.IProgressMonitor;
import org.eclipse.core.runtime.IStatus;
import org.eclipse.core.runtime.Status;
import org.eclipse.jface.text.AbstractDocument;
import org.eclipse.jface.text.DefaultLineTracker;
import org.eclipse.jface.text.Document;
import org.eclipse.jface.text.GapTextStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.jface.text.IDocumentPartitioner;
import org.eclipse.jface.text.source.IAnnotationModel;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.IStorageEditorInput;
import org.eclipse.ui.editors.text.FileDocumentProvider;
import org.eclipse.ui.part.FileEditorInput;
import org.eclipse.ui.texteditor.AbstractMarkerAnnotationModel;
public class CDocumentProvider extends FileDocumentProvider {
/**
* Bundle of all required informations to allow working copy management.
*/
protected class CDocument extends AbstractDocument {
/**
* Creates a new empty document.
*/
public CDocument() {
super();
setTextStore(new GapTextStore(50, 300));
setLineTracker(new DefaultLineTracker());
completeInitialization();
}
/**
* Creates a new document with the given initial content.
*
* @param initialContent the document's initial content
*/
public CDocument(String initialContent) {
super();
setTextStore(new GapTextStore(50, 300));
setLineTracker(new DefaultLineTracker());
getStore().set(initialContent);
getTracker().set(initialContent);
completeInitialization();
}
};
/**
* Bundle of all required informations to allow working copy management.
*/
protected class TranslationUnitFileInfo extends FileInfo {
IWorkingCopy fCopy;
TranslationUnitFileInfo(IDocument document, IAnnotationModel model, FileSynchronizer fileSynchronizer, IWorkingCopy copy) {
super(document, model, fileSynchronizer);
fCopy= copy;
}
void setModificationStamp(long timeStamp) {
fModificationStamp= timeStamp;
}
};
/**
* Creates <code>IBuffer</code>s based on documents.
*/
protected class BufferFactory implements IBufferFactory {
private IDocument internalGetDocument(IFileEditorInput input) throws CoreException {
IDocument document= getDocument(input);
if (document != null)
return document;
return CDocumentProvider.this.createDocument(input);
}
public IBuffer createBuffer(IOpenable owner) {
if (owner instanceof IWorkingCopy) {
IWorkingCopy unit= (IWorkingCopy) owner;
ITranslationUnit original= (ITranslationUnit) unit.getOriginalElement();
IResource resource= original.getResource();
if (resource instanceof IFile) {
IFileEditorInput providerKey= new FileEditorInput((IFile) resource);
IDocument document= null;
IStatus status= null;
try {
document= internalGetDocument(providerKey);
} catch (CoreException x) {
status= x.getStatus();
document= new Document();
initializeDocument(document);
}
DocumentAdapter adapter= new DocumentAdapter(unit, document, new DefaultLineTracker(), CDocumentProvider.this, providerKey);
adapter.setStatus(status);
return adapter;
}
}
return DocumentAdapter.NULL;
}
};
/** The buffer factory */
private IBufferFactory fBufferFactory= new BufferFactory();
/** Indicates whether the save has been initialized by this provider */
private boolean fIsAboutToSave= false;
/**
* @see AbstractDocumentProvider#createDocument(Object)
*/
protected IDocument createDocument(Object element) throws CoreException {
IDocument document = null;
IStorage storage = null;
if (element instanceof IEditorInputDelegate) {
if (((IEditorInputDelegate) element).getDelegate() != null)
return createDocument(((IEditorInputDelegate) element).getDelegate());
else
storage = ((IEditorInputDelegate) element).getStorage();
}
if (element instanceof IStorageEditorInput)
storage= ((IStorageEditorInput) element).getStorage();
if ( storage != null ) {
document = new CDocument();
setDocumentContent(document, storage.getContents(), getDefaultEncoding());
}
//IDocument document= super.createDocument(element);
initializeDocument(document);
return document;
}
/*
* @see AbstractDocumentProvider#createAnnotationModel(Object)
*/
protected IAnnotationModel createAnnotationModel(Object element) throws CoreException {
if ( element instanceof IEditorInputDelegate && ((IEditorInputDelegate)element).getDelegate() != null )
return createAnnotationModel( ((IEditorInputDelegate)element).getDelegate() );
if (element instanceof IFileEditorInput) {
IFileEditorInput input= (IFileEditorInput) element;
return new CMarkerAnnotationModel(input.getFile());
} else if (element instanceof IStorageEditorInput) {
// Fall back on the adapter.
IStorageEditorInput input = (IStorageEditorInput) element;
IResource res = (IResource)input.getAdapter(IResource.class);
if (res != null && res.exists()) {
return new CMarkerAnnotationModel(res);
}
}
return super.createAnnotationModel(element);
}
/*
* @see AbstractDocumentProvider#createElementInfo(Object)
*/
protected ElementInfo createElementInfo(Object element) throws CoreException {
if ( !(element instanceof IFileEditorInput))
return super.createElementInfo(element);
IFileEditorInput input= (IFileEditorInput) element;
ITranslationUnit original= createTranslationUnit(input.getFile());
if (original != null) {
try {
try {
refreshFile(input.getFile());
} catch (CoreException x) {
handleCoreException(x, CEditorMessages.getString("TranslationUnitDocumentProvider.error.createElementInfo")); //$NON-NLS-1$
}
IAnnotationModel m= createAnnotationModel(input);
IBufferFactory factory = getBufferFactory();
IWorkingCopy c= (IWorkingCopy) original.getSharedWorkingCopy(getProgressMonitor(), factory);
DocumentAdapter a= null;
try {
a= (DocumentAdapter) c.getBuffer();
} catch (ClassCastException x) {
IStatus status= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, CStatusConstants.TEMPLATE_IO_EXCEPTION, "Shared working copy has wrong buffer", x); //$NON-NLS-1$
throw new CoreException(status);
}
FileSynchronizer f= new FileSynchronizer(input);
f.install();
TranslationUnitFileInfo info= new TranslationUnitFileInfo(a.getDocument(), m, f, c);
info.setModificationStamp(computeModificationStamp(input.getFile()));
info.fStatus= a.getStatus();
info.fEncoding= getPersistedEncoding(input);
return info;
} catch (CModelException x) {
throw new CoreException(x.getStatus());
}
} else {
return super.createElementInfo(element);
}
}
/*
* Creates a translation unit using the core model
*/
protected ITranslationUnit createTranslationUnit(IFile file) {
Object element= CoreModel.getDefault().create(file);
if (element instanceof ITranslationUnit)
return (ITranslationUnit) element;
return null;
}
/*
* @see AbstractDocumentProvider#disposeElementInfo(Object, ElementInfo)
*/
protected void disposeElementInfo(Object element, ElementInfo info) {
if (info instanceof TranslationUnitFileInfo) {
TranslationUnitFileInfo cuInfo= (TranslationUnitFileInfo) info;
cuInfo.fCopy.destroy();
}
super.disposeElementInfo(element, info);
}
/*
* @see AbstractDocumentProvider#doSaveDocument(IProgressMonitor, Object, IDocument, boolean)
*/
protected void doSaveDocument(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
ElementInfo elementInfo= getElementInfo(element);
if (elementInfo instanceof TranslationUnitFileInfo) {
TranslationUnitFileInfo info= (TranslationUnitFileInfo) elementInfo;
// update structure, assumes lock on info.fCopy
info.fCopy.reconcile();
ITranslationUnit original= (ITranslationUnit) info.fCopy.getOriginalElement();
IResource resource= original.getResource();
if (resource == null) {
// underlying resource has been deleted, just recreate file, ignore the rest
super.doSaveDocument(monitor, element, document, overwrite);
return;
}
if (resource != null && !overwrite)
checkSynchronizationState(info.fModificationStamp, resource);
// if (fSavePolicy != null)
// fSavePolicy.preSave(info.fCopy);
// inform about the upcoming content change
fireElementStateChanging(element);
try {
fIsAboutToSave= true;
// commit working copy
info.fCopy.commit(overwrite, monitor);
} catch (CoreException x) {
// inform about the failure
fireElementStateChangeFailed(element);
throw x;
} catch (RuntimeException x) {
// inform about the failure
fireElementStateChangeFailed(element);
throw x;
} finally {
fIsAboutToSave= false;
}
// If here, the dirty state of the editor will change to "not dirty".
// Thus, the state changing flag will be reset.
AbstractMarkerAnnotationModel model= (AbstractMarkerAnnotationModel) info.fModel;
model.updateMarkers(info.fDocument);
if (resource != null)
info.setModificationStamp(computeModificationStamp(resource));
// if (fSavePolicy != null) {
// ICompilationUnit unit= fSavePolicy.postSave(original);
// if (unit != null) {
// IResource r= unit.getResource();
// IMarker[] markers= r.findMarkers(IMarker.MARKER, true, IResource.DEPTH_ZERO);
// if (markers != null && markers.length > 0) {
// for (int i= 0; i < markers.length; i++)
// model.updateMarker(markers[i], info.fDocument, null);
// }
// }
// }
} else {
super.doSaveDocument(monitor, element, document, overwrite);
}
}
/**
* Gets the BufferFactory.
*/
public IBufferFactory getBufferFactory() {
return fBufferFactory;
}
/**
* Returns the underlying resource for the given element.
*
* @param the element
* @return the underlying resource of the given element
*/
public IResource getUnderlyingResource(Object element) {
if (element instanceof IFileEditorInput) {
IFileEditorInput input= (IFileEditorInput) element;
return input.getFile();
}
return null;
}
public IWorkingCopy getWorkingCopy(IEditorInput element) {
ElementInfo elementInfo= getElementInfo(element);
if (elementInfo instanceof TranslationUnitFileInfo) {
TranslationUnitFileInfo info= (TranslationUnitFileInfo) elementInfo;
return info.fCopy;
}
return null;
}
protected void initializeDocument(IDocument document) {
if (document != null) {
IDocumentPartitioner partitioner= CUIPlugin.getDefault().getTextTools().createDocumentPartitioner();
partitioner.connect(document);
document.setDocumentPartitioner(partitioner);
}
}
/**
* Saves the content of the given document to the given element.
* This is only performed when this provider initiated the save.
*
* @param monitor the progress monitor
* @param element the element to which to save
* @param document the document to save
* @param overwrite <code>true</code> if the save should be enforced
*/
public void saveDocumentContent(IProgressMonitor monitor, Object element, IDocument document, boolean overwrite) throws CoreException {
if (!fIsAboutToSave)
return;
if (element instanceof IFileEditorInput) {
IFileEditorInput input= (IFileEditorInput) element;
try {
String encoding= getEncoding(element);
if (encoding == null)
encoding= ResourcesPlugin.getEncoding();
InputStream stream= new ByteArrayInputStream(document.get().getBytes(encoding));
IFile file= input.getFile();
file.setContents(stream, overwrite, true, monitor);
} catch (IOException x) {
IStatus s= new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, IStatus.OK, x.getMessage(), x);
throw new CoreException(s);
}
}
}
/**
*
*/
public void shutdown() {
// TODO Auto-generated method stub
}
/**
* @param input
* @return
*/
public boolean isConnected(IEditorInput input) {
return getElementInfo(input) != null;
}
/**
* @see org.eclipse.ui.texteditor.IDocumentProviderExtension#getStatus(Object)
*/
public IStatus getStatus(Object element) {
if (element instanceof IEditorInputDelegate) {
if (((IEditorInputDelegate) element).getDelegate() != null)
return super.getStatus(((IEditorInputDelegate) element).getDelegate());
else
return new Status(IStatus.INFO,CUIPlugin.getPluginId(),0,"",null);
}
return super.getStatus(element);
}
}