032cf26062bf1868b49819a599e366d34f460a6c
[phpeclipse.git] / net.sourceforge.phpeclipse / src / net / sourceforge / phpdt / internal / core / builder / BuildNotifier.java
1 /*******************************************************************************
2  * Copyright (c) 2000, 2003 IBM Corporation and others.
3  * All rights reserved. This program and the accompanying materials 
4  * are made available under the terms of the Common Public License v1.0
5  * which accompanies this distribution, and is available at
6  * http://www.eclipse.org/legal/cpl-v10.html
7  * 
8  * Contributors:
9  *     IBM Corporation - initial API and implementation
10  *******************************************************************************/
11 package net.sourceforge.phpdt.internal.core.builder;
12
13 import net.sourceforge.phpdt.core.compiler.IProblem;
14 import net.sourceforge.phpdt.internal.compiler.problem.AbortCompilation;
15 import net.sourceforge.phpdt.internal.compiler.util.Util;
16
17 import org.eclipse.core.resources.IMarker;
18 import org.eclipse.core.resources.IProject;
19 import org.eclipse.core.runtime.IProgressMonitor;
20 import org.eclipse.core.runtime.OperationCanceledException;
21
22 public class BuildNotifier {
23
24 protected IProgressMonitor monitor;
25 protected boolean cancelling;
26 protected float percentComplete;
27 protected float progressPerCompilationUnit;
28 protected int newErrorCount;
29 protected int fixedErrorCount;
30 protected int newWarningCount;
31 protected int fixedWarningCount;
32 protected int workDone;
33 protected int totalWork;
34 protected String previousSubtask;
35
36 public static int NewErrorCount = 0;
37 public static int FixedErrorCount = 0;
38 public static int NewWarningCount = 0;
39 public static int FixedWarningCount = 0;
40
41 public static void resetProblemCounters() {
42         NewErrorCount = 0;
43         FixedErrorCount = 0;
44         NewWarningCount = 0;
45         FixedWarningCount = 0;
46 }
47
48 public BuildNotifier(IProgressMonitor monitor, IProject project) {
49         this.monitor = monitor;
50         this.cancelling = false;
51         this.newErrorCount = NewErrorCount;
52         this.fixedErrorCount = FixedErrorCount;
53         this.newWarningCount = NewWarningCount;
54         this.fixedWarningCount = FixedWarningCount;
55         this.workDone = 0;
56         this.totalWork = 1000000;
57 }
58
59 /**
60  * Notification before a compile that a unit is about to be compiled.
61  */
62 public void aboutToCompile(SourceFile unit) {
63         String message = Util.bind("build.compiling", unit.resource.getFullPath().removeLastSegments(1).makeRelative().toString()); //$NON-NLS-1$
64         subTask(message);
65 }
66
67 public void begin() {
68         if (monitor != null)
69                 monitor.beginTask("", totalWork); //$NON-NLS-1$
70         this.previousSubtask = null;
71 }
72
73 /**
74  * Check whether the build has been canceled.
75  */
76 public void checkCancel() {
77         if (monitor != null && monitor.isCanceled())
78                 throw new OperationCanceledException();
79 }
80
81 /**
82  * Check whether the build has been canceled.
83  * Must use this call instead of checkCancel() when within the compiler.
84  */
85 public void checkCancelWithinCompiler() {
86         if (monitor != null && monitor.isCanceled() && !cancelling) {
87                 // Once the compiler has been canceled, don't check again.
88                 setCancelling(true);
89                 // Only AbortCompilation can stop the compiler cleanly.
90                 // We check cancelation again following the call to compile.
91                 throw new AbortCompilation(true, null); 
92         }
93 }
94
95 /**
96  * Notification while within a compile that a unit has finished being compiled.
97  */
98 public void compiled(SourceFile unit) {
99         String message = Util.bind("build.compiling", unit.resource.getFullPath().removeLastSegments(1).makeRelative().toString()); //$NON-NLS-1$
100         subTask(message);
101         updateProgressDelta(progressPerCompilationUnit);
102         checkCancelWithinCompiler();
103 }
104
105 public void done() {
106         NewErrorCount = this.newErrorCount;
107         FixedErrorCount = this.fixedErrorCount;
108         NewWarningCount = this.newWarningCount;
109         FixedWarningCount = this.fixedWarningCount;
110
111         updateProgress(1.0f);
112         subTask(Util.bind("build.done")); //$NON-NLS-1$
113         if (monitor != null)
114                 monitor.done();
115         this.previousSubtask = null;
116 }
117
118 /**
119  * Returns a string describing the problems.
120  */
121 protected String problemsMessage() {
122         int numNew = newErrorCount + newWarningCount;
123         int numFixed = fixedErrorCount + fixedWarningCount;
124         if (numNew == 0 && numFixed == 0) return ""; //$NON-NLS-1$
125
126         boolean displayBoth = numNew > 0 && numFixed > 0;
127         StringBuffer buffer = new StringBuffer();
128         buffer.append('(');
129         if (numNew > 0) {
130                 // (Found x errors + y warnings)
131                 buffer.append(Util.bind("build.foundHeader")); //$NON-NLS-1$
132                 buffer.append(' ');
133                 if (displayBoth || newErrorCount > 0) {
134                         if (newErrorCount == 1)
135                                 buffer.append(Util.bind("build.oneError")); //$NON-NLS-1$
136                         else
137                                 buffer.append(Util.bind("build.multipleErrors", String.valueOf(newErrorCount))); //$NON-NLS-1$
138                         if (displayBoth || newWarningCount > 0)
139                                 buffer.append(" + "); //$NON-NLS-1$
140                 }
141                 if (displayBoth || newWarningCount > 0) {
142                         if (newWarningCount == 1)
143                                 buffer.append(Util.bind("build.oneWarning")); //$NON-NLS-1$
144                         else
145                                 buffer.append(Util.bind("build.multipleWarnings", String.valueOf(newWarningCount))); //$NON-NLS-1$
146                 }
147                 if (numFixed > 0)
148                         buffer.append(", "); //$NON-NLS-1$
149         }
150         if (numFixed > 0) {
151                 // (Fixed x errors + y warnings) or (Found x errors + y warnings, Fixed x + y)
152                 buffer.append(Util.bind("build.fixedHeader")); //$NON-NLS-1$
153                 buffer.append(' ');
154                 if (displayBoth) {
155                         buffer.append(String.valueOf(fixedErrorCount));
156                         buffer.append(" + "); //$NON-NLS-1$
157                         buffer.append(String.valueOf(fixedWarningCount));
158                 } else {
159                         if (fixedErrorCount > 0) {
160                                 if (fixedErrorCount == 1)
161                                         buffer.append(Util.bind("build.oneError")); //$NON-NLS-1$
162                                 else
163                                         buffer.append(Util.bind("build.multipleErrors", String.valueOf(fixedErrorCount))); //$NON-NLS-1$
164                                 if (fixedWarningCount > 0)
165                                         buffer.append(" + "); //$NON-NLS-1$
166                         }
167                         if (fixedWarningCount > 0) {
168                                 if (fixedWarningCount == 1)
169                                         buffer.append(Util.bind("build.oneWarning")); //$NON-NLS-1$
170                                 else
171                                         buffer.append(Util.bind("build.multipleWarnings", String.valueOf(fixedWarningCount))); //$NON-NLS-1$
172                         }
173                 }
174         }
175         buffer.append(')');
176         return buffer.toString();
177 }
178
179 /**
180  * Sets the cancelling flag, which indicates we are in the middle
181  * of being cancelled.  Certain places (those callable indirectly from the compiler)
182  * should not check cancel again while this is true, to avoid OperationCanceledException
183  * being thrown at an inopportune time.
184  */
185 public void setCancelling(boolean cancelling) {
186         this.cancelling = cancelling;
187 }
188
189 /**
190  * Sets the amount of progress to report for compiling each compilation unit.
191  */
192 public void setProgressPerCompilationUnit(float progress) {
193         this.progressPerCompilationUnit = progress;
194 }
195
196 public void subTask(String message) {
197         String pm = problemsMessage();
198         String msg = pm.length() == 0 ? message : pm + " " + message; //$NON-NLS-1$
199
200         if (msg.equals(this.previousSubtask)) return; // avoid refreshing with same one
201         //if (JavaBuilder.DEBUG) System.out.println(msg);
202         if (monitor != null)
203                 monitor.subTask(msg);
204
205         this.previousSubtask = msg;
206 }
207
208 protected void updateProblemCounts(IProblem[] newProblems) {
209         for (int i = 0, l = newProblems.length; i < l; i++)
210                 if (newProblems[i].isError()) newErrorCount++; else newWarningCount++;
211 }
212
213 /**
214  * Update the problem counts from one compilation result given the old and new problems,
215  * either of which may be null.
216  */
217 protected void updateProblemCounts(IMarker[] oldProblems, IProblem[] newProblems) {
218         if (newProblems != null) {
219                 next : for (int i = 0, l = newProblems.length; i < l; i++) {
220                         IProblem newProblem = newProblems[i];
221                         if (newProblem.getID() == IProblem.Task) continue; // skip task
222                         boolean isError = newProblem.isError();
223                         String message = newProblem.getMessage();
224
225                         if (oldProblems != null) {
226                                 for (int j = 0, m = oldProblems.length; j < m; j++) {
227                                         IMarker pb = oldProblems[j];
228                                         if (pb == null) continue; // already matched up with a new problem
229                                         boolean wasError = IMarker.SEVERITY_ERROR
230                                                 == pb.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
231                                         if (isError == wasError && message.equals(pb.getAttribute(IMarker.MESSAGE, ""))) { //$NON-NLS-1$
232                                                 oldProblems[j] = null;
233                                                 continue next;
234                                         }
235                                 }
236                         }
237                         if (isError) newErrorCount++; else newWarningCount++;
238                 }
239         }
240         if (oldProblems != null) {
241                 next : for (int i = 0, l = oldProblems.length; i < l; i++) {
242                         IMarker oldProblem = oldProblems[i];
243                         if (oldProblem == null) continue next; // already matched up with a new problem
244                         boolean wasError = IMarker.SEVERITY_ERROR
245                                 == oldProblem.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR);
246                         String message = oldProblem.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$
247
248                         if (newProblems != null) {
249                                 for (int j = 0, m = newProblems.length; j < m; j++) {
250                                         IProblem pb = newProblems[j];
251                                         if (pb.getID() == IProblem.Task) continue; // skip task
252                                         if (wasError == pb.isError() && message.equals(pb.getMessage()))
253                                                 continue next;
254                                 }
255                         }
256                         if (wasError) fixedErrorCount++; else fixedWarningCount++;
257                 }
258         }
259 }
260
261 public void updateProgress(float percentComplete) {
262         if (percentComplete > this.percentComplete) {
263                 this.percentComplete = Math.min(percentComplete, 1.0f);
264                 int work = Math.round(this.percentComplete * this.totalWork);
265                 if (work > this.workDone) {
266                         if (monitor != null)
267                                 monitor.worked(work - this.workDone);
268                         //if (JavaBuilder.DEBUG)
269                                 //System.out.println(java.text.NumberFormat.getPercentInstance().format(this.percentComplete));
270                         this.workDone = work;
271                 }
272         }
273 }
274
275 public void updateProgressDelta(float percentWorked) {
276         updateProgress(percentComplete + percentWorked);
277 }
278 }