1 /******************************************************************************* 2 * Copyright (c) 2004, 2013 IBM Corporation and others. 3 * 4 * This program and the accompanying materials 5 * are made available under the terms of the Eclipse Public License 2.0 6 * which accompanies this distribution, and is available at 7 * https://www.eclipse.org/legal/epl-2.0/ 8 * 9 * SPDX-License-Identifier: EPL-2.0 10 * 11 * Contributors: 12 * IBM Corporation - initial API and implementation 13 *******************************************************************************/ 14 15 package org.eclipse.ant.internal.ui.editor.outline; 16 17 import java.util.ArrayList; 18 import java.util.HashMap; 19 import java.util.Iterator; 20 import java.util.List; 21 import java.util.Map; 22 23 import org.eclipse.ant.core.AntCorePlugin; 24 import org.eclipse.ant.internal.core.IAntCoreConstants; 25 import org.eclipse.ant.internal.ui.AntUIPlugin; 26 import org.eclipse.ant.internal.ui.model.IAntModel; 27 import org.eclipse.ant.internal.ui.model.IProblem; 28 import org.eclipse.core.resources.IFile; 29 import org.eclipse.core.resources.IMarker; 30 import org.eclipse.core.resources.IResource; 31 import org.eclipse.core.resources.ResourcesPlugin; 32 import org.eclipse.core.resources.WorkspaceJob; 33 import org.eclipse.core.runtime.CoreException; 34 import org.eclipse.core.runtime.IProgressMonitor; 35 import org.eclipse.core.runtime.IStatus; 36 import org.eclipse.core.runtime.Status; 37 import org.eclipse.core.runtime.content.IContentDescription; 38 import org.eclipse.core.runtime.content.IContentType; 39 import org.eclipse.ui.texteditor.MarkerUtilities; 40 41 public class AntEditorMarkerUpdater { 42 43 class AntEditorMarkerUpdaterJob extends WorkspaceJob { 44 45 private final List<IProblem> fProblems; 46 AntEditorMarkerUpdaterJob(List<IProblem> problems)47 public AntEditorMarkerUpdaterJob(List<IProblem> problems) { 48 super("Ant editor marker updater job"); //$NON-NLS-1$ 49 fProblems = problems; 50 setSystem(true); 51 } 52 53 @Override runInWorkspace(IProgressMonitor monitor)54 public IStatus runInWorkspace(IProgressMonitor monitor) { 55 updateMarkers0(fProblems); 56 return new Status(IStatus.OK, AntUIPlugin.getUniqueIdentifier(), IStatus.OK, IAntCoreConstants.EMPTY_STRING, null); 57 } 58 } 59 60 private IAntModel fModel = null; 61 private List<IProblem> fCollectedProblems = new ArrayList<>(); 62 public static final String BUILDFILE_PROBLEM_MARKER = AntUIPlugin.PI_ANTUI + ".buildFileProblem"; //$NON-NLS-1$ 63 private IFile fFile = null; 64 acceptProblem(IProblem problem)65 public synchronized void acceptProblem(IProblem problem) { 66 if (fCollectedProblems.contains(problem)) { 67 return; 68 } 69 fCollectedProblems.add(problem); 70 } 71 beginReporting()72 public synchronized void beginReporting() { 73 fCollectedProblems.clear(); 74 } 75 removeProblems()76 private void removeProblems() { 77 IFile file = getFile(); 78 if (file == null || !file.exists()) { 79 return; 80 } 81 try { 82 file.deleteMarkers(BUILDFILE_PROBLEM_MARKER, false, IResource.DEPTH_INFINITE); 83 } 84 catch (CoreException e) { 85 AntUIPlugin.log(e); 86 } 87 } 88 createMarker(IProblem problem)89 private void createMarker(IProblem problem) { 90 IFile file = getFile(); 91 Map<String, Object> attributes = getMarkerAttributes(problem); 92 try { 93 MarkerUtilities.createMarker(file, attributes, BUILDFILE_PROBLEM_MARKER); 94 } 95 catch (CoreException e) { 96 AntUIPlugin.log(e); 97 } 98 } 99 setModel(IAntModel model)100 public void setModel(IAntModel model) { 101 fModel = model; 102 } 103 updateMarkers()104 public synchronized void updateMarkers() { 105 IFile file = getFile(); 106 if (file != null) { 107 List<IProblem> problems = new ArrayList<>(fCollectedProblems.size()); 108 Iterator<IProblem> e = fCollectedProblems.iterator(); 109 while (e.hasNext()) { 110 problems.add(e.next()); 111 } 112 fCollectedProblems.clear(); 113 AntEditorMarkerUpdaterJob job = new AntEditorMarkerUpdaterJob(problems); 114 job.setRule(ResourcesPlugin.getWorkspace().getRuleFactory().markerRule(file)); 115 job.schedule(); 116 } 117 } 118 updateMarkers0(List<IProblem> problems)119 private void updateMarkers0(List<IProblem> problems) { 120 removeProblems(); 121 if (!shouldAddMarkers()) { 122 return; 123 } 124 125 if (problems.size() > 0) { 126 Iterator<IProblem> e = problems.iterator(); 127 while (e.hasNext()) { 128 IProblem problem = e.next(); 129 createMarker(problem); 130 } 131 } 132 } 133 getFile()134 private IFile getFile() { 135 if (fFile == null) { 136 fFile = fModel.getFile(); 137 } 138 return fFile; 139 } 140 141 /** 142 * Returns the attributes with which a newly created marker will be initialized. 143 * 144 * @return the initial marker attributes 145 */ getMarkerAttributes(IProblem problem)146 private Map<String, Object> getMarkerAttributes(IProblem problem) { 147 148 Map<String, Object> attributes = new HashMap<>(11); 149 int severity = IMarker.SEVERITY_ERROR; 150 if (problem.isWarning()) { 151 severity = IMarker.SEVERITY_WARNING; 152 } 153 // marker line numbers are 1-based 154 MarkerUtilities.setMessage(attributes, problem.getUnmodifiedMessage()); 155 MarkerUtilities.setLineNumber(attributes, problem.getLineNumber()); 156 MarkerUtilities.setCharStart(attributes, problem.getOffset()); 157 MarkerUtilities.setCharEnd(attributes, problem.getOffset() + problem.getLength()); 158 attributes.put(IMarker.SEVERITY, Integer.valueOf(severity)); 159 return attributes; 160 } 161 162 /** 163 * Returns whether or not to add markers to the file based on the file's content type. The content type is considered an Ant buildfile if the XML 164 * has a root "project" element. Content type is defined in the org.eclipse.ant.core plugin.xml. 165 * 166 * @return whether or not to add markers to the file based on the files content type 167 */ shouldAddMarkers()168 private boolean shouldAddMarkers() { 169 IFile file = getFile(); 170 if (file == null || !file.exists()) { 171 return false; 172 } 173 IContentDescription description; 174 try { 175 description = file.getContentDescription(); 176 } 177 catch (CoreException e) { 178 return false; 179 } 180 if (description != null) { 181 IContentType type = description.getContentType(); 182 return type != null && AntCorePlugin.ANT_BUILDFILE_CONTENT_TYPE.equals(type.getId()); 183 } 184 return false; 185 } 186 } 187