From 67f3e3b5597028d6fc26785de281c568fd2d3c6e Mon Sep 17 00:00:00 2001 From: Alena Laskavaia Date: Fri, 13 Aug 2010 00:21:08 +0000 Subject: [PATCH] Bug 320561 - Override markers in C++ editor, contribution from Tomasz Wesolowski --- .../icons/obj16/implm_co.gif | Bin 0 -> 104 bytes .../icons/obj16/over_co.gif | Bin 0 -> 131 bytes .../icons/obj16/shad_co.gif | Bin 0 -> 100 bytes core/org.eclipse.cdt.ui/plugin.xml | 26 ++ .../cdt/internal/ui/CPluginImages.java | 5 + .../cdt/internal/ui/editor/CEditor.java | 38 +- .../internal/ui/editor/CEditorMessages.java | 7 +- .../ui/editor/CEditorMessages.properties | 7 +- .../ConstructedCEditorMessages.properties | 6 + .../OverrideIndicatorImageProvider.java | 79 ++++ .../ui/editor/OverrideIndicatorManager.java | 426 ++++++++++++++++++ .../CSelectAnnotationRulerAction.java | 15 + 12 files changed, 606 insertions(+), 3 deletions(-) create mode 100644 core/org.eclipse.cdt.ui/icons/obj16/implm_co.gif create mode 100644 core/org.eclipse.cdt.ui/icons/obj16/over_co.gif create mode 100644 core/org.eclipse.cdt.ui/icons/obj16/shad_co.gif create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorImageProvider.java create mode 100644 core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorManager.java diff --git a/core/org.eclipse.cdt.ui/icons/obj16/implm_co.gif b/core/org.eclipse.cdt.ui/icons/obj16/implm_co.gif new file mode 100644 index 0000000000000000000000000000000000000000..b9871227abddae12e43eb3c44a7231fb0249843a GIT binary patch literal 104 zcmZ?wbhEHb6krfwSj52KrL{cRbbYM-_B4;ZIsS)EAAI#63>1H|FfuT(Gw3h?0Z1(a zvu?$%JO2z$-RxO-T%c&Fq^n^`zoJN(;)EW-1=9jqa@aU3`j|`K9G|hEz@tTlfx#L8 D;vgn? literal 0 HcmV?d00001 diff --git a/core/org.eclipse.cdt.ui/icons/obj16/over_co.gif b/core/org.eclipse.cdt.ui/icons/obj16/over_co.gif new file mode 100644 index 0000000000000000000000000000000000000000..938767b200e176bc860adbe791f25a304a238ac5 GIT binary patch literal 131 zcmZ?wbhEHb6krfw*v!DdP-MnXW5Up6%+O)P&|}EZAQ7-3xb#56tc$t-!2qZP87Tf_ zVPs(7V$cBzg3MrGF$g&6xq7d~>)7B&UQPn@r}1zYO$k?$`JlKVL`b4S?n0vCp9As@ S&o!kg7c40{Imd;8!5RQs>L+;s literal 0 HcmV?d00001 diff --git a/core/org.eclipse.cdt.ui/icons/obj16/shad_co.gif b/core/org.eclipse.cdt.ui/icons/obj16/shad_co.gif new file mode 100644 index 0000000000000000000000000000000000000000..ecf8aa36d35305eb343c1a81002f9fe5f235c15e GIT binary patch literal 100 zcmV-q0Gt0uNk%w1VGsZi0Kx|VNd(50eaW7C-JyZopo!C^kktSG{{R30A^8LW000L7 zEC2ui01yBW0009ic)HyFFv{7Cp~nDlr6vRyX~8fAqN5dqAPhyiXj^S}v!(A?@BctZ G0suQYfhC*( literal 0 HcmV?d00001 diff --git a/core/org.eclipse.cdt.ui/plugin.xml b/core/org.eclipse.cdt.ui/plugin.xml index c816a884fe7..47996073534 100644 --- a/core/org.eclipse.cdt.ui/plugin.xml +++ b/core/org.eclipse.cdt.ui/plugin.xml @@ -2525,6 +2525,31 @@ textStylePreferenceKey="org.eclipse.cdt.ui.occurrenceTextStyle" textStylePreferenceValue="NONE"> + + @@ -2676,6 +2701,7 @@ + Name: DefaultCEditorTextHover_html_prototype=
Prototype: diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ConstructedCEditorMessages.properties b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ConstructedCEditorMessages.properties index 5da3bc90c3b..c14964f394e 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ConstructedCEditorMessages.properties +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/ConstructedCEditorMessages.properties @@ -11,6 +11,7 @@ # Anton Leherbauer (Wind River Systems) # Markus Schorn (Wind River Systems) # Sergey Prigogin (Google) +# Tomasz Wesolowski ############################################################################### AddIncludeOnSelection.description=Add include statement for selected name @@ -131,3 +132,8 @@ CSelectAnnotationRulerAction.GotoAnnotation.label= &Go to Annotation CSelectAnnotationRulerAction.GotoAnnotation.tooltip= Go to Annotation CSelectAnnotationRulerAction.GotoAnnotation.description= Selects the annotation in the editor CSelectAnnotationRulerAction.GotoAnnotation.image= + +CSelectAnnotationRulerAction.OpenSuperImplementation.label= &Open Super Implementation +CSelectAnnotationRulerAction.OpenSuperImplementation.tooltip= Open Super Implementation +CSelectAnnotationRulerAction.OpenSuperImplementation.description= Opens the super implementation +CSelectAnnotationRulerAction.OpenSuperImplementation.image= diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorImageProvider.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorImageProvider.java new file mode 100644 index 00000000000..d0114ed09bc --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorImageProvider.java @@ -0,0 +1,79 @@ +/******************************************************************************* + * Copyright (c) 2010 Tomasz Wesolowski 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: + * Tomasz Wesolowski - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.editor; + +import org.eclipse.cdt.internal.ui.CPluginImages; +import org.eclipse.jface.resource.ImageDescriptor; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.swt.graphics.Image; +import org.eclipse.ui.texteditor.IAnnotationImageProvider; + +/** + * @author Tomasz Wesolowski + * + */ +public class OverrideIndicatorImageProvider implements + IAnnotationImageProvider { + + private static final String OVERRIDE_IMG_DESC_ID = "CPluginImages.DESC_OBJS_OVERRIDES"; + private static final String IMPLEMENT_IMG_DESC_ID = "CPluginImages.DESC_OBJS_IMPLEMENTS"; + private static final String SHADOW_IMG_DESC_ID = "CPluginImages.DESC_OBJS_SHADOWS"; + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IAnnotationImageProvider#getManagedImage(org.eclipse.jface.text.source.Annotation) + */ + public Image getManagedImage(Annotation annotation) { + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IAnnotationImageProvider#getImageDescriptorId(org.eclipse.jface.text.source.Annotation) + */ + public String getImageDescriptorId(Annotation annotation) { + if (!isImageProviderFor(annotation)) { + return null; + } + switch (getAnnotationType(annotation)) { + case OverrideIndicatorManager.RESULT_OVERRIDES: + return OVERRIDE_IMG_DESC_ID; + case OverrideIndicatorManager.RESULT_IMPLEMENTS: + return IMPLEMENT_IMG_DESC_ID; + case OverrideIndicatorManager.RESULT_SHADOWS: + return SHADOW_IMG_DESC_ID; + } + assert false; + return null; + } + + /* (non-Javadoc) + * @see org.eclipse.ui.texteditor.IAnnotationImageProvider#getImageDescriptor(java.lang.String) + */ + public ImageDescriptor getImageDescriptor(String imageDescritporId) { + if (imageDescritporId.equals(OVERRIDE_IMG_DESC_ID)) { + return CPluginImages.DESC_OBJS_OVERRIDES; + } else if (imageDescritporId.equals(IMPLEMENT_IMG_DESC_ID)) { + return CPluginImages.DESC_OBJS_IMPLEMENTS; + } else if (imageDescritporId.equals(SHADOW_IMG_DESC_ID)) { + return CPluginImages.DESC_OBJS_SHADOWS; + } + assert false; + return null; + } + + private boolean isImageProviderFor(Annotation annotation) { + return annotation != null && OverrideIndicatorManager.OverrideIndicator.ANNOTATION_TYPE_ID.equals(annotation.getType()); + } + + private int getAnnotationType(Annotation annotation) { + return ((OverrideIndicatorManager.OverrideIndicator)annotation).getIndicationType(); + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorManager.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorManager.java new file mode 100644 index 00000000000..a9a74dd9edd --- /dev/null +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/editor/OverrideIndicatorManager.java @@ -0,0 +1,426 @@ +/******************************************************************************* + * Copyright (c) 2010 Tomasz Wesolowski 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: + * Tomasz Wesolowski - initial API and implementation + *******************************************************************************/ +package org.eclipse.cdt.internal.ui.editor; + +import java.util.HashSet; +import java.util.Set; +import java.util.Vector; + +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.jface.text.ISynchronizable; +import org.eclipse.jface.text.Position; +import org.eclipse.jface.text.source.Annotation; +import org.eclipse.jface.text.source.IAnnotationModel; + +import org.eclipse.cdt.core.dom.ast.ASTVisitor; +import org.eclipse.cdt.core.dom.ast.DOMException; +import org.eclipse.cdt.core.dom.ast.IASTDeclSpecifier; +import org.eclipse.cdt.core.dom.ast.IASTDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFileLocation; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDeclarator; +import org.eclipse.cdt.core.dom.ast.IASTFunctionDefinition; +import org.eclipse.cdt.core.dom.ast.IASTNode; +import org.eclipse.cdt.core.dom.ast.IASTSimpleDeclaration; +import org.eclipse.cdt.core.dom.ast.IASTTranslationUnit; +import org.eclipse.cdt.core.dom.ast.IBinding; +import org.eclipse.cdt.core.dom.ast.IType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPASTCompositeTypeSpecifier; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBase; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPBinding; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPClassType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPFunctionType; +import org.eclipse.cdt.core.dom.ast.cpp.ICPPMethod; +import org.eclipse.cdt.core.index.IIndex; +import org.eclipse.cdt.ui.CDTUITools; + +import org.eclipse.cdt.internal.core.dom.parser.ASTQueries; +import org.eclipse.cdt.internal.core.dom.parser.cpp.ClassTypeHelper; +import org.eclipse.cdt.internal.core.model.ASTStringUtil; +import org.eclipse.cdt.internal.core.model.ext.ICElementHandle; + +import org.eclipse.cdt.internal.ui.text.ICReconcilingListener; +import org.eclipse.cdt.internal.ui.viewsupport.IndexUI; + +public class OverrideIndicatorManager implements ICReconcilingListener { + + private static final String MESSAGE_SEPARATOR = ";\n"; //$NON-NLS-1$ + + public static class OverrideInfo { + + public int nodeOffset; + public int resultType; + public String message; + public int nodeLength; + + public IBinding binding; + + public OverrideInfo(int nodeOffset, int nodeLength, int markerType, String message, IBinding binding) { + this.nodeOffset = nodeOffset; + this.resultType = markerType; + this.message = message; + this.binding = binding; + } + } + + public static final int RESULT_OVERRIDES = 0; + public static final int RESULT_IMPLEMENTS = 1; + public static final int RESULT_SHADOWS = 2; + + public class OverrideIndicator extends Annotation { + + public static final String ANNOTATION_TYPE_ID = "org.eclipse.cdt.ui.overrideIndicator"; //$NON-NLS-1$ + private int type; + private ICElementHandle declaration; + + public OverrideIndicator(int resultType, String message, IBinding binding, IIndex index) { + super(ANNOTATION_TYPE_ID, false, message); + this.type = resultType; + try { + declaration = IndexUI.findAnyDeclaration(index, null, binding); + if (declaration == null) { + ICElementHandle[] allDefinitions = IndexUI.findAllDefinitions(index, binding); + if (allDefinitions.length > 0) { + declaration = allDefinitions[0]; + } + } + } catch (CoreException e) { + } + } + + public int getIndicationType() { + return type; + } + + public void open() { + try { + CDTUITools.openInEditor(declaration, true, true); + } catch (CoreException e) { + } + + } + + } + + private IAnnotationModel fAnnotationModel; + private Vector fOverrideAnnotations = new Vector(); + private Object fAnnotationModelLockObject; + + public OverrideIndicatorManager(IAnnotationModel annotationModel) { + fAnnotationModel = annotationModel; + fAnnotationModelLockObject = getLockObject(fAnnotationModel); + } + + private void handleResult(OverrideInfo info, IIndex index) { + + Position position = new Position(info.nodeOffset, info.nodeLength); + + OverrideIndicator indicator = new OverrideIndicator(info.resultType, info.message, info.binding, index); + synchronized (fAnnotationModelLockObject) { + fAnnotationModel.addAnnotation(indicator, position); + } + fOverrideAnnotations.add(indicator); + } + + /** + * Removes all override indicators from this manager's annotation model. + */ + public void removeAnnotations() { + if (fOverrideAnnotations == null) + return; + + synchronized (fAnnotationModelLockObject) { + for (Annotation i : fOverrideAnnotations) + fAnnotationModel.removeAnnotation(i); + fOverrideAnnotations.clear(); + } + } + + public void generateAnnotations(IASTTranslationUnit ast, final IIndex index) { + + class MethodDeclarationFinder extends ASTVisitor { + { + shouldVisitDeclarations = true; + } + + @Override + public int visit(IASTDeclaration declaration) { + try { + IBinding binding = null; + ICPPMethod method = null; + if (isFunctionDeclaration(declaration)) { + binding = getDeclarationBinding(declaration); + } else if (declaration instanceof IASTFunctionDefinition) { + binding = getDefinitionBinding((IASTFunctionDefinition) declaration); + } + if (binding instanceof ICPPMethod) { + method = (ICPPMethod) binding; + OverrideInfo overrideInfo = testForOverride(method, declaration.getFileLocation()); + if (overrideInfo != null) { + handleResult(overrideInfo, index); + } + } + } catch (DOMException e) { + } + // go to next declaration + return PROCESS_SKIP; + } + } + class CompositeTypeFinder extends ASTVisitor { + { + shouldVisitDeclSpecifiers = true; + } + + @Override + public int visit(IASTDeclSpecifier declSpec) { + if (declSpec instanceof ICPPASTCompositeTypeSpecifier) { + declSpec.accept(new MethodDeclarationFinder()); + } + return PROCESS_CONTINUE; + } + } + + class MethodDefinitionFinder extends ASTVisitor { + { + shouldVisitDeclarations = true; + } + + @Override + public int visit(IASTDeclaration declaration) { + try { + if (!(declaration instanceof IASTFunctionDefinition)) { + return PROCESS_SKIP; + } + IASTFunctionDefinition definition = (IASTFunctionDefinition) declaration; + IBinding definitionBinding = getDefinitionBinding(definition); + if (!(definitionBinding instanceof ICPPMethod)) { + return PROCESS_SKIP; + } + ICPPMethod method = (ICPPMethod) definitionBinding; + OverrideInfo overrideInfo = testForOverride(method, definition.getFileLocation()); + if (overrideInfo != null) { + handleResult(overrideInfo, index); + } + } catch (DOMException e) { + } + return PROCESS_SKIP; + } + } + + ast.accept(new CompositeTypeFinder()); + ast.accept(new MethodDefinitionFinder()); + } + + public static OverrideInfo testForOverride(ICPPMethod testedOverride, IASTFileLocation location) throws DOMException { + + testedOverride.getClassOwner().getBases(); + + boolean onlyPureVirtual = true; + StringBuilder sb = new StringBuilder(); + Set overridenMethods = new HashSet(); + Set shadowedMethods = new HashSet(); + + Set alreadyTestedBases = new HashSet(); + + ICPPBase[] bases = testedOverride.getClassOwner().getBases(); + + // Don't override 'self' in cyclic inheritance + alreadyTestedBases.add(testedOverride.getClassOwner()); + + for (ICPPBase base : bases) { + ICPPClassType testedClass; + if (!(base.getBaseClass() instanceof ICPPClassType)) { + continue; + } + testedClass = (ICPPClassType) base.getBaseClass(); + + overridenMethods.clear(); + shadowedMethods.clear(); + handleBaseClass(testedClass, testedOverride, overridenMethods, shadowedMethods, alreadyTestedBases); + + for (ICPPMethod overriddenMethod : overridenMethods) { + + if (sb.length() > 0) { + sb.append(MESSAGE_SEPARATOR); + } + if (overriddenMethod.isPureVirtual()) { + sb.append(CEditorMessages.OverrideIndicatorManager_implements); + } else { + sb.append(CEditorMessages.OverrideIndicatorManager_overrides); + onlyPureVirtual = false; + } + sb.append(' '); + sb.append(getQualifiedNameString(overriddenMethod)); + + if (bases.length > 1 && overriddenMethod.getClassOwner() != testedClass) { + sb.append(' '); + sb.append(CEditorMessages.OverrideIndicatorManager_via); + sb.append(' '); + sb.append(getQualifiedNameString(testedClass)); + } + } + for (ICPPMethod shadowedMethod : shadowedMethods) { + if (sb.length() > 0) { + sb.append(MESSAGE_SEPARATOR); + } + sb.append(CEditorMessages.OverrideIndicatorManager_shadows); + sb.append(' '); + sb.append(getQualifiedNameString(shadowedMethod)); + } + } + + int markerType; + if (overridenMethods.size() > 0) { + markerType = onlyPureVirtual ? RESULT_IMPLEMENTS : RESULT_OVERRIDES; + } else { + markerType = RESULT_SHADOWS; + } + + IBinding bindingToOpen = null; + if (overridenMethods.size() > 0) { + bindingToOpen = overridenMethods.iterator().next(); + } else if (shadowedMethods.size() > 0) { + bindingToOpen = shadowedMethods.iterator().next(); + } + + if (sb.length() > 0) { + OverrideInfo info = new OverrideInfo(location.getNodeOffset(), location.getNodeLength(), markerType, + sb.toString(), bindingToOpen); + return info; + } + return null; + + } + + /** + * If the class directly has a valid override for testedOverride, it is added to foundBindings. Otherwise + * each base class is added to handleBaseClass. + * + * @param shadowedMethods + * @param alreadyTestedBases + * + * @throws DOMException + */ + private static void handleBaseClass(ICPPClassType aClass, ICPPMethod testedOverride, + Set foundMethods, Set shadowedMethods, Set alreadyTestedBases) throws DOMException { + + if (alreadyTestedBases.contains(aClass)) { + return; + } else { + alreadyTestedBases.add(aClass); + } + + Vector validOverrides = new Vector(); + for (ICPPMethod method : aClass.getDeclaredMethods()) { + if (testedOverride.getName().equals(method.getName())) { + if (ClassTypeHelper.isOverrider(testedOverride, method)) { + validOverrides.add(method); + } else if (sameParameters(testedOverride, method)) { + shadowedMethods.add(method); + } + } + } + if (validOverrides.size() > 1) { + /* System.err.println("Found many valid overrides"); */ + } + if (validOverrides.size() >= 1) { + foundMethods.addAll(validOverrides); + return; + } + + for (ICPPBase b : aClass.getBases()) { + if (!(b.getBaseClass() instanceof ICPPClassType)) { + continue; + } + ICPPClassType baseClass = (ICPPClassType) b.getBaseClass(); + handleBaseClass(baseClass, testedOverride, foundMethods, shadowedMethods, alreadyTestedBases); + } + } + + private static boolean sameParameters(ICPPMethod a, ICPPMethod b) throws DOMException { + ICPPFunctionType aType = a.getType(); + ICPPFunctionType bType = b.getType(); + if (aType.getParameterTypes().length != bType.getParameterTypes().length) { + return false; + } + for (int i = 0; i < aType.getParameterTypes().length; ++i) { + IType overrideParamType = aType.getParameterTypes()[i]; + IType methodParamType = bType.getParameterTypes()[i]; + if (!overrideParamType.isSameType(methodParamType)) { + return false; + } + } + return true; + } + + private static String getQualifiedNameString(ICPPBinding binding) throws DOMException { + String methodQualifiedName = ASTStringUtil.join(binding.getQualifiedName(), "::"); //$NON-NLS-1$ + return methodQualifiedName; + } + + private static boolean isFunctionDeclaration(IASTDeclaration declaration) { + if (!(declaration instanceof IASTSimpleDeclaration)) { + return false; + } + IASTSimpleDeclaration simpleDecl = (IASTSimpleDeclaration) declaration; + IASTDeclarator[] declarators = simpleDecl.getDeclarators(); + if (declarators.length < 1) { + return false; + } + IASTDeclarator declarator = ASTQueries.findInnermostDeclarator(declarators[0]); + return (declarator instanceof IASTFunctionDeclarator); + } + + private static IBinding getDefinitionBinding(IASTFunctionDefinition definition) { + IASTDeclarator declarator = ASTQueries.findInnermostDeclarator(definition.getDeclarator()); + return declarator.getName().resolveBinding(); + } + + private static IBinding getDeclarationBinding(IASTDeclaration declaration) { + for (IASTNode node : declaration.getChildren()) { + if (node instanceof IASTDeclarator) { + IASTDeclarator decl = ASTQueries.findInnermostDeclarator((IASTDeclarator) node); + return decl.getName().resolveBinding(); + } + } + return null; + } + + public void aboutToBeReconciled() { + } + + public void reconciled(IASTTranslationUnit ast, boolean force, IProgressMonitor progressMonitor) { + if (ast == null) { + return; + } + IIndex index = ast.getIndex(); + removeAnnotations(); + generateAnnotations(ast, index); + } + + /** + * Returns the lock object for the given annotation model. + * + * @param annotationModel + * the annotation model + * @return the annotation model's lock object + */ + private Object getLockObject(IAnnotationModel annotationModel) { + if (annotationModel instanceof ISynchronizable) { + Object lock = ((ISynchronizable) annotationModel).getLockObject(); + if (lock != null) + return lock; + } + return annotationModel; + } + +} diff --git a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/correction/CSelectAnnotationRulerAction.java b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/correction/CSelectAnnotationRulerAction.java index 1ed6619eb3b..172ce109fa5 100644 --- a/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/correction/CSelectAnnotationRulerAction.java +++ b/core/org.eclipse.cdt.ui/src/org/eclipse/cdt/internal/ui/text/correction/CSelectAnnotationRulerAction.java @@ -33,6 +33,8 @@ import org.eclipse.ui.texteditor.SelectMarkerRulerAction; import org.eclipse.cdt.ui.CUIPlugin; +import org.eclipse.cdt.internal.ui.editor.OverrideIndicatorManager; + /** * Action which gets triggered when selecting (annotations) in the vertical ruler. * based upon org.eclipse.jdt.internal.ui.javaeditor.JavaSelectMarkerRulerAction @@ -45,6 +47,7 @@ public class CSelectAnnotationRulerAction extends SelectMarkerRulerAction { private IPreferenceStore fStore; private boolean fHasCorrection; private ResourceBundle fBundle; + private Annotation fAnnotation; public CSelectAnnotationRulerAction(ResourceBundle bundle, String prefix, ITextEditor editor, IVerticalRulerInfo ruler) { super(bundle, prefix, editor, ruler); @@ -69,6 +72,11 @@ public class CSelectAnnotationRulerAction extends SelectMarkerRulerAction { */ @Override public void runWithEvent(Event event) { + if (fAnnotation instanceof OverrideIndicatorManager.OverrideIndicator) { + ((OverrideIndicatorManager.OverrideIndicator)fAnnotation).open(); + return; + } + if (fHasCorrection) { ITextOperationTarget operation= (ITextOperationTarget) fTextEditor.getAdapter(ITextOperationTarget.class); final int opCode= ISourceViewer.QUICK_ASSIST; @@ -91,6 +99,10 @@ public class CSelectAnnotationRulerAction extends SelectMarkerRulerAction { findCAnnotation(); setEnabled(true); + if (fAnnotation instanceof OverrideIndicatorManager.OverrideIndicator) { + initialize(fBundle, "CSelectAnnotationRulerAction.OpenSuperImplementation."); //$NON-NLS-1$ + return; + } if (fHasCorrection) { initialize(fBundle, "CSelectAnnotationRulerAction.QuickFix."); //$NON-NLS-1$ return; @@ -102,6 +114,7 @@ public class CSelectAnnotationRulerAction extends SelectMarkerRulerAction { private void findCAnnotation() { fPosition= null; + fAnnotation = null; fHasCorrection= false; AbstractMarkerAnnotationModel model= getAnnotationModel(); @@ -135,6 +148,7 @@ public class CSelectAnnotationRulerAction extends SelectMarkerRulerAction { if (!isReadOnly && CCorrectionProcessor.hasCorrections(annotation)) { fPosition= position; + fAnnotation = annotation; fHasCorrection= true; layer= annotationLayer; continue; @@ -149,6 +163,7 @@ public class CSelectAnnotationRulerAction extends SelectMarkerRulerAction { if (fStore.getBoolean(key)) { fPosition= position; + fAnnotation = annotation; fHasCorrection= false; layer= annotationLayer; }