Confluence highlighter with error/warning/unresolved supported
This commit is contained in:
@@ -3,7 +3,6 @@
|
||||
<component name="NewModuleRootManager" LANGUAGE_LEVEL="JDK_1_6" inherit-compiler-output="false">
|
||||
<output url="file://$MODULE_DIR$/target/classes" />
|
||||
<output-test url="file://$MODULE_DIR$/target/test-classes" />
|
||||
<exclude-output />
|
||||
<content url="file://$MODULE_DIR$">
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/java" isTestSource="false" />
|
||||
<sourceFolder url="file://$MODULE_DIR$/src/main/resources" isTestSource="false" />
|
||||
|
||||
@@ -1,174 +0,0 @@
|
||||
/* It's an automatically generated code. Do not modify it. */
|
||||
package org.jetbrains.jet.confluence;
|
||||
|
||||
import org.jetbrains.jet.confluence.JetTokens;
|
||||
|
||||
%%
|
||||
|
||||
%unicode
|
||||
%class _JetLexer
|
||||
%function advance
|
||||
%type JetToken
|
||||
%eof{ return;
|
||||
%eof}
|
||||
|
||||
DIGIT=[0-9]
|
||||
HEX_DIGIT=[0-9A-Fa-f]
|
||||
WHITE_SPACE_CHAR=[\ \t\f\r]
|
||||
|
||||
// TODO: prohibit '$' in identifiers?
|
||||
PLAIN_IDENTIFIER=[:jletter:] [:jletterdigit:]*
|
||||
// TODO: this one MUST allow everything accepted by the runtime
|
||||
// TODO: Replace backticks by one backslash in the begining
|
||||
ESCAPED_IDENTIFIER = `{PLAIN_IDENTIFIER}`
|
||||
IDENTIFIER = {PLAIN_IDENTIFIER}|{ESCAPED_IDENTIFIER}
|
||||
FIELD_IDENTIFIER = \${IDENTIFIER}
|
||||
LABEL_IDENTIFIER = \@{IDENTIFIER}
|
||||
|
||||
BLOCK_COMMENT=("/*"[^"*"]{COMMENT_TAIL})|"/*"
|
||||
// TODO: Wiki markup for doc comments?
|
||||
DOC_COMMENT="/*""*"+("/"|([^"/""*"]{COMMENT_TAIL}))?
|
||||
COMMENT_TAIL=([^"*"]*("*"+[^"*""/"])?)*("*"+"/")?
|
||||
EOL_COMMENT="/""/"[^\n]*
|
||||
|
||||
INTEGER_LITERAL={DECIMAL_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL}|{BIN_INTEGER_LITERAL}
|
||||
DECIMAL_INTEGER_LITERAL=(0|([1-9]({DIGIT})*))
|
||||
HEX_INTEGER_LITERAL=0[Xx]({HEX_DIGIT})*
|
||||
BIN_INTEGER_LITERAL=0[Bb]({DIGIT})*
|
||||
LONG_LITERAL=({INTEGER_LITERAL})[Ll]
|
||||
|
||||
//FLOAT_LITERAL=(({FLOATING_POINT_LITERAL1})[Ff])|(({FLOATING_POINT_LITERAL2})[Ff])|(({FLOATING_POINT_LITERAL3})[Ff])|(({FLOATING_POINT_LITERAL4})[Ff])
|
||||
//DOUBLE_LITERAL=(({FLOATING_POINT_LITERAL1})[Dd]?)|(({FLOATING_POINT_LITERAL2})[Dd]?)|(({FLOATING_POINT_LITERAL3})[Dd]?)|(({FLOATING_POINT_LITERAL4})[Dd])
|
||||
DOUBLE_LITERAL={FLOATING_POINT_LITERAL1}|{FLOATING_POINT_LITERAL2}|{FLOATING_POINT_LITERAL3}|{FLOATING_POINT_LITERAL4}
|
||||
FLOATING_POINT_LITERAL1=({DIGIT})+"."({DIGIT})+({EXPONENT_PART})?
|
||||
FLOATING_POINT_LITERAL2="."({DIGIT})+({EXPONENT_PART})?
|
||||
FLOATING_POINT_LITERAL3=({DIGIT})+({EXPONENT_PART})
|
||||
FLOATING_POINT_LITERAL4=({DIGIT})+
|
||||
EXPONENT_PART=[Ee]["+""-"]?({DIGIT})*
|
||||
HEX_FLOAT_LITERAL={HEX_SIGNIFICAND}{BINARY_EXPONENT}[Ff]
|
||||
//HEX_DOUBLE_LITERAL={HEX_SIGNIFICAND}{BINARY_EXPONENT}[Dd]?
|
||||
HEX_DOUBLE_LITERAL={HEX_SIGNIFICAND}{BINARY_EXPONENT}?
|
||||
BINARY_EXPONENT=[Pp][+-]?{DIGIT}+
|
||||
HEX_SIGNIFICAND={HEX_INTEGER_LITERAL}|0[Xx]{HEX_DIGIT}*\.{HEX_DIGIT}+
|
||||
//HEX_SIGNIFICAND={HEX_INTEGER_LITERAL}|{HEX_INTEGER_LITERAL}\.|0[Xx]{HEX_DIGIT}*\.{HEX_DIGIT}+
|
||||
|
||||
CHARACTER_LITERAL="'"([^\\\'\n]|{ESCAPE_SEQUENCE})*("'"|\\)?
|
||||
// TODO: introduce symbols (e.g. 'foo) as another way to write string literals
|
||||
STRING_LITERAL=\"([^\\\"\n]|{ESCAPE_SEQUENCE})*(\"|\\)?
|
||||
ESCAPE_SEQUENCE=\\[^\n]
|
||||
|
||||
// ANY_ESCAPE_SEQUENCE = \\[^]
|
||||
THREE_QUO = (\"\"\")
|
||||
ONE_TWO_QUO = (\"[^\"]) | (\"\"[^\"])
|
||||
QUO_STRING_CHAR = [^\"] | {ONE_TWO_QUO}
|
||||
RAW_STRING_LITERAL = {THREE_QUO} {QUO_STRING_CHAR}* {THREE_QUO}?
|
||||
|
||||
%%
|
||||
|
||||
<YYINITIAL> {BLOCK_COMMENT} { return JetTokens.BLOCK_COMMENT; }
|
||||
<YYINITIAL> {DOC_COMMENT} { return JetTokens.DOC_COMMENT; }
|
||||
|
||||
\n {return JetTokens.WHITE_SPACE; }
|
||||
({WHITE_SPACE_CHAR})+ { return JetTokens.WHITE_SPACE; }
|
||||
|
||||
<YYINITIAL> {EOL_COMMENT} { return JetTokens.EOL_COMMENT; }
|
||||
|
||||
<YYINITIAL> {INTEGER_LITERAL}\.\. { yypushback(2); return JetTokens.INTEGER_LITERAL; }
|
||||
<YYINITIAL> {INTEGER_LITERAL} { return JetTokens.INTEGER_LITERAL; }
|
||||
//<YYINITIAL> {LONG_LITERAL} { return JetTokens.LONG_LITERAL; }
|
||||
|
||||
//<YYINITIAL> {FLOAT_LITERAL} { return JetTokens.FLOAT_LITERAL; }
|
||||
//<YYINITIAL> {HEX_FLOAT_LITERAL} { return JetTokens.FLOAT_LITERAL; }
|
||||
<YYINITIAL> {DOUBLE_LITERAL} { return JetTokens.FLOAT_LITERAL; }
|
||||
<YYINITIAL> {HEX_DOUBLE_LITERAL} { return JetTokens.FLOAT_LITERAL; }
|
||||
|
||||
<YYINITIAL> {CHARACTER_LITERAL} { return JetTokens.CHARACTER_LITERAL; }
|
||||
<YYINITIAL> {STRING_LITERAL} { return JetTokens.STRING_LITERAL; }
|
||||
// TODO: Decide what to do with """ ... """"
|
||||
<YYINITIAL> {RAW_STRING_LITERAL} { return JetTokens.RAW_STRING_LITERAL; }
|
||||
|
||||
<YYINITIAL> "namespace" { return JetTokens.NAMESPACE_KEYWORD ;}
|
||||
<YYINITIAL> "extension" { return JetTokens.EXTENSION_KEYWORD ;}
|
||||
<YYINITIAL> "continue" { return JetTokens.CONTINUE_KEYWORD ;}
|
||||
<YYINITIAL> "return" { return JetTokens.RETURN_KEYWORD ;}
|
||||
<YYINITIAL> "typeof" { return JetTokens.TYPEOF_KEYWORD ;}
|
||||
<YYINITIAL> "object" { return JetTokens.OBJECT_KEYWORD ;}
|
||||
<YYINITIAL> "while" { return JetTokens.WHILE_KEYWORD ;}
|
||||
<YYINITIAL> "break" { return JetTokens.BREAK_KEYWORD ;}
|
||||
<YYINITIAL> "class" { return JetTokens.CLASS_KEYWORD ;}
|
||||
<YYINITIAL> "throw" { return JetTokens.THROW_KEYWORD ;}
|
||||
<YYINITIAL> "false" { return JetTokens.FALSE_KEYWORD ;}
|
||||
<YYINITIAL> "when" { return JetTokens.WHEN_KEYWORD ;}
|
||||
<YYINITIAL> "true" { return JetTokens.TRUE_KEYWORD ;}
|
||||
<YYINITIAL> "type" { return JetTokens.TYPE_KEYWORD ;}
|
||||
<YYINITIAL> "this" { return JetTokens.THIS_KEYWORD ;}
|
||||
<YYINITIAL> "null" { return JetTokens.NULL_KEYWORD ;}
|
||||
<YYINITIAL> "else" { return JetTokens.ELSE_KEYWORD ;}
|
||||
<YYINITIAL> "This" { return JetTokens.CAPITALIZED_THIS_KEYWORD ;}
|
||||
<YYINITIAL> "try" { return JetTokens.TRY_KEYWORD ;}
|
||||
<YYINITIAL> "val" { return JetTokens.VAL_KEYWORD ;}
|
||||
<YYINITIAL> "var" { return JetTokens.VAR_KEYWORD ;}
|
||||
<YYINITIAL> "fun" { return JetTokens.FUN_KEYWORD ;}
|
||||
<YYINITIAL> "for" { return JetTokens.FOR_KEYWORD ;}
|
||||
//<YYINITIAL> "new" { return JetTokens.NEW_KEYWORD ;}
|
||||
<YYINITIAL> "is" { return JetTokens.IS_KEYWORD ;}
|
||||
<YYINITIAL> "in" { return JetTokens.IN_KEYWORD ;}
|
||||
<YYINITIAL> "if" { return JetTokens.IF_KEYWORD ;}
|
||||
<YYINITIAL> "do" { return JetTokens.DO_KEYWORD ;}
|
||||
<YYINITIAL> "as" { return JetTokens.AS_KEYWORD ;}
|
||||
|
||||
<YYINITIAL> {FIELD_IDENTIFIER} { return JetTokens.FIELD_IDENTIFIER; }
|
||||
<YYINITIAL> {IDENTIFIER} { return JetTokens.IDENTIFIER; }
|
||||
<YYINITIAL> {LABEL_IDENTIFIER} { return JetTokens.LABEL_IDENTIFIER; }
|
||||
|
||||
<YYINITIAL> "===" { return JetTokens.EQEQEQ ; }
|
||||
<YYINITIAL> "!==" { return JetTokens.EXCLEQEQEQ; }
|
||||
<YYINITIAL> "!in" { return JetTokens.NOT_IN; }
|
||||
<YYINITIAL> "!is" { return JetTokens.NOT_IS; }
|
||||
<YYINITIAL> "as?" { return JetTokens.AS_SAFE; }
|
||||
<YYINITIAL> "++" { return JetTokens.PLUSPLUS ; }
|
||||
<YYINITIAL> "--" { return JetTokens.MINUSMINUS; }
|
||||
<YYINITIAL> "<=" { return JetTokens.LTEQ ; }
|
||||
<YYINITIAL> ">=" { return JetTokens.GTEQ ; }
|
||||
<YYINITIAL> "==" { return JetTokens.EQEQ ; }
|
||||
<YYINITIAL> "!=" { return JetTokens.EXCLEQ ; }
|
||||
<YYINITIAL> "&&" { return JetTokens.ANDAND ; }
|
||||
<YYINITIAL> "||" { return JetTokens.OROR ; }
|
||||
<YYINITIAL> "?." { return JetTokens.SAFE_ACCESS;}
|
||||
<YYINITIAL> "?:" { return JetTokens.ELVIS ; }
|
||||
//<YYINITIAL> ".*" { return JetTokens.MAP ; }
|
||||
//<YYINITIAL> ".?" { return JetTokens.FILTER ; }
|
||||
<YYINITIAL> "*=" { return JetTokens.MULTEQ ; }
|
||||
<YYINITIAL> "/=" { return JetTokens.DIVEQ ; }
|
||||
<YYINITIAL> "%=" { return JetTokens.PERCEQ ; }
|
||||
<YYINITIAL> "+=" { return JetTokens.PLUSEQ ; }
|
||||
<YYINITIAL> "-=" { return JetTokens.MINUSEQ ; }
|
||||
<YYINITIAL> "->" { return JetTokens.ARROW ; }
|
||||
<YYINITIAL> "=>" { return JetTokens.DOUBLE_ARROW; }
|
||||
<YYINITIAL> ".." { return JetTokens.RANGE ; }
|
||||
<YYINITIAL> "@@" { return JetTokens.ATAT ; }
|
||||
<YYINITIAL> "[" { return JetTokens.LBRACKET ; }
|
||||
<YYINITIAL> "]" { return JetTokens.RBRACKET ; }
|
||||
<YYINITIAL> "{" { return JetTokens.LBRACE ; }
|
||||
<YYINITIAL> "}" { return JetTokens.RBRACE ; }
|
||||
<YYINITIAL> "(" { return JetTokens.LPAR ; }
|
||||
<YYINITIAL> ")" { return JetTokens.RPAR ; }
|
||||
<YYINITIAL> "." { return JetTokens.DOT ; }
|
||||
<YYINITIAL> "*" { return JetTokens.MUL ; }
|
||||
<YYINITIAL> "+" { return JetTokens.PLUS ; }
|
||||
<YYINITIAL> "-" { return JetTokens.MINUS ; }
|
||||
<YYINITIAL> "!" { return JetTokens.EXCL ; }
|
||||
<YYINITIAL> "/" { return JetTokens.DIV ; }
|
||||
<YYINITIAL> "%" { return JetTokens.PERC ; }
|
||||
<YYINITIAL> "<" { return JetTokens.LT ; }
|
||||
<YYINITIAL> ">" { return JetTokens.GT ; }
|
||||
<YYINITIAL> "?" { return JetTokens.QUEST ; }
|
||||
<YYINITIAL> ":" { return JetTokens.COLON ; }
|
||||
<YYINITIAL> ";" { return JetTokens.SEMICOLON ; }
|
||||
<YYINITIAL> "=" { return JetTokens.EQ ; }
|
||||
<YYINITIAL> "," { return JetTokens.COMMA ; }
|
||||
<YYINITIAL> "#" { return JetTokens.HASH ; }
|
||||
<YYINITIAL> "@" { return JetTokens.AT ; }
|
||||
|
||||
<YYINITIAL> . { return JetTokens.BAD_CHARACTER; }
|
||||
|
||||
@@ -10,10 +10,10 @@ import com.intellij.psi.TokenType;
|
||||
import com.intellij.psi.tree.IElementType;
|
||||
import org.apache.velocity.VelocityContext;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author abreslav
|
||||
@@ -31,7 +31,72 @@ public class JetMacro extends BaseMacro {
|
||||
|
||||
@Override
|
||||
public String execute(Map map, String code, RenderContext renderContext) throws MacroException {
|
||||
|
||||
class ExtraTag {
|
||||
final String name;
|
||||
final String message;
|
||||
final int start;
|
||||
int end;
|
||||
|
||||
ExtraTag(String name, String message, int start) {
|
||||
this.name = name;
|
||||
this.message = message;
|
||||
this.start = start;
|
||||
}
|
||||
}
|
||||
|
||||
String[] knownExtraTagNames = {"error", "warning", "unresolved"};
|
||||
|
||||
Map<String, Pattern> openTags = new HashMap<String, Pattern>();
|
||||
Map<String, Pattern> closeTags = new HashMap<String, Pattern>();
|
||||
for (String name : knownExtraTagNames) {
|
||||
Pattern open = Pattern.compile("<" + name + "\\s*(desc=\\\"([^\n\"]*?)\\\")?>", Pattern.MULTILINE);
|
||||
openTags.put(name, open);
|
||||
closeTags.put(name, Pattern.compile("</" + name + ">"));
|
||||
}
|
||||
|
||||
Stack<ExtraTag> tagStack = new Stack<ExtraTag>();
|
||||
List<ExtraTag> tags = new ArrayList<ExtraTag>();
|
||||
|
||||
code = code.trim();
|
||||
StringBuilder normalizedNewlines = new StringBuilder();
|
||||
charLoop:
|
||||
for (int i = 0; i < code.length(); i++) {
|
||||
char c = code.charAt(i);
|
||||
if (c == '\r') continue;
|
||||
for (String tagName : knownExtraTagNames) {
|
||||
Pattern open = openTags.get(tagName);
|
||||
CharSequence remainingInput = code.subSequence(i, code.length());
|
||||
Matcher openMatcher = open.matcher(remainingInput);
|
||||
if (openMatcher.find() && openMatcher.start() == 0) {
|
||||
tagStack.push(new ExtraTag(tagName, openMatcher.group(2), normalizedNewlines.length()));
|
||||
i += openMatcher.end() - 1;
|
||||
continue charLoop;
|
||||
}
|
||||
|
||||
Pattern close = closeTags.get(tagName);
|
||||
Matcher closeMatcher = close.matcher(remainingInput);
|
||||
if (closeMatcher.find() && closeMatcher.start() == 0) {
|
||||
if (tagStack.isEmpty()) {
|
||||
return "<div style=\"jet error\">Error: unmatched closing tag: " + closeMatcher.group() + "</div>";
|
||||
}
|
||||
else {
|
||||
ExtraTag tag = tagStack.pop();
|
||||
if (!tagName.equals(tag.name)) {
|
||||
return "<div style=\"jet error\">Error: unmatched closing tag: " + closeMatcher.group() + "</div>";
|
||||
}
|
||||
|
||||
tag.end = normalizedNewlines.length();
|
||||
tags.add(tag);
|
||||
i += closeMatcher.end() - 1;
|
||||
continue charLoop;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
normalizedNewlines.append(c);
|
||||
}
|
||||
|
||||
VelocityContext context = new VelocityContext(MacroUtils.defaultVelocityContext());
|
||||
String renderedTemplate = VelocityUtils.getRenderedTemplate("template.velocity", context);
|
||||
|
||||
@@ -43,7 +108,7 @@ public class JetMacro extends BaseMacro {
|
||||
);
|
||||
|
||||
_JetLexer jetLexer = new _JetLexer(new StringReader(""));
|
||||
jetLexer.reset(code, 0, code.length(), _JetLexer.YYINITIAL);
|
||||
jetLexer.reset(normalizedNewlines, 0, normalizedNewlines.length(), _JetLexer.YYINITIAL);
|
||||
|
||||
Map<IElementType, String> styleMap = new HashMap<IElementType, String>();
|
||||
styleMap.put(JetTokens.BLOCK_COMMENT, "comment");
|
||||
@@ -67,8 +132,23 @@ public class JetMacro extends BaseMacro {
|
||||
styleMap.put(JetTokens.RAW_STRING_LITERAL, "string");
|
||||
styleMap.put(TokenType.BAD_CHARACTER, "bad");
|
||||
|
||||
Iterator<ExtraTag> iterator = tags.iterator();
|
||||
ExtraTag tag = iterator.hasNext() ? iterator.next() : null;
|
||||
while (true) {
|
||||
try {
|
||||
if (tag != null) {
|
||||
if (tag.start == jetLexer.getTokenEnd()) {
|
||||
result.append("<div class=\"jet ").append(tag.name).append("\"");
|
||||
if (tag.message != null) {
|
||||
result.append(" title=\"").append(tag.message).append("\"");
|
||||
}
|
||||
result.append(">");
|
||||
}
|
||||
else if (tag.end == jetLexer.getTokenEnd()) {
|
||||
result.append("</div>");
|
||||
tag = iterator.hasNext() ? iterator.next() : null;
|
||||
}
|
||||
}
|
||||
IElementType token = jetLexer.advance();
|
||||
if (token == null) break;
|
||||
CharSequence yytext = jetLexer.yytext();
|
||||
@@ -90,7 +170,7 @@ public class JetMacro extends BaseMacro {
|
||||
}
|
||||
result.append("<code class=\"jet ").append(style).append("\">").append(yytext).append("</code>");
|
||||
|
||||
} catch (IOException e) {
|
||||
} catch (Throwable e) {
|
||||
result.append("ERROR IN HIGHLIGHTER: ").append(e.getClass().getSimpleName()).append(" : ").append(e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* The following code was generated by JFlex 1.4.3 on 7/12/11 6:40 PM */
|
||||
/* The following code was generated by JFlex 1.4.3 on 7/12/11 9:54 PM */
|
||||
|
||||
/* It's an automatically generated code. Do not modify it. */
|
||||
package org.jetbrains.jet.lexer;
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
/**
|
||||
* This class is a scanner generated by
|
||||
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
|
||||
* on 7/12/11 6:40 PM from the specification file
|
||||
* on 7/12/11 9:54 PM from the specification file
|
||||
* <tt>/Users/abreslav/work/jet/confluence/../idea/src/org/jetbrains/jet/lexer/Jet.flex</tt>
|
||||
*/
|
||||
class _JetLexer implements FlexLexer {
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="${project.name}" plugins-version="2">
|
||||
<atlassian-plugin key="${project.groupId}.${project.artifactId}" name="jet" plugins-version="2">
|
||||
<plugin-info>
|
||||
<description>${project.description}</description>
|
||||
<version>${project.version}</version>
|
||||
@@ -11,5 +11,6 @@
|
||||
|
||||
<web-resource key="resources">
|
||||
<resource type="download" name="jet.css" location="jet.css"/>
|
||||
<resource type="download" name="underline.gif" location="underline.gif"/>
|
||||
</web-resource>
|
||||
</atlassian-plugin>
|
||||
|
||||
@@ -20,7 +20,6 @@
|
||||
}
|
||||
.jet.string {
|
||||
color : #000099;
|
||||
font-weight: bold;
|
||||
}
|
||||
.jet.escape {
|
||||
font-weight: bold;
|
||||
@@ -37,3 +36,15 @@
|
||||
background-color : #FF9999;
|
||||
color:black;
|
||||
}
|
||||
.jet.error {
|
||||
background: url(underline.gif) bottom repeat-x;
|
||||
display:inline;
|
||||
}
|
||||
.jet.warning {
|
||||
background-color : #f5eabb;
|
||||
display:inline;
|
||||
}
|
||||
.jet.unresolved {
|
||||
color : red;
|
||||
display:inline;
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
/* The following code was generated by JFlex 1.4.3 on 7/12/11 1:25 PM */
|
||||
/* The following code was generated by JFlex 1.4.3 on 7/12/11 9:54 PM */
|
||||
|
||||
/* It's an automatically generated code. Do not modify it. */
|
||||
package org.jetbrains.jet.lexer;
|
||||
@@ -14,7 +14,7 @@ import org.jetbrains.jet.lexer.JetTokens;
|
||||
/**
|
||||
* This class is a scanner generated by
|
||||
* <a href="http://www.jflex.de/">JFlex</a> 1.4.3
|
||||
* on 7/12/11 1:25 PM from the specification file
|
||||
* on 7/12/11 9:54 PM from the specification file
|
||||
* <tt>/Users/abreslav/work/jet/idea/src/org/jetbrains/jet/lexer/Jet.flex</tt>
|
||||
*/
|
||||
class _JetLexer implements FlexLexer {
|
||||
|
||||
Reference in New Issue
Block a user