diff options
Diffstat (limited to 'archive/org.eclipse.qvt.declarative.editor.imp.runtime/src/org/eclipse/imp/builder/MarkerCreatorWithBatching.java')
-rw-r--r-- | archive/org.eclipse.qvt.declarative.editor.imp.runtime/src/org/eclipse/imp/builder/MarkerCreatorWithBatching.java | 286 |
1 files changed, 286 insertions, 0 deletions
diff --git a/archive/org.eclipse.qvt.declarative.editor.imp.runtime/src/org/eclipse/imp/builder/MarkerCreatorWithBatching.java b/archive/org.eclipse.qvt.declarative.editor.imp.runtime/src/org/eclipse/imp/builder/MarkerCreatorWithBatching.java new file mode 100644 index 000000000..cbea7a0b6 --- /dev/null +++ b/archive/org.eclipse.qvt.declarative.editor.imp.runtime/src/org/eclipse/imp/builder/MarkerCreatorWithBatching.java @@ -0,0 +1,286 @@ +/******************************************************************************* +* Copyright (c) 2008 IBM Corporation. +* 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: +* Stan Sutton (suttons@us.ibm.com) - initial API and implementation +* Copied liberally and adapted from an implementation provided by +* E. D. Willink as an attachment to Eclipse bugzilla bug #245296 (and +* copyrighted 2008 under EPL v. 1.0 http://www.eclipse.org/legal/epl-v10.html). +* +*******************************************************************************/ + +package org.eclipse.imp.builder; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.Set; + +import org.eclipse.core.resources.IFile; +import org.eclipse.core.resources.IMarker; +import org.eclipse.core.resources.IWorkspace; +import org.eclipse.core.resources.IWorkspaceRunnable; +import org.eclipse.core.runtime.CoreException; +import org.eclipse.core.runtime.IProgressMonitor; +import org.eclipse.core.runtime.NullProgressMonitor; +import org.eclipse.imp.builder.ProblemLimit.LimitExceededException; +import org.eclipse.imp.core.ErrorHandler; +import org.eclipse.imp.parser.IParseController; + +/** + * An implementation of IMessageHandler for collecting messages over time + * and then creating a group of corresponding markers in one batch using + * a single workspace operation. + * + * Copied liberally from a MarkerProblemHandler implementation provided by + * E. D. Willink as an attachment to Eclipse bugzilla bug #245296 (and + * copyrighted 2008 under EPL v. 1.0 http://www.eclipse.org/legal/epl-v10.html). + * + * @author Stan Sutton (suttons@us.ibm.com) + */ +public class MarkerCreatorWithBatching extends MarkerCreator { + protected String page = null; + protected Map<Integer, List<Map<String, Object>>> entries = null; // Map of line number to list of marker attributes for line + protected ProblemLimit problemLimit = null; + protected BuilderBase builder = null; + + /* + * NOTE: The parse controller that is provided in constructing an instance of this + * type is used to obtain a parse stream that is used in processing error messages + * received by the instance. In particular, error messages are associated with positions + * in the text, those positions are used to identify corresponding parse tokens, and + * those parse tokens are used in determining positions for error markers. For that + * reason, the given parse controller should provide a parse stream that is consistent + * with (if not identical to) the one obtained when the error messages were generated. + * Also for that reason, no additional parsing is done within the marker creator. + * Violation of this assumption can lead to markers (and marker annotations) that are + * not correctly located with respect to the underling error in the text. + */ + + + /** + * Constructor to use when you want to create markers that are not related to a + * particular builder and that will have the marker type provided here. + * + * @param resource The resource (e.g., file) on which markers are to be placed + * @param parseController The source of the parse stream to which error messages will + * be related + * @param problemType The type of problem marker (i.e., the problem marker id) + */ + public MarkerCreatorWithBatching( + IFile file, + IParseController parseController, + String problemType) + { + super(file, parseController, problemType); + PROBLEM_MARKER_ID = problemType; + } + + + /** + * Constructor to use when you want to create markers that are related to a + * particular builder and that will have a marker type and builder id based + * on that builder. + * + * @param file The file on which markers are to be placed + * @param parseController The source of the parse stream to which error messages will + * be related + * @param builder The builder that is presumably driving the creation of + * markers and that defines the type of marker and builder id + * that will be used here + */ + public MarkerCreatorWithBatching( + IFile file, + IParseController parseController, + BuilderBase builder) + { + super(file, parseController, builder.getErrorMarkerID()); + + this.builder = builder; + initializeBuidlerID(builder); + initializeProblemMarkerID(builder); + } + + + public String BUILDER_ID; + + protected void initializeBuidlerID(BuilderBase builder) { + if (builder != null) { + BUILDER_ID = builder.getBuilderID(); + } else { + BUILDER_ID = parseController.getLanguage().getName() + ".builder"; + } + } + + public String PROBLEM_MARKER_ID; + + protected void initializeProblemMarkerID(BuilderBase builder) { + if (builder != null) { + PROBLEM_MARKER_ID = builder.getErrorMarkerID(); + } else { + PROBLEM_MARKER_ID = parseController.getLanguage().getName() + ".builder"; + } + } + + + public Map<Integer, Integer> severityMap = new HashMap<Integer, Integer>(); + { + severityMap.put(Integer.valueOf(IMarker.SEVERITY_ERROR), Integer.valueOf(IMarker.SEVERITY_ERROR)); + severityMap.put(IMarker.SEVERITY_INFO, Integer.valueOf(IMarker.SEVERITY_INFO)); + severityMap.put(IMarker.SEVERITY_WARNING, Integer.valueOf(IMarker.SEVERITY_WARNING)); + } + + public void setSeverityMap(Map<Integer, Integer> mapOfSeverities) { + // TODO: Figure out what to do about target severities that do not correspond + // to marker severities + severityMap = mapOfSeverities; + } + + public Map<Integer, Integer> getSeverityMap() { + return severityMap; + } + + public void addMarker(int severity, String message, int lineNumber, int charStart, int charEnd) + throws ProblemLimit.LimitExceededException + { + String adjustedMessage = message; + if (problemLimit != null) { + adjustedMessage = problemLimit.check(severity, message); + if (adjustedMessage == null) + return; + } + Map<String, Object> attributes = new HashMap<String, Object>(); + attributes.put(IMarker.MESSAGE, adjustedMessage); + attributes.put(IMarker.SEVERITY, Integer.valueOf(severity)); + if (lineNumber == -1) { + lineNumber = 1; + } + Integer lineKey = Integer.valueOf(lineNumber); + attributes.put(IMarker.LINE_NUMBER, lineKey); + if (charStart <= charEnd) { + attributes.put(IMarker.CHAR_START, Integer.valueOf(charStart)); + attributes.put(IMarker.CHAR_END, Integer.valueOf(charEnd)); + } +// attributes.put(BUILDER_ID, creationFactory.getBuilderId()); + if (builder != null) + attributes.put(BUILDER_ID, builder.getBuilderID()); + if (entries == null) + entries = new HashMap<Integer, List<Map<String, Object>>>(); + List<Map<String, Object>> lineEntries = entries.get(lineKey); + if (lineEntries == null) { + lineEntries = new ArrayList<Map<String, Object>>(); + entries.put(lineKey, lineEntries); + } + lineEntries.add(attributes); + if (adjustedMessage != message) + throw new ProblemLimit.LimitExceededException(adjustedMessage); + } + + + public void clearMessages() { + // TODO Auto-generated method stub + } + + + public void endMessageGroup() { } + + + public void flush(IProgressMonitor monitor) { + // Re-use existing markers wherever possible + // a) since many rebuilds generate the same errors + // b) to avoid a marker being deleted by a refreshMarkers on editor entry before + // gotoMarker is invoked to go to a pre-existing context. + if (file.exists()) { + IWorkspaceRunnable action = new IWorkspaceRunnable() { + public void run(IProgressMonitor monitor) throws CoreException { + String markerId = PROBLEM_MARKER_ID; + if (entries != null) { + IMarker[] oldMarkers = file.findMarkers(markerId, false, IFile.DEPTH_ZERO); + for (IMarker oldMarker : oldMarkers) { + Map<?, ?> oldAttributes = oldMarker.getAttributes(); + List<Map<String, Object>> lineEntries = entries.get(oldAttributes.get(IMarker.LINE_NUMBER)); + if (lineEntries != null) { + for (Map<String, Object> newAttributes : lineEntries) { + if (isSameMarker(oldAttributes, newAttributes)) { + lineEntries.remove(newAttributes); + oldMarker = null; + break; + } + } + } + if (oldMarker != null) + oldMarker.delete(); + } + for (List<Map<String, Object>> lineEntries : entries.values()) { + for (Map<String, Object> entry : lineEntries) { + IMarker marker = file.createMarker(markerId); + marker.setAttributes(entry); + } + } + } else + file.deleteMarkers(markerId, false, IFile.DEPTH_ZERO); + } + }; + try { + // TODO: Allow for the introduction of a non-null progress monitor +// IProgressMonitor progressMonitor = monitor != null ? BasicMonitor.toIProgressMonitor(monitor) : new NullProgressMonitor(); + IProgressMonitor progressMonitor = new NullProgressMonitor(); + file.getWorkspace().run(action, file, IWorkspace.AVOID_UPDATE, progressMonitor); + } catch (CoreException e) { + ErrorHandler.logError("Failed to update file markers", e); + } + } + } + + public void handleSimpleMessage( + String msg, int startOffset, int endOffset, + int startCol, int endCol, int startLine, int endLine) + { + try { + addMarker(IMarker.SEVERITY_ERROR, msg, startLine, startOffset, endOffset+1); + } catch (LimitExceededException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + /** + * Return true if newAttributes and oldAttributes provide the same marker description. + */ + public boolean isSameMarker(Map<?, ?> oldAttributes, Map<String, Object> newAttributes) { + Set<?> oldKeys = oldAttributes.keySet(); + Set<String> newKeys = newAttributes.keySet(); + if (oldKeys.size() != newKeys.size()) + return false; + for (String key : newKeys) { + if (!oldAttributes.containsKey(key)) + return false; + Object oldValue = oldAttributes.get(key); + Object newValue = newAttributes.get(key); + if (oldValue == newValue) + continue; + if (oldValue == null) + return false; + if (newValue == null) + return false; + if (!oldValue.equals(newValue)) + return false; + } + return true; + } + + public void setProblemLimit(ProblemLimit problemLimit) { + this.problemLimit = problemLimit; + } + + public void setPage(String page) { + this.page = page; + } + + public void startMessageGroup(String groupName) { } +} |