1 | /*
|
---|
2 | * 08/11/2009
|
---|
3 | *
|
---|
4 | * TaskTagParser.java - Parser that scans code comments for task tags.
|
---|
5 | *
|
---|
6 | * This library is distributed under a modified BSD license. See the included
|
---|
7 | * RSyntaxTextArea.License.txt file for details.
|
---|
8 | */
|
---|
9 | package org.fife.ui.rsyntaxtextarea.parser;
|
---|
10 |
|
---|
11 | import java.awt.Color;
|
---|
12 | import java.util.regex.Matcher;
|
---|
13 | import java.util.regex.Pattern;
|
---|
14 | import java.util.regex.PatternSyntaxException;
|
---|
15 | import javax.swing.text.Element;
|
---|
16 |
|
---|
17 | import org.fife.ui.rsyntaxtextarea.ErrorStrip;
|
---|
18 | import org.fife.ui.rsyntaxtextarea.RSyntaxDocument;
|
---|
19 | import org.fife.ui.rsyntaxtextarea.SyntaxConstants;
|
---|
20 | import org.fife.ui.rsyntaxtextarea.Token;
|
---|
21 |
|
---|
22 |
|
---|
23 | /**
|
---|
24 | * Parser that identifies "task tags," such as "<code>TODO</code>",
|
---|
25 | * "<code>FIXME</code>", etc. in source code comments.
|
---|
26 | *
|
---|
27 | * @author Robert Futrell
|
---|
28 | * @version 1.0
|
---|
29 | */
|
---|
30 | public class TaskTagParser extends AbstractParser {
|
---|
31 |
|
---|
32 | private DefaultParseResult result;
|
---|
33 | private String DEFAULT_TASK_PATTERN = "TODO|FIXME|HACK";
|
---|
34 | private Pattern taskPattern;
|
---|
35 |
|
---|
36 | private static final Color COLOR = new Color(48, 150, 252);
|
---|
37 |
|
---|
38 |
|
---|
39 | /**
|
---|
40 | * Creates a new task parser. The default parser treats the following
|
---|
41 | * identifiers in comments as task definitions: "<code>TODO</code>",
|
---|
42 | * "<code>FIXME</code>", and "<code>HACK</code>".
|
---|
43 | */
|
---|
44 | public TaskTagParser() {
|
---|
45 | result = new DefaultParseResult(this);
|
---|
46 | setTaskPattern(DEFAULT_TASK_PATTERN);
|
---|
47 | }
|
---|
48 |
|
---|
49 |
|
---|
50 | /**
|
---|
51 | * Returns the regular expression used to search for tasks.
|
---|
52 | *
|
---|
53 | * @return The regular expression. This may be <code>null</code> if no
|
---|
54 | * regular expression was specified (or an empty string was
|
---|
55 | * specified).
|
---|
56 | * @see #setTaskPattern(String)
|
---|
57 | */
|
---|
58 | public String getTaskPattern() {
|
---|
59 | return taskPattern==null ? null : taskPattern.pattern();
|
---|
60 | }
|
---|
61 |
|
---|
62 |
|
---|
63 | public ParseResult parse(RSyntaxDocument doc, String style) {
|
---|
64 |
|
---|
65 | Element root = doc.getDefaultRootElement();
|
---|
66 | int lineCount = root.getElementCount();
|
---|
67 |
|
---|
68 | if (taskPattern==null ||
|
---|
69 | style==null || SyntaxConstants.SYNTAX_STYLE_NONE.equals(style)){
|
---|
70 | result.clearNotices();
|
---|
71 | result.setParsedLines(0, lineCount-1);
|
---|
72 | return result;
|
---|
73 | }
|
---|
74 |
|
---|
75 | // TODO: Pass in parsed line range and just do that
|
---|
76 | result.clearNotices();
|
---|
77 | result.setParsedLines(0, lineCount-1);
|
---|
78 |
|
---|
79 | for (int line=0; line<lineCount; line++) {
|
---|
80 |
|
---|
81 | Token t = doc.getTokenListForLine(line);
|
---|
82 | int offs = -1;
|
---|
83 | int start = -1;
|
---|
84 | String text = null;
|
---|
85 |
|
---|
86 | while (t!=null && t.isPaintable()) {
|
---|
87 | if (t.isComment()) {
|
---|
88 |
|
---|
89 | offs = t.offset;
|
---|
90 | text = t.getLexeme();
|
---|
91 |
|
---|
92 | Matcher m = taskPattern.matcher(text);
|
---|
93 | if (m.find()) {
|
---|
94 | start = m.start();
|
---|
95 | offs += start;
|
---|
96 | break;
|
---|
97 | }
|
---|
98 |
|
---|
99 | }
|
---|
100 | t = t.getNextToken();
|
---|
101 | }
|
---|
102 |
|
---|
103 | if (start>-1) {
|
---|
104 | text = text.substring(start);
|
---|
105 | // TODO: Strip off end of MLC's if they're there.
|
---|
106 | int len = text.length();
|
---|
107 | TaskNotice pn = new TaskNotice(this, text, line, offs, len);
|
---|
108 | pn.setLevel(ParserNotice.INFO);
|
---|
109 | pn.setShowInEditor(false);
|
---|
110 | pn.setColor(COLOR);
|
---|
111 | result.addNotice(pn);
|
---|
112 | }
|
---|
113 |
|
---|
114 | }
|
---|
115 |
|
---|
116 | return result;
|
---|
117 |
|
---|
118 | }
|
---|
119 |
|
---|
120 |
|
---|
121 | /**
|
---|
122 | * Sets the pattern of task identifiers. You will usually want this to be
|
---|
123 | * a list of words "or'ed" together, such as
|
---|
124 | * "<code>TODO|FIXME|HACK|REMIND</code>".
|
---|
125 | *
|
---|
126 | * @param pattern The pattern. A value of <code>null</code> or an
|
---|
127 | * empty string effectively disables task parsing.
|
---|
128 | * @throws PatternSyntaxException If <code>pattern</code> is an invalid
|
---|
129 | * regular expression.
|
---|
130 | * @see #getTaskPattern()
|
---|
131 | */
|
---|
132 | public void setTaskPattern(String pattern) throws PatternSyntaxException {
|
---|
133 | if (pattern==null || pattern.length()==0) {
|
---|
134 | taskPattern = null;
|
---|
135 | }
|
---|
136 | else {
|
---|
137 | taskPattern = Pattern.compile(pattern);
|
---|
138 | }
|
---|
139 | }
|
---|
140 |
|
---|
141 |
|
---|
142 | /**
|
---|
143 | * A parser notice that signifies a task. This class is here so we can
|
---|
144 | * treat tasks specially and show them in the {@link ErrorStrip} even
|
---|
145 | * though they are <code>INFO</code>-level and marked as "don't show in
|
---|
146 | * editor."
|
---|
147 | */
|
---|
148 | public static class TaskNotice extends DefaultParserNotice {
|
---|
149 |
|
---|
150 | public TaskNotice(Parser parser, String message, int line, int offs,
|
---|
151 | int length) {
|
---|
152 | super(parser, message, line, offs, length);
|
---|
153 | }
|
---|
154 |
|
---|
155 | }
|
---|
156 |
|
---|
157 |
|
---|
158 | } |
---|