org.openrewrite.javascript.internal.TsTreePrinter Maven / Gradle / Ivy
/*
* Copyright 2023 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* https://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.openrewrite.javascript.internal;
import lombok.AllArgsConstructor;
import lombok.Data;
import org.jspecify.annotations.Nullable;
import org.openrewrite.*;
import org.openrewrite.java.tree.*;
import org.openrewrite.javascript.internal.tsc.TSCNode;
import org.openrewrite.javascript.internal.tsc.TSCSourceFileContext;
import org.openrewrite.javascript.internal.tsc.generated.TSCSyntaxKind;
import java.util.*;
import java.util.stream.Collectors;
import static java.util.stream.StreamSupport.stream;
@SuppressWarnings({"unused", "DuplicatedCode", "SameParameterValue"})
public class TsTreePrinter {
private static final String TAB = " ";
private static final String ELEMENT_PREFIX = "\\---";
private static final char BRANCH_CONTINUE_CHAR = '|';
private static final char BRANCH_END_CHAR = '\\';
private static final int CONTENT_MAX_LENGTH = 200;
private static final String CONTINUE_PREFIX = "----";
private static final String UNVISITED_PREFIX = "#";
// Set to true to print types and verify, otherwise just verify the parse to print idempotent.
private final static boolean printTypes = true;
private final List outputLines;
protected TsTreePrinter() {
outputLines = new ArrayList<>();
}
public static String print(Parser.Input input) {
return printIndexedSourceCode(input.getSource(new InMemoryExecutionContext()).readFully());
}
public static String print(Tree tree) {
return "------------\nJ Tree\n" + printJTree(tree);
}
public static String print(TSCNode node, TSCSourceFileContext context, boolean printSpace) {
return printTSTree(node, context, printSpace);
}
@AllArgsConstructor
@Data
public static class TreePrinterContext {
List lines;
int depth;
}
public static String printTSTree(TSCNode node, TSCSourceFileContext context, boolean printSpace) {
TsTreePrinter treePrinter = new TsTreePrinter();
StringBuilder sb = new StringBuilder();
sb.append("------------").append("\n");
sb.append("TS tree").append("\n");
if (printSpace) {
treePrinter.printBeforeFirstNode(node, 0, context);
}
treePrinter.printTSCNode(node, 1, context, printSpace);
sb.append(String.join("\n", treePrinter.outputLines));
context.resetScanner(0);
return sb.toString();
}
private void printBeforeFirstNode(TSCNode node, int depth, TSCSourceFileContext context) {
if (node.getStart() == 0) {
return;
}
StringBuilder line = new StringBuilder();
context.resetScanner(0);
int stop = node.getStart();
while (true) {
TSCSyntaxKind kind = context.nextScannerSyntaxType();
String text = context.scannerTokenText();
int start = context.scannerTokenStart();
int end = context.scannerTokenEnd();
if (end > stop || kind == TSCSyntaxKind.EndOfFileToken) {
break;
}
StringBuilder subLine = new StringBuilder();
subLine.append(leftPadding(depth + 1))
.append("[")
.append(start)
.append(",").append(end)
.append(")")
.append(" | ")
.append("* ")
.append(kind).append(" | Text : \"")
.append(truncate(text).replace("\n", "\\n").replace("\r", "\\r"))
.append("\"");
connectToLatestSibling(depth + 1);
outputLines.add(subLine);
}
}
private void printTSCNode(TSCNode node, int depth, TSCSourceFileContext context, boolean printSpace) {
StringBuilder line = new StringBuilder();
line.append(leftPadding(depth))
.append(toString(node));
connectToLatestSibling(depth);
outputLines.add(line);
List tscNodes = node.getAllChildNodes();
for ( int i = 0; i < tscNodes.size(); i++) {
TSCNode childNode = tscNodes.get(i);
TSCNode nextChildNode = i < tscNodes.size() - 1 ? tscNodes.get(i + 1) : null;
boolean hasGap = nextChildNode != null && nextChildNode.getStart() > childNode.getEnd();
printTSCNode(childNode, depth + 1, context, printSpace);
if (printSpace && hasGap) {
context.resetScanner(childNode.getEnd());
int stop = nextChildNode.getStart();
while (true) {
TSCSyntaxKind kind = context.nextScannerSyntaxType();
String text = context.scannerTokenText();
int start = context.scannerTokenStart();
int end = context.scannerTokenEnd();
if (end > stop || kind == TSCSyntaxKind.EndOfFileToken) {
break;
}
StringBuilder subLine = new StringBuilder();
subLine.append(leftPadding(depth + 1))
.append("[")
.append(start)
.append(",").append(end)
.append(")")
.append(" | ")
.append("* ")
.append(kind).append(" | Text : \"")
.append(truncate(text).replace("\n", "\\n").replace("\r", "\\r"))
.append("\"");
connectToLatestSibling(depth + 1);
outputLines.add(subLine);
}
}
}
}
private static String toString(TSCNode node) {
return "[" + node.getStart() + "," + node.getEnd() + ")" + " | " + node.syntaxKind().name() + " | Text : \"" +
truncate(node.getText()).replace("\n", "\\n").replace("\r", "\\r") + "\"";
}
/**
* print J tree with all types
*/
@SuppressWarnings("rawtypes")
static class TreeVisitingPrinter extends TreeVisitor {
private List