|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
package com.github.javaparser.ast.expr; |
|
|
|
import com.github.javaparser.TokenRange; |
|
import com.github.javaparser.ast.AllFieldsConstructor; |
|
import com.github.javaparser.ast.Generated; |
|
import com.github.javaparser.ast.Node; |
|
import com.github.javaparser.ast.visitor.CloneVisitor; |
|
import com.github.javaparser.ast.visitor.GenericVisitor; |
|
import com.github.javaparser.ast.visitor.VoidVisitor; |
|
import com.github.javaparser.metamodel.JavaParserMetaModel; |
|
import com.github.javaparser.metamodel.TextBlockLiteralExprMetaModel; |
|
import com.github.javaparser.utils.Pair; |
|
import java.util.Arrays; |
|
import java.util.Optional; |
|
import java.util.function.Consumer; |
|
import java.util.stream.Stream; |
|
import static com.github.javaparser.utils.StringEscapeUtils.unescapeJavaTextBlock; |
|
import static java.util.stream.Collectors.joining; |
|
import static java.util.stream.IntStream.range; |
|
|
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
public class TextBlockLiteralExpr extends LiteralStringValueExpr { |
|
|
|
public TextBlockLiteralExpr() { |
|
this(null, "empty"); |
|
} |
|
|
|
|
|
|
|
|
|
|
|
*/ |
|
@AllFieldsConstructor |
|
public TextBlockLiteralExpr(final String value) { |
|
this(null, value); |
|
} |
|
|
|
|
|
|
|
*/ |
|
@Generated("com.github.javaparser.generator.core.node.MainConstructorGenerator") |
|
public TextBlockLiteralExpr(TokenRange tokenRange, String value) { |
|
super(tokenRange, value); |
|
customInitialization(); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.AcceptGenerator") |
|
public <R, A> R accept(final GenericVisitor<R, A> v, final A arg) { |
|
return v.visit(this, arg); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.AcceptGenerator") |
|
public <A> void accept(final VoidVisitor<A> v, final A arg) { |
|
v.visit(this, arg); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.RemoveMethodGenerator") |
|
public boolean remove(Node node) { |
|
if (node == null) |
|
return false; |
|
return super.remove(node); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
|
public boolean isTextBlockLiteralExpr() { |
|
return true; |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
|
public TextBlockLiteralExpr asTextBlockLiteralExpr() { |
|
return this; |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
|
public Optional<TextBlockLiteralExpr> toTextBlockLiteralExpr() { |
|
return Optional.of(this); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.TypeCastingGenerator") |
|
public void ifTextBlockLiteralExpr(Consumer<TextBlockLiteralExpr> action) { |
|
action.accept(this); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.ReplaceMethodGenerator") |
|
public boolean replace(Node node, Node replacementNode) { |
|
if (node == null) |
|
return false; |
|
return super.replace(node, replacementNode); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.CloneGenerator") |
|
public TextBlockLiteralExpr clone() { |
|
return (TextBlockLiteralExpr) accept(new CloneVisitor(), null); |
|
} |
|
|
|
@Override |
|
@Generated("com.github.javaparser.generator.core.node.GetMetaModelGenerator") |
|
public TextBlockLiteralExprMetaModel getMetaModel() { |
|
return JavaParserMetaModel.textBlockLiteralExprMetaModel; |
|
} |
|
|
|
|
|
|
|
|
|
*/ |
|
public Stream<String> stripIndentOfLines() { |
|
|
|
Note that any line in the content which was just an LF will become an empty line in the list of individual lines. */ |
|
String[] rawLines = getValue().split("\\R", -1); |
|
/* Add all non-blank lines from the list of individual lines into a set of determining lines. |
|
(Blank lines -- lines that are empty or are composed wholly of white space -- have no visible influence on the indentation. |
|
Excluding blank lines from the set of determining lines avoids throwing off step 4 of the algorithm.) */ |
|
/* If the last line in the list of individual lines (i.e., the line with the closing delimiter) is blank, then add it to the set of determining lines. |
|
(The indentation of the closing delimiter should influence the indentation of the content as a whole -- a "significant trailing line" policy.) */ |
|
|
|
int commonWhiteSpacePrefixSize = range(0, rawLines.length).mapToObj(nr -> new Pair<>(nr, rawLines[nr])).filter(l -> !emptyOrWhitespace(l.b) || isLastLine(rawLines, l.a)).map(l -> indentSize(l.b)).min(Integer::compare).orElse(0); |
|
/* Remove the common white space prefix from each non-blank line in the list of individual lines. */ |
|
|
|
This step collapses wholly-whitespace lines in the modified list so that they are empty, but does not discard them. */ |
|
return Arrays.stream(rawLines).map(l -> l.length() < commonWhiteSpacePrefixSize ? l : l.substring(commonWhiteSpacePrefixSize)).map(this::trimTrailing); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String stripIndent() { |
|
|
|
If the final line in the list from step 6 is empty, then the joining LF from the previous line will be the last character in the result string. */ |
|
return stripIndentOfLines().collect(joining("\n")); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String translateEscapes() { |
|
return unescapeJavaTextBlock(stripIndent()); |
|
} |
|
|
|
|
|
|
|
*/ |
|
public String asString() { |
|
return translateEscapes(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private boolean isLastLine(String[] rawLines, Integer lineNr) { |
|
return lineNr == rawLines.length - 1; |
|
} |
|
|
|
|
|
|
|
*/ |
|
private boolean emptyOrWhitespace(String rawLine) { |
|
return rawLine.trim().isEmpty(); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private int indentSize(String s) { |
|
String content = s.trim(); |
|
if (content.isEmpty()) { |
|
return s.length(); |
|
} |
|
return s.indexOf(content); |
|
} |
|
|
|
|
|
|
|
*/ |
|
private String trimTrailing(String source) { |
|
int pos = source.length() - 1; |
|
while ((pos >= 0) && Character.isWhitespace(source.charAt(pos))) { |
|
pos--; |
|
} |
|
pos++; |
|
return (pos < source.length()) ? source.substring(0, pos) : source; |
|
} |
|
} |