package org.epic.perleditor.editors;
import java.util.*;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import org.eclipse.core.resources.IMarker;
import org.eclipse.jface.preference.IPreferenceStore;
import org.eclipse.jface.text.IDocument;
import org.eclipse.ui.IEditorInput;
import org.eclipse.ui.IFileEditorInput;
import org.eclipse.ui.texteditor.IDocumentProvider;
import org.epic.core.parser.PerlToken;
import org.epic.core.parser.PerlTokenTypes;
import org.epic.perleditor.PerlEditorPlugin;
import org.epic.perleditor.editors.util.MarkerUtil;
import org.epic.perleditor.preferences.ITaskTagConstants;
import org.epic.perleditor.preferences.TaskTagPreferences;
/**
* Scans an edited Perl source file for task markers,
* adding/removing corresponding IMarkers to/from the resource
* representing the source file.
*
* @author jploski
*/
public class TasksReconciler
{
private static final String EPIC_AUTOGENERATED = "epic.autogenerated";
private final PerlEditor editor;
private Pattern[] TODO_PATTERNS;
private boolean allowWhiteSpace;
private MarkerUtil markerUtil;
public TasksReconciler(PerlEditor editor)
{
this.editor = editor;
}
public void reconcile()
{
IEditorInput input = (IEditorInput) editor.getEditorInput();
if (!(input instanceof IFileEditorInput)) return;
IDocumentProvider docProvider = editor.getDocumentProvider();
if (docProvider == null) return;
IDocument doc = docProvider.getDocument(input);
if (doc == null) return;
PerlPartitioner partitioner = (PerlPartitioner) PartitionTypes.getPerlPartitioner(doc);
if (partitioner == null) return;
markerUtil = new MarkerUtil(((IFileEditorInput) input).getFile());
markerUtil.clearAllUsedFlags(IMarker.TASK, EPIC_AUTOGENERATED);
IPreferenceStore store = PerlEditorPlugin.getDefault().getPreferenceStore();
allowWhiteSpace = store.getBoolean(ITaskTagConstants.ID_WHITESPACE);
initSearchPatterns(store);
synchronized (partitioner.getTokensLock())
{
List tokens = partitioner.getTokens();
for (Iterator i = tokens.iterator(); i.hasNext();)
{
PerlToken t = (PerlToken) i.next();
if (t.getType() == PerlTokenTypes.COMMENT) parseComment(t);
}
}
markerUtil.removeUnusedMarkers(IMarker.TASK, EPIC_AUTOGENERATED);
}
private void addTaskMarker(int start, int stop, int lineNumber, String text)
{
Map attributes = new HashMap(11);
attributes.put(IMarker.CHAR_START, new Integer(start));
attributes.put(IMarker.CHAR_END, new Integer(stop));
attributes.put(IMarker.LINE_NUMBER, new Integer(lineNumber));
attributes.put(IMarker.MESSAGE, text);
attributes.put(EPIC_AUTOGENERATED, new Integer(42));
markerUtil.addMarker(attributes, IMarker.TASK);
}
private void initSearchPatterns(IPreferenceStore store)
{
int flags =
store.getBoolean(ITaskTagConstants.ID_IGNORE_CASE)
? Pattern.CASE_INSENSITIVE
: 0;
String taskTagList = store.getString(ITaskTagConstants.ID_TASK_TAGS);
String[] TODO_STRINGS = TaskTagPreferences.parseStringList(taskTagList);
TODO_PATTERNS = new Pattern[TODO_STRINGS.length];
for (int i = 0; i < TODO_STRINGS.length; i++)
{
// construct the search string
StringBuffer buffy = new StringBuffer();
buffy.append("#");
if (allowWhiteSpace) buffy.append("\\s*");
buffy.append("\\Q");
buffy.append(TODO_STRINGS[i]);
buffy.append("\\E");
TODO_PATTERNS[i] = Pattern.compile(buffy.toString(), flags);
}
}
private void parseComment(PerlToken t)
{
for (int i = 0; i < TODO_PATTERNS.length; i++)
parseComment(t, TODO_PATTERNS[i]);
}
private void parseComment(PerlToken t, Pattern todoPattern)
{
Matcher m = todoPattern.matcher(t.getText());
if (!m.find()) return;
String todoText = t.getText().substring(m.end()).trim();
if (todoText.length() > 0)
{
if(!markerUtil.isMarkerPresent(
IMarker.TASK,
t.getLine(),
todoText,
EPIC_AUTOGENERATED,
true))
{
addTaskMarker(
t.getOffset() + m.start(),
t.getOffset() + m.start() + m.group().length() + todoText.length(),
t.getLine(),
todoText);
}
}
}
}