refactoring
[fedora-idea.git] / xml / impl / src / com / intellij / lexer / HtmlHighlightingLexer.java
blob9a80a481b6c8c9e9eb28a4e91248eb2e77a1cc13
1 /*
2 * Copyright 2000-2009 JetBrains s.r.o.
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
16 package com.intellij.lexer;
18 import com.intellij.openapi.diagnostic.Logger;
19 import com.intellij.openapi.fileTypes.FileType;
20 import com.intellij.openapi.fileTypes.SyntaxHighlighter;
21 import com.intellij.psi.tree.IElementType;
22 import com.intellij.psi.xml.XmlTokenType;
23 import org.jetbrains.annotations.Nullable;
25 public class HtmlHighlightingLexer extends BaseHtmlLexer {
26 private static final Logger LOG = Logger.getInstance("#com.intellij.lexer.HtmlHighlightingLexer");
28 private static final int EMBEDDED_LEXER_ON = 0x1 << BASE_STATE_SHIFT;
29 private static final int EMBEDDED_LEXER_STATE_SHIFT = BASE_STATE_SHIFT + 1;
31 private Lexer embeddedLexer;
32 private Lexer styleLexer;
33 private Lexer scriptLexer;
34 protected Lexer elLexer;
35 private boolean hasNoEmbeddments;
36 private static FileType ourStyleFileType;
37 private static FileType ourScriptFileType;
39 public class XmlEmbeddmentHandler implements TokenHandler {
40 public void handleElement(Lexer lexer) {
41 if (!hasSeenStyle() && !hasSeenScript() || hasNoEmbeddments) return;
42 final IElementType tokenType = lexer.getTokenType();
44 if ((tokenType==XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN && hasSeenAttribute()) ||
45 (tokenType==XmlTokenType.XML_DATA_CHARACTERS && hasSeenTag()) ||
46 tokenType==XmlTokenType.XML_COMMENT_CHARACTERS && hasSeenTag()
47 ) {
48 setEmbeddedLexer();
50 if (embeddedLexer!=null) {
51 embeddedLexer.start(
52 getBufferSequence(),
53 HtmlHighlightingLexer.super.getTokenStart(),
54 skipToTheEndOfTheEmbeddment(),
55 embeddedLexer instanceof EmbedmentLexer ? ((EmbedmentLexer)embeddedLexer).getEmbeddedInitialState(tokenType) : 0
58 if (embeddedLexer.getTokenType() == null) {
59 // no content for embeddment
60 embeddedLexer = null;
67 public class ElEmbeddmentHandler implements TokenHandler {
68 public void handleElement(Lexer lexer) {
69 setEmbeddedLexer();
70 if (embeddedLexer != null) {
71 embeddedLexer.start(getBufferSequence(), HtmlHighlightingLexer.super.getTokenStart(), HtmlHighlightingLexer.super.getTokenEnd());
76 public HtmlHighlightingLexer() {
77 this(new MergingLexerAdapter(new FlexAdapter(new _HtmlLexer()),TOKENS_TO_MERGE),true);
80 protected HtmlHighlightingLexer(Lexer lexer, boolean caseInsensitive) {
81 super(lexer,caseInsensitive);
83 XmlEmbeddmentHandler value = new XmlEmbeddmentHandler();
84 registerHandler(XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN,value);
85 registerHandler(XmlTokenType.XML_DATA_CHARACTERS,value);
86 registerHandler(XmlTokenType.XML_COMMENT_CHARACTERS,value);
89 public void start(CharSequence buffer, int startOffset, int endOffset, int initialState) {
90 super.start(buffer, startOffset, endOffset, initialState);
92 if ((initialState & EMBEDDED_LEXER_ON)!=0) {
93 int state = initialState >> EMBEDDED_LEXER_STATE_SHIFT;
94 setEmbeddedLexer();
95 LOG.assertTrue(embeddedLexer!=null);
96 embeddedLexer.start(buffer,startOffset,skipToTheEndOfTheEmbeddment(),state);
97 } else {
98 embeddedLexer = null;
102 private void setEmbeddedLexer() {
103 Lexer newLexer = null;
104 if (hasSeenStyle()) {
105 if (styleLexer==null) {
106 styleLexer = (ourStyleFileType!=null)? SyntaxHighlighter.PROVIDER.create(ourStyleFileType, null, null).getHighlightingLexer():null;
109 newLexer = styleLexer;
110 } else if (hasSeenScript()) {
111 if (scriptLexer==null) {
112 scriptLexer = (ourScriptFileType!=null)? SyntaxHighlighter.PROVIDER.create(ourScriptFileType, null, null).getHighlightingLexer():null;
114 newLexer = scriptLexer;
115 } else newLexer = createELLexer(newLexer);
117 if (newLexer!=null) {
118 embeddedLexer = newLexer;
122 @Nullable
123 protected Lexer createELLexer(Lexer newLexer) {
124 return newLexer;
127 public void advance() {
128 if (embeddedLexer!=null) {
129 embeddedLexer.advance();
130 if (embeddedLexer.getTokenType()==null) {
131 embeddedLexer=null;
135 if (embeddedLexer==null) {
136 super.advance();
140 public IElementType getTokenType() {
141 if (embeddedLexer!=null) {
142 return embeddedLexer.getTokenType();
143 } else {
144 IElementType tokenType = super.getTokenType();
146 // TODO: fix no DOCTYPE highlighting
147 if (tokenType == null) return tokenType;
149 if (tokenType==XmlTokenType.XML_NAME) {
150 // we need to convert single xml_name for tag name and attribute name into to separate
151 // lex types for the highlighting!
152 final int state = getState() & BASE_STATE_MASK;
154 if (isHtmlTagState(state)) {
155 tokenType = XmlTokenType.XML_TAG_NAME;
158 else if (tokenType == XmlTokenType.XML_WHITE_SPACE || tokenType == XmlTokenType.XML_REAL_WHITE_SPACE) {
159 if (hasSeenTag() && (hasSeenStyle() || hasSeenScript())) {
160 tokenType = XmlTokenType.XML_WHITE_SPACE;
161 } else {
162 tokenType = (getState()!=0)?XmlTokenType.TAG_WHITE_SPACE:XmlTokenType.XML_REAL_WHITE_SPACE;
164 } else if (tokenType == XmlTokenType.XML_CHAR_ENTITY_REF ||
165 tokenType == XmlTokenType.XML_ENTITY_REF_TOKEN
167 // we need to convert char entity ref & entity ref in comments as comment chars
168 final int state = getState() & BASE_STATE_MASK;
169 if (state == _HtmlLexer.COMMENT) return XmlTokenType.XML_COMMENT_CHARACTERS;
171 return tokenType;
175 public int getTokenStart() {
176 if (embeddedLexer!=null) {
177 return embeddedLexer.getTokenStart();
178 } else {
179 return super.getTokenStart();
183 public int getTokenEnd() {
184 if (embeddedLexer!=null) {
185 return embeddedLexer.getTokenEnd();
186 } else {
187 return super.getTokenEnd();
191 public static final void registerStyleFileType(FileType fileType) {
192 ourStyleFileType = fileType;
195 public static void registerScriptFileType(FileType _scriptFileType) {
196 ourScriptFileType = _scriptFileType;
199 public int getState() {
200 int state = super.getState();
202 state |= ((embeddedLexer!=null)?EMBEDDED_LEXER_ON:0);
203 if (embeddedLexer!=null) state |= (embeddedLexer.getState() << EMBEDDED_LEXER_STATE_SHIFT);
205 return state;
208 protected boolean isHtmlTagState(int state) {
209 return state == _HtmlLexer.START_TAG_NAME || state == _HtmlLexer.END_TAG_NAME ||
210 state == _HtmlLexer.START_TAG_NAME2 || state == _HtmlLexer.END_TAG_NAME2;
213 public void setHasNoEmbeddments(boolean hasNoEmbeddments) {
214 this.hasNoEmbeddments = hasNoEmbeddments;