/******************************************************************************* * Copyright (c) 2000, 2008 IBM Corporation 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: * IBM Corporation - initial API and implementation *******************************************************************************/ package org.eclipse.jdt.internal.core.builder; import org.eclipse.core.resources.*; import org.eclipse.core.runtime.*; import org.eclipse.jdt.core.compiler.CategorizedProblem; import org.eclipse.jdt.core.compiler.IProblem; import org.eclipse.jdt.internal.compiler.problem.AbortCompilation; import org.eclipse.jdt.internal.core.util.Messages; public class BuildNotifier { protected IProgressMonitor monitor; protected boolean cancelling; protected float percentComplete; protected float progressPerCompilationUnit; protected int newErrorCount; protected int fixedErrorCount; protected int newWarningCount; protected int fixedWarningCount; protected int workDone; protected int totalWork; protected String previousSubtask; public static int NewErrorCount = 0; public static int FixedErrorCount = 0; public static int NewWarningCount = 0; public static int FixedWarningCount = 0; public static void resetProblemCounters() { NewErrorCount = 0; FixedErrorCount = 0; NewWarningCount = 0; FixedWarningCount = 0; } public BuildNotifier(IProgressMonitor monitor, IProject project) { this.monitor = monitor; this.cancelling = false; this.newErrorCount = NewErrorCount; this.fixedErrorCount = FixedErrorCount; this.newWarningCount = NewWarningCount; this.fixedWarningCount = FixedWarningCount; this.workDone = 0; this.totalWork = 1000000; } /** * Notification before a compile that a unit is about to be compiled. */ public void aboutToCompile(SourceFile unit) { String message = Messages.bind(Messages.build_compiling, unit.resource.getFullPath().removeLastSegments(1).makeRelative().toString()); subTask(message); } public void begin() { if (this.monitor != null) this.monitor.beginTask("", this.totalWork); //$NON-NLS-1$ this.previousSubtask = null; } /** * Check whether the build has been canceled. */ public void checkCancel() { if (this.monitor != null && this.monitor.isCanceled()) throw new OperationCanceledException(); } /** * Check whether the build has been canceled. * Must use this call instead of checkCancel() when within the compiler. */ public void checkCancelWithinCompiler() { if (this.monitor != null && this.monitor.isCanceled() && !this.cancelling) { // Once the compiler has been canceled, don't check again. setCancelling(true); // Only AbortCompilation can stop the compiler cleanly. // We check cancelation again following the call to compile. throw new AbortCompilation(true, null); } } /** * Notification while within a compile that a unit has finished being compiled. */ public void compiled(SourceFile unit) { String message = Messages.bind(Messages.build_compiling, unit.resource.getFullPath().removeLastSegments(1).makeRelative().toString()); subTask(message); updateProgressDelta(this.progressPerCompilationUnit); checkCancelWithinCompiler(); } public void done() { NewErrorCount = this.newErrorCount; FixedErrorCount = this.fixedErrorCount; NewWarningCount = this.newWarningCount; FixedWarningCount = this.fixedWarningCount; updateProgress(1.0f); subTask(Messages.build_done); if (this.monitor != null) this.monitor.done(); this.previousSubtask = null; } /** * Returns a string describing the problems. */ protected String problemsMessage() { int numNew = this.newErrorCount + this.newWarningCount; int numFixed = this.fixedErrorCount + this.fixedWarningCount; if (numNew == 0 && numFixed == 0) return ""; //$NON-NLS-1$ boolean displayBoth = numNew > 0 && numFixed > 0; StringBuffer buffer = new StringBuffer(); buffer.append('('); if (numNew > 0) { // (Found x errors + y warnings) buffer.append(Messages.build_foundHeader); buffer.append(' '); if (displayBoth || this.newErrorCount > 0) { if (this.newErrorCount == 1) buffer.append(Messages.build_oneError); else buffer.append(Messages.bind(Messages.build_multipleErrors, String.valueOf(this.newErrorCount))); if (displayBoth || this.newWarningCount > 0) buffer.append(" + "); //$NON-NLS-1$ } if (displayBoth || this.newWarningCount > 0) { if (this.newWarningCount == 1) buffer.append(Messages.build_oneWarning); else buffer.append(Messages.bind(Messages.build_multipleWarnings, String.valueOf(this.newWarningCount))); } if (numFixed > 0) buffer.append(", "); //$NON-NLS-1$ } if (numFixed > 0) { // (Fixed x errors + y warnings) or (Found x errors + y warnings, Fixed x + y) buffer.append(Messages.build_fixedHeader); buffer.append(' '); if (displayBoth) { buffer.append(String.valueOf(this.fixedErrorCount)); buffer.append(" + "); //$NON-NLS-1$ buffer.append(String.valueOf(this.fixedWarningCount)); } else { if (this.fixedErrorCount > 0) { if (this.fixedErrorCount == 1) buffer.append(Messages.build_oneError); else buffer.append(Messages.bind(Messages.build_multipleErrors, String.valueOf(this.fixedErrorCount))); if (this.fixedWarningCount > 0) buffer.append(" + "); //$NON-NLS-1$ } if (this.fixedWarningCount > 0) { if (this.fixedWarningCount == 1) buffer.append(Messages.build_oneWarning); else buffer.append(Messages.bind(Messages.build_multipleWarnings, String.valueOf(this.fixedWarningCount))); } } } buffer.append(')'); return buffer.toString(); } /** * Sets the cancelling flag, which indicates we are in the middle * of being cancelled. Certain places (those callable indirectly from the compiler) * should not check cancel again while this is true, to avoid OperationCanceledException * being thrown at an inopportune time. */ public void setCancelling(boolean cancelling) { this.cancelling = cancelling; } /** * Sets the amount of progress to report for compiling each compilation unit. */ public void setProgressPerCompilationUnit(float progress) { this.progressPerCompilationUnit = progress; } public void subTask(String message) { String pm = problemsMessage(); String msg = pm.length() == 0 ? message : pm + " " + message; //$NON-NLS-1$ if (msg.equals(this.previousSubtask)) return; // avoid refreshing with same one //if (JavaBuilder.DEBUG) System.out.println(msg); if (this.monitor != null) this.monitor.subTask(msg); this.previousSubtask = msg; } protected void updateProblemCounts(CategorizedProblem[] newProblems) { for (int i = 0, l = newProblems.length; i < l; i++) if (newProblems[i].isError()) this.newErrorCount++; else this.newWarningCount++; } /** * Update the problem counts from one compilation result given the old and new problems, * either of which may be null. */ protected void updateProblemCounts(IMarker[] oldProblems, CategorizedProblem[] newProblems) { if (newProblems != null) { next : for (int i = 0, l = newProblems.length; i < l; i++) { CategorizedProblem newProblem = newProblems[i]; if (newProblem.getID() == IProblem.Task) continue; // skip task boolean isError = newProblem.isError(); String message = newProblem.getMessage(); if (oldProblems != null) { for (int j = 0, m = oldProblems.length; j < m; j++) { IMarker pb = oldProblems[j]; if (pb == null) continue; // already matched up with a new problem boolean wasError = IMarker.SEVERITY_ERROR == pb.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); if (isError == wasError && message.equals(pb.getAttribute(IMarker.MESSAGE, ""))) { //$NON-NLS-1$ oldProblems[j] = null; continue next; } } } if (isError) this.newErrorCount++; else this.newWarningCount++; } } if (oldProblems != null) { next : for (int i = 0, l = oldProblems.length; i < l; i++) { IMarker oldProblem = oldProblems[i]; if (oldProblem == null) continue next; // already matched up with a new problem boolean wasError = IMarker.SEVERITY_ERROR == oldProblem.getAttribute(IMarker.SEVERITY, IMarker.SEVERITY_ERROR); String message = oldProblem.getAttribute(IMarker.MESSAGE, ""); //$NON-NLS-1$ if (newProblems != null) { for (int j = 0, m = newProblems.length; j < m; j++) { CategorizedProblem pb = newProblems[j]; if (pb.getID() == IProblem.Task) continue; // skip task if (wasError == pb.isError() && message.equals(pb.getMessage())) continue next; } } if (wasError) this.fixedErrorCount++; else this.fixedWarningCount++; } } } public void updateProgress(float newPercentComplete) { if (newPercentComplete > this.percentComplete) { this.percentComplete = Math.min(newPercentComplete, 1.0f); int work = Math.round(this.percentComplete * this.totalWork); if (work > this.workDone) { if (this.monitor != null) this.monitor.worked(work - this.workDone); //if (JavaBuilder.DEBUG) //System.out.println(java.text.NumberFormat.getPercentInstance().format(this.percentComplete)); this.workDone = work; } } } public void updateProgressDelta(float percentWorked) { updateProgress(this.percentComplete + percentWorked); } }