Refactor generator of JS source map
- refactor pipeline for generation of source map - generate "empty" mappings for nodes that impossible to map to something reasonable - generate more accurate locations in source maps for specific JS AST nodes - for binary operation nodes parser now returns location of binary operator tokens instead of location of first operand - change completely how source map remapper works
This commit is contained in:
@@ -12,10 +12,7 @@ import org.jetbrains.kotlin.js.util.TextOutput;
|
||||
import gnu.trove.THashSet;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Produces text output from a JavaScript AST.
|
||||
@@ -47,6 +44,11 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
private static final char[] CHARS_WHILE = "while".toCharArray();
|
||||
private static final char[] HEX_DIGITS = {
|
||||
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'};
|
||||
@NotNull
|
||||
private final SourceLocationConsumer sourceLocationConsumer;
|
||||
|
||||
@NotNull
|
||||
private final List<Object> sourceInfoStack = new ArrayList<>();
|
||||
|
||||
public static CharSequence javaScriptString(String value) {
|
||||
return javaScriptString(value, false);
|
||||
@@ -60,7 +62,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
*/
|
||||
@SuppressWarnings({"ConstantConditions", "UnnecessaryFullyQualifiedName", "JavadocReference"})
|
||||
public static CharSequence javaScriptString(CharSequence chars, boolean forceDoubleQuote) {
|
||||
final int n = chars.length();
|
||||
int n = chars.length();
|
||||
int quoteCount = 0;
|
||||
int aposCount = 0;
|
||||
|
||||
@@ -174,25 +176,40 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
* those that appear directly within these global blocks.
|
||||
*/
|
||||
private Set<JsBlock> globalBlocks = new THashSet<JsBlock>();
|
||||
|
||||
@NotNull
|
||||
protected final TextOutput p;
|
||||
|
||||
public JsToStringGenerationVisitor(TextOutput out) {
|
||||
public JsToStringGenerationVisitor(@NotNull TextOutput out, @NotNull SourceLocationConsumer sourceLocationConsumer) {
|
||||
p = out;
|
||||
this.sourceLocationConsumer = sourceLocationConsumer;
|
||||
}
|
||||
|
||||
public JsToStringGenerationVisitor(@NotNull TextOutput out) {
|
||||
this(out, NoOpSourceLocationConsumer.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArrayAccess(@NotNull JsArrayAccess x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
printPair(x, x.getArrayExpression());
|
||||
leftSquare();
|
||||
accept(x.getIndexExpression());
|
||||
rightSquare();
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArray(@NotNull JsArrayLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
leftSquare();
|
||||
printExpressions(x.getExpressions());
|
||||
rightSquare();
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
private void printExpressions(List<JsExpression> expressions) {
|
||||
@@ -209,6 +226,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitBinaryExpression(@NotNull JsBinaryOperation binaryOperation) {
|
||||
pushSourceInfo(binaryOperation.getSource());
|
||||
|
||||
JsBinaryOperator operator = binaryOperation.getOperator();
|
||||
JsExpression arg1 = binaryOperation.getArg1();
|
||||
boolean isExpressionEnclosed = parenPush(binaryOperation, arg1, !operator.isLeftAssociative());
|
||||
@@ -250,6 +269,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
if (isParenOpened) {
|
||||
rightParen();
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -259,29 +280,41 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitBoolean(@NotNull JsBooleanLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
if (x.getValue()) {
|
||||
p.print(CHARS_TRUE);
|
||||
}
|
||||
else {
|
||||
p.print(CHARS_FALSE);
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreak(@NotNull JsBreak x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_BREAK);
|
||||
continueOrBreakLabel(x);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitContinue(@NotNull JsContinue x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_CONTINUE);
|
||||
continueOrBreakLabel(x);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
private void continueOrBreakLabel(JsContinue x) {
|
||||
JsNameRef label = x.getLabel();
|
||||
if (label != null && label.getIdent() != null) {
|
||||
if (label != null) {
|
||||
space();
|
||||
p.print(label.getIdent());
|
||||
}
|
||||
@@ -289,13 +322,20 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitCase(@NotNull JsCase x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_CASE);
|
||||
space();
|
||||
accept(x.getCaseExpression());
|
||||
_colon();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
newlineOpt();
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
printSwitchMemberStatements(x);
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
private void printSwitchMemberStatements(JsSwitchMember x) {
|
||||
@@ -314,6 +354,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitCatch(@NotNull JsCatch x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
spaceOpt();
|
||||
p.print(CHARS_CATCH);
|
||||
spaceOpt();
|
||||
@@ -332,11 +374,18 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
rightParen();
|
||||
spaceOpt();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(x.getBody());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitConditional(@NotNull JsConditional x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
// Associativity: for the then and else branches, it is safe to insert
|
||||
// another
|
||||
// ternary expression, but if the test expression is a ternary, it should
|
||||
@@ -350,6 +399,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
_colon();
|
||||
spaceOpt();
|
||||
printPair(x, x.getElseExpression());
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
private void printPair(JsExpression parent, JsExpression expression, boolean wrongAssoc) {
|
||||
@@ -369,35 +420,57 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitDebugger(@NotNull JsDebugger x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_DEBUGGER);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDefault(@NotNull JsDefault x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_DEFAULT);
|
||||
_colon();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
printSwitchMemberStatements(x);
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitWhile(@NotNull JsWhile x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
_while();
|
||||
spaceOpt();
|
||||
leftParen();
|
||||
accept(x.getCondition());
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
nestedPush(x.getBody());
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(x.getBody());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
nestedPop(x.getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDoWhile(@NotNull JsDoWhile x) {
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
|
||||
p.print(CHARS_DO);
|
||||
nestedPush(x.getBody());
|
||||
accept(x.getBody());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
nestedPop(x.getBody());
|
||||
|
||||
pushSourceInfo(x.getCondition().getSource());
|
||||
if (needSemi) {
|
||||
semi();
|
||||
newlineOpt();
|
||||
@@ -406,11 +479,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
spaceOpt();
|
||||
needSemi = true;
|
||||
}
|
||||
|
||||
_while();
|
||||
spaceOpt();
|
||||
leftParen();
|
||||
accept(x.getCondition());
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -419,6 +495,12 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitExpressionStatement(@NotNull JsExpressionStatement x) {
|
||||
Object source = x.getSource();
|
||||
if (source == null) {
|
||||
source = x.getExpression().getSource();
|
||||
}
|
||||
pushSourceInfo(source);
|
||||
|
||||
boolean surroundWithParentheses = JsFirstExpressionVisitor.exec(x);
|
||||
if (surroundWithParentheses) {
|
||||
leftParen();
|
||||
@@ -427,10 +509,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
if (surroundWithParentheses) {
|
||||
rightParen();
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFor(@NotNull JsFor x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
_for();
|
||||
spaceOpt();
|
||||
leftParen();
|
||||
@@ -463,15 +549,22 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
nestedPush(x.getBody());
|
||||
if (x.getBody() != null) {
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(x.getBody());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
nestedPop(x.getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitForIn(@NotNull JsForIn x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
_for();
|
||||
spaceOpt();
|
||||
leftParen();
|
||||
@@ -500,13 +593,20 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(x.getObjectExpression());
|
||||
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
nestedPush(x.getBody());
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(x.getBody());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
nestedPop(x.getBody());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFunction(@NotNull JsFunction x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_FUNCTION);
|
||||
space();
|
||||
if (x.getName() != null) {
|
||||
@@ -524,24 +624,39 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
space();
|
||||
|
||||
lineBreakAfterBlock = false;
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(x.getBody());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
|
||||
needSemi = true;
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIf(@NotNull JsIf x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
_if();
|
||||
spaceOpt();
|
||||
leftParen();
|
||||
accept(x.getIfExpression());
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
JsStatement thenStmt = x.getThenStatement();
|
||||
JsStatement elseStatement = x.getElseStatement();
|
||||
if (elseStatement != null && thenStmt instanceof JsIf && ((JsIf)thenStmt).getElseStatement() == null) {
|
||||
thenStmt = new JsBlock(thenStmt);
|
||||
}
|
||||
nestedPush(thenStmt);
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(thenStmt);
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
|
||||
nestedPop(thenStmt);
|
||||
if (elseStatement != null) {
|
||||
if (needSemi) {
|
||||
@@ -560,7 +675,9 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
else {
|
||||
space();
|
||||
}
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(elseStatement);
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
if (!elseIf) {
|
||||
nestedPop(elseStatement);
|
||||
}
|
||||
@@ -569,11 +686,15 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitInvocation(@NotNull JsInvocation invocation) {
|
||||
pushSourceInfo(invocation.getSource());
|
||||
|
||||
printPair(invocation, invocation.getQualifier());
|
||||
|
||||
leftParen();
|
||||
printExpressions(invocation.getArguments());
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -581,14 +702,19 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
nameOf(x);
|
||||
_colon();
|
||||
spaceOpt();
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
accept(x.getStatement());
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNameRef(@NotNull JsNameRef nameRef) {
|
||||
pushSourceInfo(nameRef.getSource());
|
||||
|
||||
JsExpression qualifier = nameRef.getQualifier();
|
||||
if (qualifier != null) {
|
||||
final boolean enclose;
|
||||
boolean enclose;
|
||||
if (qualifier instanceof JsLiteral.JsValueLiteral) {
|
||||
// "42.foo" is not allowed, but "(42).foo" is.
|
||||
enclose = qualifier instanceof JsNumberLiteral;
|
||||
@@ -609,10 +735,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
p.maybeIndent();
|
||||
p.print(nameRef.getIdent());
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNew(@NotNull JsNew x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_NEW);
|
||||
space();
|
||||
|
||||
@@ -629,26 +759,43 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
leftParen();
|
||||
printExpressions(x.getArguments());
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNull(@NotNull JsNullLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_NULL);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInt(@NotNull JsIntLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(x.value);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDouble(@NotNull JsDoubleLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(x.value);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectLiteral(@NotNull JsObjectLiteral objectLiteral) {
|
||||
pushSourceInfo(objectLiteral.getSource());
|
||||
|
||||
p.print('{');
|
||||
|
||||
if (objectLiteral.isMultiline()) {
|
||||
p.indentIn();
|
||||
}
|
||||
@@ -668,6 +815,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
notFirst = true;
|
||||
|
||||
pushSourceInfo(item.getSource());
|
||||
|
||||
JsExpression labelExpr = item.getLabelExpr();
|
||||
// labels can be either string, integral, or decimal literals
|
||||
if (labelExpr instanceof JsNameRef) {
|
||||
@@ -688,6 +837,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
if (wasEnclosed) {
|
||||
rightParen();
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
if (objectLiteral.isMultiline()) {
|
||||
@@ -696,6 +847,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
|
||||
p.print('}');
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -705,15 +857,21 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitPostfixOperation(@NotNull JsPostfixOperation x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
JsUnaryOperator op = x.getOperator();
|
||||
JsExpression arg = x.getArg();
|
||||
// unary operators always associate correctly (I think)
|
||||
printPair(x, arg);
|
||||
p.print(op.getSymbol());
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPrefixOperation(@NotNull JsPrefixOperation x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
JsUnaryOperator op = x.getOperator();
|
||||
p.print(op.getSymbol());
|
||||
JsExpression arg = x.getArg();
|
||||
@@ -722,15 +880,19 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
// unary operators always associate correctly (I think)
|
||||
printPair(x, arg);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitProgram(@NotNull JsProgram x) {
|
||||
p.print("<JsProgram>");
|
||||
x.acceptChildren(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitRegExp(@NotNull JsRegExp x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
slash();
|
||||
p.print(x.getPattern());
|
||||
slash();
|
||||
@@ -738,46 +900,72 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
if (flags != null) {
|
||||
p.print(flags);
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturn(@NotNull JsReturn x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_RETURN);
|
||||
JsExpression expr = x.getExpression();
|
||||
if (expr != null) {
|
||||
space();
|
||||
accept(expr);
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitString(@NotNull JsStringLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(javaScriptString(x.getValue()));
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull JsSwitch x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_SWITCH);
|
||||
spaceOpt();
|
||||
leftParen();
|
||||
accept(x.getExpression());
|
||||
rightParen();
|
||||
|
||||
popSourceInfo();
|
||||
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
spaceOpt();
|
||||
blockOpen();
|
||||
acceptList(x.getCases());
|
||||
blockClose();
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThis(@NotNull JsThisRef x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_THIS);
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThrow(@NotNull JsThrow x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
p.print(CHARS_THROW);
|
||||
space();
|
||||
accept(x.getExpression());
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -798,6 +986,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull JsVar var) {
|
||||
pushSourceInfo(var.getSource());
|
||||
|
||||
nameOf(var);
|
||||
JsExpression initExpr = var.getInitExpression();
|
||||
if (initExpr != null) {
|
||||
@@ -810,10 +1000,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
rightParen();
|
||||
}
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVars(@NotNull JsVars vars) {
|
||||
pushSourceInfo(vars.getSource());
|
||||
|
||||
var();
|
||||
space();
|
||||
boolean sep = false;
|
||||
@@ -831,6 +1025,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
accept(var);
|
||||
}
|
||||
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -844,13 +1040,13 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
space();
|
||||
}
|
||||
else {
|
||||
p.newline();
|
||||
newline();
|
||||
}
|
||||
|
||||
boolean notFirst = false;
|
||||
for (Map.Entry<String, Object> entry : comment.getTags().entrySet()) {
|
||||
if (notFirst) {
|
||||
p.newline();
|
||||
newline();
|
||||
p.print(' ');
|
||||
p.print('*');
|
||||
}
|
||||
@@ -872,7 +1068,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
|
||||
if (!asSingleLine) {
|
||||
p.newline();
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -890,18 +1086,39 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
protected final void newlineOpt() {
|
||||
private void newlineOpt() {
|
||||
if (!p.isCompact()) {
|
||||
p.newline();
|
||||
newline();
|
||||
}
|
||||
}
|
||||
|
||||
protected void printJsBlock(JsBlock x, boolean finalNewline) {
|
||||
private void newline() {
|
||||
p.newline();
|
||||
sourceLocationConsumer.newLine();
|
||||
}
|
||||
|
||||
private void pushSourceInfo(Object location) {
|
||||
p.maybeIndent();
|
||||
sourceInfoStack.add(location);
|
||||
if (location != null) {
|
||||
sourceLocationConsumer.pushSourceInfo(location);
|
||||
}
|
||||
}
|
||||
|
||||
private void popSourceInfo() {
|
||||
if (!sourceInfoStack.isEmpty() && sourceInfoStack.remove(sourceInfoStack.size() - 1) != null) {
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
}
|
||||
|
||||
private void printJsBlock(JsBlock x, boolean finalNewline) {
|
||||
if (!lineBreakAfterBlock) {
|
||||
finalNewline = false;
|
||||
lineBreakAfterBlock = true;
|
||||
}
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
|
||||
boolean needBraces = !x.isGlobalBlock();
|
||||
if (needBraces) {
|
||||
blockOpen();
|
||||
@@ -949,7 +1166,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
newlineOpt();
|
||||
}
|
||||
else {
|
||||
p.newline();
|
||||
newline();
|
||||
}
|
||||
}
|
||||
else {
|
||||
@@ -973,6 +1190,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
}
|
||||
needSemi = false;
|
||||
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
private void assignment() {
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.backend
|
||||
|
||||
object NoOpSourceLocationConsumer : SourceLocationConsumer {
|
||||
override fun newLine() {}
|
||||
|
||||
override fun pushSourceInfo(info: Any?) {}
|
||||
|
||||
override fun popSourceInfo() {}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* Copyright 2010-2017 JetBrains s.r.o.
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.backend
|
||||
|
||||
interface SourceLocationConsumer {
|
||||
fun newLine()
|
||||
|
||||
fun pushSourceInfo(info: Any?)
|
||||
|
||||
fun popSourceInfo()
|
||||
}
|
||||
@@ -32,21 +32,7 @@ public interface TextOutput {
|
||||
|
||||
void printOpt(char c);
|
||||
|
||||
void printOpt(char[] s);
|
||||
|
||||
void printOpt(String s);
|
||||
|
||||
boolean isCompact();
|
||||
|
||||
boolean isJustNewlined();
|
||||
|
||||
void setOutListener(OutListener outListener);
|
||||
|
||||
void maybeIndent();
|
||||
|
||||
public interface OutListener {
|
||||
void newLined();
|
||||
|
||||
void indentedAfterNewLine();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,6 @@ public class TextOutputImpl implements TextOutput {
|
||||
private int line = 0;
|
||||
private int column = 0;
|
||||
|
||||
private OutListener outListener;
|
||||
|
||||
public TextOutputImpl() {
|
||||
this(false);
|
||||
}
|
||||
@@ -78,9 +76,6 @@ public class TextOutputImpl implements TextOutput {
|
||||
line++;
|
||||
column = 0;
|
||||
justNewlined = true;
|
||||
if (outListener != null) {
|
||||
outListener.newLined();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -151,9 +146,6 @@ public class TextOutputImpl implements TextOutput {
|
||||
if (justNewlined && !compact) {
|
||||
printAndCount(indents[identLevel]);
|
||||
justNewlined = false;
|
||||
if (outListener != null) {
|
||||
outListener.indentedAfterNewLine();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,9 +165,4 @@ public class TextOutputImpl implements TextOutput {
|
||||
public boolean isJustNewlined() {
|
||||
return justNewlined && !compact;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOutListener(OutListener outListener) {
|
||||
this.outListener = outListener;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user