diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java index 804d4f23896..1c21587bff5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/CFileElementWorkingCopy.java @@ -7,19 +7,17 @@ package org.eclipse.cdt.internal.ui; import java.io.IOException; +import org.eclipse.cdt.internal.core.model.WorkingCopy; +import org.eclipse.core.resources.IStorage; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.Path; import org.eclipse.jface.text.IDocument; +import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IStorageEditorInput; -import org.eclipse.ui.IEditorInput; import org.eclipse.ui.texteditor.IDocumentProvider; -import org.eclipse.core.resources.IStorage; -import org.eclipse.core.runtime.Path; -import org.eclipse.core.runtime.CoreException; - -import org.eclipse.cdt.internal.core.model.TranslationUnit; - -public class CFileElementWorkingCopy extends TranslationUnit { +public class CFileElementWorkingCopy extends WorkingCopy { private IDocumentProvider fProvider; //private IFileEditorInput input; @@ -29,7 +27,7 @@ public class CFileElementWorkingCopy extends TranslationUnit { * Creates a working copy of this element */ public CFileElementWorkingCopy(IFileEditorInput fileInput, IDocumentProvider provider) throws CoreException { - super(null, fileInput.getFile()); + super(null, fileInput.getFile(), null); input= fileInput; fProvider= provider; } @@ -38,7 +36,7 @@ public class CFileElementWorkingCopy extends TranslationUnit { * Creates a working copy of this element */ public CFileElementWorkingCopy(IStorageEditorInput StoreInput, IDocumentProvider provider) throws CoreException { - super(null, new Path(StoreInput.getName())); + super(null, new Path(StoreInput.getName()), null); input = StoreInput; fProvider = provider; IStorage storage = StoreInput.getStorage(); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java index 006da940cbb..1a9e83e4b03 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CContentOutlinePage.java @@ -8,11 +8,16 @@ package org.eclipse.cdt.internal.ui.editor; import java.util.ArrayList; import java.util.Iterator; -import org.eclipse.swt.SWT; -import org.eclipse.swt.widgets.Composite; -import org.eclipse.swt.widgets.Control; -import org.eclipse.swt.widgets.Menu; - +import org.eclipse.cdt.core.model.ICElement; +import org.eclipse.cdt.internal.core.model.WorkingCopy; +import org.eclipse.cdt.internal.ui.CFileElementWorkingCopy; +import org.eclipse.cdt.internal.ui.StandardCElementLabelProvider; +import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; +import org.eclipse.cdt.ui.CElementContentProvider; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.core.runtime.Status; import org.eclipse.jface.action.IMenuListener; import org.eclipse.jface.action.IMenuManager; import org.eclipse.jface.action.IToolBarManager; @@ -25,29 +30,21 @@ import org.eclipse.jface.viewers.IStructuredSelection; import org.eclipse.jface.viewers.SelectionChangedEvent; import org.eclipse.jface.viewers.StructuredSelection; import org.eclipse.jface.viewers.TreeViewer; - +import org.eclipse.swt.SWT; +import org.eclipse.swt.widgets.Composite; +import org.eclipse.swt.widgets.Control; +import org.eclipse.swt.widgets.Menu; import org.eclipse.ui.IActionBars; +import org.eclipse.ui.IEditorInput; import org.eclipse.ui.IFileEditorInput; import org.eclipse.ui.IStorageEditorInput; -import org.eclipse.ui.IEditorInput; import org.eclipse.ui.part.Page; import org.eclipse.ui.texteditor.IDocumentProvider; - import org.eclipse.ui.views.contentoutline.IContentOutlinePage; -import org.eclipse.core.runtime.CoreException; -import org.eclipse.core.runtime.Status; -import org.eclipse.core.runtime.IStatus; - -import org.eclipse.cdt.core.model.ICElement; -import org.eclipse.cdt.internal.ui.CFileElementWorkingCopy; -import org.eclipse.cdt.internal.ui.StandardCElementLabelProvider; -import org.eclipse.cdt.internal.ui.util.ProblemTreeViewer; -import org.eclipse.cdt.ui.CElementContentProvider; -import org.eclipse.cdt.ui.CUIPlugin; public class CContentOutlinePage extends Page implements IContentOutlinePage, ISelectionChangedListener { private CEditor fEditor; - private CFileElementWorkingCopy fInput; + private WorkingCopy fInput; private ProblemTreeViewer treeViewer; private ListenerList selectionChangedListeners = new ListenerList(); @@ -73,7 +70,8 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS public void contentUpdated() { if (fInput != null) { try { - fInput.update(); + //fInput.update(); + fInput.reconcile(); } catch (CoreException e) { CUIPlugin.getDefault().log(e.getStatus()); fInput= null; @@ -154,13 +152,15 @@ public class CContentOutlinePage extends Page implements IContentOutlinePage, IS IEditorInput editorInput= (IEditorInput)fEditor.getEditorInput(); IDocumentProvider provider= fEditor.getDocumentProvider(); try { - if (editorInput instanceof IFileEditorInput) - //fInput = ((CUIPlugin.ElementFactory)plugin.getCCore()).createWorkingCopy((IFileEditorInput)editorInput, provider); - fInput = new CFileElementWorkingCopy((IFileEditorInput)editorInput, provider); - else if (editorInput instanceof IStorageEditorInput) + if (editorInput instanceof IFileEditorInput){ + //fInput = new CFileElementWorkingCopy((IFileEditorInput)editorInput, provider); + IWorkingCopyManager wcManager = CUIPlugin.getDefault().getWorkingCopyManager(); + fInput = (WorkingCopy)wcManager.getWorkingCopy(editorInput); + } else if (editorInput instanceof IStorageEditorInput){ + // CHECKPOINT: do we create a CFileElementWorkingCopy or just a working copy for the IStorageEditorInput? //fInput = ((CUIPlugin.ElementFactory)plugin.getCCore()).createWorkingCopy((IStorageEditorInput)editorInput, provider); fInput = new CFileElementWorkingCopy((IStorageEditorInput)editorInput, provider); - else + } else throw new CoreException(new Status(IStatus.ERROR, CUIPlugin.PLUGIN_ID, 0, "no Editor Input", null)); treeViewer.setInput(fInput); diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java index ecaba1b80d2..1efd5f263aa 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/CDocumentProvider.java @@ -5,23 +5,44 @@ package org.eclipse.cdt.internal.ui.editor; * 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.ICOpenable; +import org.eclipse.cdt.core.model.ITranslationUnit; +import org.eclipse.cdt.internal.core.model.IBuffer; +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.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.IDocumentExtension; import org.eclipse.jface.text.IDocumentListener; 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 { +public class CDocumentProvider extends FileDocumentProvider implements IWorkingCopyManager { static private class RegisteredReplace { IDocumentListener fOwner; @@ -62,6 +83,74 @@ public class CDocumentProvider extends FileDocumentProvider { } }; + /** + * 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 IBuffers 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(ICOpenable owner) { + try { + 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; + } + + } + } catch (CModelException e) { + return DocumentAdapter.NULL; + } + 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) */ @@ -77,11 +166,7 @@ public class CDocumentProvider extends FileDocumentProvider { return null; } //IDocument document= super.createDocument(element); - if (document != null) { - IDocumentPartitioner partitioner= CUIPlugin.getDefault().getTextTools().createDocumentPartitioner(); - partitioner.connect(document); - document.setDocumentPartitioner(partitioner); - } + initializeDocument(document); return document; } @@ -103,4 +188,214 @@ public class CDocumentProvider extends FileDocumentProvider { 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); + IWorkingCopy c= (IWorkingCopy) original.getSharedWorkingCopy(getProgressMonitor(), fBufferFactory); + + 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 true 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); + } + } + } + + } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DocumentAdapter.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DocumentAdapter.java new file mode 100644 index 00000000000..3eb4584240e --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/DocumentAdapter.java @@ -0,0 +1,486 @@ +package org.eclipse.cdt.internal.ui.editor; + +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * Rational Software - Initial API and implementation +***********************************************************************/ + + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.core.model.ICOpenable; +import org.eclipse.cdt.internal.core.model.BufferChangedEvent; +import org.eclipse.cdt.internal.core.model.IBuffer; +import org.eclipse.cdt.internal.core.model.IBufferChangedListener; +import org.eclipse.core.resources.IResource; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.IStatus; +import org.eclipse.jface.text.BadLocationException; +import org.eclipse.jface.text.DocumentEvent; +import org.eclipse.jface.text.IDocument; +import org.eclipse.jface.text.IDocumentListener; +import org.eclipse.jface.text.ILineTracker; +import org.eclipse.jface.text.IRegion; +import org.eclipse.jface.util.Assert; +import org.eclipse.swt.widgets.Display; + + +/** + * Adapts IDocument to IBuffer. Uses the + * same algorithm as the text widget to determine the buffer's line delimiter. + * All text inserted into the buffer is converted to this line delimiter. + * This class is public for test purposes only. + * + * This class is similar to the JDT DocumentAdapter class. + */ +public class DocumentAdapter implements IBuffer, IDocumentListener { + + /** + * Internal implementation of a NULL instanceof IBuffer. + */ + static private class NullBuffer implements IBuffer { + + public void addBufferChangedListener(IBufferChangedListener listener) {} + + public void append(char[] text) {} + + public void append(String text) {} + + public void close() {} + + public char getChar(int position) { + return 0; + } + + public char[] getCharacters() { + return null; + } + + public String getContents() { + return null; + } + + public int getLength() { + return 0; + } + + public ICOpenable getOwner() { + return null; + } + + public String getText(int offset, int length) { + return null; + } + + public IResource getUnderlyingResource() { + return null; + } + + public boolean hasUnsavedChanges() { + return false; + } + + public boolean isClosed() { + return false; + } + + public boolean isReadOnly() { + return true; + } + + public void removeBufferChangedListener(IBufferChangedListener listener) {} + + public void replace(int position, int length, char[] text) {} + + public void replace(int position, int length, String text) {} + + public void save(IProgressMonitor progress, boolean force) throws CModelException {} + + public void setContents(char[] contents) {} + + public void setContents(String contents) {} + }; + + + /** NULL implementing IBuffer */ + public final static IBuffer NULL= new NullBuffer(); + /* + * @see IBuffer#addBufferChangedListener(IBufferChangedListener) + */ + public void addBufferChangedListener(IBufferChangedListener listener) { + Assert.isNotNull(listener); + if (!fBufferListeners.contains(listener)) + fBufferListeners.add(listener); + } + /** + * Executes a document set content call in the ui thread. + */ + protected class DocumentSetCommand implements Runnable { + + private String fContents; + + public void run() { + fDocument.set(fContents); + } + + public void set(String contents) { + fContents= contents; + Display.getDefault().syncExec(this); + } + }; + /** + * Executes a document replace call in the ui thread. + */ + protected class DocumentReplaceCommand implements Runnable { + + private int fOffset; + private int fLength; + private String fText; + + public void run() { + try { + fDocument.replace(fOffset, fLength, fText); + } catch (BadLocationException x) { + // ignore + } + } + + public void replace(int offset, int length, String text) { + fOffset= offset; + fLength= length; + fText= text; + Display.getDefault().syncExec(this); + } + }; + + private ICOpenable fOwner; + private IDocument fDocument; + private DocumentSetCommand fSetCmd= new DocumentSetCommand(); + private DocumentReplaceCommand fReplaceCmd= new DocumentReplaceCommand(); + + private Object fProviderKey; + private CDocumentProvider fProvider; + private String fLineDelimiter; + private ILineTracker fLineTracker; + + private List fBufferListeners= new ArrayList(3); + + private IStatus fStatus; + + + public DocumentAdapter(ICOpenable owner, IDocument document, ILineTracker lineTracker, CDocumentProvider provider, Object providerKey) { + + Assert.isNotNull(document); + Assert.isNotNull(lineTracker); + + fOwner= owner; + fDocument= document; + fLineTracker= lineTracker; + fProvider= provider; + fProviderKey= providerKey; + + fDocument.addPrenotifiedDocumentListener(this); + + } + /** + * Sets the status of this document adapter. + */ + public void setStatus(IStatus status) { + fStatus= status; + } + + /** + * Returns the status of this document adapter. + */ + public IStatus getStatus() { + return fStatus; + } + + /** + * Returns the adapted document. + * + * @return the adapted document + */ + public IDocument getDocument() { + return fDocument; + } + /** + * Returns the line delimiter of this buffer. As a document has a set of + * valid line delimiters, this set must be reduced to size 1. + */ + protected String getLineDelimiter() { + + if (fLineDelimiter == null) { + + try { + fLineDelimiter= fDocument.getLineDelimiter(0); + } catch (BadLocationException x) { + } + + if (fLineDelimiter == null) { + /* + * Follow up fix for: 1GF5UU0: ITPJUI:WIN2000 - "Organize Imports" in java editor inserts lines in wrong format + * The line delimiter must always be a legal document line delimiter. + */ + String sysLineDelimiter= System.getProperty("line.separator"); //$NON-NLS-1$ + String[] delimiters= fDocument.getLegalLineDelimiters(); + Assert.isTrue(delimiters.length > 0); + for (int i= 0; i < delimiters.length; i++) { + if (delimiters[i].equals(sysLineDelimiter)) { + fLineDelimiter= sysLineDelimiter; + break; + } + } + + if (fLineDelimiter == null) { + // system line delimiter is not a legal document line delimiter + fLineDelimiter= delimiters[0]; + } + } + } + + return fLineDelimiter; + } + + /** + * Converts the given string to the line delimiter of this buffer. + * This method is public for test purposes only. + */ + public String normalize(String text) { + fLineTracker.set(text); + + int lines= fLineTracker.getNumberOfLines(); + if (lines <= 1) + return text; + + StringBuffer buffer= new StringBuffer(text); + + try { + IRegion previous= fLineTracker.getLineInformation(0); + for (int i= 1; i < lines; i++) { + int lastLineEnd= previous.getOffset() + previous.getLength(); + int lineStart= fLineTracker.getLineInformation(i).getOffset(); + fLineTracker.replace(lastLineEnd, lineStart - lastLineEnd, getLineDelimiter()); + buffer.replace(lastLineEnd, lineStart, getLineDelimiter()); + previous= fLineTracker.getLineInformation(i); + } + + // last line + String delimiter= fLineTracker.getLineDelimiter(lines -1); + if (delimiter != null && delimiter.length() > 0) + buffer.replace(previous.getOffset() + previous.getLength(), buffer.length(), getLineDelimiter()); + + return buffer.toString(); + } catch (BadLocationException x) { + } + + return text; + } + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#append(char) + */ + public void append(char[] text) { + append(new String(text)); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#append(java.lang.String) + */ + public void append(String text) { + fReplaceCmd.replace(fDocument.getLength(), 0, normalize(text)); + } + + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#close() + */ + public void close() { + if (isClosed()) + return; + + IDocument d= fDocument; + fDocument= null; + d.removePrenotifiedDocumentListener(this); + + fireBufferChanged(new BufferChangedEvent(this, 0, 0, null)); + fBufferListeners.clear(); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getChar(int) + */ + public char getChar(int position) { + try { + return fDocument.getChar(position); + } catch (BadLocationException x) { + throw new ArrayIndexOutOfBoundsException(); + } + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getCharacters() + */ + public char[] getCharacters() { + String content= getContents(); + return content == null ? null : content.toCharArray(); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getContents() + */ + public String getContents() { + return fDocument.get(); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getLength() + */ + public int getLength() { + return fDocument.getLength(); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getOwner() + */ + public ICOpenable getOwner() { + return (ICOpenable) fOwner; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getText(int, int) + */ + public String getText(int offset, int length) { + try { + return fDocument.get(offset, length); + } catch (BadLocationException x) { + throw new ArrayIndexOutOfBoundsException(); + } + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#getUnderlyingResource() + */ + public IResource getUnderlyingResource() { + //return null; + return fProvider != null ? fProvider.getUnderlyingResource(fProviderKey) : null; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#hasUnsavedChanges() + */ + public boolean hasUnsavedChanges() { + //return false; + return fProvider != null ? fProvider.canSaveDocument(fProviderKey) : false; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#isClosed() + */ + public boolean isClosed() { + return fDocument == null; + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#isReadOnly() + */ + public boolean isReadOnly() { + //return false; + IResource resource= getUnderlyingResource(); + return resource == null ? true : resource.isReadOnly(); + } + + /* + * @see IBuffer#removeBufferChangedListener(IBufferChangedListener) + */ + public void removeBufferChangedListener(IBufferChangedListener listener) { + Assert.isNotNull(listener); + fBufferListeners.remove(listener); + } + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#replace(int, int, char) + */ + public void replace(int position, int length, char[] text) { + replace(position, length, new String(text)); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#replace(int, int, java.lang.String) + */ + public void replace(int position, int length, String text) { + fReplaceCmd.replace(position, length, normalize(text)); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#save(org.eclipse.core.runtime.IProgressMonitor, boolean) + */ + public void save(IProgressMonitor progress, boolean force) throws CModelException { + if (fProvider != null) { + try { + fProvider.saveDocumentContent(progress, fProviderKey, fDocument, force); + } catch (CoreException e) { + throw new CModelException(e); + } + } + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#setContents(char) + */ + public void setContents(char[] contents) { + setContents(new String(contents)); + } + + /** + * @see org.eclipse.cdt.internal.core.model.IBuffer#setContents(java.lang.String) + */ + public void setContents(String contents) { + int oldLength= fDocument.getLength(); + + if (contents == null) { + + if (oldLength != 0) + fSetCmd.set(""); //$NON-NLS-1$ + + } else { + + // set only if different + String newContents= normalize(contents); + int newLength= newContents.length(); + + if (oldLength != newLength || !newContents.equals(fDocument.get())) + fSetCmd.set(newContents); + } + } + /* + * @see IDocumentListener#documentAboutToBeChanged(DocumentEvent) + */ + public void documentAboutToBeChanged(DocumentEvent event) { + // there is nothing to do here + } + + /* + * @see IDocumentListener#documentChanged(DocumentEvent) + */ + public void documentChanged(DocumentEvent event) { + fireBufferChanged(new BufferChangedEvent(this, event.getOffset(), event.getLength(), event.getText())); + } + + private void fireBufferChanged(BufferChangedEvent event) { + if (fBufferListeners != null && fBufferListeners.size() > 0) { + Iterator e= new ArrayList(fBufferListeners).iterator(); + while (e.hasNext()) + ((IBufferChangedListener) e.next()).bufferChanged(event); + } + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IWorkingCopyManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IWorkingCopyManager.java new file mode 100644 index 00000000000..a87b46ad0bb --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/IWorkingCopyManager.java @@ -0,0 +1,34 @@ +package org.eclipse.cdt.internal.ui.editor; + +/********************************************************************** + * Copyright (c) 2002,2003 Rational Software Corporation and others. + * All rights reserved. This program and the accompanying materials + * are made available under the terms of the Common Public License v0.5 + * which accompanies this distribution, and is available at + * http://www.eclipse.org/legal/cpl-v05.html + * + * Contributors: + * Rational Software - Initial API and implementation +***********************************************************************/ + +import org.eclipse.cdt.internal.core.model.IWorkingCopy; +import org.eclipse.ui.IEditorInput; + +/** + * Interface for accessing working copies of ITranslationUnit + * objects. The original Translation unit is only given indirectly by means of + * an IEditorInput. + *

+ * This interface is not intended to be implemented by clients. + *

+ * + * @see CUIPlugin#getWorkingCopyManager + * + * This interface is similar to the JDT IWorkingCopyManager. + */ + +public interface IWorkingCopyManager { + + IWorkingCopy getWorkingCopy(IEditorInput input); + +} \ No newline at end of file diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java index b394fc6da98..94ad30e70dd 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/CReconcilingStrategy.java @@ -5,12 +5,19 @@ package org.eclipse.cdt.internal.ui.text; * All Rights Reserved. */ +import org.eclipse.cdt.core.model.CModelException; +import org.eclipse.cdt.internal.core.model.IWorkingCopy; import org.eclipse.cdt.internal.ui.editor.CContentOutlinePage; import org.eclipse.cdt.internal.ui.editor.CEditor; +import org.eclipse.cdt.internal.ui.editor.IWorkingCopyManager; +import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.core.runtime.IProgressMonitor; import org.eclipse.jface.text.IDocument; import org.eclipse.jface.text.IRegion; import org.eclipse.jface.text.reconciler.DirtyRegion; import org.eclipse.jface.text.reconciler.IReconcilingStrategy; +import org.eclipse.ui.texteditor.IDocumentProvider; +import org.eclipse.ui.texteditor.ITextEditor; public class CReconcilingStrategy implements IReconcilingStrategy { @@ -18,11 +25,18 @@ public class CReconcilingStrategy implements IReconcilingStrategy { private CContentOutlinePage fOutliner; private int fLastRegionOffset; + private ITextEditor fEditor; + private IWorkingCopyManager fManager; + private IDocumentProvider fDocumentProvider; + private IProgressMonitor fProgressMonitor; public CReconcilingStrategy(CEditor editor) { fOutliner= editor.getOutlinePage(); fLastRegionOffset = Integer.MAX_VALUE; + fEditor= editor; + fManager= CUIPlugin.getDefault().getWorkingCopyManager(); + fDocumentProvider= CUIPlugin.getDefault().getDocumentProvider(); } /** @@ -32,6 +46,13 @@ public class CReconcilingStrategy implements IReconcilingStrategy { } + /* + * @see IReconcilingStrategyExtension#setProgressMonitor(IProgressMonitor) + */ + public void setProgressMonitor(IProgressMonitor monitor) { + fProgressMonitor= monitor; + } + /** * @see IReconcilingStrategy#reconcile(region) */ @@ -57,6 +78,17 @@ public class CReconcilingStrategy implements IReconcilingStrategy { } private void reconcile() { - fOutliner.contentUpdated(); - } + try { + IWorkingCopy workingCopy = fManager.getWorkingCopy(fEditor.getEditorInput()); + if (workingCopy != null) { + // reconcile + synchronized (workingCopy) { + workingCopy.reconcile(true, fProgressMonitor); + } + } + fOutliner.contentUpdated(); + } catch(CModelException e) { + + } + } } diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java index 80741f2fe2f..c81da24a110 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/ui/CUIPlugin.java @@ -18,6 +18,7 @@ import org.eclipse.cdt.internal.ui.CPluginImages; import org.eclipse.cdt.internal.ui.ResourceAdapterFactory; import org.eclipse.cdt.internal.ui.cview.CView; import org.eclipse.cdt.internal.ui.editor.CDocumentProvider; +import org.eclipse.cdt.internal.ui.editor.IWorkingCopyManager; import org.eclipse.cdt.internal.ui.editor.asm.AsmTextTools; import org.eclipse.cdt.internal.ui.preferences.BuildConsolePreferencePage; import org.eclipse.cdt.internal.ui.preferences.CEditorPreferencePage; @@ -151,6 +152,14 @@ public class CUIPlugin extends AbstractUIPlugin { return fDocumentProvider; } + /** + * Returns the working copy manager + * @return IWorkingCopyManager + */ + public synchronized IWorkingCopyManager getWorkingCopyManager() { + return getDocumentProvider(); + } + /** * Returns the shared text tools */