mirror of
https://github.com/eclipse-cdt/cdt
synced 2025-06-30 21:55:31 +02:00
Bug 423679: CEditor navigation actions disabled outside of CEditor
The Open Declaration (F3), etc. actions use code in the ASTProvider. If the provider is not able to get an AST then the actions are disabled. The implementation of the ASTProvider has an "instanceof CEditor" check the result being that ASTProvider can only be used when the editor is a CEditor. This breaks our use case where we have a CEditor embedded as a tab in a multi-pane editor (see org.eclipse.papyrus.infra.core.sasheditor .editor.AbstractMultiPageSashEditor). This patch modifies the ASTProvider to use #getAdapter instead of only the instanceof check. I've kept the common case (where the editor is a CEditor) unchanged and added the new code as extra handling. I've also introduced a public interface, ITranslationUnitProvider, to avoid forcing clients to adapt to the internal CEditor class. The only part of CEditor that ASTProvider cares about is the ITranslationUnit. The existing implementation has an unchecked cast. The new interface provides the required type directly. Change-Id: Ie7e68e8909928374fa11fe2b8a857f09d042fb5c Signed-off-by: Andrew Eidsness <andrewe@jfront.com> Reviewed-on: https://git.eclipse.org/r/20026 Tested-by: Hudson CI Reviewed-by: Doug Schaefer <dschaefer@qnx.com> IP-Clean: Doug Schaefer <dschaefer@qnx.com>
This commit is contained in:
parent
71fa7cf819
commit
d046e0a25f
5 changed files with 102 additions and 47 deletions
|
@ -0,0 +1,23 @@
|
|||
/*
|
||||
* Copyright (c) 2013 Zeligsoft (2009) Limited.
|
||||
* 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
|
||||
*/
|
||||
package org.eclipse.cdt.core.model;
|
||||
|
||||
/**
|
||||
* Represents a workbench object that is able to provide instances of ITranslationUnit. For
|
||||
* example, the CEditor (in the CDT UI plugin) implements this interface in order to provide
|
||||
* the IWorkingCopy of the editor's active translation unit.
|
||||
*
|
||||
* @since 5.6
|
||||
*/
|
||||
public interface ITranslationUnitHolder {
|
||||
/**
|
||||
* Returns the translation unit that is provided by the receiver or null if there is no
|
||||
* such translation unit.
|
||||
*/
|
||||
public ITranslationUnit getTranslationUnit();
|
||||
}
|
|
@ -20,6 +20,7 @@ import org.eclipse.core.runtime.Status;
|
|||
import org.eclipse.jface.text.IDocument;
|
||||
import org.eclipse.jface.text.IDocumentExtension4;
|
||||
import org.eclipse.ui.IEditorInput;
|
||||
import org.eclipse.ui.IEditorPart;
|
||||
import org.eclipse.ui.IPartListener2;
|
||||
import org.eclipse.ui.IWindowListener;
|
||||
import org.eclipse.ui.IWorkbenchPart;
|
||||
|
@ -33,6 +34,7 @@ import org.eclipse.cdt.core.index.IIndex;
|
|||
import org.eclipse.cdt.core.model.ICElement;
|
||||
import org.eclipse.cdt.core.model.ILanguage;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnitHolder;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
|
||||
import org.eclipse.cdt.internal.core.model.ASTCache;
|
||||
|
@ -41,7 +43,7 @@ import org.eclipse.cdt.internal.core.model.ASTCache.ASTRunnable;
|
|||
/**
|
||||
* Provides a shared AST for clients. The shared AST is
|
||||
* the AST of the active CEditor's input element.
|
||||
*
|
||||
*
|
||||
* @since 4.0
|
||||
*/
|
||||
public final class ASTProvider {
|
||||
|
@ -69,7 +71,7 @@ public final class ASTProvider {
|
|||
* wants to wait until an AST is ready. If the translation unit is not open no AST will
|
||||
* be provided.
|
||||
* <p>
|
||||
* If not yet cached and if the translation unit is open, an AST will be created by
|
||||
* If not yet cached and if the translation unit is open, an AST will be created by
|
||||
* this AST provider.
|
||||
* </p>
|
||||
*/
|
||||
|
@ -77,7 +79,7 @@ public final class ASTProvider {
|
|||
|
||||
/**
|
||||
* Wait flag indicating that a client requesting an AST
|
||||
* only wants to wait for the shared AST of the active editor.
|
||||
* only wants to wait for the shared AST of the active editor.
|
||||
* If the translation unit is not open no AST will be provided.
|
||||
* <p>
|
||||
* No AST will be created by the AST provider.
|
||||
|
@ -222,7 +224,17 @@ public final class ASTProvider {
|
|||
return false;
|
||||
|
||||
String id= ref.getId();
|
||||
return CUIPlugin.EDITOR_ID.equals(id) || ref.getPart(false) instanceof CEditor;
|
||||
if (CUIPlugin.EDITOR_ID.equals(id))
|
||||
return true;
|
||||
|
||||
IWorkbenchPart part = ref.getPart(false);
|
||||
if (part instanceof CEditor)
|
||||
return true;
|
||||
|
||||
// Other editors can behave as CEditors if they can provide a copy of their ITranslationUnit.
|
||||
if (part instanceof IEditorPart)
|
||||
return part.getAdapter(ITranslationUnitHolder.class) != null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -233,7 +245,7 @@ public final class ASTProvider {
|
|||
|
||||
/**
|
||||
* Returns the C plug-in's AST provider.
|
||||
*
|
||||
*
|
||||
* @return the AST provider
|
||||
*/
|
||||
public static ASTProvider getASTProvider() {
|
||||
|
@ -264,14 +276,17 @@ public final class ASTProvider {
|
|||
}
|
||||
|
||||
private void activeEditorChanged(IWorkbenchPart editor) {
|
||||
ICElement cElement= null;
|
||||
if (editor instanceof CEditor) {
|
||||
cElement= ((CEditor) editor).getInputCElement();
|
||||
ITranslationUnit tu = null;
|
||||
if (editor != null) {
|
||||
ITranslationUnitHolder provider = (ITranslationUnitHolder) editor.getAdapter(ITranslationUnitHolder.class);
|
||||
if (provider != null)
|
||||
tu = provider.getTranslationUnit();
|
||||
}
|
||||
|
||||
synchronized (this) {
|
||||
fActiveEditor= editor;
|
||||
fTimeStamp= IDocumentExtension4.UNKNOWN_MODIFICATION_STAMP;
|
||||
fCache.setActiveElement((ITranslationUnit) cElement);
|
||||
fCache.setActiveElement(tu);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -343,7 +358,7 @@ public final class ASTProvider {
|
|||
* Executes {@link ASTRunnable#runOnAST(ILanguage, IASTTranslationUnit)}
|
||||
* with the shared AST for the given translation unit. Handles acquiring
|
||||
* and releasing the index read-lock for the client.
|
||||
*
|
||||
*
|
||||
* @param cElement the translation unit
|
||||
* @param waitFlag condition for waiting for the AST to be built.
|
||||
* @param monitor a progress monitor, may be <code>null</code>
|
||||
|
@ -368,7 +383,7 @@ public final class ASTProvider {
|
|||
* <p>
|
||||
* An index lock must be held by the caller when calling this method. The index lock may
|
||||
* not be released until the AST is released.
|
||||
*
|
||||
*
|
||||
* @param tu The translation unit to get the AST for.
|
||||
* @param index index with read lock held.
|
||||
* @param waitFlag condition for waiting for the AST to be built.
|
||||
|
@ -396,7 +411,7 @@ public final class ASTProvider {
|
|||
|
||||
/**
|
||||
* Prepares the AST cache to be used for the given translation unit.
|
||||
*
|
||||
*
|
||||
* @param tu the translation unit.
|
||||
* @param waitFlag condition for waiting for the AST to be built.
|
||||
* @return <code>true</code> if the AST cache can be used for the given translation unit,
|
||||
|
@ -407,7 +422,7 @@ public final class ASTProvider {
|
|||
return false;
|
||||
|
||||
// http://bugs.eclipse.org/bugs/show_bug.cgi?id=342506 explains
|
||||
// benign nature of the race conditions in the code below.
|
||||
// benign nature of the race conditions in the code below.
|
||||
final boolean isActive= fCache.isActiveElement(tu);
|
||||
if (waitFlag == WAIT_ACTIVE_ONLY && !isActive) {
|
||||
return false;
|
||||
|
|
|
@ -184,6 +184,7 @@ import org.eclipse.cdt.core.model.ILanguage;
|
|||
import org.eclipse.cdt.core.model.ISourceRange;
|
||||
import org.eclipse.cdt.core.model.ISourceReference;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnit;
|
||||
import org.eclipse.cdt.core.model.ITranslationUnitHolder;
|
||||
import org.eclipse.cdt.core.model.IWorkingCopy;
|
||||
import org.eclipse.cdt.ui.CUIPlugin;
|
||||
import org.eclipse.cdt.ui.ICEditor;
|
||||
|
@ -241,7 +242,7 @@ import org.eclipse.cdt.internal.ui.viewsupport.SelectionListenerWithASTManager;
|
|||
/**
|
||||
* C/C++ source editor.
|
||||
*/
|
||||
public class CEditor extends TextEditor implements ICEditor, ISelectionChangedListener, ICReconcilingListener {
|
||||
public class CEditor extends TextEditor implements ICEditor, ISelectionChangedListener, ICReconcilingListener, ITranslationUnitHolder {
|
||||
/** Marker used for synchronization from Problems View to the editor on double-click. */
|
||||
private IMarker fSyncProblemsViewMarker;
|
||||
|
||||
|
@ -1514,6 +1515,11 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
|||
return CUIPlugin.getDefault().getWorkingCopyManager().getWorkingCopy(getEditorInput());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ITranslationUnit getTranslationUnit() {
|
||||
return getInputCElement();
|
||||
}
|
||||
|
||||
/**
|
||||
* @see org.eclipse.ui.ISaveablePart#isSaveAsAllowed()
|
||||
*/
|
||||
|
@ -1575,7 +1581,8 @@ public class CEditor extends TextEditor implements ICEditor, ISelectionChangedLi
|
|||
fTemplatesPage = new CTemplatesPage(this);
|
||||
}
|
||||
return fTemplatesPage;
|
||||
}
|
||||
} else if (adapterClass.isAssignableFrom(ITranslationUnitHolder.class))
|
||||
return this;
|
||||
return super.getAdapter(adapterClass);
|
||||
}
|
||||
|
||||
|
|
|
@ -89,8 +89,8 @@ public class SelectionParseAction extends Action {
|
|||
clearStatusLine();
|
||||
|
||||
IEditorPart editor = EditorUtility.openInEditor(path, fEditor.getInputCElement());
|
||||
if (editor instanceof ITextEditor) {
|
||||
ITextEditor textEditor = (ITextEditor) editor;
|
||||
ITextEditor textEditor = EditorUtility.getTextEditor(editor);
|
||||
if (textEditor != null) {
|
||||
textEditor.selectAndReveal(currentOffset, currentLength);
|
||||
} else {
|
||||
reportSourceFileOpenFailure(path);
|
||||
|
@ -101,8 +101,8 @@ public class SelectionParseAction extends Action {
|
|||
clearStatusLine();
|
||||
|
||||
IEditorPart editor = EditorUtility.openInEditor(tu, true);
|
||||
if (editor instanceof ITextEditor) {
|
||||
ITextEditor textEditor = (ITextEditor) editor;
|
||||
ITextEditor textEditor = EditorUtility.getTextEditor(editor);
|
||||
if (textEditor != null) {
|
||||
textEditor.selectAndReveal(currentOffset, currentLength);
|
||||
} else {
|
||||
reportSourceFileOpenFailure(tu.getPath());
|
||||
|
|
|
@ -338,7 +338,7 @@ public class EditorUtility {
|
|||
IEditorInput input= getEditorInputForLocation(location, element);
|
||||
return EditorUtility.openInEditor(input, getEditorID(input, element), activate);
|
||||
}
|
||||
|
||||
|
||||
public static IEditorPart openInEditor(URI locationURI, ICElement element) throws PartInitException {
|
||||
IEditorInput input= getEditorInputForLocation(locationURI, element);
|
||||
return EditorUtility.openInEditor(input, getEditorID(input, element), true);
|
||||
|
@ -376,7 +376,7 @@ public class EditorUtility {
|
|||
IPath path = URIUtil.toPath(locationURI);
|
||||
if(path == null)
|
||||
path = new Path(locationURI.getPath());
|
||||
|
||||
|
||||
if (includeReferences[j].isOnIncludeEntry(path)) {
|
||||
context = projects[i];
|
||||
break outerFor;
|
||||
|
@ -405,7 +405,7 @@ public class EditorUtility {
|
|||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
if(fileStore != null)
|
||||
return new ExternalEditorInput(unit);
|
||||
}
|
||||
|
@ -486,18 +486,18 @@ public class EditorUtility {
|
|||
IFile file= ResourceLookup.selectFileForLocation(location, project);
|
||||
if (file != null && file.isAccessible())
|
||||
return file;
|
||||
|
||||
|
||||
IWorkspaceRoot root= ResourcesPlugin.getWorkspace().getRoot();
|
||||
// workaround http://bugs.eclipse.org/233939
|
||||
file= root.getFileForLocation(location);
|
||||
if (file != null && file.isAccessible())
|
||||
if (file != null && file.isAccessible())
|
||||
return file;
|
||||
|
||||
// try workspace relative path
|
||||
if (location.segmentCount() >= 2) {
|
||||
// @see IContainer#getFile for the required number of segments
|
||||
file= root.getFile(location);
|
||||
if (file != null && file.isAccessible())
|
||||
if (file != null && file.isAccessible())
|
||||
return file;
|
||||
}
|
||||
return null;
|
||||
|
@ -520,14 +520,14 @@ public class EditorUtility {
|
|||
project= cProject.getProject();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IFile file= ResourceLookup.selectFileForLocationURI(locationURI, project);
|
||||
if (file != null && file.isAccessible())
|
||||
return file;
|
||||
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* If the current active editor edits a c element return it, else
|
||||
* return null
|
||||
|
@ -722,7 +722,7 @@ public class EditorUtility {
|
|||
String newModifierString= Action.findModifierString(modifier);
|
||||
if (modifierString.length() == 0)
|
||||
return newModifierString;
|
||||
return NLS.bind(CEditorMessages.EditorUtility_concatModifierStrings, new String[] {modifierString, newModifierString});
|
||||
return NLS.bind(CEditorMessages.EditorUtility_concatModifierStrings, new String[] {modifierString, newModifierString});
|
||||
}
|
||||
|
||||
public static IStorage getStorage(IBinary bin) {
|
||||
|
@ -869,10 +869,10 @@ public class EditorUtility {
|
|||
}
|
||||
}
|
||||
|
||||
if (!(ep instanceof ITextEditor))
|
||||
ITextEditor textEditor = getTextEditor(ep);
|
||||
if (textEditor == null)
|
||||
return saveUnknownEditors;
|
||||
|
||||
ITextEditor textEditor= (ITextEditor) ep;
|
||||
IDocumentProvider documentProvider= textEditor.getDocumentProvider();
|
||||
if (!(documentProvider instanceof TextFileDocumentProvider))
|
||||
return saveUnknownEditors;
|
||||
|
@ -885,7 +885,7 @@ public class EditorUtility {
|
|||
* last save occurred. Each region in the result spans over the size of at least one line.
|
||||
* If successive lines have changed a region spans over the size of all successive lines.
|
||||
* The regions include line delimiters.
|
||||
*
|
||||
*
|
||||
* @param buffer the buffer to compare contents from
|
||||
* @param monitor to report progress to
|
||||
* @return the regions of the changed lines
|
||||
|
@ -896,7 +896,7 @@ public class EditorUtility {
|
|||
final IProgressMonitor monitor) throws CoreException {
|
||||
final IRegion[][] result= new IRegion[1][];
|
||||
final IStatus[] errorStatus= new IStatus[] { Status.OK_STATUS };
|
||||
|
||||
|
||||
try {
|
||||
SafeRunner.run(new ISafeRunnable() {
|
||||
/*
|
||||
|
@ -912,7 +912,7 @@ public class EditorUtility {
|
|||
ICStatusConstants.EDITOR_CHANGED_REGION_CALCULATION, msg, exception);
|
||||
result[0]= null;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* @see org.eclipse.core.runtime.ISafeRunnable#run()
|
||||
*/
|
||||
|
@ -920,14 +920,14 @@ public class EditorUtility {
|
|||
public void run() throws Exception {
|
||||
monitor.beginTask(Messages.EditorUtility_calculatingChangedRegions_message, 20);
|
||||
IFileStore fileStore= buffer.getFileStore();
|
||||
|
||||
|
||||
ITextFileBufferManager fileBufferManager= FileBuffers.createTextFileBufferManager();
|
||||
fileBufferManager.connectFileStore(fileStore, getSubProgressMonitor(monitor, 15));
|
||||
try {
|
||||
IDocument currentDocument= buffer.getDocument();
|
||||
IDocument oldDocument=
|
||||
IDocument oldDocument=
|
||||
((ITextFileBuffer) fileBufferManager.getFileStoreFileBuffer(fileStore)).getDocument();
|
||||
|
||||
|
||||
result[0]= getChangedLineRegions(oldDocument, currentDocument);
|
||||
} finally {
|
||||
fileBufferManager.disconnectFileStore(fileStore, getSubProgressMonitor(monitor, 5));
|
||||
|
@ -938,7 +938,7 @@ public class EditorUtility {
|
|||
/**
|
||||
* Return regions of all lines which differ comparing <code>oldDocument</code>s content
|
||||
* with <code>currentDocument</code>s content. Successive lines are merged into one region.
|
||||
*
|
||||
*
|
||||
* @param oldDocument a document containing the old content
|
||||
* @param currentDocument a document containing the current content
|
||||
* @return the changed regions
|
||||
|
@ -973,7 +973,7 @@ public class EditorUtility {
|
|||
startLineRegion = currentDocument.getLineInformation(startLine);
|
||||
if (startLine >= endLine) {
|
||||
// startLine > endLine indicates a deletion of one or more lines.
|
||||
// Deletions are ignored except at the end of the document.
|
||||
// Deletions are ignored except at the end of the document.
|
||||
if (startLine == endLine ||
|
||||
startLineRegion.getOffset() + startLineRegion.getLength() == currentDocument.getLength()) {
|
||||
regions.add(startLineRegion);
|
||||
|
@ -997,7 +997,7 @@ public class EditorUtility {
|
|||
if (!errorStatus[0].isOK())
|
||||
throw new CoreException(errorStatus[0]);
|
||||
}
|
||||
|
||||
|
||||
return result[0];
|
||||
}
|
||||
|
||||
|
@ -1015,13 +1015,13 @@ public class EditorUtility {
|
|||
|
||||
return new NullProgressMonitor();
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the project contains the resource, which is currently open in the active editor.
|
||||
* If the active part is no ITextEditor or if the editorInput is no FileEditorInput,
|
||||
* If the active part is no ITextEditor or if the editorInput is no FileEditorInput,
|
||||
* <code>null</code> is returned.
|
||||
*
|
||||
*
|
||||
* @return the project which the selected editor input belongs to or null
|
||||
*/
|
||||
public static IProject getProjectForActiveEditor() {
|
||||
|
@ -1030,9 +1030,9 @@ public class EditorUtility {
|
|||
if(window != null) {
|
||||
IWorkbenchPage activePage = window.getActivePage();
|
||||
if(activePage != null) {
|
||||
IEditorPart activeEditor = activePage.getActiveEditor();
|
||||
if(activeEditor instanceof ITextEditor) {
|
||||
IEditorInput editorInput = ((ITextEditor)activeEditor).getEditorInput();
|
||||
ITextEditor activeEditor = getTextEditor(activePage.getActiveEditor());
|
||||
if (activeEditor != null) {
|
||||
IEditorInput editorInput = activeEditor.getEditorInput();
|
||||
IFile file = ResourceUtil.getFile(editorInput);
|
||||
if(file != null) {
|
||||
project = file.getProject();
|
||||
|
@ -1042,4 +1042,14 @@ public class EditorUtility {
|
|||
}
|
||||
return project;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tries to convert the given editor to an implementation of ITextEditor. Returns that implementation
|
||||
* if possible and null otherwise.
|
||||
*
|
||||
* @param editor The editor to be converted or null if there is nothing to convert.
|
||||
*/
|
||||
public static ITextEditor getTextEditor(IEditorPart editor) {
|
||||
return editor == null ? null : (ITextEditor) editor.getAdapter(ITextEditor.class);
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Add table
Reference in a new issue