Source code: com/port80/eclipse/xml/editors/XMLTagScanner.java
1 package com.port80.eclipse.xml.editors;
2
3 import java.util.Vector;
4
5 import org.apache.xerces.util.XMLChar;
6 import org.eclipse.jface.text.BadLocationException;
7 import org.eclipse.jface.text.IDocument;
8 import org.eclipse.jface.text.TextAttribute;
9 import org.eclipse.jface.text.rules.IRule;
10 import org.eclipse.jface.text.rules.IToken;
11 import org.eclipse.jface.text.rules.IWordDetector;
12 import org.eclipse.jface.text.rules.PatternRule;
13 import org.eclipse.jface.text.rules.RuleBasedScanner;
14 import org.eclipse.jface.text.rules.Token;
15 import org.eclipse.jface.text.rules.WhitespaceRule;
16 import org.eclipse.jface.text.rules.WordRule;
17 import org.eclipse.swt.SWT;
18
19 import com.port80.eclipse.editors.ThemeManager;
20 import com.port80.eclipse.xml.util.WhitespaceDetector;
21
22 public class XMLTagScanner extends RuleBasedScanner {
23
24 ////////////////////////////////////////////////////////////////////////
25
26 private boolean isElement;
27 private boolean isEndElement;
28 private IToken fDefaultToken;
29 private IToken fElementToken;
30 private IToken fEndElementToken;
31 private WordRule fElementRule;
32
33 ////////////////////////////////////////////////////////////////////////
34
35 public XMLTagScanner(ThemeManager manager) {
36 fDefaultToken = new Token(new TextAttribute(manager.getColor("XMLAttribute")));
37 fElementToken = new Token(new TextAttribute(manager.getColor("XMLTag"), null, SWT.BOLD));
38 fEndElementToken = new Token(new TextAttribute(manager.getColor("XMLEndTag"),null,SWT.BOLD));
39 IToken string = new Token(new TextAttribute(manager.getColor("XMLString")));
40 setDefaultReturnToken(fDefaultToken);
41
42 fElementRule = new WordRule(new XMLElementDetector(), fDefaultToken);
43
44 Vector rules = new Vector();
45 // Add rule for single and double quotes
46 rules.add(new PatternRule("\"", "\"", string, '\0', true));
47 rules.add(new PatternRule("'", "'", string, '\0', true));
48 // Add generic whitespace rule.
49 rules.add(new WhitespaceRule(new WhitespaceDetector()));
50
51 IRule[] result = new IRule[rules.size()];
52 rules.copyInto(result);
53 setRules(result);
54 }
55
56 ////////////////////////////////////////////////////////////////////////
57
58 public IToken nextToken() {
59 IToken token;
60 fTokenOffset = fOffset;
61 fColumn = UNDEFINED;
62 if (fRules != null) {
63 for (int i = 0; i < fRules.length; i++) {
64 token = (fRules[i].evaluate(this));
65 if (!token.isUndefined())
66 return token;
67 }
68 }
69 token = fElementRule.evaluate(this);
70 if (!token.isUndefined()) {
71 if(isEndElement) {
72 isEndElement=false;
73 return fEndElementToken;
74 } else if (isElement) {
75 isElement = false;
76 return fElementToken;
77 } else
78 return fDefaultToken;
79 } else if (read() == EOF)
80 return Token.EOF;
81 else
82 return fDefaultReturnToken;
83 }
84
85 /**
86 * @see org.eclipse.jface.text.rules.ITokenScanner#setRange(IDocument, int, int)
87 */
88 public void setRange(IDocument document, int offset, int length) {
89 // Range includes '<' and '>'.
90 super.setRange(document, offset, length);
91 isElement=false;
92 isEndElement=false;
93 try {
94 if(document.getChar(offset)=='<') {
95 if(length>0 && document.getChar(offset+1)=='/')
96 isEndElement=true;
97 else
98 isElement = true;
99 }
100 } catch (BadLocationException e) {
101 }
102 }
103
104 ////////////////////////////////////////////////////////////////////////
105
106 class XMLElementDetector implements IWordDetector {
107
108 /**
109 * @see IWordDetector#isWordStart
110 */
111 public boolean isWordStart(char c) {
112 return XMLChar.isNameStart(c);
113 }
114
115 /**
116 * @see IWordDetector#isWordPart
117 */
118 public boolean isWordPart(char c) {
119 return XMLChar.isName(c);
120 }
121 }
122
123 ////////////////////////////////////////////////////////////////////////
124
125 }