package org.eclipse.dltk.javascript.internal.ui.text; import java.io.StringReader; import java.util.List; import org.eclipse.dltk.ast.ASTNode; import org.eclipse.dltk.ast.ASTVisitor; import org.eclipse.dltk.compiler.env.IModuleSource; import org.eclipse.dltk.javascript.ast.Expression; import org.eclipse.dltk.javascript.ast.ForEachInStatement; import org.eclipse.dltk.javascript.ast.GetMethod; import org.eclipse.dltk.javascript.ast.Identifier; import org.eclipse.dltk.javascript.ast.Keyword; import org.eclipse.dltk.javascript.ast.Method; import org.eclipse.dltk.javascript.ast.PropertyInitializer; import org.eclipse.dltk.javascript.ast.RegExpLiteral; import org.eclipse.dltk.javascript.ast.Script; import org.eclipse.dltk.javascript.ast.SetMethod; import org.eclipse.dltk.javascript.ast.StringLiteral; import org.eclipse.dltk.javascript.ast.XmlFragment; import org.eclipse.dltk.javascript.ast.XmlLiteral; import org.eclipse.dltk.javascript.ast.XmlTextFragment; import org.eclipse.dltk.javascript.internal.ui.JavaScriptUI; import org.eclipse.dltk.javascript.parser.JavaScriptParserUtil; import org.eclipse.dltk.ui.editor.highlighting.AbortSemanticHighlightingException; import org.eclipse.dltk.ui.editor.highlighting.ISemanticHighlighter; import org.eclipse.dltk.ui.editor.highlighting.ISemanticHighlightingRequestor; public class JavaScriptXmlHighlighter extends AbstractJavaScriptHighlighter implements ISemanticHighlighter { private static final String HL_XML_TAG = JavascriptColorConstants.JS_XML_TAG_NAME; private static final String HL_XML_ATTRIBUTE = JavascriptColorConstants.JS_XML_ATTR_NAME; private static final String HL_XML_COMMENT = JavascriptColorConstants.JS_XML_COMMENT_NAME; private static final String HL_KEYWORD = JavascriptColorConstants.JS_KEYWORD; private static final String HL_REGEXP = JavascriptColorConstants.JS_REGEXP; private static final String HL_PROPERTY = JavascriptColorConstants.JS_PROPERTY; public String[] getHighlightingKeys() { return new String[] { HL_XML_TAG, HL_XML_ATTRIBUTE, HL_XML_COMMENT, HL_KEYWORD, HL_REGEXP, HL_PROPERTY }; } public void process(IModuleSource code, ISemanticHighlightingRequestor requestor) { final Script declaration = JavaScriptParserUtil.parse(code, null); if (declaration == null) { throw new AbortSemanticHighlightingException(); } try { declaration.traverse(new HighlightingVisitor(requestor)); } catch (Exception e) { JavaScriptUI.log(e); } } static class HighlightingVisitor extends ASTVisitor { final ISemanticHighlightingRequestor requestor; final boolean bPropertyNames = isSemanticHighlightingEnabled(HL_PROPERTY); public HighlightingVisitor(ISemanticHighlightingRequestor requestor) { this.requestor = requestor; } @Override public boolean visitGeneral(ASTNode node) throws Exception { if (node instanceof XmlLiteral) { handleXML((XmlLiteral) node); } else if (node instanceof Method) { handleMethod((Method) node); } else if (node instanceof RegExpLiteral) { handleRegExp((RegExpLiteral) node); } else if (node instanceof PropertyInitializer) { if (bPropertyNames) { handlePropertyInitializer((PropertyInitializer) node); } } else if (node instanceof ForEachInStatement) { handleForEachIn((ForEachInStatement) node); } return true; } private void handleXML(XmlLiteral literal) { for (XmlFragment fragment : literal.getFragments()) { if (fragment instanceof XmlTextFragment) { final XMLTokenizer tokenizer = new XMLTokenizer( new StringReader( ((XmlTextFragment) fragment).getXml())); final int offset = fragment.sourceStart(); @SuppressWarnings("unchecked") final List<Token> tokens = tokenizer.getRegions(); for (Token token : tokens) { if (token.context == XMLTokenizer.XML_TAG_NAME) { addRange(requestor, offset, token, HL_XML_TAG); } else if (token.context == XMLTokenizer.XML_TAG_ATTRIBUTE_NAME) { addRange(requestor, offset, token, HL_XML_ATTRIBUTE); } else if (token.context == XMLTokenizer.XML_COMMENT_OPEN || token.context == XMLTokenizer.XML_COMMENT_TEXT || token.context == XMLTokenizer.XML_COMMENT_CLOSE) { addRange(requestor, offset, token, HL_XML_COMMENT); } else if (token.context == XMLTokenizer.XML_TAG_ATTRIBUTE_VALUE) { // } } } } } private void handleMethod(Method method) { Keyword keyword; if (method instanceof GetMethod) { keyword = ((GetMethod) method).getGetKeyword(); } else if (method instanceof SetMethod) { keyword = ((SetMethod) method).getSetKeyword(); } else { return; } requestor.addPosition(keyword.sourceStart(), keyword.sourceEnd(), HL_KEYWORD); } private void handleForEachIn(ForEachInStatement forEach) { final Keyword keyword = forEach.getEachKeyword(); requestor.addPosition(keyword.sourceStart(), keyword.sourceEnd(), HL_KEYWORD); } private void handleRegExp(RegExpLiteral regExp) { requestor.addPosition(regExp.sourceStart(), regExp.sourceEnd(), HL_REGEXP); } private void handlePropertyInitializer(PropertyInitializer property) { final Expression name = property.getName(); if (name instanceof Identifier || name instanceof StringLiteral) { requestor.addPosition(name.sourceStart(), name.sourceEnd(), HL_PROPERTY); } } private static void addRange(ISemanticHighlightingRequestor requestor, int start, Token token, String highlightingKey) { requestor.addPosition(start + token.start, start + token.start + token.textLength, highlightingKey); } } }