From 8074629b7762fd685ab249aea3c1fe9f4895b76e Mon Sep 17 00:00:00 2001 From: "Natalia.Ukhorskaya" Date: Thu, 19 Apr 2012 20:09:47 +0400 Subject: [PATCH] Refactoring in JetMacro --- confluence/buildConfluenceLexer.xml | 2 +- .../org/jetbrains/jet/ConfluenceUtils.java | 47 +++++ .../org/jetbrains/jet/lexer/JetMacro.java | 167 +++++------------- .../jetbrains/jet/tags/StyledDivTagType.java | 31 ++++ .../java/org/jetbrains/jet/tags/TagData.java | 44 +++++ .../java/org/jetbrains/jet/tags/TagType.java | 25 +++ 6 files changed, 195 insertions(+), 121 deletions(-) create mode 100644 confluence/src/main/java/org/jetbrains/jet/ConfluenceUtils.java create mode 100644 confluence/src/main/java/org/jetbrains/jet/tags/StyledDivTagType.java create mode 100644 confluence/src/main/java/org/jetbrains/jet/tags/TagData.java create mode 100644 confluence/src/main/java/org/jetbrains/jet/tags/TagType.java diff --git a/confluence/buildConfluenceLexer.xml b/confluence/buildConfluenceLexer.xml index e0f993ff4911c..3d22623e2ed4d 100644 --- a/confluence/buildConfluenceLexer.xml +++ b/confluence/buildConfluenceLexer.xml @@ -1,6 +1,6 @@ - + diff --git a/confluence/src/main/java/org/jetbrains/jet/ConfluenceUtils.java b/confluence/src/main/java/org/jetbrains/jet/ConfluenceUtils.java new file mode 100644 index 0000000000000..da0dd0145ebb0 --- /dev/null +++ b/confluence/src/main/java/org/jetbrains/jet/ConfluenceUtils.java @@ -0,0 +1,47 @@ +package org.jetbrains.jet; + +/** + * @author Natalia.Ukhorskaya + */ + +public class ConfluenceUtils { + + public static void escapeHTML(StringBuilder builder, CharSequence seq) { + if (seq == null) return; + for (int i = 0; i < seq.length(); i++) { + char c = seq.charAt(i); + switch (c) { + case '<': + builder.append("<"); + break; + case '>': + builder.append(">"); + break; + case '&': + builder.append("&"); + break; + case ' ': + builder.append(" "); + break; + case '"': + builder.append("""); + break; + default: + builder.append(c); + } + } + } + + public static String getErrorInHtml(Throwable e, String info) { + StringBuilder stringBuilder = new StringBuilder(); + stringBuilder.append("
Jet highlighter error [").append(e.getClass().getSimpleName()).append("]: "); + ConfluenceUtils.escapeHTML(stringBuilder, e.getMessage()); + stringBuilder.append("
"); + stringBuilder.append("Original text:"); + stringBuilder.append("
");
+        ConfluenceUtils.escapeHTML(stringBuilder, info);
+        stringBuilder.append("
"); + stringBuilder.append("
"); + return stringBuilder.toString(); + } +} diff --git a/confluence/src/main/java/org/jetbrains/jet/lexer/JetMacro.java b/confluence/src/main/java/org/jetbrains/jet/lexer/JetMacro.java index 431fb12051135..09bfa123fb2da 100644 --- a/confluence/src/main/java/org/jetbrains/jet/lexer/JetMacro.java +++ b/confluence/src/main/java/org/jetbrains/jet/lexer/JetMacro.java @@ -25,6 +25,10 @@ import com.intellij.psi.TokenType; import com.intellij.psi.tree.IElementType; import org.apache.velocity.VelocityContext; +import org.jetbrains.jet.ConfluenceUtils; +import org.jetbrains.jet.tags.StyledDivTagType; +import org.jetbrains.jet.tags.TagData; +import org.jetbrains.jet.tags.TagType; import java.io.StringReader; import java.util.*; @@ -38,61 +42,6 @@ public class JetMacro extends BaseMacro { public static final StringReader DUMMY_READER = new StringReader(""); - private static class TagData { - final TagType type; - final String message; - final int start; - final boolean nextToken; - int end; - - TagData(TagType type, String message, int start, boolean nextToken) { - this.type = type; - this.message = message; - this.start = start; - this.nextToken = nextToken; - } - } - - private static abstract class TagType { - public final String tagName; - - private TagType(String tagName) { - this.tagName = tagName; - } - - public abstract void appendOpenTag(StringBuilder builder, TagData tagData); - public abstract void appendCloseTag(StringBuilder builder, TagData tagData); - - @Override - public String toString() { - return tagName; - } - } - - private static class StyledDivTagType extends TagType { - - private StyledDivTagType(String tagName) { - super(tagName); - } - - @Override - public void appendOpenTag(StringBuilder builder, TagData tagData) { - assert tagData.type == this; - builder.append("
"); - } - - @Override - public void appendCloseTag(StringBuilder builder, TagData tagData) { - builder.append("
"); - } - } - private static final TagType[] knownExtraTagTypes = { new StyledDivTagType("error"), new StyledDivTagType("warning"), @@ -101,7 +50,7 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { @Override public void appendOpenTag(StringBuilder builder, TagData tagData) { builder.append(""); } @@ -114,7 +63,7 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { @Override public void appendOpenTag(StringBuilder builder, TagData tagData) { builder.append(""); } @@ -127,7 +76,7 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { @Override public void appendOpenTag(StringBuilder builder, TagData tagData) { builder.append(""); } @@ -140,7 +89,7 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { @Override public void appendOpenTag(StringBuilder builder, TagData tagData) { builder.append("
"); } @@ -153,7 +102,7 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { @Override public void appendOpenTag(StringBuilder builder, TagData tagData) { builder.append("
"); } @@ -167,9 +116,10 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { private static final Map nextTokenTags = new HashMap(); private static final Map closedTags = new HashMap(); private static final Map closeTags = new HashMap(); + static { for (TagType type : knownExtraTagTypes) { - String tagName = type.tagName; + String tagName = type.getTagName(); openTags.put(type, Pattern.compile("<" + tagName + "\\s*((desc)?=\\\"([^\n\"]*?)\\\")?>", Pattern.MULTILINE)); closeTags.put(type, Pattern.compile("")); @@ -179,6 +129,7 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { } private static final Map styleMap = new HashMap(); + static { styleMap.put(JetTokens.BLOCK_COMMENT, "jet-comment"); styleMap.put(JetTokens.DOC_COMMENT, "jet-comment"); @@ -198,7 +149,6 @@ public void appendCloseTag(StringBuilder builder, TagData tagData) { styleMap.put(JetTokens.LABEL_IDENTIFIER, "label"); styleMap.put(JetTokens.ATAT, "label"); styleMap.put(JetTokens.FIELD_IDENTIFIER, "field"); - styleMap.put(JetTokens.RAW_STRING_LITERAL, "string"); styleMap.put(TokenType.BAD_CHARACTER, "bad"); } @@ -212,32 +162,6 @@ public RenderMode getBodyRenderMode() { return RenderMode.allow(0); } - private static void escapeHTML(StringBuilder builder, CharSequence seq) { - if (seq == null) return; - for (int i = 0; i < seq.length(); i++) { - char c = seq.charAt(i); - switch (c) { - case '<': - builder.append("<"); - break; - case '>': - builder.append(">"); - break; - case '&': - builder.append("&"); - break; - case ' ': - builder.append(" "); - break; - case '"': - builder.append("""); - break; - default: - builder.append(c); - } - } - } - private String addNewLineOpenTag() { return "
"; } @@ -246,7 +170,7 @@ private String addNewLineCloseTag() { return "
"; } - private void addNewLines(StringBuilder result, String yytext) { + private void convertNewLines(StringBuilder result, String yytext) { for (int i = 0; i < yytext.length(); i++) { if (yytext.charAt(i) == '\n') { result.append(" "); @@ -259,14 +183,23 @@ private void addNewLines(StringBuilder result, String yytext) { @Override public String execute(Map map, String code, RenderContext renderContext) throws MacroException { try { - List tags = new ArrayList(); - - StringBuilder afterPreprocessing = preprocess(code.trim(), tags); - VelocityContext context = new VelocityContext(MacroUtils.defaultVelocityContext()); String renderedTemplate = VelocityUtils.getRenderedTemplate("template.velocity", context); - StringBuilder result = new StringBuilder(renderedTemplate); + + generateHtmlFromCode(code, result); + + return result.toString(); + } catch (Throwable e) { + return ConfluenceUtils.getErrorInHtml(e, code); + } + } + + public void generateHtmlFromCode(String code, StringBuilder result) throws java.io.IOException { + try { + List tags = new ArrayList(); + StringBuilder afterPreprocessing = preprocess(code.trim(), tags); + result.append( "
" + "
" + @@ -282,24 +215,24 @@ public String execute(Map map, String code, RenderContext renderContext) throws TagData tag = iterator.hasNext() ? iterator.next() : null; while (true) { int tokenEnd = jetLexer.getTokenEnd(); - while (tag != null && tag.end < tokenEnd) { - result.append("
Skipping a tag in the middle of a token: <").append(tag.type).append(">
"); + while (tag != null && tag.getEnd() < tokenEnd) { + result.append("
Skipping a tag in the middle of a token: <").append(tag.getType()).append(">
"); tag = iterator.hasNext() ? iterator.next() : null; } if (tag != null) { - if (tag.start == tokenEnd) { + if (tag.getStart() == tokenEnd) { // result.append("
"); - tag.type.appendOpenTag(result, tag); + tag.getType().appendOpenTag(result, tag); } } if (tag != null) { - if (tag.end == tokenEnd || (tag.nextToken && tag.start < tokenEnd)) { - tag.type.appendCloseTag(result, tag); + if (tag.getEnd() == tokenEnd || (tag.isNextToken() && tag.getStart() < tokenEnd)) { + tag.getType().appendCloseTag(result, tag); tag = iterator.hasNext() ? iterator.next() : null; } } @@ -310,14 +243,15 @@ public String execute(Map map, String code, RenderContext renderContext) throws String yytext = jetLexer.yytext().toString(); if (yytext.contains("\n")) { - addNewLines(result, yytext); + convertNewLines(result, yytext); yytext = yytext.replaceAll("\n", ""); } String style = null; if (token instanceof JetKeywordToken) { style = "keyword"; - } else if (token == JetTokens.IDENTIFIER) { + } + else if (token == JetTokens.IDENTIFIER) { for (IElementType softKeyword : JetTokens.SOFT_KEYWORDS.asSet()) { if (((JetKeywordToken) softKeyword).getValue().equals(yytext.toString())) { style = "softkeyword"; @@ -325,13 +259,15 @@ public String execute(Map map, String code, RenderContext renderContext) throws } } style = style == null ? "plain" : style; - } else if (styleMap.containsKey(token)) { + } + else if (styleMap.containsKey(token)) { style = styleMap.get(token); - } else { + } + else { style = "plain"; } result.append(""); - escapeHTML(result, yytext); + ConfluenceUtils.escapeHTML(result, yytext); result.append(""); } @@ -339,19 +275,10 @@ public String execute(Map map, String code, RenderContext renderContext) throws result.append("
"); result.append("
"); result.append("
"); - return result.toString(); } catch (Throwable e) { - StringBuilder stringBuilder = new StringBuilder(); - stringBuilder.append("
Jet highlighter error [").append(e.getClass().getSimpleName()).append("]: "); - escapeHTML(stringBuilder, e.getMessage()); - stringBuilder.append("
"); - stringBuilder.append("Original text:"); - stringBuilder.append("
");
-            escapeHTML(stringBuilder, code);
-            stringBuilder.append("
"); - stringBuilder.append("
"); - return stringBuilder.toString(); + result = new StringBuilder(ConfluenceUtils.getErrorInHtml(e, code)); } + } private StringBuilder preprocess(CharSequence code, Collection tags) { @@ -382,11 +309,11 @@ private StringBuilder preprocess(CharSequence code, Collection tags) { } else { TagData tag = tagStack.pop(); - if (type != tag.type) { + if (type != tag.getType()) { throw new IllegalArgumentException("Unmatched closing tag: " + closeMatcher.group()); } - tag.end = position; + tag.setEnd(position); tags.add(tag); i += closeMatcher.end() - 1; continue charLoop; @@ -397,7 +324,7 @@ private StringBuilder preprocess(CharSequence code, Collection tags) { Matcher closedMatcher = matchFrom(code, i, closed); if (closedMatcher != null) { TagData tag = new TagData(type, closedMatcher.group(3), position, false); - tag.end = position; + tag.setEnd(position); tags.add(tag); i += closedMatcher.end() - 1; continue charLoop; @@ -408,7 +335,7 @@ private StringBuilder preprocess(CharSequence code, Collection tags) { if (nextMatcher != null) { TagData tag = new TagData(type, nextMatcher.group(3), position, true); tags.add(tag); - tag.end = code.length(); + tag.setEnd(code.length()); i += nextMatcher.end() - 1; continue charLoop; } diff --git a/confluence/src/main/java/org/jetbrains/jet/tags/StyledDivTagType.java b/confluence/src/main/java/org/jetbrains/jet/tags/StyledDivTagType.java new file mode 100644 index 0000000000000..a6a4b7bbe25ea --- /dev/null +++ b/confluence/src/main/java/org/jetbrains/jet/tags/StyledDivTagType.java @@ -0,0 +1,31 @@ +package org.jetbrains.jet.tags; + +import org.jetbrains.jet.ConfluenceUtils; + +/** + * @author abreslav + */ + +public class StyledDivTagType extends TagType { + + public StyledDivTagType(String tagName) { + super(tagName); + } + + @Override + public void appendOpenTag(StringBuilder builder, TagData tagData) { + assert tagData.getType() == this; + builder.append("
"); + } + + @Override + public void appendCloseTag(StringBuilder builder, TagData tagData) { + builder.append("
"); + } +} diff --git a/confluence/src/main/java/org/jetbrains/jet/tags/TagData.java b/confluence/src/main/java/org/jetbrains/jet/tags/TagData.java new file mode 100644 index 0000000000000..0bf112f79866e --- /dev/null +++ b/confluence/src/main/java/org/jetbrains/jet/tags/TagData.java @@ -0,0 +1,44 @@ +package org.jetbrains.jet.tags; + +/** + * @author abreslav + */ + +public class TagData { + private final TagType type; + private final String message; + private final int start; + private final boolean nextToken; + private int end; + + public TagData(TagType type, String message, int start, boolean nextToken) { + this.type = type; + this.message = message; + this.start = start; + this.nextToken = nextToken; + } + + public TagType getType() { + return type; + } + + public String getMessage() { + return message; + } + + public int getStart() { + return start; + } + + public boolean isNextToken() { + return nextToken; + } + + public int getEnd() { + return end; + } + + public void setEnd(int end) { + this.end = end; + } +} diff --git a/confluence/src/main/java/org/jetbrains/jet/tags/TagType.java b/confluence/src/main/java/org/jetbrains/jet/tags/TagType.java new file mode 100644 index 0000000000000..dcaea651a7bde --- /dev/null +++ b/confluence/src/main/java/org/jetbrains/jet/tags/TagType.java @@ -0,0 +1,25 @@ +package org.jetbrains.jet.tags; + +/** + * @author abreslav + */ + +public abstract class TagType { + private final String tagName; + + protected TagType(String tagName) { + this.tagName = tagName; + } + + public abstract void appendOpenTag(StringBuilder builder, TagData tagData); + public abstract void appendCloseTag(StringBuilder builder, TagData tagData); + + @Override + public String toString() { + return tagName; + } + + public String getTagName() { + return tagName; + } +}