feat(KT-51123): save comments from js-function call inside arguments list.
This commit is contained in:
@@ -173,9 +173,11 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
protected boolean insideComments = false;
|
||||
protected boolean needSemi = true;
|
||||
private boolean lineBreakAfterBlock = true;
|
||||
|
||||
|
||||
/**
|
||||
* "Global" blocks are either the global block of a fragment, or a block
|
||||
* nested directly within some other global block. This definition matters
|
||||
@@ -198,6 +200,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitArrayAccess(@NotNull JsArrayAccess x) {
|
||||
printCommentsBeforeNode(x);
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
printPair(x, x.getArrayExpression());
|
||||
@@ -205,17 +208,20 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(x.getIndexExpression());
|
||||
rightSquare();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitArray(@NotNull JsArrayLiteral x) {
|
||||
printCommentsBeforeNode(x);
|
||||
pushSourceInfo(x.getSource());
|
||||
|
||||
leftSquare();
|
||||
printExpressions(x.getExpressions());
|
||||
rightSquare();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -233,6 +239,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitBinaryExpression(@NotNull JsBinaryOperation binaryOperation) {
|
||||
printCommentsBeforeNode(binaryOperation);
|
||||
pushSourceInfo(binaryOperation.getSource());
|
||||
|
||||
JsBinaryOperator operator = binaryOperation.getOperator();
|
||||
@@ -277,6 +284,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
rightParen();
|
||||
}
|
||||
|
||||
printCommentsAfterNode(binaryOperation);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -288,6 +296,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitBoolean(@NotNull JsBooleanLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
if (x.getValue()) {
|
||||
p.print(CHARS_TRUE);
|
||||
@@ -296,26 +305,31 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
p.print(CHARS_FALSE);
|
||||
}
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitBreak(@NotNull JsBreak x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_BREAK);
|
||||
continueOrBreakLabel(x);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitContinue(@NotNull JsContinue x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_CONTINUE);
|
||||
continueOrBreakLabel(x);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -330,12 +344,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitCase(@NotNull JsCase x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_CASE);
|
||||
space();
|
||||
accept(x.getCaseExpression());
|
||||
_colon();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
newlineOpt();
|
||||
@@ -362,6 +378,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitCatch(@NotNull JsCatch x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
spaceOpt();
|
||||
p.print(CHARS_CATCH);
|
||||
@@ -382,6 +399,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
rightParen();
|
||||
spaceOpt();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
@@ -392,6 +410,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitConditional(@NotNull JsConditional x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
// Associativity: for the then and else branches, it is safe to insert
|
||||
// another
|
||||
@@ -407,6 +426,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
spaceOpt();
|
||||
printPair(x, x.getElseExpression());
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -428,19 +448,23 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitDebugger(@NotNull JsDebugger x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_DEBUGGER);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDefault(@NotNull JsDefault x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_DEFAULT);
|
||||
_colon();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
newlineOpt();
|
||||
|
||||
@@ -452,6 +476,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitWhile(@NotNull JsWhile x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
_while();
|
||||
spaceOpt();
|
||||
@@ -459,6 +484,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(x.getCondition());
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
JsStatement body = materialize(x.getBody());
|
||||
@@ -473,6 +499,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitDoWhile(@NotNull JsDoWhile x) {
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_DO);
|
||||
|
||||
@@ -499,6 +526,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(x.getCondition());
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -513,6 +541,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
source = x.getExpression().getSource();
|
||||
}
|
||||
pushSourceInfo(source);
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
boolean surroundWithParentheses = JsFirstExpressionVisitor.exec(x);
|
||||
if (surroundWithParentheses) {
|
||||
@@ -523,12 +552,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
rightParen();
|
||||
}
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitFor(@NotNull JsFor x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
_for();
|
||||
spaceOpt();
|
||||
@@ -563,6 +594,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
JsStatement body = materialize(x.getBody());
|
||||
@@ -579,6 +611,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitForIn(@NotNull JsForIn x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
_for();
|
||||
spaceOpt();
|
||||
@@ -609,6 +642,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
JsStatement body = materialize(x.getBody());
|
||||
@@ -622,12 +656,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitFunction(@NotNull JsFunction x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_FUNCTION);
|
||||
space();
|
||||
|
||||
printFunction(x);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -659,6 +695,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitClass(@NotNull JsClass x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_CLASS);
|
||||
space();
|
||||
@@ -699,12 +736,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
needSemi = false;
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitIf(@NotNull JsIf x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
_if();
|
||||
spaceOpt();
|
||||
@@ -712,6 +751,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(x.getIfExpression());
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
JsStatement thenStmt = x.getThenStatement();
|
||||
@@ -777,6 +817,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitInvocation(@NotNull JsInvocation invocation) {
|
||||
pushSourceInfo(invocation.getSource());
|
||||
printCommentsBeforeNode(invocation);
|
||||
|
||||
printPair(invocation, invocation.getQualifier());
|
||||
|
||||
@@ -784,6 +825,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
printExpressions(invocation.getArguments());
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(invocation);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -800,10 +842,15 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
|
||||
@Override
|
||||
public void visitNameRef(@NotNull JsNameRef nameRef) {
|
||||
visitNameRef(nameRef, true);
|
||||
}
|
||||
|
||||
public void visitNameRef(@NotNull JsNameRef nameRef, boolean withQualifier) {
|
||||
pushSourceInfo(nameRef.getSource());
|
||||
printCommentsBeforeNode(nameRef);
|
||||
|
||||
JsExpression qualifier = nameRef.getQualifier();
|
||||
if (qualifier != null) {
|
||||
if (qualifier != null && withQualifier) {
|
||||
boolean enclose;
|
||||
if (qualifier instanceof JsLiteral.JsValueLiteral) {
|
||||
// "42.foo" is not allowed, but "(42).foo" is.
|
||||
@@ -826,12 +873,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
p.maybeIndent();
|
||||
p.print(nameRef.getIdent());
|
||||
|
||||
printCommentsAfterNode(nameRef);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNew(@NotNull JsNew x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_NEW);
|
||||
space();
|
||||
@@ -850,39 +899,47 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
printExpressions(x.getArguments());
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitNull(@NotNull JsNullLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_NULL);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitInt(@NotNull JsIntLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(x.value);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitDouble(@NotNull JsDoubleLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(x.value);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitObjectLiteral(@NotNull JsObjectLiteral objectLiteral) {
|
||||
pushSourceInfo(objectLiteral.getSource());
|
||||
printCommentsBeforeNode(objectLiteral);
|
||||
|
||||
p.print('{');
|
||||
|
||||
@@ -908,26 +965,18 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
pushSourceInfo(item.getSource());
|
||||
|
||||
JsExpression labelExpr = item.getLabelExpr();
|
||||
// labels can be either string, integral, or decimal literals
|
||||
if (labelExpr instanceof JsNameRef) {
|
||||
p.print(((JsNameRef) labelExpr).getIdent());
|
||||
}
|
||||
else if (labelExpr instanceof JsStringLiteral) {
|
||||
|
||||
if (labelExpr instanceof JsStringLiteral) {
|
||||
JsStringLiteral stringLiteral = (JsStringLiteral) labelExpr;
|
||||
String value = stringLiteral.getValue();
|
||||
boolean isValidIdentifier = IdentifierPolicyKt.isValidES5Identifier(value);
|
||||
|
||||
if (!isValidIdentifier) {
|
||||
p.print('\'');
|
||||
}
|
||||
|
||||
p.print(value);
|
||||
|
||||
if (!isValidIdentifier) {
|
||||
p.print('\'');
|
||||
if (IdentifierPolicyKt.isValidES5Identifier(value)) {
|
||||
labelExpr = new JsNameRef(value).withMetadataFrom(stringLiteral);
|
||||
}
|
||||
}
|
||||
else {
|
||||
// labels can be either string, integral, or decimal literals
|
||||
if (labelExpr instanceof JsNameRef) {
|
||||
visitNameRef((JsNameRef) labelExpr, false);
|
||||
} else {
|
||||
accept(labelExpr);
|
||||
}
|
||||
|
||||
@@ -949,6 +998,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
|
||||
p.print('}');
|
||||
|
||||
printCommentsAfterNode(objectLiteral);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -960,6 +1011,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitPostfixOperation(@NotNull JsPostfixOperation x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
JsUnaryOperator op = x.getOperator();
|
||||
JsExpression arg = x.getArg();
|
||||
@@ -967,12 +1019,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
printPair(x, arg);
|
||||
p.print(op.getSymbol());
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitPrefixOperation(@NotNull JsPrefixOperation x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
JsUnaryOperator op = x.getOperator();
|
||||
p.print(op.getSymbol());
|
||||
@@ -983,6 +1037,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
// unary operators always associate correctly (I think)
|
||||
printPair(x, arg);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@@ -994,6 +1049,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitRegExp(@NotNull JsRegExp x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
slash();
|
||||
p.print(x.getPattern());
|
||||
@@ -1003,12 +1059,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
p.print(flags);
|
||||
}
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitReturn(@NotNull JsReturn x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_RETURN);
|
||||
JsExpression expr = x.getExpression();
|
||||
@@ -1017,21 +1075,25 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(expr);
|
||||
}
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitString(@NotNull JsStringLiteral x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(javaScriptString(x.getValue()));
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull JsSwitch x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_SWITCH);
|
||||
spaceOpt();
|
||||
@@ -1039,6 +1101,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(x.getExpression());
|
||||
rightParen();
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
|
||||
|
||||
@@ -1053,25 +1116,30 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
@Override
|
||||
public void visitThis(@NotNull JsThisRef x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_THIS);
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitThrow(@NotNull JsThrow x) {
|
||||
pushSourceInfo(x.getSource());
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
p.print(CHARS_THROW);
|
||||
space();
|
||||
accept(x.getExpression());
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitTry(@NotNull JsTry x) {
|
||||
printCommentsBeforeNode(x);
|
||||
p.print(CHARS_TRY);
|
||||
spaceOpt();
|
||||
lineBreakAfterBlock = false;
|
||||
@@ -1085,11 +1153,13 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
spaceOpt();
|
||||
accept(finallyBlock);
|
||||
}
|
||||
printCommentsAfterNode(x);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visit(@NotNull JsVar var) {
|
||||
pushSourceInfo(var.getSource());
|
||||
printCommentsBeforeNode(var);
|
||||
|
||||
nameOf(var);
|
||||
JsExpression initExpr = var.getInitExpression();
|
||||
@@ -1104,12 +1174,14 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
printCommentsAfterNode(var);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitVars(@NotNull JsVars vars) {
|
||||
pushSourceInfo(vars.getSource());
|
||||
printCommentsBeforeNode(vars);
|
||||
|
||||
var();
|
||||
space();
|
||||
@@ -1129,15 +1201,20 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
accept(var);
|
||||
}
|
||||
|
||||
printCommentsAfterNode(vars);
|
||||
popSourceInfo();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSingleLineComment(@NotNull JsSingleLineComment comment) {
|
||||
if (needSemi && insideComments) {
|
||||
semi();
|
||||
space();
|
||||
}
|
||||
p.print("//");
|
||||
p.print(comment.getText());
|
||||
needSemi = false;
|
||||
newline();
|
||||
needSemi = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1153,8 +1230,6 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
|
||||
p.print("*/");
|
||||
needSemi = false;
|
||||
newline();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -1295,6 +1370,32 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
}
|
||||
|
||||
private void printCommentsBeforeNode(JsNode x) {
|
||||
printComments(x.getCommentsBeforeNode(), false);
|
||||
}
|
||||
|
||||
private void printCommentsAfterNode(JsNode x) {
|
||||
printComments(x.getCommentsAfterNode(), true);
|
||||
}
|
||||
|
||||
private void printComments(List<JsComment> comments, boolean isAfterNode) {
|
||||
if (comments == null) return;
|
||||
|
||||
boolean previousNeedSemi = needSemi;
|
||||
needSemi = isAfterNode;
|
||||
insideComments = true;
|
||||
|
||||
for (JsComment comment : comments) {
|
||||
comment.accept(this);
|
||||
}
|
||||
|
||||
insideComments = false;
|
||||
|
||||
if (!isAfterNode) {
|
||||
needSemi = previousNeedSemi;
|
||||
}
|
||||
}
|
||||
|
||||
private void popSourceInfo() {
|
||||
if (!sourceInfoStack.isEmpty() && sourceInfoStack.remove(sourceInfoStack.size() - 1) != null) {
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
@@ -1308,6 +1409,7 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
|
||||
sourceLocationConsumer.pushSourceInfo(null);
|
||||
printCommentsBeforeNode(x);
|
||||
|
||||
boolean needBraces = !x.isTransparent();
|
||||
|
||||
@@ -1390,6 +1492,8 @@ public class JsToStringGenerationVisitor extends JsVisitor {
|
||||
}
|
||||
needSemi = false;
|
||||
|
||||
|
||||
printCommentsAfterNode(x);
|
||||
sourceLocationConsumer.popSourceInfo();
|
||||
}
|
||||
|
||||
|
||||
@@ -20,7 +20,13 @@ import org.jetbrains.kotlin.js.backend.JsToStringGenerationVisitor;
|
||||
import org.jetbrains.kotlin.js.backend.ast.metadata.HasMetadata;
|
||||
import org.jetbrains.kotlin.js.util.TextOutputImpl;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
abstract class AbstractNode extends HasMetadata implements JsNode {
|
||||
private List<JsComment> commentsBefore = null;
|
||||
private List<JsComment> commentsAfter = null;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
TextOutputImpl out = new TextOutputImpl();
|
||||
@@ -29,12 +35,34 @@ abstract class AbstractNode extends HasMetadata implements JsNode {
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
protected <T extends HasMetadata & JsNode> T withMetadataFrom(T other) {
|
||||
public <T extends HasMetadata & JsNode> T withMetadataFrom(T other) {
|
||||
this.copyMetadataFrom(other);
|
||||
Object otherSource = other.getSource();
|
||||
if (otherSource != null) {
|
||||
source(otherSource);
|
||||
}
|
||||
setCommentsBeforeNode(other.getCommentsBeforeNode());
|
||||
setCommentsAfterNode(other.getCommentsAfterNode());
|
||||
return (T) this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JsComment> getCommentsBeforeNode() {
|
||||
return commentsBefore;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<JsComment> getCommentsAfterNode() {
|
||||
return commentsAfter;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCommentsBeforeNode(List<JsComment> comments) {
|
||||
commentsBefore = comments;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setCommentsAfterNode(List<JsComment> comments) {
|
||||
commentsAfter = comments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package org.jetbrains.kotlin.js.backend.ast
|
||||
|
||||
interface JsComment : JsStatement {
|
||||
val text: String
|
||||
}
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.backend.ast
|
||||
|
||||
class JsMultiLineComment(val text: String) : SourceInfoAwareJsNode(), JsStatement {
|
||||
class JsMultiLineComment(override val text: String) : SourceInfoAwareJsNode(), JsComment {
|
||||
override fun accept(visitor: JsVisitor) {
|
||||
visitor.visitMultiLineComment(this)
|
||||
}
|
||||
|
||||
@@ -6,6 +6,9 @@ package org.jetbrains.kotlin.js.backend.ast;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public interface JsNode {
|
||||
/**
|
||||
* Causes this object to have the visitor visit itself and its children.
|
||||
@@ -40,4 +43,12 @@ public interface JsNode {
|
||||
* @param ctx the context of an existing traversal
|
||||
*/
|
||||
void traverse(JsVisitorWithContext visitor, JsContext ctx);
|
||||
|
||||
List<JsComment> getCommentsBeforeNode();
|
||||
|
||||
List<JsComment> getCommentsAfterNode();
|
||||
|
||||
void setCommentsBeforeNode(List<JsComment> comment);
|
||||
|
||||
void setCommentsAfterNode(List<JsComment> comment);
|
||||
}
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
|
||||
package org.jetbrains.kotlin.js.backend.ast
|
||||
|
||||
class JsSingleLineComment(val text: String) : SourceInfoAwareJsNode(), JsStatement {
|
||||
class JsSingleLineComment(override val text: String) : SourceInfoAwareJsNode(), JsComment {
|
||||
override fun accept(visitor: JsVisitor) {
|
||||
visitor.visitSingleLineComment(this)
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@ package com.google.gwt.dev.js;
|
||||
|
||||
import com.google.gwt.dev.js.parserExceptions.JsParserException;
|
||||
import com.google.gwt.dev.js.rhino.CodePosition;
|
||||
import com.google.gwt.dev.js.rhino.Comment;
|
||||
import com.google.gwt.dev.js.rhino.Node;
|
||||
import com.google.gwt.dev.js.rhino.TokenStream;
|
||||
import com.intellij.util.SmartList;
|
||||
@@ -25,6 +26,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.kotlin.js.backend.ast.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
|
||||
public class JsAstMapper {
|
||||
@@ -44,7 +46,18 @@ public class JsAstMapper {
|
||||
}
|
||||
|
||||
private JsNode map(Node node) throws JsParserException {
|
||||
return withLocation(mapWithoutLocation(node), node);
|
||||
return withLocation(mapWithComments(node), node);
|
||||
}
|
||||
|
||||
private JsNode mapWithComments(Node node) throws JsParserException {
|
||||
JsNode jsNode = mapWithoutLocation(node);
|
||||
|
||||
if (jsNode != null) {
|
||||
jsNode.setCommentsBeforeNode(mapComments(node.getCommentsBeforeNode()));
|
||||
jsNode.setCommentsAfterNode(mapComments(node.getCommentsAfterNode()));
|
||||
}
|
||||
|
||||
return jsNode;
|
||||
}
|
||||
|
||||
private JsNode mapWithoutLocation(Node node) throws JsParserException {
|
||||
@@ -216,12 +229,6 @@ public class JsAstMapper {
|
||||
case TokenStream.LABEL:
|
||||
return mapLabel(node);
|
||||
|
||||
case TokenStream.SINGLE_LINE_COMMENT:
|
||||
return mapSingleLineComment(node);
|
||||
|
||||
case TokenStream.MULTI_LINE_COMMENT:
|
||||
return mapMultiLineComment(node);
|
||||
|
||||
default:
|
||||
int tokenType = node.getType();
|
||||
throw createParserException("Unexpected top-level token type: "
|
||||
@@ -1139,4 +1146,19 @@ public class JsAstMapper {
|
||||
}
|
||||
return astNode;
|
||||
}
|
||||
|
||||
private List<JsComment> mapComments(Comment comment) {
|
||||
if (comment == null) return null;
|
||||
|
||||
List<JsComment> comments = new LinkedList<>();
|
||||
|
||||
while (comment != null) {
|
||||
String text = comment.getText();
|
||||
JsComment jsComment = comment.isMultiLine() ? new JsMultiLineComment(text) : new JsSingleLineComment(text);
|
||||
comments.add(jsComment);
|
||||
comment = comment.getNext();
|
||||
}
|
||||
|
||||
return comments;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
/*
|
||||
* Copyright 2010-2022 JetBrains s.r.o. and Kotlin Programming Language contributors.
|
||||
* Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file.
|
||||
*/
|
||||
|
||||
package com.google.gwt.dev.js.rhino
|
||||
|
||||
class Comment(val text: String, val isMultiLine: Boolean) {
|
||||
var next: Comment? = null;
|
||||
}
|
||||
@@ -331,14 +331,6 @@ public class IRFactory {
|
||||
return new Node(nodeType, left, right, nodeOp, location);
|
||||
}
|
||||
|
||||
public Node createSingleLineComment(String string, CodePosition position) {
|
||||
return Node.newComment(TokenStream.SINGLE_LINE_COMMENT, string, position);
|
||||
}
|
||||
|
||||
public Node createMultiLineComment(String string, CodePosition position) {
|
||||
return Node.newComment(TokenStream.MULTI_LINE_COMMENT, string, position);
|
||||
}
|
||||
|
||||
public Node createAssignment(int nodeOp, Node left, Node right, CodePosition location) {
|
||||
int nodeType = left.getType();
|
||||
switch (nodeType) {
|
||||
|
||||
@@ -90,37 +90,6 @@ public class Node implements Cloneable {
|
||||
private String str;
|
||||
}
|
||||
|
||||
private static class CommentNode extends Node {
|
||||
CommentNode(int type, String str, CodePosition position) {
|
||||
super(type, position);
|
||||
if (null == str) {
|
||||
throw new IllegalArgumentException("CommentNode: str is null");
|
||||
}
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
/** returns the string content.
|
||||
* @return non null.
|
||||
*/
|
||||
@Override
|
||||
public String getString() {
|
||||
return this.str;
|
||||
}
|
||||
|
||||
/** sets the string content.
|
||||
* @param str the new value. Non null.
|
||||
*/
|
||||
@Override
|
||||
public void setString(String str) {
|
||||
if (null == str) {
|
||||
throw new IllegalArgumentException("CommentNode: str is null");
|
||||
}
|
||||
this.str = str;
|
||||
}
|
||||
|
||||
private String str;
|
||||
}
|
||||
|
||||
public Node(int nodeType) {
|
||||
type = nodeType;
|
||||
}
|
||||
@@ -222,10 +191,6 @@ public class Node implements Cloneable {
|
||||
return new StringNode(type, str, position);
|
||||
}
|
||||
|
||||
public static Node newComment(int type, String str, CodePosition position) {
|
||||
return new CommentNode(type, str, position);
|
||||
}
|
||||
|
||||
public int getType() {
|
||||
return type;
|
||||
}
|
||||
@@ -278,6 +243,24 @@ public class Node implements Cloneable {
|
||||
}
|
||||
}
|
||||
|
||||
public Comment getCommentsBeforeNode() {
|
||||
return commentBefore;
|
||||
}
|
||||
|
||||
public Comment getCommentsAfterNode() {
|
||||
return commentAfter;
|
||||
}
|
||||
|
||||
public void setCommentsBeforeNode(Comment comment) {
|
||||
if (comment == null) return;
|
||||
commentBefore = comment;
|
||||
}
|
||||
|
||||
public void setCommentsAfterNode(Comment comment) {
|
||||
if (comment == null) return;
|
||||
commentAfter = comment;
|
||||
}
|
||||
|
||||
public static final int
|
||||
TARGET_PROP = 1,
|
||||
BREAK_PROP = 2,
|
||||
@@ -441,5 +424,9 @@ public class Node implements Cloneable {
|
||||
private Node first; // first element of a linked list of children
|
||||
private Node last; // last element of a linked list of children
|
||||
private CodePosition position;
|
||||
|
||||
private Comment commentBefore;
|
||||
|
||||
private Comment commentAfter;
|
||||
private int operation;
|
||||
}
|
||||
|
||||
@@ -110,7 +110,7 @@ public class Parser {
|
||||
|
||||
while (true) {
|
||||
ts.flags |= TokenStream.TSF_REGEXP;
|
||||
tt = ts.getTokenWithComment();
|
||||
tt = ts.getToken();
|
||||
ts.flags &= ~TokenStream.TSF_REGEXP;
|
||||
|
||||
if (tt <= TokenStream.EOF) {
|
||||
@@ -153,7 +153,7 @@ public class Parser {
|
||||
Node pn = nf.createBlock(ts.tokenPosition);
|
||||
try {
|
||||
int tt;
|
||||
while ((tt = ts.peekTokenWithComment()) > TokenStream.EOF && tt != TokenStream.RC) {
|
||||
while ((tt = ts.peekToken()) > TokenStream.EOF && tt != TokenStream.RC) {
|
||||
if (tt == TokenStream.FUNCTION) {
|
||||
ts.getToken();
|
||||
pn.addChildToBack(function(ts, false));
|
||||
@@ -334,7 +334,13 @@ public class Parser {
|
||||
private Node statement(TokenStream ts) throws IOException {
|
||||
CodePosition position = ts.lastPosition;
|
||||
try {
|
||||
return statementHelper(ts);
|
||||
Comment commentsBefore = getComments(ts);
|
||||
ts.collectCommentsAfter();
|
||||
Node result = statementHelper(ts);
|
||||
result.setCommentsBeforeNode(commentsBefore);
|
||||
ts.collectCommentsAfter();
|
||||
result.setCommentsAfterNode(getComments(ts));
|
||||
return result;
|
||||
}
|
||||
catch (JavaScriptException e) {
|
||||
// skip to end of statement
|
||||
@@ -360,7 +366,7 @@ public class Parser {
|
||||
|
||||
int lastExprType; // For wellTerminated
|
||||
|
||||
tt = ts.getTokenWithComment();
|
||||
tt = ts.getToken();
|
||||
CodePosition position = ts.tokenPosition;
|
||||
|
||||
switch (tt) {
|
||||
@@ -594,14 +600,6 @@ public class Parser {
|
||||
break;
|
||||
}
|
||||
|
||||
case TokenStream.SINGLE_LINE_COMMENT:
|
||||
pn = nf.createSingleLineComment(ts.getString(), ts.tokenPosition);
|
||||
break;
|
||||
|
||||
case TokenStream.MULTI_LINE_COMMENT:
|
||||
pn = nf.createMultiLineComment(ts.getString(), ts.tokenPosition);
|
||||
break;
|
||||
|
||||
case TokenStream.RETURN: {
|
||||
Node retExpr = null;
|
||||
int lineno;
|
||||
@@ -703,9 +701,7 @@ public class Parser {
|
||||
}
|
||||
}
|
||||
|
||||
if (pn.type != TokenStream.SINGLE_LINE_COMMENT && pn.type != TokenStream.MULTI_LINE_COMMENT) {
|
||||
ts.matchToken(TokenStream.SEMI);
|
||||
}
|
||||
ts.matchToken(TokenStream.SEMI);
|
||||
|
||||
return pn;
|
||||
}
|
||||
@@ -740,22 +736,32 @@ public class Parser {
|
||||
|
||||
public Node expr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException {
|
||||
Node pn = assignExpr(ts, inForInit);
|
||||
|
||||
|
||||
while (ts.matchToken(TokenStream.COMMA)) {
|
||||
CodePosition position = ts.tokenPosition;
|
||||
pn = nf.createBinary(TokenStream.COMMA, pn, assignExpr(ts, inForInit), position);
|
||||
}
|
||||
|
||||
return pn;
|
||||
}
|
||||
|
||||
private Node assignExpr(TokenStream ts, boolean inForInit) throws IOException, JavaScriptException {
|
||||
Comment commentBeforeNode = getComments(ts);
|
||||
|
||||
Node pn = condExpr(ts, inForInit);
|
||||
|
||||
pn.setCommentsBeforeNode(commentBeforeNode);
|
||||
|
||||
if (ts.matchToken(TokenStream.ASSIGN)) {
|
||||
// omitted: "invalid assignment left-hand side" check.
|
||||
CodePosition position = ts.tokenPosition;
|
||||
pn = nf.createBinary(TokenStream.ASSIGN, ts.getOp(), pn, assignExpr(ts, inForInit), position);
|
||||
}
|
||||
|
||||
ts.collectCommentsAfter();
|
||||
pn.setCommentsAfterNode(getComments(ts));
|
||||
|
||||
return pn;
|
||||
}
|
||||
|
||||
@@ -952,8 +958,7 @@ public class Parser {
|
||||
if (!matched) {
|
||||
do {
|
||||
listNode.addChildToBack(assignExpr(ts, false));
|
||||
}
|
||||
while (ts.matchToken(TokenStream.COMMA));
|
||||
} while (ts.matchToken(TokenStream.COMMA));
|
||||
|
||||
mustMatchToken(ts, TokenStream.GWT, "msg.no.paren.arg");
|
||||
}
|
||||
@@ -1012,7 +1017,7 @@ public class Parser {
|
||||
) throws IOException, JavaScriptException {
|
||||
lastExprEndLine = ts.getLineno();
|
||||
int tt;
|
||||
while ((tt = ts.getTokenWithComment()) > TokenStream.EOF) {
|
||||
while ((tt = ts.getToken()) > TokenStream.EOF) {
|
||||
CodePosition position = ts.tokenPosition;
|
||||
if (tt == TokenStream.DOT) {
|
||||
ts.treatKeywordAsIdentifier = true;
|
||||
@@ -1050,6 +1055,15 @@ public class Parser {
|
||||
}
|
||||
|
||||
public Node primaryExpr(TokenStream ts) throws IOException, JavaScriptException {
|
||||
Comment commentsBeforeNode = getComments(ts);
|
||||
Node node = primaryExprHelper(ts);
|
||||
node.setCommentsBeforeNode(commentsBeforeNode);
|
||||
ts.collectCommentsAfter();
|
||||
node.setCommentsAfterNode(getComments(ts));
|
||||
return node;
|
||||
}
|
||||
|
||||
private Node primaryExprHelper(TokenStream ts) throws IOException, JavaScriptException {
|
||||
int tt;
|
||||
|
||||
Node pn;
|
||||
@@ -1195,6 +1209,14 @@ public class Parser {
|
||||
return null; // should never reach here
|
||||
}
|
||||
|
||||
private Comment getComments(TokenStream ts) {
|
||||
Comment comment = ts.getHeadComment();
|
||||
if (comment != null) {
|
||||
ts.releaseComments();
|
||||
}
|
||||
return comment;
|
||||
}
|
||||
|
||||
private int lastExprEndLine; // Hack to handle function expr termination.
|
||||
private final IRFactory nf;
|
||||
private boolean ok; // Did the parse encounter an error?
|
||||
|
||||
@@ -253,8 +253,6 @@ public class TokenStream {
|
||||
|
||||
LAST_TOKEN = 147,
|
||||
NUMBER_INT = 148,
|
||||
SINGLE_LINE_COMMENT = 149,
|
||||
MULTI_LINE_COMMENT = 150,
|
||||
|
||||
// This value is only used as a return value for getTokenHelper,
|
||||
// which is only called from getToken and exists to avoid an excessive
|
||||
@@ -415,8 +413,6 @@ public class TokenStream {
|
||||
case NEWLOCAL: return "newlocal";
|
||||
case USELOCAL: return "uselocal";
|
||||
case SCRIPT: return "script";
|
||||
case SINGLE_LINE_COMMENT: return "singlelinecomment";
|
||||
case MULTI_LINE_COMMENT: return "multilinecomment";
|
||||
}
|
||||
return "<unknown="+token+">";
|
||||
}
|
||||
@@ -539,10 +535,6 @@ public class TokenStream {
|
||||
return peekTokenHelper(getToken());
|
||||
}
|
||||
|
||||
public int peekTokenWithComment() throws IOException {
|
||||
return peekTokenHelper(getTokenWithComment());
|
||||
}
|
||||
|
||||
private int peekTokenHelper(int token) throws IOException {
|
||||
this.pushbackToken = token;
|
||||
lastPosition = secondToLastPosition;
|
||||
@@ -596,15 +588,8 @@ public class TokenStream {
|
||||
in.unread();
|
||||
}
|
||||
|
||||
public int getTokenWithComment() throws IOException {
|
||||
lastTokenPosition = tokenPosition;
|
||||
int c;
|
||||
do {
|
||||
c = getTokenHelper();
|
||||
} while (c == RETRY_TOKEN);
|
||||
|
||||
updatePosition();
|
||||
return c;
|
||||
public void collectCommentsAfter() throws IOException {
|
||||
ungetToken(getToken());
|
||||
}
|
||||
|
||||
public int getToken() throws IOException {
|
||||
@@ -612,7 +597,7 @@ public class TokenStream {
|
||||
int c;
|
||||
do {
|
||||
c = getTokenHelper();
|
||||
} while (c == RETRY_TOKEN || c == SINGLE_LINE_COMMENT || c == MULTI_LINE_COMMENT);
|
||||
} while (c == RETRY_TOKEN);
|
||||
|
||||
updatePosition();
|
||||
return c;
|
||||
@@ -1084,8 +1069,8 @@ public class TokenStream {
|
||||
while ((c = in.read()) != -1 && c != '\n') {
|
||||
addToString(c);
|
||||
}
|
||||
this.string = getStringFromBuffer();
|
||||
return SINGLE_LINE_COMMENT;
|
||||
addCommentToQueue(new Comment(getStringFromBuffer(), false));
|
||||
return RETRY_TOKEN;
|
||||
}
|
||||
if (in.match('*')) {
|
||||
stringBufferTop = 0;
|
||||
@@ -1097,8 +1082,8 @@ public class TokenStream {
|
||||
reportTokenError("msg.unterminated.comment", null);
|
||||
return ERROR;
|
||||
}
|
||||
this.string = getStringFromBuffer();
|
||||
return MULTI_LINE_COMMENT; // `goto retry'
|
||||
addCommentToQueue(new Comment(getStringFromBuffer(), true));
|
||||
return RETRY_TOKEN; // `goto retry'
|
||||
}
|
||||
|
||||
// is it a regexp?
|
||||
@@ -1481,6 +1466,17 @@ public class TokenStream {
|
||||
}
|
||||
}
|
||||
|
||||
private void addCommentToQueue(Comment comment) {
|
||||
if (headComment == null) {
|
||||
headComment = comment;
|
||||
lastComment = comment;
|
||||
}
|
||||
else {
|
||||
lastComment.setNext(comment);
|
||||
lastComment = comment;
|
||||
}
|
||||
}
|
||||
|
||||
public String getSourceName() { return sourceName; }
|
||||
public int getLineno() { return in.getLineno(); }
|
||||
public int getOp() { return op; }
|
||||
@@ -1491,6 +1487,15 @@ public class TokenStream {
|
||||
public int getTokenno() { return tokenno; }
|
||||
public boolean eof() { return in.eof(); }
|
||||
|
||||
public Comment getHeadComment() {
|
||||
return headComment;
|
||||
}
|
||||
|
||||
public void releaseComments() {
|
||||
headComment = null;
|
||||
lastComment = null;
|
||||
}
|
||||
|
||||
// instance variables
|
||||
private LineBuffer in;
|
||||
|
||||
@@ -1511,6 +1516,9 @@ public class TokenStream {
|
||||
CodePosition tokenPosition;
|
||||
CodePosition lastTokenPosition;
|
||||
|
||||
private Comment headComment;
|
||||
private Comment lastComment;
|
||||
|
||||
private int op;
|
||||
public boolean treatKeywordAsIdentifier;
|
||||
|
||||
|
||||
@@ -47,6 +47,8 @@ message Expression {
|
||||
optional bool synthetic = 3 [default = false];
|
||||
optional SideEffects side_effects = 4 [default = AFFECTS_STATE];
|
||||
optional JsImportedModule local_alias = 5;
|
||||
repeated Comment before_comments = 6;
|
||||
repeated Comment after_comments = 7;
|
||||
|
||||
oneof expression {
|
||||
int32 simple_name_reference = 22;
|
||||
@@ -128,6 +130,11 @@ message DocCommentTag {
|
||||
}
|
||||
}
|
||||
|
||||
message Comment {
|
||||
required string text = 1;
|
||||
required bool multiline = 2;
|
||||
}
|
||||
|
||||
message BinaryOperation {
|
||||
required Expression left = 1;
|
||||
required Expression right = 2;
|
||||
@@ -233,6 +240,8 @@ message Statement {
|
||||
optional int32 fileId = 1;
|
||||
optional Location location = 2;
|
||||
optional bool synthetic = 3 [default = false];
|
||||
repeated Comment before_comments = 4;
|
||||
repeated Comment after_comments = 5;
|
||||
|
||||
oneof statement {
|
||||
Return return_statement = 21;
|
||||
|
||||
+34
-2
@@ -28,7 +28,19 @@ abstract class JsAstDeserializerBase {
|
||||
return statement
|
||||
}
|
||||
|
||||
protected fun deserializeNoMetadata(proto: JsAstProtoBuf.Statement): JsStatement = when (proto.statementCase) {
|
||||
protected fun deserializeNoMetadata(proto: JsAstProtoBuf.Statement): JsStatement {
|
||||
return deserializeNoMetadataHelper(proto).apply {
|
||||
if (proto.beforeCommentsCount != 0) {
|
||||
commentsBeforeNode = proto.beforeCommentsList.map(::deserializeComment)
|
||||
}
|
||||
|
||||
if (proto.afterCommentsCount != 0) {
|
||||
commentsAfterNode = proto.afterCommentsList.map(::deserializeComment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun deserializeNoMetadataHelper(proto: JsAstProtoBuf.Statement): JsStatement = when (proto.statementCase) {
|
||||
JsAstProtoBuf.Statement.StatementCase.RETURN_STATEMENT -> {
|
||||
val returnProto = proto.returnStatement
|
||||
JsReturn(if (returnProto.hasValue()) deserialize(returnProto.value) else null)
|
||||
@@ -192,7 +204,19 @@ abstract class JsAstDeserializerBase {
|
||||
)
|
||||
}
|
||||
|
||||
protected fun deserializeNoMetadata(proto: JsAstProtoBuf.Expression): JsExpression = when (proto.expressionCase) {
|
||||
protected fun deserializeNoMetadata(proto: JsAstProtoBuf.Expression): JsExpression {
|
||||
return deserializeNoMetadataHelper(proto).apply {
|
||||
if (proto.beforeCommentsCount != 0) {
|
||||
commentsBeforeNode = proto.beforeCommentsList.map(::deserializeComment)
|
||||
}
|
||||
|
||||
if (proto.afterCommentsCount != 0) {
|
||||
commentsAfterNode = proto.afterCommentsList.map(::deserializeComment)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected fun deserializeNoMetadataHelper(proto: JsAstProtoBuf.Expression): JsExpression = when (proto.expressionCase) {
|
||||
JsAstProtoBuf.Expression.ExpressionCase.THIS_LITERAL -> JsThisRef()
|
||||
JsAstProtoBuf.Expression.ExpressionCase.NULL_LITERAL -> JsNullLiteral()
|
||||
JsAstProtoBuf.Expression.ExpressionCase.TRUE_LITERAL -> JsBooleanLiteral(true)
|
||||
@@ -480,5 +504,13 @@ abstract class JsAstDeserializerBase {
|
||||
return node
|
||||
}
|
||||
|
||||
protected fun deserializeComment(comment: JsAstProtoBuf.Comment): JsComment {
|
||||
return if (comment.multiline) {
|
||||
JsMultiLineComment(comment.text)
|
||||
} else {
|
||||
JsSingleLineComment(comment.text)
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract fun embedSources(deserializedLocation: JsLocation, file: String): JsLocationWithSource?
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
+31
-4
@@ -174,8 +174,10 @@ abstract class JsAstSerializerBase {
|
||||
}
|
||||
}
|
||||
|
||||
withLocation(statement, { visitor.builder.fileId = it }, { visitor.builder.location = it }) {
|
||||
statement.accept(visitor)
|
||||
withComments(statement, { visitor.builder.addBeforeComments(it) }, { visitor.builder.addAfterComments(it) }) {
|
||||
withLocation(statement, { visitor.builder.fileId = it }, { visitor.builder.location = it }) {
|
||||
statement.accept(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
if (statement is HasMetadata && statement.synthetic) {
|
||||
@@ -348,8 +350,10 @@ abstract class JsAstSerializerBase {
|
||||
}
|
||||
}
|
||||
|
||||
withLocation(expression, { visitor.builder.fileId = it }, { visitor.builder.location = it }) {
|
||||
expression.accept(visitor)
|
||||
withComments(expression, { visitor.builder.addBeforeComments(it) }, { visitor.builder.addAfterComments(it) }) {
|
||||
withLocation(expression, { visitor.builder.fileId = it }, { visitor.builder.location = it }) {
|
||||
expression.accept(visitor)
|
||||
}
|
||||
}
|
||||
|
||||
with(visitor.builder) {
|
||||
@@ -522,6 +526,18 @@ abstract class JsAstSerializerBase {
|
||||
result
|
||||
}
|
||||
|
||||
protected fun serialize(comment: JsComment): JsAstProtoBuf.Comment {
|
||||
val builder = JsAstProtoBuf.Comment.newBuilder().apply {
|
||||
text = comment.text
|
||||
multiline = when (comment) {
|
||||
is JsSingleLineComment -> false
|
||||
is JsMultiLineComment -> true
|
||||
else -> error("Unknown type of comment ${comment.javaClass.name}")
|
||||
}
|
||||
}
|
||||
return builder.build()
|
||||
}
|
||||
|
||||
private inline fun withLocation(node: JsNode, fileConsumer: (Int) -> Unit, locationConsumer: (JsAstProtoBuf.Location) -> Unit, inner: () -> Unit) {
|
||||
val location = extractLocation(node)
|
||||
var fileChanged = false
|
||||
@@ -546,5 +562,16 @@ abstract class JsAstSerializerBase {
|
||||
}
|
||||
}
|
||||
|
||||
private inline fun withComments(
|
||||
node: JsNode,
|
||||
beforeCommentsConsumer: (JsAstProtoBuf.Comment) -> Unit,
|
||||
afterCommentsConsumer: (JsAstProtoBuf.Comment) -> Unit,
|
||||
inner: () -> Unit
|
||||
) {
|
||||
node.commentsBeforeNode?.forEach { beforeCommentsConsumer(serialize(it))}
|
||||
node.commentsAfterNode?.forEach { afterCommentsConsumer(serialize(it))}
|
||||
inner()
|
||||
}
|
||||
|
||||
abstract fun extractLocation(node: JsNode): JsLocation?
|
||||
}
|
||||
@@ -184,6 +184,10 @@ public class DirectiveTestUtils {
|
||||
this.isElementExists = isElementExists;
|
||||
}
|
||||
|
||||
protected boolean isElementExists() {
|
||||
return isElementExists;
|
||||
}
|
||||
|
||||
@Override
|
||||
void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception {
|
||||
loadArguments(arguments);
|
||||
@@ -306,26 +310,41 @@ public class DirectiveTestUtils {
|
||||
|
||||
@Override
|
||||
protected JsVisitor getJsVisitorForElement() {
|
||||
return isMultiLine ? new RecursiveJsVisitor() {
|
||||
return new RecursiveJsVisitor() {
|
||||
@Override
|
||||
public void visitMultiLineComment(@NotNull JsMultiLineComment comment) {
|
||||
if (isTheSameText(comment.getText(), text)) {
|
||||
setElementExists(true);
|
||||
protected void visitElement(@NotNull JsNode node) {
|
||||
checkCommentExistsIn(node.getCommentsBeforeNode());
|
||||
checkCommentExistsIn(node.getCommentsAfterNode());
|
||||
super.visitElement(node);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitSingleLineComment(JsSingleLineComment comment) {
|
||||
checkCommentExistsIn(Arrays.asList(comment));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void visitMultiLineComment(JsMultiLineComment comment) {
|
||||
checkCommentExistsIn(Arrays.asList(comment));
|
||||
}
|
||||
private void checkCommentExistsIn(List<JsComment> comments) {
|
||||
if (comments == null) return;
|
||||
for (JsComment comment : comments) {
|
||||
if (isNeededCommentType(comment) && isTheSameText(comment.getText(), text)) {
|
||||
setElementExists(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
} : new RecursiveJsVisitor() {
|
||||
@Override
|
||||
public void visitSingleLineComment(@NotNull JsSingleLineComment comment) {
|
||||
if (isTheSameText(comment.getText(), text)) {
|
||||
setElementExists(true);
|
||||
}
|
||||
|
||||
private boolean isNeededCommentType(JsComment comment) {
|
||||
return isMultiLine ? comment instanceof JsMultiLineComment : comment instanceof JsSingleLineComment;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadArguments(@NotNull ArgumentsHelper arguments) {
|
||||
this.text = arguments.findNamedArgument("text").replace("\\n", System.lineSeparator());
|
||||
this.text = arguments.findNamedArgument("text").replace("\\n", System.lineSeparator());;
|
||||
this.isMultiLine = Boolean.parseBoolean(arguments.findNamedArgument("multiline"));
|
||||
}
|
||||
|
||||
@@ -338,44 +357,10 @@ public class DirectiveTestUtils {
|
||||
for (int i = 0; i < lines1.size(); i++) {
|
||||
if (!lines1.get(i).trim().equals(lines2.get(i).trim())) return false;
|
||||
}
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler CHECK_COMMENT_DOESNT_EXIST = new NodeExistenceDirective("CHECK_COMMENT_DOESNT_EXIST", false) {
|
||||
private String text;
|
||||
private boolean isMultiLine;
|
||||
|
||||
@Override
|
||||
protected String getTextForError() {
|
||||
return (isMultiLine ? "Multi line" : "Single line") + " comment with text '" + text + "' exists, but it should not";
|
||||
}
|
||||
|
||||
@Override
|
||||
protected JsVisitor getJsVisitorForElement() {
|
||||
return isMultiLine ? new RecursiveJsVisitor() {
|
||||
@Override
|
||||
public void visitMultiLineComment(@NotNull JsMultiLineComment comment) {
|
||||
if (comment.getText().trim() == text) {
|
||||
setElementExists(true);
|
||||
}
|
||||
}
|
||||
} : new RecursiveJsVisitor() {
|
||||
@Override
|
||||
public void visitSingleLineComment(@NotNull JsSingleLineComment comment) {
|
||||
if (comment.getText().trim() == text) {
|
||||
setElementExists(true);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void loadArguments(@NotNull ArgumentsHelper arguments) {
|
||||
this.text = arguments.findNamedArgument("text");
|
||||
this.isMultiLine = Boolean.parseBoolean(arguments.findNamedArgument("multiline"));
|
||||
}
|
||||
};
|
||||
|
||||
private static final DirectiveHandler ONLY_THIS_QUALIFIED_REFERENCES = new DirectiveHandler("ONLY_THIS_QUALIFIED_REFERENCES") {
|
||||
@@ -496,7 +481,6 @@ public class DirectiveTestUtils {
|
||||
FUNCTIONS_HAVE_SAME_LINES,
|
||||
ONLY_THIS_QUALIFIED_REFERENCES,
|
||||
CHECK_COMMENT_EXISTS,
|
||||
CHECK_COMMENT_DOESNT_EXIST,
|
||||
COUNT_LABELS,
|
||||
COUNT_VARS,
|
||||
COUNT_BREAKS,
|
||||
|
||||
+33
-5
@@ -9,13 +9,28 @@
|
||||
// CHECK_COMMENT_EXISTS: text="After call single line comment" multiline=false
|
||||
// CHECK_COMMENT_EXISTS: text="After call multi line comment" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="The header multiline\ncomment" multiline=true
|
||||
// CHECK_COMMENT_DOESNT_EXIST: text="random position comment 1" multiline=true
|
||||
// CHECK_COMMENT_DOESNT_EXIST: text="random position comment 2" multiline=true
|
||||
// CHECK_COMMENT_DOESNT_EXIST: text="random position comment 3" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="1Multi line comment\n" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="2Multi line comment\n\n\n" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="3Multi line\n\n\n\n\ncomment\n" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="Multi line comment inside function" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="After call single line comment" multiline=false
|
||||
// CHECK_COMMENT_EXISTS: text="After call multi line comment" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="Before argument 1" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="Before argument 2" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="After argument 1" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="After argument 2" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="object:" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="property:" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="descriptor:" multiline=true
|
||||
// CHECK_COMMENT_EXISTS: text="Descriptor end" multiline=true
|
||||
|
||||
/*
|
||||
* java.lang.AssertionError(Multi line comment with text 'The header multiline\ncomment' doesn't exist)
|
||||
java.lang.AssertionError(Multi line comment with text '1Multi line comment\n' doesn't exist)
|
||||
java.lang.AssertionError(Multi line comment with text '2Multi line comment\n\n\n' doesn't exist)
|
||||
java.lang.AssertionError(Multi line comment with text '3Multi line\n\n\n\n\ncomment\n' doesn't exist)
|
||||
* */
|
||||
|
||||
package foo
|
||||
|
||||
@@ -42,8 +57,6 @@ fun box(): String {
|
||||
|
||||
foo(); /* After call multi line comment */
|
||||
|
||||
var /*random position comment 1*/ c /*random position comment 2*/ = /*random position comment 3*/ "Random position";
|
||||
|
||||
/* 1Multi line comment
|
||||
*/
|
||||
foo();
|
||||
@@ -63,6 +76,21 @@ fun box(): String {
|
||||
|
||||
/**/
|
||||
foo();
|
||||
|
||||
foo(
|
||||
/* Before argument 1 */
|
||||
/* Before argument 2 */
|
||||
4
|
||||
/* After argument 1 */
|
||||
/* After argument 2 */
|
||||
);
|
||||
|
||||
var test = {
|
||||
test: Object.defineProperty(/* object: */{}, /* property: */'some_property', /* descriptor: */ {
|
||||
value: 42,
|
||||
writable: false
|
||||
} /* Descriptor end */)
|
||||
}
|
||||
""")
|
||||
return "OK"
|
||||
}
|
||||
-1
@@ -1,5 +1,4 @@
|
||||
function test(n) {
|
||||
/*synthetic*/
|
||||
return n >= 0 ? n : -n;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user