]> git.uio.no Git - ifi-stolz-refaktor.git/blob - case-study/jdt-after/ui/org/eclipse/jdt/internal/ui/javaeditor/OverrideIndicatorManager.java
Case Study: adding data and statistics
[ifi-stolz-refaktor.git] / case-study / jdt-after / ui / org / eclipse / jdt / internal / ui / javaeditor / OverrideIndicatorManager.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2011 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials
4  * are made available under the terms of the Eclipse Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/epl-v10.html
7  *
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11
12 package org.eclipse.jdt.internal.ui.javaeditor;
13
14 import java.util.HashMap;
15 import java.util.Iterator;
16 import java.util.Map;
17 import java.util.Map.Entry;
18
19 import org.eclipse.core.runtime.Assert;
20 import org.eclipse.core.runtime.CoreException;
21 import org.eclipse.core.runtime.IProgressMonitor;
22 import org.eclipse.core.runtime.NullProgressMonitor;
23
24 import org.eclipse.jface.dialogs.MessageDialog;
25
26 import org.eclipse.jface.text.ISynchronizable;
27 import org.eclipse.jface.text.Position;
28 import org.eclipse.jface.text.source.Annotation;
29 import org.eclipse.jface.text.source.IAnnotationModel;
30 import org.eclipse.jface.text.source.IAnnotationModelExtension;
31
32 import org.eclipse.jdt.core.IJavaElement;
33 import org.eclipse.jdt.core.ITypeRoot;
34 import org.eclipse.jdt.core.dom.ASTNode;
35 import org.eclipse.jdt.core.dom.ASTVisitor;
36 import org.eclipse.jdt.core.dom.CompilationUnit;
37 import org.eclipse.jdt.core.dom.IMethodBinding;
38 import org.eclipse.jdt.core.dom.ITypeBinding;
39 import org.eclipse.jdt.core.dom.MethodDeclaration;
40 import org.eclipse.jdt.core.dom.SimpleName;
41
42 import org.eclipse.jdt.internal.corext.dom.Bindings;
43 import org.eclipse.jdt.internal.corext.util.JdtFlags;
44 import org.eclipse.jdt.internal.corext.util.Messages;
45
46 import org.eclipse.jdt.ui.JavaUI;
47 import org.eclipse.jdt.ui.SharedASTProvider;
48
49 import org.eclipse.jdt.internal.ui.JavaPlugin;
50 import org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener;
51 import org.eclipse.jdt.internal.ui.util.ExceptionHandler;
52 import org.eclipse.jdt.internal.ui.viewsupport.BasicElementLabels;
53
54 /**
55  * Manages the override and overwrite indicators for
56  * the given Java element and annotation model.
57  *
58  * @since 3.0
59  */
60 class OverrideIndicatorManager implements IJavaReconcilingListener {
61
62         /**
63          * Overwrite and override indicator annotation.
64          *
65          * @since 3.0
66          */
67         class OverrideIndicator extends Annotation {
68
69                 private boolean fIsOverwriteIndicator;
70                 private String fAstNodeKey;
71
72                 /**
73                  * Creates a new override annotation.
74                  *
75                  * @param isOverwriteIndicator <code>true</code> if this annotation is
76                  *            an overwrite indicator, <code>false</code> otherwise
77                  * @param text the text associated with this annotation
78                  * @param key the method binding key
79                  * @since 3.0
80                  */
81                 OverrideIndicator(boolean isOverwriteIndicator, String text, String key) {
82                         super(ANNOTATION_TYPE, false, text);
83                         fIsOverwriteIndicator= isOverwriteIndicator;
84                         fAstNodeKey= key;
85                 }
86
87                 /**
88                  * Tells whether this is an overwrite or an override indicator.
89                  *
90                  * @return <code>true</code> if this is an overwrite indicator
91                  */
92                 public boolean isOverwriteIndicator() {
93                         return fIsOverwriteIndicator;
94                 }
95
96                 /**
97                  * Opens and reveals the defining method.
98                  */
99                 public void open() {
100                         CompilationUnit ast= SharedASTProvider.getAST(fJavaElement, SharedASTProvider.WAIT_ACTIVE_ONLY, null);
101                         if (ast != null) {
102                                 ASTNode node= ast.findDeclaringNode(fAstNodeKey);
103                                 if (node instanceof MethodDeclaration) {
104                                         try {
105                                                 IMethodBinding methodBinding= ((MethodDeclaration)node).resolveBinding();
106                                                 IMethodBinding definingMethodBinding= Bindings.findOverriddenMethod(methodBinding, true);
107                                                 if (definingMethodBinding != null) {
108                                                         IJavaElement definingMethod= definingMethodBinding.getJavaElement();
109                                                         if (definingMethod != null) {
110                                                                 JavaUI.openInEditor(definingMethod, true, true);
111                                                                 return;
112                                                         }
113                                                 }
114                                         } catch (CoreException e) {
115                                                 ExceptionHandler.handle(e, JavaEditorMessages.OverrideIndicatorManager_open_error_title, JavaEditorMessages.OverrideIndicatorManager_open_error_messageHasLogEntry);
116                                                 return;
117                                         }
118                                 }
119                         }
120                         String title= JavaEditorMessages.OverrideIndicatorManager_open_error_title;
121                         String message= JavaEditorMessages.OverrideIndicatorManager_open_error_message;
122                         MessageDialog.openError(JavaPlugin.getActiveWorkbenchShell(), title, message);
123                 }
124         }
125
126         static final String ANNOTATION_TYPE= "org.eclipse.jdt.ui.overrideIndicator"; //$NON-NLS-1$
127
128         private IAnnotationModel fAnnotationModel;
129         private Object fAnnotationModelLockObject;
130         private Annotation[] fOverrideAnnotations;
131         private ITypeRoot fJavaElement;
132
133
134         public OverrideIndicatorManager(IAnnotationModel annotationModel, ITypeRoot javaElement, CompilationUnit ast) {
135                 Assert.isNotNull(annotationModel);
136                 Assert.isNotNull(javaElement);
137
138                 fJavaElement= javaElement;
139                 fAnnotationModel=annotationModel;
140                 fAnnotationModelLockObject= getLockObject(fAnnotationModel);
141
142                 updateAnnotations(ast, new NullProgressMonitor());
143         }
144
145         /**
146          * Returns the lock object for the given annotation model.
147          *
148          * @param annotationModel the annotation model
149          * @return the annotation model's lock object
150          * @since 3.0
151          */
152         private Object getLockObject(IAnnotationModel annotationModel) {
153                 if (annotationModel instanceof ISynchronizable) {
154                         Object lock= ((ISynchronizable)annotationModel).getLockObject();
155                         if (lock != null)
156                                 return lock;
157                 }
158                 return annotationModel;
159         }
160
161         /**
162          * Updates the override and implements annotations based
163          * on the given AST.
164          *
165          * @param ast the compilation unit AST
166          * @param progressMonitor the progress monitor
167          * @since 3.0
168          */
169         protected void updateAnnotations(CompilationUnit ast, IProgressMonitor progressMonitor) {
170
171                 if (ast == null || progressMonitor.isCanceled())
172                         return;
173
174                 final Map<Annotation, Position> annotationMap= new HashMap<Annotation, Position>(50);
175
176                 ast.accept(new ASTVisitor(false) {
177                         /*
178                          * @see org.eclipse.jdt.core.dom.ASTVisitor#visit(org.eclipse.jdt.core.dom.MethodDeclaration)
179                          */
180                         @Override
181                         public boolean visit(MethodDeclaration node) {
182                                 IMethodBinding binding= node.resolveBinding();
183                                 if (binding != null) {
184                                         IMethodBinding definingMethod= Bindings.findOverriddenMethod(binding, true);
185                                         if (definingMethod != null) {
186
187                                                 ITypeBinding definingType= definingMethod.getDeclaringClass();
188                                                 String qualifiedMethodName= definingType.getQualifiedName() + "." + binding.getName(); //$NON-NLS-1$
189
190                                                 boolean isImplements= JdtFlags.isAbstract(definingMethod);
191                                                 String text;
192                                                 if (isImplements)
193                                                         text= Messages.format(JavaEditorMessages.OverrideIndicatorManager_implements, BasicElementLabels.getJavaElementName(qualifiedMethodName));
194                                                 else
195                                                         text= Messages.format(JavaEditorMessages.OverrideIndicatorManager_overrides, BasicElementLabels.getJavaElementName(qualifiedMethodName));
196
197                                                 SimpleName name= node.getName();
198                                                 Position position= new Position(name.getStartPosition(), name.getLength());
199
200                                                 annotationMap.put(
201                                                                 new OverrideIndicator(isImplements, text, binding.getKey()),
202                                                                 position);
203
204                                         }
205                                 }
206                                 return true;
207                         }
208                 });
209
210                 if (progressMonitor.isCanceled())
211                         return;
212
213                 synchronized (fAnnotationModelLockObject) {
214                         if (fAnnotationModel instanceof IAnnotationModelExtension) {
215                                 ((IAnnotationModelExtension)fAnnotationModel).replaceAnnotations(fOverrideAnnotations, annotationMap);
216                         } else {
217                                 removeAnnotations();
218                                 Iterator<Entry<Annotation, Position>> iter= annotationMap.entrySet().iterator();
219                                 while (iter.hasNext()) {
220                                         Entry<Annotation, Position> mapEntry= iter.next();
221                                         fAnnotationModel.addAnnotation(mapEntry.getKey(), mapEntry.getValue());
222                                 }
223                         }
224                         fOverrideAnnotations= annotationMap.keySet().toArray(new Annotation[annotationMap.keySet().size()]);
225                 }
226         }
227
228         /**
229          * Removes all override indicators from this manager's annotation model.
230          */
231         void removeAnnotations() {
232                 if (fOverrideAnnotations == null)
233                         return;
234
235                 synchronized (fAnnotationModelLockObject) {
236                         if (fAnnotationModel instanceof IAnnotationModelExtension) {
237                                 ((IAnnotationModelExtension)fAnnotationModel).replaceAnnotations(fOverrideAnnotations, null);
238                         } else {
239                                 for (int i= 0, length= fOverrideAnnotations.length; i < length; i++)
240                                         fAnnotationModel.removeAnnotation(fOverrideAnnotations[i]);
241                         }
242                         fOverrideAnnotations= null;
243                 }
244         }
245
246         /*
247          * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#aboutToBeReconciled()
248          */
249         public void aboutToBeReconciled() {
250         }
251
252         /*
253          * @see org.eclipse.jdt.internal.ui.text.java.IJavaReconcilingListener#reconciled(CompilationUnit, boolean, IProgressMonitor)
254          */
255         public void reconciled(CompilationUnit ast, boolean forced, IProgressMonitor progressMonitor) {
256                 updateAnnotations(ast, progressMonitor);
257         }
258 }
259