diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt index c1dd2aee108..45a2c20dbe3 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/lower/JsCodeOutliningLowering.kt @@ -163,7 +163,7 @@ private class JsCodeOutlineTransformer( } // Building JS Ast function - val lastStatement = jsStatements.last() + val lastStatement = jsStatements.findLast { it !is JsSingleLineComment && it !is JsMultiLineComment } val newStatements = jsStatements.toMutableList() when (lastStatement) { is JsReturn -> { diff --git a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt index 920ff1da4a4..de7ecb1ec73 100644 --- a/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt +++ b/compiler/ir/backend.js/src/org/jetbrains/kotlin/ir/backend/js/transformers/irToJs/JsCallTransformer.kt @@ -31,14 +31,14 @@ class JsCallTransformer(private val jsOrJsFuncCall: IrCall, private val context: 0 -> JsEmpty 1 -> newStatements.single().withSource(jsOrJsFuncCall, context) // TODO: use transparent block (e.g. JsCompositeBlock) - else -> JsBlock(newStatements) + else -> JsGlobalBlock().apply { statements += newStatements } } } fun generateExpression(): JsExpression { if (statements.isEmpty()) return JsPrefixOperation(JsUnaryOperator.VOID, JsIntLiteral(3)) // TODO: report warning or even error - val lastStatement = statements.last() + val lastStatement = statements.findLast { it !is JsSingleLineComment && it !is JsMultiLineComment } val lastExpression = when (lastStatement) { is JsReturn -> lastStatement.expression is JsExpressionStatement -> lastStatement.expression diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java index b8a603f3f7d..2d56153cf7f 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/JsToStringGenerationVisitor.java @@ -1138,6 +1138,15 @@ public class JsToStringGenerationVisitor extends JsVisitor { newline(); } + @Override + public void visitMultiLineComment(@NotNull JsMultiLineComment comment) { + p.print("/*"); + p.print(comment.getText()); + p.print("*/"); + needSemi = false; + newline(); + } + @Override public void visitDocComment(@NotNull JsDocComment comment) { boolean asSingleLine = comment.getTags().size() == 1; diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsMultiLineComment.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsMultiLineComment.kt new file mode 100644 index 00000000000..12a7496f511 --- /dev/null +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsMultiLineComment.kt @@ -0,0 +1,22 @@ +/* + * Copyright 2010-2019 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 + +class JsMultiLineComment(val text: String) : SourceInfoAwareJsNode(), JsStatement { + override fun accept(visitor: JsVisitor) { + visitor.visitMultiLineComment(this) + } + + override fun acceptChildren(visitor: JsVisitor) { + } + + override fun traverse(visitor: JsVisitorWithContext, ctx: JsContext<*>) { + visitor.visit(this, ctx) + visitor.endVisit(this, ctx) + } + + override fun deepCopy() = this +} \ No newline at end of file diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt index 856175537fb..32bf16690a9 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitor.kt @@ -165,6 +165,9 @@ abstract class JsVisitor { open fun visitSingleLineComment(comment: JsSingleLineComment): Unit = visitElement(comment) + open fun visitMultiLineComment(comment: JsMultiLineComment): Unit = + visitElement(comment) + open fun visitExport(export: JsExport): Unit = visitElement(export) diff --git a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java index 955c38e86fd..049aea8faef 100644 --- a/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java +++ b/js/js.ast/src/org/jetbrains/kotlin/js/backend/ast/JsVisitorWithContext.java @@ -214,6 +214,9 @@ public abstract class JsVisitorWithContext { public void endVisit(@NotNull JsSingleLineComment x, @NotNull JsContext ctx) { } + public void endVisit(@NotNull JsMultiLineComment x, @NotNull JsContext ctx) { + } + public void endVisit(@NotNull JsExport x, @NotNull JsContext ctx) { } @@ -404,6 +407,10 @@ public abstract class JsVisitorWithContext { return true; } + public boolean visit(@NotNull JsMultiLineComment x, @NotNull JsContext ctx) { + return true; + } + public boolean visit(@NotNull JsExport x, @NotNull JsContext ctx) { return true; } diff --git a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java index fac1ca8ec13..85e51ab9361 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java +++ b/js/js.parser/src/com/google/gwt/dev/js/JsAstMapper.java @@ -216,6 +216,12 @@ 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: " @@ -1096,6 +1102,14 @@ public class JsAstMapper { return toVars; } + private JsSingleLineComment mapSingleLineComment(Node node) { + return new JsSingleLineComment(node.getString()); + } + + private JsMultiLineComment mapMultiLineComment(Node node) { + return new JsMultiLineComment(node.getString()); + } + private JsNode mapWithStatement(Node withNode) throws JsParserException { // The "with" statement is unsupported because it introduces ambiguity // related to whether or not a name is obfuscatable that we cannot resolve diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java index 1ab1de0aff1..31ff4c9d459 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/IRFactory.java @@ -331,6 +331,14 @@ 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) { diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java index faeb0c66e0a..587855daf95 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Node.java @@ -90,6 +90,37 @@ 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; } @@ -191,6 +222,10 @@ 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; } diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java index ace1c7d6c1e..9ada1f7a2fc 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/Parser.java @@ -110,7 +110,7 @@ public class Parser { while (true) { ts.flags |= TokenStream.TSF_REGEXP; - tt = ts.getToken(); + tt = ts.getTokenWithComment(); ts.flags &= ~TokenStream.TSF_REGEXP; if (tt <= TokenStream.EOF) { @@ -360,7 +360,7 @@ public class Parser { int lastExprType; // For wellTerminated - tt = ts.getToken(); + tt = ts.getTokenWithComment(); CodePosition position = ts.tokenPosition; switch (tt) { @@ -593,6 +593,15 @@ 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; @@ -1000,7 +1009,7 @@ public class Parser { ) throws IOException, JavaScriptException { lastExprEndLine = ts.getLineno(); int tt; - while ((tt = ts.getToken()) > TokenStream.EOF) { + while ((tt = ts.getTokenWithComment()) > TokenStream.EOF) { CodePosition position = ts.tokenPosition; if (tt == TokenStream.DOT) { ts.treatKeywordAsIdentifier = true; diff --git a/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java b/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java index 017f05b0b20..7b628a1b80a 100644 --- a/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java +++ b/js/js.parser/src/com/google/gwt/dev/js/rhino/TokenStream.java @@ -40,6 +40,7 @@ package com.google.gwt.dev.js.rhino; import java.io.*; import java.util.HashMap; import java.util.Map; +import java.util.function.Predicate; /** * This class implements the JavaScript scanner. @@ -253,7 +254,9 @@ 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 // recursion problem if a number of lines in a row are comments. @@ -413,6 +416,8 @@ 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 ""; } @@ -586,7 +591,7 @@ public class TokenStream { in.unread(); } - public int getToken() throws IOException { + public int getTokenWithComment() throws IOException { lastTokenPosition = tokenPosition; int c; do { @@ -597,6 +602,17 @@ public class TokenStream { return c; } + public int getToken() throws IOException { + lastTokenPosition = tokenPosition; + int c; + do { + c = getTokenHelper(); + } while (c == RETRY_TOKEN || c == SINGLE_LINE_COMMENT || c == MULTI_LINE_COMMENT); + + updatePosition(); + return c; + } + private int getTokenHelper() throws IOException { int c; tokenno++; @@ -1059,19 +1075,25 @@ public class TokenStream { case '/': // is it a // comment? if (in.match('/')) { - skipLine(); - return RETRY_TOKEN; + stringBufferTop = 0; + while ((c = in.read()) != -1 && c != '\n') { + addToString(c); + } + this.string = getStringFromBuffer(); + return SINGLE_LINE_COMMENT; } if (in.match('*')) { + stringBufferTop = 0; while ((c = in.read()) != -1 && !(c == '*' && in.match('/'))) { - ; // empty loop body + addToString(c); } if (c == EOF_CHAR) { reportTokenError("msg.unterminated.comment", null); return ERROR; } - return RETRY_TOKEN; // `goto retry' + this.string = getStringFromBuffer(); + return MULTI_LINE_COMMENT; // `goto retry' } // is it a regexp? diff --git a/js/js.serializer/src/js-ast.proto b/js/js.serializer/src/js-ast.proto index 9d3d4870979..1510c0cd137 100644 --- a/js/js.serializer/src/js-ast.proto +++ b/js/js.serializer/src/js-ast.proto @@ -254,6 +254,7 @@ message Statement { Try try_statement = 37; Empty empty = 38; SingleLineComment single_line_comment = 39; + MultiLineComment multi_line_comment = 40; } } @@ -377,6 +378,10 @@ message SingleLineComment { required string message = 1; } +message MultiLineComment { + required string message = 1; +} + enum InlineStrategy { AS_FUNCTION = 0; IN_PLACE = 1; diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializerBase.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializerBase.kt index 70ad614a81c..e8a0affe22f 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializerBase.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstDeserializerBase.kt @@ -164,6 +164,8 @@ abstract class JsAstDeserializerBase { JsAstProtoBuf.Statement.StatementCase.SINGLE_LINE_COMMENT -> JsSingleLineComment(proto.singleLineComment.message) + JsAstProtoBuf.Statement.StatementCase.MULTI_LINE_COMMENT -> JsMultiLineComment(proto.multiLineComment.message) + JsAstProtoBuf.Statement.StatementCase.STATEMENT_NOT_SET, null -> error("Statement not set") } diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java index d41395f5d59..99e31bfc7a9 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstProtoBuf.java @@ -15664,6 +15664,15 @@ public final class JsAstProtoBuf { * optional .org.jetbrains.kotlin.serialization.js.ast.SingleLineComment single_line_comment = 39; */ org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.SingleLineComment getSingleLineComment(); + + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + boolean hasMultiLineComment(); + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment getMultiLineComment(); } /** * Protobuf type {@code org.jetbrains.kotlin.serialization.js.ast.Statement} @@ -15985,6 +15994,19 @@ public final class JsAstProtoBuf { statementCase_ = 39; break; } + case 322: { + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.Builder subBuilder = null; + if (statementCase_ == 40) { + subBuilder = ((org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_).toBuilder(); + } + statement_ = input.readMessage(org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.PARSER, extensionRegistry); + if (subBuilder != null) { + subBuilder.mergeFrom((org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_); + statement_ = subBuilder.buildPartial(); + } + statementCase_ = 40; + break; + } } } } catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) { @@ -16042,6 +16064,7 @@ public final class JsAstProtoBuf { TRY_STATEMENT(37), EMPTY(38), SINGLE_LINE_COMMENT(39), + MULTI_LINE_COMMENT(40), STATEMENT_NOT_SET(0); private int value = 0; private StatementCase(int value) { @@ -16068,6 +16091,7 @@ public final class JsAstProtoBuf { case 37: return TRY_STATEMENT; case 38: return EMPTY; case 39: return SINGLE_LINE_COMMENT; + case 40: return MULTI_LINE_COMMENT; case 0: return STATEMENT_NOT_SET; default: throw new java.lang.IllegalArgumentException( "Value is undefined for this oneof enum."); @@ -16452,6 +16476,23 @@ public final class JsAstProtoBuf { return org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.SingleLineComment.getDefaultInstance(); } + public static final int MULTI_LINE_COMMENT_FIELD_NUMBER = 40; + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public boolean hasMultiLineComment() { + return statementCase_ == 40; + } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment getMultiLineComment() { + if (statementCase_ == 40) { + return (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_; + } + return org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.getDefaultInstance(); + } + private void initFields() { fileId_ = 0; location_ = org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.Location.getDefaultInstance(); @@ -16559,6 +16600,12 @@ public final class JsAstProtoBuf { return false; } } + if (hasMultiLineComment()) { + if (!getMultiLineComment().isInitialized()) { + memoizedIsInitialized = 0; + return false; + } + } memoizedIsInitialized = 1; return true; } @@ -16632,6 +16679,9 @@ public final class JsAstProtoBuf { if (statementCase_ == 39) { output.writeMessage(39, (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.SingleLineComment) statement_); } + if (statementCase_ == 40) { + output.writeMessage(40, (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_); + } output.writeRawBytes(unknownFields); } @@ -16729,6 +16779,10 @@ public final class JsAstProtoBuf { size += org.jetbrains.kotlin.protobuf.CodedOutputStream .computeMessageSize(39, (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.SingleLineComment) statement_); } + if (statementCase_ == 40) { + size += org.jetbrains.kotlin.protobuf.CodedOutputStream + .computeMessageSize(40, (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_); + } size += unknownFields.size(); memoizedSerializedSize = size; return size; @@ -16923,6 +16977,9 @@ public final class JsAstProtoBuf { if (statementCase_ == 39) { result.statement_ = statement_; } + if (statementCase_ == 40) { + result.statement_ = statement_; + } result.bitField0_ = to_bitField0_; result.statementCase_ = statementCase_; return result; @@ -17016,6 +17073,10 @@ public final class JsAstProtoBuf { mergeSingleLineComment(other.getSingleLineComment()); break; } + case MULTI_LINE_COMMENT: { + mergeMultiLineComment(other.getMultiLineComment()); + break; + } case STATEMENT_NOT_SET: { break; } @@ -17122,6 +17183,12 @@ public final class JsAstProtoBuf { return false; } } + if (hasMultiLineComment()) { + if (!getMultiLineComment().isInitialized()) { + + return false; + } + } return true; } @@ -18498,6 +18565,70 @@ public final class JsAstProtoBuf { return this; } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public boolean hasMultiLineComment() { + return statementCase_ == 40; + } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment getMultiLineComment() { + if (statementCase_ == 40) { + return (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_; + } + return org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.getDefaultInstance(); + } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public Builder setMultiLineComment(org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment value) { + if (value == null) { + throw new NullPointerException(); + } + statement_ = value; + + statementCase_ = 40; + return this; + } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public Builder setMultiLineComment( + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.Builder builderForValue) { + statement_ = builderForValue.build(); + + statementCase_ = 40; + return this; + } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public Builder mergeMultiLineComment(org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment value) { + if (statementCase_ == 40 && + statement_ != org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.getDefaultInstance()) { + statement_ = org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.newBuilder((org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) statement_) + .mergeFrom(value).buildPartial(); + } else { + statement_ = value; + } + + statementCase_ = 40; + return this; + } + /** + * optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40; + */ + public Builder clearMultiLineComment() { + if (statementCase_ == 40) { + statementCase_ = 0; + statement_ = null; + + } + return this; + } + // @@protoc_insertion_point(builder_scope:org.jetbrains.kotlin.serialization.js.ast.Statement) } @@ -30815,6 +30946,445 @@ public final class JsAstProtoBuf { // @@protoc_insertion_point(class_scope:org.jetbrains.kotlin.serialization.js.ast.SingleLineComment) } + public interface MultiLineCommentOrBuilder extends + // @@protoc_insertion_point(interface_extends:org.jetbrains.kotlin.serialization.js.ast.MultiLineComment) + org.jetbrains.kotlin.protobuf.MessageLiteOrBuilder { + + /** + * required string message = 1; + */ + boolean hasMessage(); + /** + * required string message = 1; + */ + java.lang.String getMessage(); + /** + * required string message = 1; + */ + org.jetbrains.kotlin.protobuf.ByteString + getMessageBytes(); + } + /** + * Protobuf type {@code org.jetbrains.kotlin.serialization.js.ast.MultiLineComment} + */ + public static final class MultiLineComment extends + org.jetbrains.kotlin.protobuf.GeneratedMessageLite implements + // @@protoc_insertion_point(message_implements:org.jetbrains.kotlin.serialization.js.ast.MultiLineComment) + MultiLineCommentOrBuilder { + // Use MultiLineComment.newBuilder() to construct. + private MultiLineComment(org.jetbrains.kotlin.protobuf.GeneratedMessageLite.Builder builder) { + super(builder); + this.unknownFields = builder.getUnknownFields(); + } + private MultiLineComment(boolean noInit) { this.unknownFields = org.jetbrains.kotlin.protobuf.ByteString.EMPTY;} + + private static final MultiLineComment defaultInstance; + public static MultiLineComment getDefaultInstance() { + return defaultInstance; + } + + public MultiLineComment getDefaultInstanceForType() { + return defaultInstance; + } + + private final org.jetbrains.kotlin.protobuf.ByteString unknownFields; + private MultiLineComment( + org.jetbrains.kotlin.protobuf.CodedInputStream input, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException { + initFields(); + int mutable_bitField0_ = 0; + org.jetbrains.kotlin.protobuf.ByteString.Output unknownFieldsOutput = + org.jetbrains.kotlin.protobuf.ByteString.newOutput(); + org.jetbrains.kotlin.protobuf.CodedOutputStream unknownFieldsCodedOutput = + org.jetbrains.kotlin.protobuf.CodedOutputStream.newInstance( + unknownFieldsOutput, 1); + try { + boolean done = false; + while (!done) { + int tag = input.readTag(); + switch (tag) { + case 0: + done = true; + break; + default: { + if (!parseUnknownField(input, unknownFieldsCodedOutput, + extensionRegistry, tag)) { + done = true; + } + break; + } + case 10: { + org.jetbrains.kotlin.protobuf.ByteString bs = input.readBytes(); + bitField0_ |= 0x00000001; + message_ = bs; + break; + } + } + } + } catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) { + throw e.setUnfinishedMessage(this); + } catch (java.io.IOException e) { + throw new org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException( + e.getMessage()).setUnfinishedMessage(this); + } finally { + try { + unknownFieldsCodedOutput.flush(); + } catch (java.io.IOException e) { + // Should not happen + } finally { + unknownFields = unknownFieldsOutput.toByteString(); + } + makeExtensionsImmutable(); + } + } + public static org.jetbrains.kotlin.protobuf.Parser PARSER = + new org.jetbrains.kotlin.protobuf.AbstractParser() { + public MultiLineComment parsePartialFrom( + org.jetbrains.kotlin.protobuf.CodedInputStream input, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException { + return new MultiLineComment(input, extensionRegistry); + } + }; + + @java.lang.Override + public org.jetbrains.kotlin.protobuf.Parser getParserForType() { + return PARSER; + } + + private int bitField0_; + public static final int MESSAGE_FIELD_NUMBER = 1; + private java.lang.Object message_; + /** + * required string message = 1; + */ + public boolean hasMessage() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string message = 1; + */ + public java.lang.String getMessage() { + java.lang.Object ref = message_; + if (ref instanceof java.lang.String) { + return (java.lang.String) ref; + } else { + org.jetbrains.kotlin.protobuf.ByteString bs = + (org.jetbrains.kotlin.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + message_ = s; + } + return s; + } + } + /** + * required string message = 1; + */ + public org.jetbrains.kotlin.protobuf.ByteString + getMessageBytes() { + java.lang.Object ref = message_; + if (ref instanceof java.lang.String) { + org.jetbrains.kotlin.protobuf.ByteString b = + org.jetbrains.kotlin.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + message_ = b; + return b; + } else { + return (org.jetbrains.kotlin.protobuf.ByteString) ref; + } + } + + private void initFields() { + message_ = ""; + } + private byte memoizedIsInitialized = -1; + public final boolean isInitialized() { + byte isInitialized = memoizedIsInitialized; + if (isInitialized == 1) return true; + if (isInitialized == 0) return false; + + if (!hasMessage()) { + memoizedIsInitialized = 0; + return false; + } + memoizedIsInitialized = 1; + return true; + } + + public void writeTo(org.jetbrains.kotlin.protobuf.CodedOutputStream output) + throws java.io.IOException { + getSerializedSize(); + if (((bitField0_ & 0x00000001) == 0x00000001)) { + output.writeBytes(1, getMessageBytes()); + } + output.writeRawBytes(unknownFields); + } + + private int memoizedSerializedSize = -1; + public int getSerializedSize() { + int size = memoizedSerializedSize; + if (size != -1) return size; + + size = 0; + if (((bitField0_ & 0x00000001) == 0x00000001)) { + size += org.jetbrains.kotlin.protobuf.CodedOutputStream + .computeBytesSize(1, getMessageBytes()); + } + size += unknownFields.size(); + memoizedSerializedSize = size; + return size; + } + + private static final long serialVersionUID = 0L; + @java.lang.Override + protected java.lang.Object writeReplace() + throws java.io.ObjectStreamException { + return super.writeReplace(); + } + + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom( + org.jetbrains.kotlin.protobuf.ByteString data) + throws org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom( + org.jetbrains.kotlin.protobuf.ByteString data, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom(byte[] data) + throws org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom( + byte[] data, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException { + return PARSER.parseFrom(data, extensionRegistry); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom( + java.io.InputStream input, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseDelimitedFrom(java.io.InputStream input) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseDelimitedFrom( + java.io.InputStream input, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseDelimitedFrom(input, extensionRegistry); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom( + org.jetbrains.kotlin.protobuf.CodedInputStream input) + throws java.io.IOException { + return PARSER.parseFrom(input); + } + public static org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parseFrom( + org.jetbrains.kotlin.protobuf.CodedInputStream input, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + return PARSER.parseFrom(input, extensionRegistry); + } + + public static Builder newBuilder() { return Builder.create(); } + public Builder newBuilderForType() { return newBuilder(); } + public static Builder newBuilder(org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment prototype) { + return newBuilder().mergeFrom(prototype); + } + public Builder toBuilder() { return newBuilder(this); } + + /** + * Protobuf type {@code org.jetbrains.kotlin.serialization.js.ast.MultiLineComment} + */ + public static final class Builder extends + org.jetbrains.kotlin.protobuf.GeneratedMessageLite.Builder< + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment, Builder> + implements + // @@protoc_insertion_point(builder_implements:org.jetbrains.kotlin.serialization.js.ast.MultiLineComment) + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineCommentOrBuilder { + // Construct using org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.newBuilder() + private Builder() { + maybeForceBuilderInitialization(); + } + + private void maybeForceBuilderInitialization() { + } + private static Builder create() { + return new Builder(); + } + + public Builder clear() { + super.clear(); + message_ = ""; + bitField0_ = (bitField0_ & ~0x00000001); + return this; + } + + public Builder clone() { + return create().mergeFrom(buildPartial()); + } + + public org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment getDefaultInstanceForType() { + return org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.getDefaultInstance(); + } + + public org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment build() { + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment result = buildPartial(); + if (!result.isInitialized()) { + throw newUninitializedMessageException(result); + } + return result; + } + + public org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment buildPartial() { + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment result = new org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment(this); + int from_bitField0_ = bitField0_; + int to_bitField0_ = 0; + if (((from_bitField0_ & 0x00000001) == 0x00000001)) { + to_bitField0_ |= 0x00000001; + } + result.message_ = message_; + result.bitField0_ = to_bitField0_; + return result; + } + + public Builder mergeFrom(org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment other) { + if (other == org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.getDefaultInstance()) return this; + if (other.hasMessage()) { + bitField0_ |= 0x00000001; + message_ = other.message_; + + } + setUnknownFields( + getUnknownFields().concat(other.unknownFields)); + return this; + } + + public final boolean isInitialized() { + if (!hasMessage()) { + + return false; + } + return true; + } + + public Builder mergeFrom( + org.jetbrains.kotlin.protobuf.CodedInputStream input, + org.jetbrains.kotlin.protobuf.ExtensionRegistryLite extensionRegistry) + throws java.io.IOException { + org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment parsedMessage = null; + try { + parsedMessage = PARSER.parsePartialFrom(input, extensionRegistry); + } catch (org.jetbrains.kotlin.protobuf.InvalidProtocolBufferException e) { + parsedMessage = (org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment) e.getUnfinishedMessage(); + throw e; + } finally { + if (parsedMessage != null) { + mergeFrom(parsedMessage); + } + } + return this; + } + private int bitField0_; + + private java.lang.Object message_ = ""; + /** + * required string message = 1; + */ + public boolean hasMessage() { + return ((bitField0_ & 0x00000001) == 0x00000001); + } + /** + * required string message = 1; + */ + public java.lang.String getMessage() { + java.lang.Object ref = message_; + if (!(ref instanceof java.lang.String)) { + org.jetbrains.kotlin.protobuf.ByteString bs = + (org.jetbrains.kotlin.protobuf.ByteString) ref; + java.lang.String s = bs.toStringUtf8(); + if (bs.isValidUtf8()) { + message_ = s; + } + return s; + } else { + return (java.lang.String) ref; + } + } + /** + * required string message = 1; + */ + public org.jetbrains.kotlin.protobuf.ByteString + getMessageBytes() { + java.lang.Object ref = message_; + if (ref instanceof String) { + org.jetbrains.kotlin.protobuf.ByteString b = + org.jetbrains.kotlin.protobuf.ByteString.copyFromUtf8( + (java.lang.String) ref); + message_ = b; + return b; + } else { + return (org.jetbrains.kotlin.protobuf.ByteString) ref; + } + } + /** + * required string message = 1; + */ + public Builder setMessage( + java.lang.String value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + message_ = value; + + return this; + } + /** + * required string message = 1; + */ + public Builder clearMessage() { + bitField0_ = (bitField0_ & ~0x00000001); + message_ = getDefaultInstance().getMessage(); + + return this; + } + /** + * required string message = 1; + */ + public Builder setMessageBytes( + org.jetbrains.kotlin.protobuf.ByteString value) { + if (value == null) { + throw new NullPointerException(); + } + bitField0_ |= 0x00000001; + message_ = value; + + return this; + } + + // @@protoc_insertion_point(builder_scope:org.jetbrains.kotlin.serialization.js.ast.MultiLineComment) + } + + static { + defaultInstance = new MultiLineComment(true); + defaultInstance.initFields(); + } + + // @@protoc_insertion_point(class_scope:org.jetbrains.kotlin.serialization.js.ast.MultiLineComment) + } + public interface FragmentOrBuilder extends // @@protoc_insertion_point(interface_extends:org.jetbrains.kotlin.serialization.js.ast.Fragment) org.jetbrains.kotlin.protobuf.MessageLiteOrBuilder { diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt index 10dee0b7d03..191d6285535 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializer.kt @@ -18,10 +18,7 @@ package org.jetbrains.kotlin.serialization.js.ast import com.intellij.psi.PsiElement import org.jetbrains.kotlin.js.backend.ast.* -import org.jetbrains.kotlin.js.backend.ast.JsImportedModule import org.jetbrains.kotlin.js.backend.ast.metadata.* -import org.jetbrains.kotlin.js.backend.ast.metadata.LocalAlias -import org.jetbrains.kotlin.js.backend.ast.metadata.SpecialFunction import org.jetbrains.kotlin.resolve.calls.util.isFakePsiElement import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.* import org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.BinaryOperation.Type.* diff --git a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializerBase.kt b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializerBase.kt index 5553ddfc473..a569e8611cc 100644 --- a/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializerBase.kt +++ b/js/js.serializer/src/org/jetbrains/kotlin/serialization/js/ast/JsAstSerializerBase.kt @@ -168,6 +168,10 @@ abstract class JsAstSerializerBase { override fun visitSingleLineComment(comment: JsSingleLineComment) { builder.singleLineComment = JsAstProtoBuf.SingleLineComment.newBuilder().setMessage(comment.text).build() } + + override fun visitMultiLineComment(comment: JsMultiLineComment) { + builder.multiLineComment = JsAstProtoBuf.MultiLineComment.newBuilder().setMessage(comment.text).build() + } } withLocation(statement, { visitor.builder.fileId = it }, { visitor.builder.location = it }) { diff --git a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/utils/DirectiveTestUtils.java b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/utils/DirectiveTestUtils.java index f06eb9e8bf4..14d3ab4b196 100644 --- a/js/js.tests/test/org/jetbrains/kotlin/js/testOld/utils/DirectiveTestUtils.java +++ b/js/js.tests/test/org/jetbrains/kotlin/js/testOld/utils/DirectiveTestUtils.java @@ -26,6 +26,8 @@ import org.jetbrains.kotlin.test.TargetBackend; import org.junit.runners.model.MultipleFailureException; import java.util.*; +import java.util.regex.Pattern; +import java.util.regex.Matcher; import static org.jetbrains.kotlin.js.inline.util.CollectUtilsKt.collectInstances; import static org.jetbrains.kotlin.test.InTextDirectivesUtils.findLinesWithPrefixesRemoved; @@ -164,6 +166,41 @@ public class DirectiveTestUtils { } }; + private static abstract class NodeExistenceDirective extends DirectiveHandler { + private boolean isElementExists = false; + private boolean shouldCheckForExistence; + + NodeExistenceDirective(@NotNull String directive, boolean shouldCheckForExistence) { + super(directive); + this.shouldCheckForExistence = shouldCheckForExistence; + } + + protected abstract String getTextForError(); + protected abstract JsVisitor getJsVisitorForElement(); + protected abstract void loadArguments(@NotNull ArgumentsHelper arguments); + + protected void setElementExists(boolean isElementExists) { + this.isElementExists = isElementExists; + } + + @Override + void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception { + loadArguments(arguments); + getJsVisitorForElement().accept(ast); + assertExistence(); + setElementExists(false); + } + + private void assertExistence() { + String message = getTextForError(); + if (shouldCheckForExistence) { + assertTrue(message, isElementExists); + } else { + assertFalse(message, isElementExists); + } + } + } + private static class CountNodesDirective extends DirectiveHandler { @NotNull @@ -257,6 +294,76 @@ public class DirectiveTestUtils { } }; + private static final DirectiveHandler CHECK_COMMENT_EXISTS = new NodeExistenceDirective("CHECK_COMMENT_EXISTS", true) { + private String text; + private boolean isMultiLine; + + @Override + protected String getTextForError() { + return (isMultiLine ? "Multi line" : "Single line") + " comment with text '" + text + "' doesn't exist"; + } + + @Override + protected JsVisitor getJsVisitorForElement() { + return isMultiLine ? new RecursiveJsVisitor() { + @Override + public void visitMultiLineComment(@NotNull JsMultiLineComment comment) { + if (comment.getText().trim().equals(text)) { + setElementExists(true); + } + } + } : new RecursiveJsVisitor() { + @Override + public void visitSingleLineComment(@NotNull JsSingleLineComment comment) { + if (comment.getText().trim().equals(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 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") { @Override void processEntry(@NotNull JsNode ast, @NotNull ArgumentsHelper arguments) throws Exception { @@ -374,6 +481,8 @@ public class DirectiveTestUtils { FUNCTION_NOT_CALLED_IN_SCOPE, FUNCTIONS_HAVE_SAME_LINES, ONLY_THIS_QUALIFIED_REFERENCES, + CHECK_COMMENT_EXISTS, + CHECK_COMMENT_DOESNT_EXIST, COUNT_LABELS, COUNT_VARS, COUNT_BREAKS, @@ -422,6 +531,10 @@ public class DirectiveTestUtils { return node; } + public static void checkCommentExists(JsNode node, String content, boolean isMultiline) { + + } + public static void checkPropertyNotUsed(JsNode node, String propertyName, String scope, boolean isGetAllowed, boolean isSetAllowed) throws Exception { PropertyReferenceCollector counter = PropertyReferenceCollector.Companion.collect(findScope(node, scope)); @@ -565,8 +678,8 @@ public class DirectiveTestUtils { /** * Arguments format: ((namedArg|positionalArg)\s+)*` * - * Where: namedArg -- "key=value" - * positionalArg -- "value" + * Where: namedArg -- 'key=value' or 'key="spaced value"' + * positionalArg -- 'value' * * Neither key, nor value should contain spaces. */ @@ -574,16 +687,25 @@ public class DirectiveTestUtils { private final List positionalArguments = new ArrayList<>(); private final Map namedArguments = new HashMap<>(); private final String entry; + private final Pattern argumentsPattern = Pattern.compile("\\w+(=((\".*?\")|\\w+))?"); ArgumentsHelper(@NotNull String directiveEntry) { entry = directiveEntry; - for (String argument: directiveEntry.split("\\s+")) { - String[] keyVal = argument.split("="); + Matcher matcher = argumentsPattern.matcher(directiveEntry); + while (matcher.find()) { + String argument = matcher.group(); + String[] keyVal = argument.split("="); switch (keyVal.length) { case 1: positionalArguments.add(keyVal[0]); break; - case 2: namedArguments.put(keyVal[0], keyVal[1]); break; + case 2: + String value = keyVal[1]; + if (value.charAt(0) == '"') { + value = value.substring(1, value.length() - 1); + } + namedArguments.put(keyVal[0], value); + break; default: throw new AssertionError("Wrong argument format: " + argument); } } diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java index bbf563280f3..12144879b96 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/BoxJsTestGenerated.java @@ -6126,6 +6126,12 @@ public class BoxJsTestGenerated extends AbstractBoxJsTest { runTest("js/js.translator/testData/box/jsCode/codeFromVariable.kt"); } + @Test + @TestMetadata("comments.kt") + public void testComments() throws Exception { + runTest("js/js.translator/testData/box/jsCode/comments.kt"); + } + @Test @TestMetadata("constantExpression.kt") public void testConstantExpression() throws Exception { diff --git a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java index e53705715d0..18b76aee9db 100644 --- a/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java +++ b/js/js.tests/tests-gen/org/jetbrains/kotlin/js/test/ir/IrBoxJsTestGenerated.java @@ -6510,6 +6510,12 @@ public class IrBoxJsTestGenerated extends AbstractIrBoxJsTest { runTest("js/js.translator/testData/box/jsCode/codeFromVariable.kt"); } + @Test + @TestMetadata("comments.kt") + public void testComments() throws Exception { + runTest("js/js.translator/testData/box/jsCode/comments.kt"); + } + @Test @TestMetadata("constantExpression.kt") public void testConstantExpression() throws Exception { diff --git a/js/js.translator/testData/box/jsCode/comments.kt b/js/js.translator/testData/box/jsCode/comments.kt new file mode 100644 index 00000000000..09b0e7640af --- /dev/null +++ b/js/js.translator/testData/box/jsCode/comments.kt @@ -0,0 +1,29 @@ +// EXPECTED_REACHABLE_NODES: 1282 +// CHECK_COMMENT_EXISTS: text="Single line comment" multiline=false +// CHECK_COMMENT_EXISTS: text="Multi line comment" 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_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 + +package foo + +fun box(): String { + js(""" + function foo() {} + + // Single line comment + foo(); + + /* Multi line comment */ + foo(); + + foo(); // After call single line comment + + foo(); /* After call multi line comment */ + + var /*random position comment 1*/ c /*random position comment 2*/ = /*random position comment 3*/ "Random position"; + """) + return "OK" +} \ No newline at end of file