| /******************************************************************************* |
| * Copyright (c) 2001, 2013 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 |
| * Jens Lukowski/Innoopract - initial renaming/restructuring |
| * |
| *******************************************************************************/ |
| package org.eclipse.wst.xml.core.internal.tasks; |
| |
| import java.io.BufferedReader; |
| import java.io.IOException; |
| import java.io.InputStreamReader; |
| import java.io.UnsupportedEncodingException; |
| import java.util.ArrayList; |
| import java.util.HashMap; |
| import java.util.List; |
| import java.util.Locale; |
| import java.util.Map; |
| |
| import org.eclipse.core.resources.IFile; |
| import org.eclipse.core.resources.IMarker; |
| import org.eclipse.core.resources.IProject; |
| import org.eclipse.core.resources.IResource; |
| import org.eclipse.core.resources.ResourcesPlugin; |
| import org.eclipse.core.runtime.CoreException; |
| import org.eclipse.core.runtime.IConfigurationElement; |
| import org.eclipse.core.runtime.IExecutableExtension; |
| import org.eclipse.core.runtime.IProgressMonitor; |
| import org.eclipse.jface.text.BadLocationException; |
| import org.eclipse.jface.text.DefaultLineTracker; |
| import org.eclipse.jface.text.IRegion; |
| import org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner; |
| import org.eclipse.wst.sse.core.internal.provisional.tasks.TaskTag; |
| import org.eclipse.wst.xml.core.internal.Logger; |
| import org.eclipse.wst.xml.core.internal.parser.XMLLineTokenizer; |
| import org.eclipse.wst.xml.core.internal.regions.DOMRegionContext; |
| |
| /** |
| * A delegate to create IMarker.TASKs for "todos" and similar comments. |
| */ |
| public class XMLStreamingFileTaskScanner extends XMLLineTokenizer implements IFileTaskScanner, IExecutableExtension { |
| private static final boolean DEBUG_TASKSPERF = true; |
| |
| // the list of attribute maps for the new tasks for the current file |
| protected List fNewMarkerAttributeMaps = null; |
| |
| List oldMarkers = null; |
| private long time0; |
| private String runtimeMarkerType; |
| |
| public XMLStreamingFileTaskScanner() { |
| super(); |
| } |
| |
| /** |
| * Returns the attributes with which a newly created marker will be |
| * initialized. Modified from the method in MarkerRulerAction |
| * |
| * @return the initial marker attributes |
| */ |
| protected Map createInitialMarkerAttributes(String text, int documentLine, int startOffset, int length, int priority) { |
| Map attributes = new HashMap(6); |
| // marker line numbers are 1-based |
| attributes.put(IMarker.LINE_NUMBER, new Integer(documentLine + 1)); |
| attributes.put(IMarker.TASK, getMarkerType()); |
| attributes.put(IMarker.CHAR_START, new Integer(startOffset)); |
| attributes.put(IMarker.CHAR_END, new Integer(startOffset + length)); |
| attributes.put(IMarker.MESSAGE, text); |
| attributes.put(IMarker.USER_EDITABLE, Boolean.FALSE); |
| |
| switch (priority) { |
| case IMarker.PRIORITY_HIGH : { |
| attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_HIGH)); |
| } |
| break; |
| case IMarker.PRIORITY_LOW : { |
| attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_LOW)); |
| } |
| break; |
| default : { |
| attributes.put(IMarker.PRIORITY, new Integer(IMarker.PRIORITY_NORMAL)); |
| } |
| } |
| |
| return attributes; |
| } |
| |
| String detectCharset(IFile file) { |
| if (file.getType() == IResource.FILE && file.isAccessible()) { |
| try { |
| return file.getCharset(true); |
| } |
| catch (CoreException e) { |
| Logger.logException(e); |
| } |
| } |
| return ResourcesPlugin.getEncoding(); |
| } |
| |
| void findTasks(IFile file, final TaskTag[] taskTags, final IProgressMonitor monitor) { |
| String charset = detectCharset(file); |
| monitor.beginTask("", IProgressMonitor.UNKNOWN); |
| // used for breaking multi-line comments into individual lines |
| DefaultLineTracker lineTracker = new DefaultLineTracker(); |
| String[] searchTags = new String[taskTags.length]; |
| for (int i = 0; i < searchTags.length; i++) { |
| searchTags[i] = taskTags[i].getTag().toLowerCase(Locale.ENGLISH); |
| } |
| try { |
| reset(new BufferedReader(new InputStreamReader(file.getContents(true), charset))); |
| while (!isEOF()) { |
| String regionType = primGetNextToken(); |
| if (isCommentType(regionType)) { |
| String comment = yytext(); |
| lineTracker.set(comment); |
| for (int lineNumber = 0; lineNumber < lineTracker.getNumberOfLines(); lineNumber++) { |
| IRegion line = lineTracker.getLineInformation(lineNumber); |
| String lineComment = comment.substring(line.getOffset(), line.getOffset() + line.getLength()); |
| String lowercaseText = lineComment.toLowerCase(Locale.ENGLISH); |
| |
| for (int i = 0; i < taskTags.length; i++) { |
| int tagIndex = lowercaseText.indexOf(searchTags[i]); |
| if (tagIndex >= 0) { |
| String markerDescription = lineComment.substring(tagIndex); |
| int markerOffset = getOffset() + line.getOffset() + tagIndex; |
| int markerLength = line.getLength() - tagIndex; |
| fNewMarkerAttributeMaps.add(createInitialMarkerAttributes(markerDescription, lineNumber + getLine(), markerOffset, markerLength, taskTags[i].getPriority())); |
| } |
| } |
| } |
| } |
| } |
| } |
| catch (UnsupportedEncodingException e) { |
| Logger.logException(e); |
| } |
| catch (IOException e) { |
| Logger.logException(e); |
| } |
| catch (CoreException e) { |
| Logger.logException(e); |
| } |
| catch (BadLocationException e) { |
| Logger.logException(e); |
| } |
| monitor.done(); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.wst.sse.core.internal.provisional.tasks.IFileTaskScanner |
| * #getMarkerType() |
| */ |
| public String getMarkerType() { |
| if (runtimeMarkerType != null) { |
| return runtimeMarkerType; |
| } |
| |
| return org.eclipse.core.resources.IMarker.TASK; |
| } |
| |
| protected boolean isCommentType(String regionType) { |
| return DOMRegionContext.XML_COMMENT_TEXT.equals(regionType); |
| } |
| |
| public synchronized Map[] scan(IFile file, TaskTag[] taskTags, IProgressMonitor monitor) { |
| fNewMarkerAttributeMaps = new ArrayList(); |
| if (monitor.isCanceled() || !shouldScan(file)) { |
| return new Map[0]; |
| } |
| if (DEBUG_TASKSPERF) { |
| time0 = System.currentTimeMillis(); |
| } |
| if (taskTags.length > 0) { |
| findTasks(file, taskTags, monitor); |
| } |
| if (DEBUG_TASKSPERF) { |
| System.out.println("" + (System.currentTimeMillis() - time0) + "ms for " + file.getFullPath()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| return (Map[]) fNewMarkerAttributeMaps.toArray(new Map[fNewMarkerAttributeMaps.size()]); |
| } |
| |
| /* |
| * (non-Javadoc) |
| * |
| * @see |
| * org.eclipse.core.runtime.IExecutableExtension#setInitializationData |
| * (org.eclipse.core.runtime.IConfigurationElement, java.lang.String, |
| * java.lang.Object) |
| */ |
| public void setInitializationData(IConfigurationElement config, String propertyName, Object data) throws CoreException { |
| if (data != null && data instanceof String) { |
| runtimeMarkerType = data.toString(); |
| } |
| if (data != null && data instanceof Map) { |
| runtimeMarkerType = ((Map) data).get("runtimeMarkerType").toString(); |
| } |
| } |
| |
| boolean shouldScan(IResource r) { |
| return true; |
| } |
| |
| public void shutdown(IProject project) { |
| } |
| |
| public void startup(IProject project) { |
| if (DEBUG_TASKSPERF) { |
| time0 = System.currentTimeMillis(); |
| } |
| if (DEBUG_TASKSPERF) { |
| System.out.println("" + (System.currentTimeMillis() - time0) + "ms loading prefs for " + project.getName()); //$NON-NLS-1$ //$NON-NLS-2$ |
| } |
| } |
| } |