feat: add limited support of comments inside js call.

This commit is contained in:
Artem Kobzar
2022-04-07 15:32:03 +02:00
committed by teamcity
parent 6e30ce2763
commit 45e3c94a8b
20 changed files with 890 additions and 20 deletions
@@ -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 -> {
@@ -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
@@ -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;
@@ -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
}
@@ -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)
@@ -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;
}
@@ -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
@@ -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) {
@@ -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;
}
@@ -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;
@@ -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 "<unknown="+token+">";
}
@@ -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?
+5
View File
@@ -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;
@@ -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")
}
@@ -15664,6 +15664,15 @@ public final class JsAstProtoBuf {
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.SingleLineComment single_line_comment = 39;</code>
*/
org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.SingleLineComment getSingleLineComment();
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
boolean hasMultiLineComment();
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
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;
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
public boolean hasMultiLineComment() {
return statementCase_ == 40;
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
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;
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
public boolean hasMultiLineComment() {
return statementCase_ == 40;
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
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();
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
public Builder setMultiLineComment(org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment value) {
if (value == null) {
throw new NullPointerException();
}
statement_ = value;
statementCase_ = 40;
return this;
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
public Builder setMultiLineComment(
org.jetbrains.kotlin.serialization.js.ast.JsAstProtoBuf.MultiLineComment.Builder builderForValue) {
statement_ = builderForValue.build();
statementCase_ = 40;
return this;
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
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;
}
/**
* <code>optional .org.jetbrains.kotlin.serialization.js.ast.MultiLineComment multi_line_comment = 40;</code>
*/
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 {
/**
* <code>required string message = 1;</code>
*/
boolean hasMessage();
/**
* <code>required string message = 1;</code>
*/
java.lang.String getMessage();
/**
* <code>required string message = 1;</code>
*/
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<MultiLineComment> PARSER =
new org.jetbrains.kotlin.protobuf.AbstractParser<MultiLineComment>() {
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<MultiLineComment> getParserForType() {
return PARSER;
}
private int bitField0_;
public static final int MESSAGE_FIELD_NUMBER = 1;
private java.lang.Object message_;
/**
* <code>required string message = 1;</code>
*/
public boolean hasMessage() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>required string message = 1;</code>
*/
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;
}
}
/**
* <code>required string message = 1;</code>
*/
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_ = "";
/**
* <code>required string message = 1;</code>
*/
public boolean hasMessage() {
return ((bitField0_ & 0x00000001) == 0x00000001);
}
/**
* <code>required string message = 1;</code>
*/
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;
}
}
/**
* <code>required string message = 1;</code>
*/
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;
}
}
/**
* <code>required string message = 1;</code>
*/
public Builder setMessage(
java.lang.String value) {
if (value == null) {
throw new NullPointerException();
}
bitField0_ |= 0x00000001;
message_ = value;
return this;
}
/**
* <code>required string message = 1;</code>
*/
public Builder clearMessage() {
bitField0_ = (bitField0_ & ~0x00000001);
message_ = getDefaultInstance().getMessage();
return this;
}
/**
* <code>required string message = 1;</code>
*/
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 {
@@ -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.*
@@ -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 }) {
@@ -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<T extends JsNode> 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<String> positionalArguments = new ArrayList<>();
private final Map<String, String> 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);
}
}
@@ -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 {
@@ -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 {
+29
View File
@@ -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"
}