KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > eclipse > jdt > internal > core > ReconcileWorkingCopyOperation


1 /*******************************************************************************
2  * Copyright (c) 2000, 2007 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 package org.eclipse.jdt.internal.core;
12
13 import java.util.HashMap JavaDoc;
14 import java.util.Iterator JavaDoc;
15 import java.util.Map JavaDoc;
16
17 import org.eclipse.core.runtime.ISafeRunnable;
18 import org.eclipse.core.runtime.OperationCanceledException;
19 import org.eclipse.core.runtime.SafeRunner;
20 import org.eclipse.jdt.core.*;
21 import org.eclipse.jdt.core.compiler.CategorizedProblem;
22 import org.eclipse.jdt.core.compiler.CompilationParticipant;
23 import org.eclipse.jdt.core.compiler.ReconcileContext;
24 import org.eclipse.jdt.core.dom.AST;
25 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
26 import org.eclipse.jdt.internal.core.util.Messages;
27 import org.eclipse.jdt.internal.core.util.Util;
28
29 /**
30  * Reconcile a working copy and signal the changes through a delta.
31  * <p>
32  * High level summmary of what a reconcile does:
33  * <ul>
34  * <li>populates the model with the new working copy contents</li>
35  * <li>fires a fine grained delta (flag F_FINE_GRAINED) describing the difference between the previous content
36  * and the new content (which method was added/removed, which field was changed, etc.)</li>
37  * <li>computes problems and reports them to the IProblemRequestor (begingReporting(), n x acceptProblem(...), endReporting()) iff
38  * (working copy is not consistent with its buffer || forceProblemDetection is set)
39  * && problem requestor is active
40  * </li>
41  * <li>produces a DOM AST (either JLS_2, JLS_3 or NO_AST) that is resolved if flag is set</li>
42  * <li>notifies compilation participants of the reconcile allowing them to participate in this operation and report problems</li>
43  * </ul>
44  */

45 public class ReconcileWorkingCopyOperation extends JavaModelOperation {
46     public static boolean PERF = false;
47
48     public int astLevel;
49     public boolean resolveBindings;
50     public HashMap JavaDoc problems;
51     public int reconcileFlags;
52     WorkingCopyOwner workingCopyOwner;
53     public org.eclipse.jdt.core.dom.CompilationUnit ast;
54     public JavaElementDeltaBuilder deltaBuilder;
55     public boolean requestorIsActive;
56
57     public ReconcileWorkingCopyOperation(IJavaElement workingCopy, int astLevel, int reconcileFlags, WorkingCopyOwner workingCopyOwner) {
58         super(new IJavaElement[] {workingCopy});
59         this.astLevel = astLevel;
60         this.reconcileFlags = reconcileFlags;
61         this.workingCopyOwner = workingCopyOwner;
62     }
63
64     /**
65      * @exception JavaModelException if setting the source
66      * of the original compilation unit fails
67      */

68     protected void executeOperation() throws JavaModelException {
69         checkCanceled();
70         try {
71             beginTask(Messages.element_reconciling, 2);
72
73             CompilationUnit workingCopy = getWorkingCopy();
74             boolean wasConsistent = workingCopy.isConsistent();
75
76             // check is problem requestor is active
77
IProblemRequestor problemRequestor = workingCopy.getPerWorkingCopyInfo();
78             if (problemRequestor != null)
79                 problemRequestor = ((JavaModelManager.PerWorkingCopyInfo)problemRequestor).getProblemRequestor();
80             boolean defaultRequestorIsActive = problemRequestor != null && problemRequestor.isActive();
81             IProblemRequestor ownerProblemRequestor = this.workingCopyOwner.getProblemRequestor(workingCopy);
82             boolean ownerRequestorIsActive = ownerProblemRequestor != null && ownerProblemRequestor != problemRequestor && ownerProblemRequestor.isActive();
83             this.requestorIsActive = defaultRequestorIsActive || ownerRequestorIsActive;
84
85             // create the delta builder (this remembers the current content of the cu)
86
this.deltaBuilder = new JavaElementDeltaBuilder(workingCopy);
87
88             // make working copy consistent if needed and compute AST if needed
89
makeConsistent(workingCopy);
90
91             // notify reconcile participants only if working copy was not consistent or if forcing problem detection
92
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=177319)
93
if (!wasConsistent || ((this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0)) {
94                 notifyParticipants(workingCopy);
95
96                 // recreate ast if one participant reset it
97
if (this.ast == null)
98                     makeConsistent(workingCopy);
99             }
100
101             // report problems
102
if (this.problems != null && (((this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0) || !wasConsistent)) {
103                 if (defaultRequestorIsActive) {
104                     reportProblems(workingCopy, problemRequestor);
105                 }
106                 if (ownerRequestorIsActive) {
107                     reportProblems(workingCopy, ownerProblemRequestor);
108                 }
109             }
110
111             // report delta
112
JavaElementDelta delta = this.deltaBuilder.delta;
113             if (delta != null) {
114                 addReconcileDelta(workingCopy, delta);
115             }
116         } finally {
117             done();
118         }
119     }
120
121     /**
122      * Report working copy problems to a given requestor.
123      *
124      * @param workingCopy
125      * @param problemRequestor
126      */

127     private void reportProblems(CompilationUnit workingCopy, IProblemRequestor problemRequestor) {
128         try {
129             problemRequestor.beginReporting();
130             for (Iterator JavaDoc iteraror = this.problems.values().iterator(); iteraror.hasNext();) {
131                 CategorizedProblem[] categorizedProblems = (CategorizedProblem[]) iteraror.next();
132                 if (categorizedProblems == null) continue;
133                 for (int i = 0, length = categorizedProblems.length; i < length; i++) {
134                     CategorizedProblem problem = categorizedProblems[i];
135                     if (JavaModelManager.VERBOSE){
136                         System.out.println("PROBLEM FOUND while reconciling : " + problem.getMessage());//$NON-NLS-1$
137
}
138                     if (this.progressMonitor != null && this.progressMonitor.isCanceled()) break;
139                     problemRequestor.acceptProblem(problem);
140                 }
141             }
142         } finally {
143             problemRequestor.endReporting();
144         }
145     }
146
147     /**
148      * Returns the working copy this operation is working on.
149      */

150     protected CompilationUnit getWorkingCopy() {
151         return (CompilationUnit)getElementToProcess();
152     }
153
154     /* (non-Javadoc)
155      * @see org.eclipse.jdt.internal.core.JavaModelOperation#isReadOnly()
156      */

157     public boolean isReadOnly() {
158         return true;
159     }
160
161     /*
162      * Makes the given working copy consistent, computes the delta and computes an AST if needed.
163      * Returns the AST.
164      */

165     public org.eclipse.jdt.core.dom.CompilationUnit makeConsistent(CompilationUnit workingCopy) throws JavaModelException {
166         if (!workingCopy.isConsistent()) {
167             // make working copy consistent
168
if (this.problems == null) this.problems = new HashMap JavaDoc();
169             this.resolveBindings = this.requestorIsActive;
170             this.ast = workingCopy.makeConsistent(this.astLevel, this.resolveBindings, reconcileFlags, this.problems, this.progressMonitor);
171             this.deltaBuilder.buildDeltas();
172             if (this.ast != null && this.deltaBuilder.delta != null)
173                 this.deltaBuilder.delta.changedAST(this.ast);
174             return this.ast;
175         }
176         if (this.ast != null)
177             return this.ast; // no need to recompute AST if known already
178

179         CompilationUnitDeclaration unit = null;
180         char[] contents = null;
181         try {
182             // find problems if needed
183
if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject())
184                     && (this.reconcileFlags & ICompilationUnit.FORCE_PROBLEM_DETECTION) != 0) {
185                 this.resolveBindings = this.requestorIsActive;
186                 if (this.problems == null)
187                     this.problems = new HashMap JavaDoc();
188                 contents = workingCopy.getContents();
189                 unit =
190                     CompilationUnitProblemFinder.process(
191                         workingCopy,
192                         contents,
193                         this.workingCopyOwner,
194                         this.problems,
195                         this.astLevel != ICompilationUnit.NO_AST/*creating AST if level is not NO_AST */,
196                         reconcileFlags,
197                         this.progressMonitor);
198                 if (this.progressMonitor != null) this.progressMonitor.worked(1);
199             }
200             
201             // create AST if needed
202
if (this.astLevel != ICompilationUnit.NO_AST
203                     && unit !=null/*unit is null if working copy is consistent && (problem detection not forced || non-Java project) -> don't create AST as per API*/) {
204                 Map JavaDoc options = workingCopy.getJavaProject().getOptions(true);
205                 // convert AST
206
this.ast =
207                     AST.convertCompilationUnit(
208                         this.astLevel,
209                         unit,
210                         contents,
211                         options,
212                         this.resolveBindings,
213                         workingCopy,
214                         reconcileFlags,
215                         this.progressMonitor);
216                 if (this.ast != null) {
217                     this.deltaBuilder.delta = new JavaElementDelta(workingCopy);
218                     this.deltaBuilder.delta.changedAST(this.ast);
219                 }
220                 if (this.progressMonitor != null) this.progressMonitor.worked(1);
221             }
222         } catch (JavaModelException e) {
223             if (JavaProject.hasJavaNature(workingCopy.getJavaProject().getProject()))
224                 throw e;
225             // else JavaProject has lost its nature (or most likely was closed/deleted) while reconciling -> ignore
226
// (see https://bugs.eclipse.org/bugs/show_bug.cgi?id=100919)
227
} finally {
228             if (unit != null) {
229                 unit.cleanUp();
230             }
231         }
232         return this.ast;
233     }
234     
235     private void notifyParticipants(final CompilationUnit workingCopy) {
236         IJavaProject javaProject = getWorkingCopy().getJavaProject();
237         CompilationParticipant[] participants = JavaModelManager.getJavaModelManager().compilationParticipants.getCompilationParticipants(javaProject);
238         if (participants == null) return;
239
240         final ReconcileContext context = new ReconcileContext(this, workingCopy);
241         for (int i = 0, length = participants.length; i < length; i++) {
242             final CompilationParticipant participant = participants[i];
243             SafeRunner.run(new ISafeRunnable() {
244                 public void handleException(Throwable JavaDoc exception) {
245                     if (exception instanceof Error JavaDoc) {
246                         throw (Error JavaDoc) exception; // errors are not supposed to be caught
247
} else if (exception instanceof OperationCanceledException)
248                         throw (OperationCanceledException) exception;
249                     else if (exception instanceof UnsupportedOperationException JavaDoc) {
250                         // might want to disable participant as it tried to modify the buffer of the working copy being reconciled
251
Util.log(exception, "Reconcile participant attempted to modify the buffer of the working copy being reconciled"); //$NON-NLS-1$
252
} else
253                         Util.log(exception, "Exception occurred in reconcile participant"); //$NON-NLS-1$
254
}
255                 public void run() throws Exception JavaDoc {
256                     participant.reconcile(context);
257                 }
258             });
259         }
260     }
261
262     protected IJavaModelStatus verify() {
263         IJavaModelStatus status = super.verify();
264         if (!status.isOK()) {
265             return status;
266         }
267         CompilationUnit workingCopy = getWorkingCopy();
268         if (!workingCopy.isWorkingCopy()) {
269             return new JavaModelStatus(IJavaModelStatusConstants.ELEMENT_DOES_NOT_EXIST, workingCopy); //was destroyed
270
}
271         return status;
272     }
273
274 }
275
Popular Tags