mirror of https://github.com/PaperMC/Paper.git
unflatten closure representation
This commit is contained in:
parent
b0d9d2d6ed
commit
8294f7dca4
|
@ -1,17 +1,14 @@
|
|||
package io.papermc.generator.rewriter.parser;
|
||||
|
||||
public enum ClosureAdvanceResult {
|
||||
/**
|
||||
* When the pointer advance on a closure. Escaped end closure are skipped!
|
||||
*/
|
||||
CHANGED,
|
||||
/**
|
||||
* When the pointer doesn't advance and cannot find the closure.
|
||||
*/
|
||||
IGNORED,
|
||||
/**
|
||||
* When the pointer advance by skipping strong closure within weak closure
|
||||
* or by reaching a weak end closure escaped by '\' char preceding it.
|
||||
*/
|
||||
SKIPPED
|
||||
public record ClosureAdvanceResult(boolean found, boolean advanced) {
|
||||
|
||||
public static final ClosureAdvanceResult NONE = new ClosureAdvanceResult(false, false);
|
||||
|
||||
public static ClosureAdvanceResult find(boolean found) {
|
||||
return new ClosureAdvanceResult(found, true);
|
||||
}
|
||||
|
||||
public static ClosureAdvanceResult skip() {
|
||||
return new ClosureAdvanceResult(false, true);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
package io.papermc.generator.rewriter.parser;
|
||||
|
||||
import java.util.EnumSet;
|
||||
|
||||
public enum ClosureType { // todo refactor? this become bigger than initially planned
|
||||
PARENTHESIS("(", ")", false),
|
||||
CURLY_BRACKET("{", "}", false),
|
||||
BRACKET("[", "]", false),
|
||||
COMMENT("/*", "*/"),
|
||||
|
||||
// escape allowed
|
||||
// todo could handle the extra newline needed after """
|
||||
PARAGRAPH("\"\"\"", "\"\"\""), // order matter here this one must be checked before string for the strong check
|
||||
STRING("\"", "\""),
|
||||
CHAR("'", "'");
|
||||
|
||||
public final String start;
|
||||
public final String end;
|
||||
public final boolean strong; // once within this closure ignore all the weak ones
|
||||
|
||||
ClosureType(String start, String end) {
|
||||
this(start, end, true);
|
||||
}
|
||||
|
||||
ClosureType(String start, String end, boolean strong) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
this.strong = strong;
|
||||
}
|
||||
|
||||
public static final EnumSet<ClosureType> ALLOW_ESCAPE = EnumSet.of(STRING, CHAR, PARAGRAPH);
|
||||
}
|
|
@ -0,0 +1,20 @@
|
|||
package io.papermc.generator.rewriter.parser;
|
||||
|
||||
import io.papermc.generator.rewriter.parser.closure.ClosureType;
|
||||
|
||||
public enum ClosureTypeAdvanceResult {
|
||||
/**
|
||||
* When the pointer advance on a closure. Escaped end closure are skipped!
|
||||
*/
|
||||
CHANGED,
|
||||
/**
|
||||
* When the pointer doesn't advance and cannot find the closure.
|
||||
*/
|
||||
IGNORED,
|
||||
/**
|
||||
* When the pointer advance by reaching a leaf closure escaped by '\' char preceding it.
|
||||
*
|
||||
* @see ClosureType#ALLOW_ESCAPE
|
||||
*/
|
||||
SKIPPED
|
||||
}
|
|
@ -1,93 +1,143 @@
|
|||
package io.papermc.generator.rewriter.parser;
|
||||
|
||||
import com.google.common.base.Preconditions;
|
||||
import io.papermc.generator.rewriter.context.ImportCollector;
|
||||
import io.papermc.generator.rewriter.parser.closure.AbstractClosure;
|
||||
import io.papermc.generator.rewriter.parser.closure.Closure;
|
||||
import io.papermc.generator.rewriter.parser.closure.ClosureType;
|
||||
import io.papermc.generator.rewriter.parser.step.IterativeStep;
|
||||
import io.papermc.generator.rewriter.parser.step.StepManager;
|
||||
import io.papermc.generator.rewriter.parser.step.model.AnnotationSteps;
|
||||
import io.papermc.generator.rewriter.parser.step.model.ImportSteps;
|
||||
import io.papermc.generator.rewriter.parser.step.model.AnnotationSkipSteps;
|
||||
import io.papermc.generator.rewriter.parser.step.model.ImportStatementSteps;
|
||||
import org.jetbrains.annotations.ApiStatus;
|
||||
import java.util.EnumSet;
|
||||
import java.util.Set;
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.List;
|
||||
|
||||
@ApiStatus.Internal
|
||||
public class LineParser {
|
||||
|
||||
private final Set<ClosureType> closures = EnumSet.noneOf(ClosureType.class);
|
||||
private final StepManager stepManager = new StepManager();
|
||||
|
||||
private ClosureType strongClosure;
|
||||
private Closure nearestClosure;
|
||||
|
||||
public boolean advanceEnclosure(ClosureType type, StringReader line) {
|
||||
return this.advanceEnclosure0(type, line) == ClosureAdvanceResult.CHANGED;
|
||||
@Nullable
|
||||
public Closure getNearestClosure() {
|
||||
return this.nearestClosure;
|
||||
}
|
||||
|
||||
public ClosureAdvanceResult advanceEnclosure0(ClosureType type, StringReader line) {
|
||||
boolean inside = this.closures.contains(type);
|
||||
String closure = !inside ? type.start : type.end;
|
||||
|
||||
// skip comments, char and string inside the upper closure for weak closure type
|
||||
if (!type.strong && inside) {
|
||||
ClosureType skipClosure = this.strongClosure;
|
||||
if (skipClosure == null) {
|
||||
for (ClosureType strongClosure : ClosureType.values()) {
|
||||
if (!strongClosure.strong) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (this.advanceEnclosure(strongClosure, line)) {
|
||||
skipClosure = strongClosure;
|
||||
break;
|
||||
}
|
||||
// internal use only or when nearestClosure = null
|
||||
// doesn't support leaf closure char escape
|
||||
public boolean tryAdvanceStartClosure(@NotNull ClosureType type, @NotNull StringReader line) {
|
||||
if (line.trySkipString(type.start)) { // closure has been consumed
|
||||
Closure previousNearestClosure = this.nearestClosure;
|
||||
this.nearestClosure = Closure.create(type);
|
||||
if (previousNearestClosure != null) {
|
||||
if (ClosureType.LEAFS.contains(previousNearestClosure.getType())) {
|
||||
throw new ParserException("Nested closure in a leaf closure is not allowed", line);
|
||||
}
|
||||
((AbstractClosure) this.nearestClosure).setParent(previousNearestClosure);
|
||||
}
|
||||
|
||||
if (skipClosure != null) {
|
||||
ClosureAdvanceResult result;
|
||||
while ((result = this.advanceEnclosure0(skipClosure, line)) != ClosureAdvanceResult.CHANGED && line.canRead()) {
|
||||
if (result == ClosureAdvanceResult.IGNORED) {
|
||||
line.skip();
|
||||
}
|
||||
}
|
||||
return ClosureAdvanceResult.SKIPPED;
|
||||
}
|
||||
this.nearestClosure.onStart(line);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// for all closure, leaf closure type should use the other similar method after this one if possible
|
||||
// ignoreNestedClosureTypes order matter here
|
||||
public ClosureAdvanceResult tryAdvanceEndClosure(@NotNull Closure closure, @NotNull StringReader line) {
|
||||
Preconditions.checkState(this.nearestClosure != null && this.nearestClosure.hasUpperClosure(closure), "Need to be in an upper closure of " + closure + " to find its end identifier");
|
||||
boolean directClosureFound = this.nearestClosure == closure;
|
||||
boolean canSearchEndClosure = this.nearestClosure == null || directClosureFound;
|
||||
|
||||
char previousChar = '\0';
|
||||
if (line.getCursor() >= 1) {
|
||||
previousChar = line.peek(-1);
|
||||
}
|
||||
|
||||
if (line.trySkipString(closure)) { // closure has been consumed
|
||||
if (!inside) {
|
||||
if (!this.closures.add(type)) {
|
||||
throw new ParserException("Nested same closure detected for " + type, line);
|
||||
}
|
||||
} else {
|
||||
// skip escape closed closure
|
||||
if (closure.length() == 1 && type.start.equals(type.end) && ClosureType.ALLOW_ESCAPE.contains(type)) {
|
||||
if (previousChar == '\\') {
|
||||
return ClosureAdvanceResult.SKIPPED;
|
||||
}
|
||||
ClosureType type = closure.getType();
|
||||
if (canSearchEndClosure && line.trySkipString(type.end)) { // closure has been consumed
|
||||
// skip escape closed closure
|
||||
if (type.end.length() == 1 && type.start.equals(type.end) && ClosureType.ALLOW_ESCAPE.contains(type)) {
|
||||
if (previousChar == '\\') {
|
||||
return ClosureAdvanceResult.skip();
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.closures.remove(type)) {
|
||||
throw new ParserException("Missing open closure? for " + type, line);
|
||||
}
|
||||
this.nearestClosure.onEnd(line);
|
||||
if (this.nearestClosure.parent() != null) {
|
||||
this.nearestClosure = this.nearestClosure.parent();
|
||||
} else {
|
||||
this.nearestClosure = null;
|
||||
}
|
||||
if (type.strong) {
|
||||
this.strongClosure = !inside ? type : null;
|
||||
}
|
||||
return ClosureAdvanceResult.CHANGED;
|
||||
return ClosureAdvanceResult.find(directClosureFound);
|
||||
}
|
||||
return ClosureAdvanceResult.IGNORED;
|
||||
|
||||
return ClosureAdvanceResult.NONE;
|
||||
}
|
||||
|
||||
public boolean skipComment(StringReader line) {
|
||||
public boolean trySkipNestedClosures(@NotNull Closure inClosure, @NotNull StringReader line, @NotNull List<ClosureType> computedTypes) {
|
||||
boolean directClosureFound = this.nearestClosure == inClosure;
|
||||
boolean isLeaf = this.nearestClosure != null && ClosureType.LEAFS.contains(this.nearestClosure.getType());
|
||||
if (this.nearestClosure != null && !directClosureFound) {
|
||||
final boolean advanced;
|
||||
if (isLeaf) {
|
||||
advanced = this.tryAdvanceEndClosure(this.nearestClosure.getType(), line) != ClosureTypeAdvanceResult.IGNORED;
|
||||
} else {
|
||||
advanced = this.tryAdvanceEndClosure(this.nearestClosure, line).advanced();
|
||||
}
|
||||
if (advanced) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (this.nearestClosure == null || !isLeaf) { // leaf take the priority and doesn't allow any other nested type
|
||||
for (ClosureType type : computedTypes) {
|
||||
if (this.tryAdvanceStartClosure(type, line)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
// only valid for leaf closure type
|
||||
public ClosureTypeAdvanceResult tryAdvanceEndClosure(@NotNull ClosureType type, @NotNull StringReader line) {
|
||||
Preconditions.checkArgument(ClosureType.LEAFS.contains(type), "Only leaf closure can be advanced using its type only, for other, use the closure equivalent method to take in account nested closure");
|
||||
Preconditions.checkState(this.nearestClosure != null && this.nearestClosure.getType() == type, "Need an direct upper closure of " + type);
|
||||
|
||||
char previousChar = '\0';
|
||||
if (line.getCursor() >= 1) {
|
||||
previousChar = line.peek(-1);
|
||||
}
|
||||
|
||||
if (line.trySkipString(type.end)) { // closure has been consumed
|
||||
// skip escape closed closure
|
||||
if (type.end.length() == 1 && type.start.equals(type.end) && ClosureType.ALLOW_ESCAPE.contains(type)) {
|
||||
if (previousChar == '\\') {
|
||||
return ClosureTypeAdvanceResult.SKIPPED;
|
||||
}
|
||||
}
|
||||
|
||||
this.nearestClosure.onEnd(line);
|
||||
if (this.nearestClosure.parent() != null) {
|
||||
this.nearestClosure = this.nearestClosure.parent();
|
||||
} else {
|
||||
this.nearestClosure = null;
|
||||
}
|
||||
return ClosureTypeAdvanceResult.CHANGED;
|
||||
}
|
||||
return ClosureTypeAdvanceResult.IGNORED;
|
||||
}
|
||||
|
||||
public boolean skipComment(@NotNull StringReader line) {
|
||||
int previousCursor = line.getCursor();
|
||||
if (this.closures.contains(ClosureType.COMMENT) || this.advanceEnclosure(ClosureType.COMMENT, line)) { // open comment?
|
||||
ClosureAdvanceResult result;
|
||||
while ((result = this.advanceEnclosure0(ClosureType.COMMENT, line)) != ClosureAdvanceResult.CHANGED && line.canRead()) { // closed comment?
|
||||
if (result == ClosureAdvanceResult.IGNORED) {
|
||||
if ((this.nearestClosure != null && this.nearestClosure.getType() == ClosureType.COMMENT) ||
|
||||
this.tryAdvanceStartClosure(ClosureType.COMMENT, line)) { // open comment?
|
||||
ClosureTypeAdvanceResult result;
|
||||
while ((result = this.tryAdvanceEndClosure(ClosureType.COMMENT, line)) != ClosureTypeAdvanceResult.CHANGED && line.canRead()) { // closed comment?
|
||||
if (result == ClosureTypeAdvanceResult.IGNORED) {
|
||||
line.skip();
|
||||
}
|
||||
}
|
||||
|
@ -96,7 +146,7 @@ public class LineParser {
|
|||
return false;
|
||||
}
|
||||
|
||||
public boolean skipCommentOrWhitespace(StringReader line) {
|
||||
public boolean skipCommentOrWhitespace(@NotNull StringReader line) {
|
||||
boolean skipped = false;
|
||||
while (this.skipComment(line) || line.skipWhitespace() > 0) {
|
||||
skipped = true;
|
||||
|
@ -104,7 +154,7 @@ public class LineParser {
|
|||
return skipped;
|
||||
}
|
||||
|
||||
public boolean trySkipCommentOrWhitespaceUntil(StringReader line, char terminator) {
|
||||
public boolean trySkipCommentOrWhitespaceUntil(@NotNull StringReader line, char terminator) {
|
||||
int previousCursor = line.getCursor();
|
||||
boolean skipped = this.skipCommentOrWhitespace(line);
|
||||
if (skipped && line.canRead() && line.peek() != terminator) {
|
||||
|
@ -115,11 +165,11 @@ public class LineParser {
|
|||
return skipped;
|
||||
}
|
||||
|
||||
public boolean peekSingleLineComment(StringReader line) {
|
||||
return line.peek() == '/' && line.canRead(2) && line.peek(1) == '/';
|
||||
public boolean peekSingleLineComment(@NotNull StringReader line) {
|
||||
return line.canRead(2) && line.peek() == '/' && line.peek(1) == '/';
|
||||
}
|
||||
|
||||
public boolean consumeImports(StringReader line, ImportCollector collector) {
|
||||
public boolean consumeImports(@NotNull StringReader line, @NotNull ImportCollector collector) {
|
||||
outerLoop:
|
||||
while (line.canRead()) {
|
||||
IterativeStep step;
|
||||
|
@ -141,13 +191,13 @@ public class LineParser {
|
|||
|
||||
// not commented
|
||||
char c = line.peek();
|
||||
if (AnnotationSteps.canStart(c)) { // handle annotation with param to avoid open curly bracket that occur in array argument
|
||||
this.stepManager.enqueue(new AnnotationSteps());
|
||||
if (AnnotationSkipSteps.canStart(c)) { // handle annotation with param to avoid open curly bracket that occur in array argument
|
||||
this.stepManager.enqueue(new AnnotationSkipSteps());
|
||||
continue;
|
||||
} else if (c == '{') {
|
||||
return true;
|
||||
} else if (ImportSteps.canStart(line)) {
|
||||
this.stepManager.enqueue(new ImportSteps(collector));
|
||||
} else if (ImportStatementSteps.canStart(line)) {
|
||||
this.stepManager.enqueue(new ImportStatementSteps(collector));
|
||||
continue;
|
||||
}
|
||||
|
||||
|
@ -156,6 +206,7 @@ public class LineParser {
|
|||
return false;
|
||||
}
|
||||
|
||||
@NotNull
|
||||
public StepManager getSteps() {
|
||||
return this.stepManager;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,33 @@
|
|||
package io.papermc.generator.rewriter.parser.closure;
|
||||
|
||||
public class AbstractClosure implements Closure {
|
||||
|
||||
private final ClosureType type;
|
||||
private Closure parent;
|
||||
|
||||
protected AbstractClosure(ClosureType type) {
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ClosureType getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Closure parent() {
|
||||
return this.parent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Closure[" + this.type.name() + "](start=" + this.type.start + ", end=" + this.type.end + ")";
|
||||
}
|
||||
|
||||
public void setParent(Closure parent) {
|
||||
if (this.parent != null && parent != null) {
|
||||
throw new IllegalStateException("Cannot set this parent closure since it is already in a closure: " + this.parent);
|
||||
}
|
||||
this.parent = parent;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,52 @@
|
|||
package io.papermc.generator.rewriter.parser.closure;
|
||||
|
||||
import io.papermc.generator.rewriter.parser.ParserException;
|
||||
import io.papermc.generator.rewriter.parser.StringReader;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
import java.util.function.Supplier;
|
||||
|
||||
public interface Closure {
|
||||
|
||||
ClosureType getType();
|
||||
|
||||
@Nullable
|
||||
Closure parent();
|
||||
|
||||
default boolean hasUpperClosure(Closure closure) {
|
||||
Closure parent = this;
|
||||
while (parent != null) {
|
||||
if (parent == closure) {
|
||||
return true;
|
||||
}
|
||||
parent = parent.parent();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
default void onStart(StringReader line) {
|
||||
|
||||
}
|
||||
|
||||
default void onEnd(StringReader line) {
|
||||
|
||||
}
|
||||
|
||||
static Closure create(ClosureType type) {
|
||||
class SpecialClosure {
|
||||
public static final Supplier<Closure> PARAGRAPH = () -> new AbstractClosure(ClosureType.PARAGRAPH) {
|
||||
|
||||
@Override
|
||||
public void onStart(StringReader line) {
|
||||
if (line.canRead()) {
|
||||
throw new ParserException("Paragraph closure start must be followed by a newline", line);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
if (type == ClosureType.PARAGRAPH) {
|
||||
return SpecialClosure.PARAGRAPH.get();
|
||||
}
|
||||
return new AbstractClosure(type);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,38 @@
|
|||
package io.papermc.generator.rewriter.parser.closure;
|
||||
|
||||
import java.util.Comparator;
|
||||
import java.util.EnumSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public enum ClosureType {
|
||||
PARENTHESIS("(", ")"),
|
||||
CURLY_BRACKET("{", "}"),
|
||||
BRACKET("[", "]"),
|
||||
COMMENT("/*", "*/"),
|
||||
PARAGRAPH("\"\"\"", "\"\"\""),
|
||||
STRING("\"", "\""),
|
||||
CHAR("'", "'");
|
||||
|
||||
public final String start;
|
||||
public final String end;
|
||||
|
||||
ClosureType(String start, String end) {
|
||||
this.start = start;
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public static final EnumSet<ClosureType> ALLOW_ESCAPE = EnumSet.of(STRING, CHAR, PARAGRAPH);
|
||||
public static final EnumSet<ClosureType> LEAFS = EnumSet.of(COMMENT, STRING, CHAR, PARAGRAPH);
|
||||
|
||||
private static final List<ClosureType> CHECK_FIRST = List.of(PARAGRAPH);
|
||||
|
||||
public static List<ClosureType> prioritySort(Set<ClosureType> types) {
|
||||
return types.stream()
|
||||
.sorted(Comparator.comparingInt(o -> {
|
||||
int index = CHECK_FIRST.indexOf(o);
|
||||
return index == -1 ? CHECK_FIRST.size() : index;
|
||||
}))
|
||||
.toList();
|
||||
}
|
||||
}
|
|
@ -1,19 +1,23 @@
|
|||
package io.papermc.generator.rewriter.parser.step.model;
|
||||
|
||||
import io.papermc.generator.rewriter.parser.ClosureAdvanceResult;
|
||||
import io.papermc.generator.rewriter.parser.ClosureType;
|
||||
import io.papermc.generator.rewriter.parser.LineParser;
|
||||
import io.papermc.generator.rewriter.parser.ParserException;
|
||||
import io.papermc.generator.rewriter.parser.ProtoTypeName;
|
||||
import io.papermc.generator.rewriter.parser.ClosureAdvanceResult;
|
||||
import io.papermc.generator.rewriter.parser.closure.Closure;
|
||||
import io.papermc.generator.rewriter.parser.closure.ClosureType;
|
||||
import io.papermc.generator.rewriter.parser.step.IterativeStep;
|
||||
import io.papermc.generator.rewriter.parser.step.StepHolder;
|
||||
import io.papermc.generator.rewriter.parser.StringReader;
|
||||
import io.papermc.generator.utils.NamingManager;
|
||||
import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
// start once "@" is detected unless commented
|
||||
// order is: skipAtSign -> skipPartName -> checkOpenParenthesis (-> skipParentheses)
|
||||
public final class AnnotationSteps implements StepHolder {
|
||||
// order is: skipAtSign -> skipPartName -> checkAnnotationName -> checkOpenParenthesis (-> skipParentheses)
|
||||
public final class AnnotationSkipSteps implements StepHolder {
|
||||
|
||||
public static boolean canStart(char currentChar) {
|
||||
return currentChar == '@';
|
||||
|
@ -22,6 +26,7 @@ public final class AnnotationSteps implements StepHolder {
|
|||
private final IterativeStep skipParenthesesStep = IterativeStep.createUntil(this::skipParentheses);
|
||||
|
||||
private @MonotonicNonNull ProtoTypeName name;
|
||||
private Closure parenthesisClosure;
|
||||
|
||||
public void skipAtSign(StringReader line, LineParser parser) {
|
||||
line.skip(); // skip @
|
||||
|
@ -43,20 +48,29 @@ public final class AnnotationSteps implements StepHolder {
|
|||
|
||||
this.name = line.getPartNameUntil('(', parser::skipCommentOrWhitespace, this.name);
|
||||
|
||||
if (line.canRead() && parser.peekSingleLineComment(line)) {
|
||||
if (parser.peekSingleLineComment(line)) {
|
||||
// ignore single line comment at the end and allow the name to continue
|
||||
line.setCursor(line.getTotalLength());
|
||||
}
|
||||
return !line.canRead();
|
||||
}
|
||||
|
||||
private static final List<ClosureType> IGNORE_NESTED_CLOSURES;
|
||||
static {
|
||||
Set<ClosureType> types = new HashSet<>(ClosureType.LEAFS.size() + 1);
|
||||
types.addAll(ClosureType.LEAFS);
|
||||
types.add(ClosureType.PARENTHESIS); // skip nested annotation too
|
||||
|
||||
IGNORE_NESTED_CLOSURES = ClosureType.prioritySort(types);
|
||||
}
|
||||
|
||||
public boolean skipParentheses(StringReader line, LineParser parser) {
|
||||
ClosureAdvanceResult result;
|
||||
while ((result = parser.advanceEnclosure0(ClosureType.PARENTHESIS, line)) != ClosureAdvanceResult.CHANGED) { // closed parenthesis?
|
||||
while (!(result = parser.tryAdvanceEndClosure(this.parenthesisClosure, line)).found()) {
|
||||
if (!line.canRead()) { // parenthesis on another line?
|
||||
return true;
|
||||
}
|
||||
if (result == ClosureAdvanceResult.IGNORED) {
|
||||
if (!result.advanced() && !parser.trySkipNestedClosures(this.parenthesisClosure, line, IGNORE_NESTED_CLOSURES)) {
|
||||
line.skip();
|
||||
}
|
||||
}
|
||||
|
@ -88,7 +102,8 @@ public final class AnnotationSteps implements StepHolder {
|
|||
return true;
|
||||
}
|
||||
|
||||
if (parser.advanceEnclosure(ClosureType.PARENTHESIS, line)) { // open parenthesis?
|
||||
if (parser.tryAdvanceStartClosure(ClosureType.PARENTHESIS, line)) { // open parenthesis?
|
||||
this.parenthesisClosure = parser.getNearestClosure();
|
||||
parser.getSteps().addPriority(this.skipParenthesesStep);
|
||||
}
|
||||
return false;
|
|
@ -12,7 +12,7 @@ import org.checkerframework.checker.nullness.qual.MonotonicNonNull;
|
|||
|
||||
// start once "import" is detected unless commented
|
||||
// order is: enforceSpace -> checkStatic (-> enforceSpace) -> getPartName (-> skipUntilSemicolonAfterStar) -> collectImport
|
||||
public final class ImportSteps implements StepHolder {
|
||||
public final class ImportStatementSteps implements StepHolder {
|
||||
|
||||
public static boolean canStart(StringReader line) {
|
||||
return line.trySkipString("import");
|
||||
|
@ -28,12 +28,12 @@ public final class ImportSteps implements StepHolder {
|
|||
private boolean isStatic;
|
||||
private @MonotonicNonNull ProtoTypeName name;
|
||||
|
||||
public ImportSteps(ImportCollector collector) {
|
||||
public ImportStatementSteps(ImportCollector collector) {
|
||||
this.collector = collector;
|
||||
}
|
||||
|
||||
public void enforceSpace(StringReader line, LineParser parser) {
|
||||
if (line.canRead() && parser.peekSingleLineComment(line)) {
|
||||
if (parser.peekSingleLineComment(line)) {
|
||||
// ignore single line comment at the end of import/static
|
||||
line.setCursor(line.getTotalLength());
|
||||
return;
|
|
@ -1,6 +1,10 @@
|
|||
package io.papermc.generator.rewriter.data.sample.parser.area;
|
||||
|
||||
@AnnotationTrapClass.Trapped(strings = {"trap: ) \" ) {"}, chars = {')', '{', '\''}, paragraphs = """
|
||||
@AnnotationTrapClass.Trapped(strings = {"trap: ) \" ) {"}, annotation = @AnnotationTrapClass.Trapped2(strings = {"trap: ) \" ) {"}, chars = {')', '{', '\''}, paragraphs = """
|
||||
)
|
||||
\"\"\"
|
||||
{
|
||||
""", clazz = AnnotationTrapClass.Trapped.class), chars = {')', '{', '\''}, paragraphs = """
|
||||
)
|
||||
\"\"\"
|
||||
{
|
||||
|
@ -13,5 +17,19 @@ public class AnnotationTrapClass { // << 33
|
|||
char[] chars();
|
||||
|
||||
String[] paragraphs();
|
||||
|
||||
Trapped2 annotation();
|
||||
}
|
||||
|
||||
@interface Trapped2 {
|
||||
|
||||
String[] strings();
|
||||
|
||||
char[] chars();
|
||||
|
||||
String[] paragraphs();
|
||||
|
||||
Class<? extends Trapped> clazz();
|
||||
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue