parsing of JS in HTML

This commit is contained in:
Maxim Mossienko
2005-01-27 15:55:30 +03:00
parent 608d3811fb
commit f10557cb07
7 changed files with 101 additions and 35 deletions
@@ -39,4 +39,5 @@ public interface CustomHighlighterTokenType {
IElementType R_BRACKET = new CustomElementType("R_BRACKET");
IElementType L_PARENTH = new CustomElementType("L_PARENTH");
IElementType R_PARENTH = new CustomElementType("R_PARENTH");
IElementType CUSTOM_CONTENT = new CustomElementType("CUSTOM_CONTENT");
}
@@ -4,6 +4,7 @@ import com.intellij.psi.PsiElement;
import com.intellij.psi.PsiFile;
import com.intellij.psi.PsiPlainTextFile;
import com.intellij.psi.PsiPlainText;
import com.intellij.psi.impl.source.tree.LeafPsiElement;
import com.intellij.psi.filters.TrueFilter;
import com.intellij.psi.xml.XmlTag;
import com.intellij.psi.xml.XmlToken;
@@ -28,6 +29,7 @@ public class SyntaxTableCompletionData extends WordCompletionData {
final CompletionVariant variant = new CompletionVariant(TrueFilter.INSTANCE);
variant.includeScopeClass(PsiPlainText.class, true);
variant.includeScopeClass(XmlToken.class, true); // for embedding custom file types into xml
variant.includeScopeClass(LeafPsiElement.class, true); // for embedding custom file types into xml
variant.addCompletionFilterOnElement(TrueFilter.INSTANCE);
final String[] empty = {};
+25 -1
View File
@@ -138,9 +138,29 @@ abstract class BaseHtmlLexer implements Lexer {
baseLexer.start(buffer, startOffset, endOffset, initialState & BASE_STATE_MASK);
}
protected int skipToTheEndOfTheEmbeddment() {
int myTokenEnd = baseLexer.getTokenEnd();
if (seenTag) {
int lastState = 0;
int lastStart = 0;
while(baseLexer.getTokenType() != XmlTokenType.XML_END_TAG_START) {
lastState = baseLexer.getState();
myTokenEnd = baseLexer.getTokenEnd();
lastStart = baseLexer.getTokenStart();
if (myTokenEnd == getBufferEnd()) break;
baseLexer.advance();
}
baseLexer.start(getBuffer(),lastStart,getBufferEnd(),lastState);
baseLexer.getTokenType();
}
return myTokenEnd;
}
public void advance() {
baseLexer.advance();
IElementType type = getTokenType();
IElementType type = baseLexer.getTokenType();
TokenHandler tokenHandler = tokenHandlers.get(type);
if (tokenHandler!=null) tokenHandler.handleElement(this);
}
@@ -211,4 +231,8 @@ abstract class BaseHtmlLexer implements Lexer {
}
protected abstract boolean isHtmlTagState(int state);
protected Lexer getBaseLexer() {
return baseLexer;
}
}
@@ -91,10 +91,7 @@ public class HtmlHighlightingLexer extends BaseHtmlLexer {
if (newLexer!=null) {
embeddedLexer = newLexer;
embeddedLexer.start(
getBuffer(),
HtmlHighlightingLexer.super.getTokenStart(),
HtmlHighlightingLexer.super.getTokenEnd());
embeddedLexer.start(getBuffer(),HtmlHighlightingLexer.super.getTokenStart(),skipToTheEndOfTheEmbeddment());
}
}
+37 -30
View File
@@ -12,13 +12,14 @@ import com.intellij.psi.impl.source.tree.ElementType;
* To change this template use File | Settings | File Templates.
*/
public class HtmlLexer extends BaseHtmlLexer {
private static IElementType styleElementType;
private static IElementType inlineStyleElementType;
private static IElementType ourStyleElementType;
private static IElementType ourInlineStyleElementType;
private static IElementType ourScriptElementType;
private static IElementType ourInlineScriptElementType;
private IElementType myTokenType;
private int myTokenStart;
private int myTokenEnd;
private boolean mySkippingTokens;
public void start(char[] buffer) {
myTokenType = null;
@@ -43,40 +44,41 @@ public class HtmlLexer extends BaseHtmlLexer {
public IElementType getTokenType() {
if (myTokenType!=null) return myTokenType;
IElementType tokenType = super.getTokenType();
if (mySkippingTokens) return tokenType;
myTokenStart = super.getTokenStart();
myTokenEnd = super.getTokenEnd();
if (hasSeenStyle() && hasSeenTag() && styleElementType!=null &&
(tokenType == XmlTokenType.XML_DATA_CHARACTERS ||
tokenType == XmlTokenType.XML_COMMENT_START ||
tokenType == ElementType.WHITE_SPACE
)) {
assert hasSeenTag();
mySkippingTokens = true;
// we need to advance till the end of tag
int lastState = 0;
int lastStart = 0;
while(hasSeenStyle()) {
lastState = super.getState();
myTokenEnd = super.getTokenEnd();
lastStart = super.getTokenStart();
if (myTokenEnd == getBufferEnd()) break;
super.advance();
if (hasSeenStyle()) {
if (hasSeenTag() && ourStyleElementType!=null && isStartOfEmbeddmentTagContent(tokenType)) {
myTokenEnd = skipToTheEndOfTheEmbeddment();
tokenType = ourStyleElementType;
} else if (ourInlineStyleElementType!=null && isStartOfEmbeddmentAttributeValue(tokenType) && hasSeenAttribute()) {
tokenType = ourInlineStyleElementType;
}
} else if (hasSeenScript()) {
if (hasSeenTag() && ourScriptElementType!=null && isStartOfEmbeddmentTagContent(tokenType)) {
myTokenEnd = skipToTheEndOfTheEmbeddment();
tokenType = ourScriptElementType;
} else if (hasSeenAttribute() && isStartOfEmbeddmentAttributeValue(tokenType) && ourInlineScriptElementType!=null) {
myTokenEnd = skipToTheEndOfTheEmbeddment();
tokenType = ourInlineScriptElementType;
}
super.start(getBuffer(),lastStart,getBufferEnd(),lastState);
super.getTokenType();
mySkippingTokens = false;
tokenType = styleElementType;
} else if (inlineStyleElementType!=null && tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN && hasSeenStyle() && hasSeenAttribute()) {
tokenType = inlineStyleElementType;
}
return myTokenType = tokenType;
}
private boolean isStartOfEmbeddmentAttributeValue(final IElementType tokenType) {
return tokenType == XmlTokenType.XML_ATTRIBUTE_VALUE_TOKEN;
}
private boolean isStartOfEmbeddmentTagContent(final IElementType tokenType) {
return (tokenType == XmlTokenType.XML_DATA_CHARACTERS ||
tokenType == XmlTokenType.XML_COMMENT_START ||
tokenType == ElementType.WHITE_SPACE
);
}
public HtmlLexer() {
this(new _HtmlLexer(),true);
}
@@ -86,8 +88,8 @@ public class HtmlLexer extends BaseHtmlLexer {
}
public static final void setStyleElementTypes(IElementType _styleElementType,IElementType _inlineStyleElementType) {
styleElementType = _styleElementType;
inlineStyleElementType = _inlineStyleElementType;
ourStyleElementType = _styleElementType;
ourInlineStyleElementType = _inlineStyleElementType;
}
protected boolean isHtmlTagState(int state) {
@@ -107,4 +109,9 @@ public class HtmlLexer extends BaseHtmlLexer {
}
return super.getTokenEnd();
}
public static void setScriptElementTypes(final IElementType scriptElementType, final IElementType inlineScriptElementType) {
ourScriptElementType = scriptElementType;
ourInlineScriptElementType = inlineScriptElementType;
}
}
@@ -106,6 +106,38 @@ public class ParseUtil implements Constants {
boolean isTokenValid(IElementType tokenType);
}
public static abstract class DefaultWhiteSpaceTokenProcessorImpl implements TokenProcessor {
public boolean isTokenValid(IElementType tokenType) {
return tokenType != null && isInSet(tokenType);
}
public TreeElement process(Lexer lexer, ParsingContext context) {
TreeElement first = null;
TreeElement last = null;
while (isTokenValid(lexer.getTokenType())) {
TreeElement tokenElement = ParseUtil.createTokenElement(lexer, context.getCharTable());
IElementType type = lexer.getTokenType();
if (!isInSet(type)) {
LOG.error("Missed token should be white space or comment:" + tokenElement);
throw new RuntimeException();
}
if (last != null) {
last.setTreeNext(tokenElement);
tokenElement.setTreePrev(last);
last = tokenElement;
}
else {
first = last = tokenElement;
}
lexer.advance();
}
return first;
}
protected abstract boolean isInSet(final IElementType type);
}
public static class WhiteSpaceAndCommentsProcessor implements TokenProcessor {
public static final TokenProcessor INSTANCE = new WhiteSpaceAndCommentsProcessor();
@@ -4,6 +4,7 @@ import com.intellij.aspects.psi.IAspectElementType;
import com.intellij.openapi.diagnostic.Logger;
import com.intellij.psi.JavaDocTokenType;
import com.intellij.psi.PsiManager;
import com.intellij.psi.CustomHighlighterTokenType;
import com.intellij.psi.impl.source.*;
import com.intellij.psi.impl.source.html.HtmlDocumentImpl;
import com.intellij.psi.impl.source.html.HtmlTagImpl;
@@ -517,6 +518,8 @@ public class Factory implements Constants {
}
else if (type == ANNOTATION_PARAMETER_LIST) {
element = new PsiAnnotationParameterListImpl();
} else if (type == CustomHighlighterTokenType.CUSTOM_CONTENT) {
element = new CompositePsiElement(type) {};
}
else {
if (type instanceof IAspectElementType) {