1 11 12 package org.eclipse.ui.internal.console; 13 14 import java.util.ArrayList ; 15 import java.util.Iterator ; 16 import java.util.regex.Matcher ; 17 import java.util.regex.Pattern ; 18 19 import org.eclipse.core.runtime.IProgressMonitor; 20 import org.eclipse.core.runtime.IStatus; 21 import org.eclipse.core.runtime.Status; 22 import org.eclipse.core.runtime.jobs.Job; 23 import org.eclipse.jface.text.BadLocationException; 24 import org.eclipse.jface.text.DocumentEvent; 25 import org.eclipse.jface.text.IDocument; 26 import org.eclipse.jface.text.IDocumentListener; 27 import org.eclipse.ui.console.ConsolePlugin; 28 import org.eclipse.ui.console.IPatternMatchListener; 29 import org.eclipse.ui.console.PatternMatchEvent; 30 import org.eclipse.ui.console.TextConsole; 31 32 public class ConsolePatternMatcher implements IDocumentListener { 33 34 private MatchJob fMatchJob = new MatchJob(); 35 36 39 private ArrayList fPatterns = new ArrayList (); 40 41 private TextConsole fConsole; 42 43 private boolean fFinalMatch; 44 45 private boolean fScheduleFinal; 46 47 public ConsolePatternMatcher(TextConsole console) { 48 fConsole = console; 49 } 50 51 private class MatchJob extends Job { 52 MatchJob() { 53 super("Match Job"); setSystem(true); 55 } 56 57 62 protected IStatus run(IProgressMonitor monitor) { 63 IDocument doc = fConsole.getDocument(); 64 String text = null; 65 int prevBaseOffset = -1; 66 if (doc != null && !monitor.isCanceled()) { 67 int endOfSearch = doc.getLength(); 68 int indexOfLastChar = endOfSearch; 69 if (indexOfLastChar > 0) { 70 indexOfLastChar--; 71 } 72 int lastLineToSearch = 0; 73 int offsetOfLastLineToSearch = 0; 74 try { 75 lastLineToSearch = doc.getLineOfOffset(indexOfLastChar); 76 offsetOfLastLineToSearch = doc.getLineOffset(lastLineToSearch); 77 } catch (BadLocationException e) { 78 return Status.OK_STATUS; 80 } 81 for (int i = 0; i < fPatterns.size(); i++) { 82 if (monitor.isCanceled()) { 83 break; 84 } 85 CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) fPatterns.get(i); 86 int baseOffset = notifier.end; 87 int lengthToSearch = endOfSearch - baseOffset; 88 if (lengthToSearch > 0) { 89 try { 90 if (prevBaseOffset != baseOffset) { 91 text = doc.get(baseOffset, lengthToSearch); 93 } 94 Matcher reg = notifier.pattern.matcher(text); 95 Matcher quick = null; 96 if (notifier.qualifier != null) { 97 quick = notifier.qualifier.matcher(text); 98 } 99 int startOfNextSearch = 0; 100 int endOfLastMatch = -1; 101 int lineOfLastMatch = -1; 102 while ((startOfNextSearch < lengthToSearch) && !monitor.isCanceled()) { 103 if (quick != null) { 104 if (quick.find(startOfNextSearch)) { 105 int matchLine = doc.getLineOfOffset(baseOffset + quick.start()); 110 if (lineOfLastMatch == matchLine) { 111 startOfNextSearch = endOfLastMatch; 112 } else { 113 startOfNextSearch = doc.getLineOffset(matchLine) - baseOffset; 114 } 115 } else { 116 startOfNextSearch = lengthToSearch; 117 } 118 } 119 if (startOfNextSearch < 0) { 120 startOfNextSearch = 0; 121 } 122 if (startOfNextSearch < lengthToSearch) { 123 if (reg.find(startOfNextSearch)) { 124 endOfLastMatch = reg.end(); 125 lineOfLastMatch = doc.getLineOfOffset(baseOffset + endOfLastMatch - 1); 126 int regStart = reg.start(); 127 IPatternMatchListener listener = notifier.listener; 128 if (listener != null && !monitor.isCanceled()) { 129 listener.matchFound(new PatternMatchEvent(fConsole, baseOffset + regStart, endOfLastMatch - regStart)); 130 } 131 startOfNextSearch = endOfLastMatch; 132 } else { 133 startOfNextSearch = lengthToSearch; 134 } 135 } 136 } 137 if (lastLineToSearch == lineOfLastMatch) { 143 notifier.end = baseOffset + endOfLastMatch; 144 } else { 145 notifier.end = offsetOfLastLineToSearch; 146 } 147 } catch (BadLocationException e) { 148 ConsolePlugin.log(e); 149 } 150 } 151 prevBaseOffset = baseOffset; 152 } 153 } 154 155 if (fFinalMatch) { 156 disconnect(); 157 fConsole.matcherFinished(); 158 } else if (fScheduleFinal) { 159 fFinalMatch = true; 160 schedule(); 161 } 162 163 return Status.OK_STATUS; 164 } 165 166 public boolean belongsTo(Object family) { 167 return family == fConsole; 168 } 169 170 171 } 172 173 private class CompiledPatternMatchListener { 174 Pattern pattern; 175 176 Pattern qualifier; 177 178 IPatternMatchListener listener; 179 180 int end = 0; 181 182 CompiledPatternMatchListener(Pattern pattern, Pattern qualifier, IPatternMatchListener matchListener) { 183 this.pattern = pattern; 184 this.listener = matchListener; 185 this.qualifier = qualifier; 186 } 187 188 public void dispose() { 189 listener.disconnect(); 190 pattern = null; 191 qualifier = null; 192 listener = null; 193 } 194 } 195 196 203 public void addPatternMatchListener(IPatternMatchListener matchListener) { 204 synchronized (fPatterns) { 205 206 for (Iterator iter = fPatterns.iterator(); iter.hasNext();) { 208 CompiledPatternMatchListener element = (CompiledPatternMatchListener) iter.next(); 209 if (element.listener == matchListener) { 210 return; 211 } 212 } 213 214 if (matchListener == null || matchListener.getPattern() == null) { 215 throw new IllegalArgumentException ("Pattern cannot be null"); } 217 218 Pattern pattern = Pattern.compile(matchListener.getPattern(), matchListener.getCompilerFlags()); 219 String qualifier = matchListener.getLineQualifier(); 220 Pattern qPattern = null; 221 if (qualifier != null) { 222 qPattern = Pattern.compile(qualifier, matchListener.getCompilerFlags()); 223 } 224 CompiledPatternMatchListener notifier = new CompiledPatternMatchListener(pattern, qPattern, matchListener); 225 fPatterns.add(notifier); 226 matchListener.connect(fConsole); 227 fMatchJob.schedule(); 228 } 229 } 230 231 238 public void removePatternMatchListener(IPatternMatchListener matchListener) { 239 synchronized (fPatterns) { 240 for (Iterator iter = fPatterns.iterator(); iter.hasNext();) { 241 CompiledPatternMatchListener element = (CompiledPatternMatchListener) iter.next(); 242 if (element.listener == matchListener) { 243 iter.remove(); 244 matchListener.disconnect(); 245 } 246 } 247 } 248 } 249 250 public void disconnect() { 251 fMatchJob.cancel(); 252 synchronized (fPatterns) { 253 Iterator iterator = fPatterns.iterator(); 254 while (iterator.hasNext()) { 255 CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iterator.next(); 256 notifier.dispose(); 257 } 258 fPatterns.clear(); 259 } 260 } 261 262 267 public void documentAboutToBeChanged(DocumentEvent event) { 268 } 269 270 275 public void documentChanged(DocumentEvent event) { 276 if (event.fLength > 0) { 277 synchronized (fPatterns) { 278 if (event.fDocument.getLength() == 0) { 279 Iterator iter = fPatterns.iterator(); 281 while (iter.hasNext()) { 282 CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iter.next(); 283 notifier.end = 0; 284 } 285 } else { 286 if (event.fOffset == 0) { 287 Iterator iter = fPatterns.iterator(); 289 while (iter.hasNext()) { 290 CompiledPatternMatchListener notifier = (CompiledPatternMatchListener) iter.next(); 291 notifier.end = notifier.end > event.fLength ? notifier.end-event.fLength : 0; 292 } 293 } 294 } 295 } 296 } 297 fMatchJob.schedule(); 298 } 299 300 301 public void forceFinalMatching() { 302 fScheduleFinal = true; 303 fMatchJob.schedule(); 304 } 305 306 } 307 | Popular Tags |