From 2586748a25b90b3d7f272a8f06bf80ea4628550e Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Wed, 15 Jan 2025 18:17:53 -0800 Subject: [PATCH 001/173] When resolving maven pom properties give system properties precedence. This matches Maven's own behavior. --- .../openrewrite/maven/tree/ResolvedPom.java | 4 ++- .../openrewrite/maven/MavenParserTest.java | 29 +++++++++++++++++++ 2 files changed, 32 insertions(+), 1 deletion(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java b/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java index d23f22dbe2c..7f5a0d343e1 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java @@ -281,7 +281,9 @@ public String getPackaging() { if (property == null) { return null; } - String propVal = properties.get(property); + // Maven allows system properties to override project properties + // This facilitates the usage of "-D" arguments on the command line to customize builds + String propVal = System.getProperty(property, properties.get(property)); if (propVal != null) { return propVal; } diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java index cef61f90ef3..3b3367c23ff 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/MavenParserTest.java @@ -3358,4 +3358,33 @@ void exclusionsAffectTransitiveDependencies() { ) ); } + + @Test + void systemPropertyTakesPrecedence() { + System.setProperty("hatversion", "2.3.0"); + rewriteRun( + pomXml( + """ + + com.mycompany.app + parent + 1.0-SNAPSHOT + pom + parent + http://www.example.com + + SYSTEM_PROPERTY_SHOULD_OVERRIDE_THIS + + + + org.springframework.hateoas + spring-hateoas + ${hatversion} + + + + """ + ) + ); + } } From 6cd1e2aa00f17fe24ab396ff0fb558f357cd6b47 Mon Sep 17 00:00:00 2001 From: Greg Oledzki Date: Thu, 16 Jan 2025 06:14:27 +0100 Subject: [PATCH 002/173] Refactoring, extract normalizeNewLines() (#4904) --- .../org/openrewrite/format/LineBreaks.java | 34 +++++++++++++++++++ .../format/NormalizeLineBreaksVisitor.java | 18 ++-------- .../format/NormalizeLineBreaksVisitor.java | 19 ++--------- .../format/NormalizeLineBreaksVisitor.java | 20 ++--------- 4 files changed, 40 insertions(+), 51 deletions(-) create mode 100644 rewrite-core/src/main/java/org/openrewrite/format/LineBreaks.java diff --git a/rewrite-core/src/main/java/org/openrewrite/format/LineBreaks.java b/rewrite-core/src/main/java/org/openrewrite/format/LineBreaks.java new file mode 100644 index 00000000000..da2bdfc05ea --- /dev/null +++ b/rewrite-core/src/main/java/org/openrewrite/format/LineBreaks.java @@ -0,0 +1,34 @@ +/* + * Copyright 2025 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.format; + +public class LineBreaks { + public static String normalizeNewLines(String text, boolean useCrlf) { + if (!text.contains("\n")) { + return text; + } + StringBuilder normalized = new StringBuilder(); + for (int i = 0; i < text.length(); i++) { + char c = text.charAt(i); + if (useCrlf && c == '\n' && (i == 0 || text.charAt(i - 1) != '\r')) { + normalized.append('\r').append('\n'); + } else if (useCrlf || c != '\r') { + normalized.append(c); + } + } + return normalized.toString(); + } +} diff --git a/rewrite-java/src/main/java/org/openrewrite/java/format/NormalizeLineBreaksVisitor.java b/rewrite-java/src/main/java/org/openrewrite/java/format/NormalizeLineBreaksVisitor.java index 1e6f9e72aae..a67c26f7ff5 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/format/NormalizeLineBreaksVisitor.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/format/NormalizeLineBreaksVisitor.java @@ -24,6 +24,8 @@ import org.openrewrite.java.tree.*; import org.openrewrite.style.GeneralFormatStyle; +import static org.openrewrite.format.LineBreaks.normalizeNewLines; + public class NormalizeLineBreaksVisitor

extends JavaIsoVisitor

{ @Nullable private final Tree stopAfter; @@ -66,22 +68,6 @@ public Space visitSpace(Space space, Space.Location loc, P p) { })); } - private static String normalizeNewLines(String text, boolean useCrlf) { - if (!text.contains("\n")) { - return text; - } - StringBuilder normalized = new StringBuilder(); - for (int i = 0; i < text.length(); i++) { - char c = text.charAt(i); - if (useCrlf && c == '\n' && (i == 0 || text.charAt(i - 1) != '\r')) { - normalized.append('\r').append('\n'); - } else if (useCrlf || c != '\r') { - normalized.append(c); - } - } - return normalized.toString(); - } - @Override public J postVisit(J tree, P p) { if (stopAfter != null && stopAfter.isScope(tree)) { diff --git a/rewrite-xml/src/main/java/org/openrewrite/xml/format/NormalizeLineBreaksVisitor.java b/rewrite-xml/src/main/java/org/openrewrite/xml/format/NormalizeLineBreaksVisitor.java index 90467568ff4..758ae736820 100644 --- a/rewrite-xml/src/main/java/org/openrewrite/xml/format/NormalizeLineBreaksVisitor.java +++ b/rewrite-xml/src/main/java/org/openrewrite/xml/format/NormalizeLineBreaksVisitor.java @@ -21,6 +21,8 @@ import org.openrewrite.xml.XmlIsoVisitor; import org.openrewrite.xml.tree.Xml; +import static org.openrewrite.format.LineBreaks.normalizeNewLines; + public class NormalizeLineBreaksVisitor

extends XmlIsoVisitor

{ @Nullable private final Tree stopAfter; @@ -51,23 +53,6 @@ public NormalizeLineBreaksVisitor(GeneralFormatStyle style, @Nullable Tree stopA return super.visit(tree, p); } - private static String normalizeNewLines(String text, boolean useCrlf) { - if (!text.contains("\n")) { - return text; - } - StringBuilder normalized = new StringBuilder(); - char[] charArray = text.toCharArray(); - for (int i = 0; i < charArray.length; i++) { - char c = charArray[i]; - if (useCrlf && c == '\n' && (i == 0 || text.charAt(i - 1) != '\r')) { - normalized.append('\r').append('\n'); - } else if (useCrlf || c != '\r') { - normalized.append(c); - } - } - return normalized.toString(); - } - @Override public @Nullable Xml postVisit(Xml tree, P p) { if (stopAfter != null && stopAfter.isScope(tree)) { diff --git a/rewrite-yaml/src/main/java/org/openrewrite/yaml/format/NormalizeLineBreaksVisitor.java b/rewrite-yaml/src/main/java/org/openrewrite/yaml/format/NormalizeLineBreaksVisitor.java index b50e8e5db17..1077bae9366 100644 --- a/rewrite-yaml/src/main/java/org/openrewrite/yaml/format/NormalizeLineBreaksVisitor.java +++ b/rewrite-yaml/src/main/java/org/openrewrite/yaml/format/NormalizeLineBreaksVisitor.java @@ -21,6 +21,8 @@ import org.openrewrite.yaml.YamlIsoVisitor; import org.openrewrite.yaml.tree.Yaml; +import static org.openrewrite.format.LineBreaks.normalizeNewLines; + public class NormalizeLineBreaksVisitor

extends YamlIsoVisitor

{ private final GeneralFormatStyle generalFormatStyle; @@ -55,22 +57,4 @@ public NormalizeLineBreaksVisitor(GeneralFormatStyle generalFormatStyle, @Nullab } return y; } - - private static String normalizeNewLines(String text, boolean useCrlf) { - if (!text.contains("\n")) { - return text; - } - - StringBuilder normalized = new StringBuilder(); - char[] charArray = text.toCharArray(); - for (int i = 0; i < charArray.length; i++) { - char c = charArray[i]; - if (useCrlf && c == '\n' && (i == 0 || text.charAt(i - 1) != '\r')) { - normalized.append('\r').append('\n'); - } else if (useCrlf || c != '\r') { - normalized.append(c); - } - } - return normalized.toString(); - } } From 462dc74efaacc3d1f548ab6214dd17bd24b8da61 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Thu, 16 Jan 2025 10:16:24 +0100 Subject: [PATCH 003/173] Correct TOML table parsing (#4910) * Correct TOML table parsing Tables in TOML are not nested. I.e. the following should result in an AST with two top-level tables: ```toml [table-1] key1 = "some string" key2 = 123 [table-2] key1 = "another string" key2 = 456 ``` This has now been corrected in the parser. * Adjust Gradle build script for ANTLR generation * Add missing line terminators --- rewrite-toml/build.gradle.kts | 8 +- rewrite-toml/src/main/antlr/TomlParser.g4 | 7 +- .../toml/internal/TomlParserVisitor.java | 4 +- .../toml/internal/grammar/TomlLexer.interp | 5 +- .../toml/internal/grammar/TomlLexer.java | 801 +++++++++--------- .../toml/internal/grammar/TomlParser.interp | 2 +- .../toml/internal/grammar/TomlParser.java | 117 ++- .../org/openrewrite/toml/TomlParserTest.java | 14 +- 8 files changed, 481 insertions(+), 477 deletions(-) diff --git a/rewrite-toml/build.gradle.kts b/rewrite-toml/build.gradle.kts index 13534f609c6..b7e2005ef2e 100644 --- a/rewrite-toml/build.gradle.kts +++ b/rewrite-toml/build.gradle.kts @@ -2,6 +2,10 @@ plugins { id("org.openrewrite.build.language-library") } +val antlrGeneration by configurations.creating { + extendsFrom(configurations.implementation.get()) +} + tasks.register("generateAntlrSources") { mainClass.set("org.antlr.v4.Tool") @@ -11,7 +15,7 @@ tasks.register("generateAntlrSources") { "-visitor" ) + fileTree("src/main/antlr").matching { include("**/*.g4") }.map { it.path } - classpath = sourceSets["main"].runtimeClasspath + classpath = antlrGeneration } dependencies { @@ -19,6 +23,8 @@ dependencies { implementation("org.antlr:antlr4-runtime:4.11.1") implementation("io.micrometer:micrometer-core:1.9.+") + antlrGeneration("org.antlr:antlr4:4.11.1") + compileOnly(project(":rewrite-test")) testImplementation(project(":rewrite-test")) diff --git a/rewrite-toml/src/main/antlr/TomlParser.g4 b/rewrite-toml/src/main/antlr/TomlParser.g4 index 46e51369ef8..c177f35ce54 100644 --- a/rewrite-toml/src/main/antlr/TomlParser.g4 +++ b/rewrite-toml/src/main/antlr/TomlParser.g4 @@ -109,8 +109,7 @@ dateTime ; commentOrNl - : COMMENT NL - | NL + : COMMENT? NL ; array @@ -124,7 +123,7 @@ table ; standardTable - : L_BRACKET key R_BRACKET (commentOrNl* expression)* + : L_BRACKET key R_BRACKET (commentOrNl* keyValue)* ; inlineTable @@ -133,5 +132,5 @@ inlineTable ; arrayTable - : DOUBLE_L_BRACKET key DOUBLE_R_BRACKET (commentOrNl* expression)* + : DOUBLE_L_BRACKET key DOUBLE_R_BRACKET (commentOrNl* keyValue)* ; diff --git a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/TomlParserVisitor.java b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/TomlParserVisitor.java index e72c3f29f44..61c8a4a7551 100644 --- a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/TomlParserVisitor.java +++ b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/TomlParserVisitor.java @@ -384,7 +384,7 @@ public Toml visitStandardTable(TomlParser.StandardTableContext ctx) { Toml.Identifier tableName = visitKey(c.key()); TomlRightPadded nameRightPadded = TomlRightPadded.build(tableName).withAfter(sourceBefore("]")); - List values = c.expression(); + List values = c.keyValue(); List> elements = new ArrayList<>(); for (int i = 0; i < values.size(); i++) { elements.add(TomlRightPadded.build(visit(values.get(i)))); @@ -407,7 +407,7 @@ public Toml visitArrayTable(TomlParser.ArrayTableContext ctx) { Toml.Identifier tableName = visitKey(c.key()); TomlRightPadded nameRightPadded = TomlRightPadded.build(tableName).withAfter(sourceBefore("]]")); - List values = c.expression(); + List values = c.keyValue(); List> elements = new ArrayList<>(); for (int i = 0; i < values.size(); i++) { elements.add(TomlRightPadded.build(visit(values.get(i)))); diff --git a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.interp b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.interp index e1b1838c219..45ff08e0e5f 100644 --- a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.interp +++ b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.interp @@ -162,9 +162,6 @@ ARRAY_LOCAL_TIME channel names: DEFAULT_TOKEN_CHANNEL HIDDEN -null -null -COMMENTS_CHANNEL mode names: DEFAULT_MODE @@ -173,4 +170,4 @@ INLINE_TABLE_MODE ARRAY_MODE atn: -[4, 0, 32, 671, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 1, 0, 4, 0, 184, 8, 0, 11, 0, 12, 0, 185, 1, 0, 1, 0, 1, 1, 3, 1, 191, 8, 1, 1, 1, 4, 1, 194, 8, 1, 11, 1, 12, 1, 195, 1, 2, 1, 2, 5, 2, 200, 8, 2, 10, 2, 12, 2, 203, 9, 2, 1, 2, 1, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 235, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 5, 15, 256, 8, 15, 10, 15, 12, 15, 259, 9, 15, 1, 15, 1, 15, 1, 16, 1, 16, 5, 16, 265, 8, 16, 10, 16, 12, 16, 268, 9, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 4, 17, 275, 8, 17, 11, 17, 12, 17, 276, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 301, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 3, 22, 307, 8, 22, 1, 22, 1, 22, 3, 22, 311, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 5, 24, 324, 8, 24, 10, 24, 12, 24, 327, 9, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 5, 26, 345, 8, 26, 10, 26, 12, 26, 348, 9, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 3, 27, 358, 8, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 5, 28, 366, 8, 28, 10, 28, 12, 28, 369, 9, 28, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 378, 8, 30, 3, 30, 380, 8, 30, 1, 30, 1, 30, 1, 31, 3, 31, 385, 8, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 3, 32, 394, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 404, 8, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 3, 37, 413, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 4, 37, 420, 8, 37, 11, 37, 12, 37, 421, 3, 37, 424, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 435, 8, 38, 10, 38, 12, 38, 438, 9, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 5, 39, 449, 8, 39, 10, 39, 12, 39, 452, 9, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 5, 40, 463, 8, 40, 10, 40, 12, 40, 466, 9, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 4, 48, 494, 8, 48, 11, 48, 12, 48, 495, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 3, 50, 505, 8, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 3, 51, 513, 8, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 4, 257, 266, 325, 346, 0, 89, 4, 1, 6, 2, 8, 3, 10, 4, 12, 5, 14, 6, 16, 7, 18, 8, 20, 9, 22, 10, 24, 0, 26, 0, 28, 0, 30, 0, 32, 0, 34, 11, 36, 12, 38, 13, 40, 14, 42, 15, 44, 0, 46, 16, 48, 0, 50, 0, 52, 17, 54, 0, 56, 18, 58, 0, 60, 0, 62, 0, 64, 19, 66, 20, 68, 21, 70, 0, 72, 0, 74, 0, 76, 0, 78, 22, 80, 23, 82, 24, 84, 25, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100, 0, 102, 0, 104, 0, 106, 0, 108, 0, 110, 0, 112, 26, 114, 27, 116, 28, 118, 29, 120, 30, 122, 0, 124, 0, 126, 31, 128, 0, 130, 0, 132, 0, 134, 0, 136, 32, 138, 0, 140, 0, 142, 0, 144, 0, 146, 0, 148, 0, 150, 0, 152, 0, 154, 0, 156, 0, 158, 0, 160, 0, 162, 0, 164, 0, 166, 0, 168, 0, 170, 0, 172, 0, 174, 0, 176, 0, 178, 0, 180, 0, 4, 0, 1, 2, 3, 16, 2, 0, 9, 9, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 10, 10, 34, 34, 92, 92, 2, 0, 10, 10, 39, 39, 2, 0, 45, 45, 95, 95, 2, 0, 34, 34, 92, 92, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 65, 70, 97, 102, 1, 0, 49, 57, 1, 0, 48, 55, 1, 0, 48, 49, 3, 0, 32, 32, 84, 84, 116, 116, 680, 0, 4, 1, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 1, 40, 1, 0, 0, 0, 1, 42, 1, 0, 0, 0, 1, 44, 1, 0, 0, 0, 1, 46, 1, 0, 0, 0, 1, 50, 1, 0, 0, 0, 1, 52, 1, 0, 0, 0, 1, 54, 1, 0, 0, 0, 1, 56, 1, 0, 0, 0, 1, 64, 1, 0, 0, 0, 1, 66, 1, 0, 0, 0, 1, 68, 1, 0, 0, 0, 1, 78, 1, 0, 0, 0, 1, 80, 1, 0, 0, 0, 1, 82, 1, 0, 0, 0, 1, 84, 1, 0, 0, 0, 1, 112, 1, 0, 0, 0, 1, 114, 1, 0, 0, 0, 1, 116, 1, 0, 0, 0, 1, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 3, 136, 1, 0, 0, 0, 3, 138, 1, 0, 0, 0, 3, 140, 1, 0, 0, 0, 3, 142, 1, 0, 0, 0, 3, 144, 1, 0, 0, 0, 3, 146, 1, 0, 0, 0, 3, 148, 1, 0, 0, 0, 3, 150, 1, 0, 0, 0, 3, 152, 1, 0, 0, 0, 3, 154, 1, 0, 0, 0, 3, 156, 1, 0, 0, 0, 3, 158, 1, 0, 0, 0, 3, 160, 1, 0, 0, 0, 3, 162, 1, 0, 0, 0, 3, 164, 1, 0, 0, 0, 3, 166, 1, 0, 0, 0, 3, 168, 1, 0, 0, 0, 3, 170, 1, 0, 0, 0, 3, 172, 1, 0, 0, 0, 3, 174, 1, 0, 0, 0, 3, 176, 1, 0, 0, 0, 3, 178, 1, 0, 0, 0, 3, 180, 1, 0, 0, 0, 4, 183, 1, 0, 0, 0, 6, 193, 1, 0, 0, 0, 8, 197, 1, 0, 0, 0, 10, 206, 1, 0, 0, 0, 12, 208, 1, 0, 0, 0, 14, 211, 1, 0, 0, 0, 16, 213, 1, 0, 0, 0, 18, 216, 1, 0, 0, 0, 20, 220, 1, 0, 0, 0, 22, 222, 1, 0, 0, 0, 24, 226, 1, 0, 0, 0, 26, 228, 1, 0, 0, 0, 28, 230, 1, 0, 0, 0, 30, 236, 1, 0, 0, 0, 32, 242, 1, 0, 0, 0, 34, 252, 1, 0, 0, 0, 36, 262, 1, 0, 0, 0, 38, 274, 1, 0, 0, 0, 40, 278, 1, 0, 0, 0, 42, 282, 1, 0, 0, 0, 44, 286, 1, 0, 0, 0, 46, 300, 1, 0, 0, 0, 48, 310, 1, 0, 0, 0, 50, 312, 1, 0, 0, 0, 52, 317, 1, 0, 0, 0, 54, 334, 1, 0, 0, 0, 56, 339, 1, 0, 0, 0, 58, 355, 1, 0, 0, 0, 60, 361, 1, 0, 0, 0, 62, 370, 1, 0, 0, 0, 64, 373, 1, 0, 0, 0, 66, 384, 1, 0, 0, 0, 68, 393, 1, 0, 0, 0, 70, 403, 1, 0, 0, 0, 72, 405, 1, 0, 0, 0, 74, 407, 1, 0, 0, 0, 76, 409, 1, 0, 0, 0, 78, 412, 1, 0, 0, 0, 80, 427, 1, 0, 0, 0, 82, 441, 1, 0, 0, 0, 84, 455, 1, 0, 0, 0, 86, 469, 1, 0, 0, 0, 88, 474, 1, 0, 0, 0, 90, 477, 1, 0, 0, 0, 92, 480, 1, 0, 0, 0, 94, 482, 1, 0, 0, 0, 96, 485, 1, 0, 0, 0, 98, 488, 1, 0, 0, 0, 100, 491, 1, 0, 0, 0, 102, 497, 1, 0, 0, 0, 104, 504, 1, 0, 0, 0, 106, 506, 1, 0, 0, 0, 108, 514, 1, 0, 0, 0, 110, 520, 1, 0, 0, 0, 112, 523, 1, 0, 0, 0, 114, 529, 1, 0, 0, 0, 116, 535, 1, 0, 0, 0, 118, 539, 1, 0, 0, 0, 120, 543, 1, 0, 0, 0, 122, 547, 1, 0, 0, 0, 124, 551, 1, 0, 0, 0, 126, 555, 1, 0, 0, 0, 128, 559, 1, 0, 0, 0, 130, 563, 1, 0, 0, 0, 132, 567, 1, 0, 0, 0, 134, 571, 1, 0, 0, 0, 136, 576, 1, 0, 0, 0, 138, 580, 1, 0, 0, 0, 140, 584, 1, 0, 0, 0, 142, 588, 1, 0, 0, 0, 144, 592, 1, 0, 0, 0, 146, 597, 1, 0, 0, 0, 148, 602, 1, 0, 0, 0, 150, 607, 1, 0, 0, 0, 152, 611, 1, 0, 0, 0, 154, 615, 1, 0, 0, 0, 156, 619, 1, 0, 0, 0, 158, 623, 1, 0, 0, 0, 160, 627, 1, 0, 0, 0, 162, 631, 1, 0, 0, 0, 164, 635, 1, 0, 0, 0, 166, 639, 1, 0, 0, 0, 168, 643, 1, 0, 0, 0, 170, 647, 1, 0, 0, 0, 172, 651, 1, 0, 0, 0, 174, 655, 1, 0, 0, 0, 176, 659, 1, 0, 0, 0, 178, 663, 1, 0, 0, 0, 180, 667, 1, 0, 0, 0, 182, 184, 7, 0, 0, 0, 183, 182, 1, 0, 0, 0, 184, 185, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 185, 186, 1, 0, 0, 0, 186, 187, 1, 0, 0, 0, 187, 188, 6, 0, 0, 0, 188, 5, 1, 0, 0, 0, 189, 191, 5, 13, 0, 0, 190, 189, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 194, 5, 10, 0, 0, 193, 190, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 7, 1, 0, 0, 0, 197, 201, 5, 35, 0, 0, 198, 200, 8, 1, 0, 0, 199, 198, 1, 0, 0, 0, 200, 203, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 204, 1, 0, 0, 0, 203, 201, 1, 0, 0, 0, 204, 205, 6, 2, 1, 0, 205, 9, 1, 0, 0, 0, 206, 207, 5, 91, 0, 0, 207, 11, 1, 0, 0, 0, 208, 209, 5, 91, 0, 0, 209, 210, 5, 91, 0, 0, 210, 13, 1, 0, 0, 0, 211, 212, 5, 93, 0, 0, 212, 15, 1, 0, 0, 0, 213, 214, 5, 93, 0, 0, 214, 215, 5, 93, 0, 0, 215, 17, 1, 0, 0, 0, 216, 217, 5, 61, 0, 0, 217, 218, 1, 0, 0, 0, 218, 219, 6, 7, 2, 0, 219, 19, 1, 0, 0, 0, 220, 221, 5, 46, 0, 0, 221, 21, 1, 0, 0, 0, 222, 223, 5, 44, 0, 0, 223, 224, 1, 0, 0, 0, 224, 225, 6, 9, 0, 0, 225, 23, 1, 0, 0, 0, 226, 227, 7, 2, 0, 0, 227, 25, 1, 0, 0, 0, 228, 229, 7, 3, 0, 0, 229, 27, 1, 0, 0, 0, 230, 234, 5, 92, 0, 0, 231, 235, 7, 4, 0, 0, 232, 235, 3, 30, 13, 0, 233, 235, 3, 32, 14, 0, 234, 231, 1, 0, 0, 0, 234, 232, 1, 0, 0, 0, 234, 233, 1, 0, 0, 0, 235, 29, 1, 0, 0, 0, 236, 237, 5, 117, 0, 0, 237, 238, 3, 70, 33, 0, 238, 239, 3, 70, 33, 0, 239, 240, 3, 70, 33, 0, 240, 241, 3, 70, 33, 0, 241, 31, 1, 0, 0, 0, 242, 243, 5, 85, 0, 0, 243, 244, 3, 70, 33, 0, 244, 245, 3, 70, 33, 0, 245, 246, 3, 70, 33, 0, 246, 247, 3, 70, 33, 0, 247, 248, 3, 70, 33, 0, 248, 249, 3, 70, 33, 0, 249, 250, 3, 70, 33, 0, 250, 251, 3, 70, 33, 0, 251, 33, 1, 0, 0, 0, 252, 257, 5, 34, 0, 0, 253, 256, 3, 28, 12, 0, 254, 256, 8, 5, 0, 0, 255, 253, 1, 0, 0, 0, 255, 254, 1, 0, 0, 0, 256, 259, 1, 0, 0, 0, 257, 258, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 258, 260, 1, 0, 0, 0, 259, 257, 1, 0, 0, 0, 260, 261, 5, 34, 0, 0, 261, 35, 1, 0, 0, 0, 262, 266, 5, 39, 0, 0, 263, 265, 8, 6, 0, 0, 264, 263, 1, 0, 0, 0, 265, 268, 1, 0, 0, 0, 266, 267, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 267, 269, 1, 0, 0, 0, 268, 266, 1, 0, 0, 0, 269, 270, 5, 39, 0, 0, 270, 37, 1, 0, 0, 0, 271, 275, 3, 26, 11, 0, 272, 275, 3, 24, 10, 0, 273, 275, 7, 7, 0, 0, 274, 271, 1, 0, 0, 0, 274, 272, 1, 0, 0, 0, 274, 273, 1, 0, 0, 0, 275, 276, 1, 0, 0, 0, 276, 274, 1, 0, 0, 0, 276, 277, 1, 0, 0, 0, 277, 39, 1, 0, 0, 0, 278, 279, 3, 4, 0, 0, 279, 280, 1, 0, 0, 0, 280, 281, 6, 18, 0, 0, 281, 41, 1, 0, 0, 0, 282, 283, 5, 123, 0, 0, 283, 284, 1, 0, 0, 0, 284, 285, 6, 19, 3, 0, 285, 43, 1, 0, 0, 0, 286, 287, 3, 10, 3, 0, 287, 288, 1, 0, 0, 0, 288, 289, 6, 20, 4, 0, 289, 290, 6, 20, 5, 0, 290, 45, 1, 0, 0, 0, 291, 292, 5, 116, 0, 0, 292, 293, 5, 114, 0, 0, 293, 294, 5, 117, 0, 0, 294, 301, 5, 101, 0, 0, 295, 296, 5, 102, 0, 0, 296, 297, 5, 97, 0, 0, 297, 298, 5, 108, 0, 0, 298, 299, 5, 115, 0, 0, 299, 301, 5, 101, 0, 0, 300, 291, 1, 0, 0, 0, 300, 295, 1, 0, 0, 0, 301, 302, 1, 0, 0, 0, 302, 303, 6, 21, 6, 0, 303, 47, 1, 0, 0, 0, 304, 306, 5, 92, 0, 0, 305, 307, 5, 13, 0, 0, 306, 305, 1, 0, 0, 0, 306, 307, 1, 0, 0, 0, 307, 308, 1, 0, 0, 0, 308, 311, 5, 10, 0, 0, 309, 311, 3, 28, 12, 0, 310, 304, 1, 0, 0, 0, 310, 309, 1, 0, 0, 0, 311, 49, 1, 0, 0, 0, 312, 313, 3, 34, 15, 0, 313, 314, 1, 0, 0, 0, 314, 315, 6, 23, 7, 0, 315, 316, 6, 23, 6, 0, 316, 51, 1, 0, 0, 0, 317, 318, 5, 34, 0, 0, 318, 319, 5, 34, 0, 0, 319, 320, 5, 34, 0, 0, 320, 325, 1, 0, 0, 0, 321, 324, 3, 48, 22, 0, 322, 324, 8, 8, 0, 0, 323, 321, 1, 0, 0, 0, 323, 322, 1, 0, 0, 0, 324, 327, 1, 0, 0, 0, 325, 326, 1, 0, 0, 0, 325, 323, 1, 0, 0, 0, 326, 328, 1, 0, 0, 0, 327, 325, 1, 0, 0, 0, 328, 329, 5, 34, 0, 0, 329, 330, 5, 34, 0, 0, 330, 331, 5, 34, 0, 0, 331, 332, 1, 0, 0, 0, 332, 333, 6, 24, 6, 0, 333, 53, 1, 0, 0, 0, 334, 335, 3, 36, 16, 0, 335, 336, 1, 0, 0, 0, 336, 337, 6, 25, 8, 0, 337, 338, 6, 25, 6, 0, 338, 55, 1, 0, 0, 0, 339, 340, 5, 39, 0, 0, 340, 341, 5, 39, 0, 0, 341, 342, 5, 39, 0, 0, 342, 346, 1, 0, 0, 0, 343, 345, 9, 0, 0, 0, 344, 343, 1, 0, 0, 0, 345, 348, 1, 0, 0, 0, 346, 347, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 349, 1, 0, 0, 0, 348, 346, 1, 0, 0, 0, 349, 350, 5, 39, 0, 0, 350, 351, 5, 39, 0, 0, 351, 352, 5, 39, 0, 0, 352, 353, 1, 0, 0, 0, 353, 354, 6, 26, 6, 0, 354, 57, 1, 0, 0, 0, 355, 357, 7, 9, 0, 0, 356, 358, 7, 10, 0, 0, 357, 356, 1, 0, 0, 0, 357, 358, 1, 0, 0, 0, 358, 359, 1, 0, 0, 0, 359, 360, 3, 60, 28, 0, 360, 59, 1, 0, 0, 0, 361, 367, 3, 24, 10, 0, 362, 366, 3, 24, 10, 0, 363, 364, 5, 95, 0, 0, 364, 366, 3, 24, 10, 0, 365, 362, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 366, 369, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 367, 368, 1, 0, 0, 0, 368, 61, 1, 0, 0, 0, 369, 367, 1, 0, 0, 0, 370, 371, 5, 46, 0, 0, 371, 372, 3, 60, 28, 0, 372, 63, 1, 0, 0, 0, 373, 379, 3, 78, 37, 0, 374, 380, 3, 58, 27, 0, 375, 377, 3, 62, 29, 0, 376, 378, 3, 58, 27, 0, 377, 376, 1, 0, 0, 0, 377, 378, 1, 0, 0, 0, 378, 380, 1, 0, 0, 0, 379, 374, 1, 0, 0, 0, 379, 375, 1, 0, 0, 0, 380, 381, 1, 0, 0, 0, 381, 382, 6, 30, 6, 0, 382, 65, 1, 0, 0, 0, 383, 385, 7, 10, 0, 0, 384, 383, 1, 0, 0, 0, 384, 385, 1, 0, 0, 0, 385, 386, 1, 0, 0, 0, 386, 387, 5, 105, 0, 0, 387, 388, 5, 110, 0, 0, 388, 389, 5, 102, 0, 0, 389, 390, 1, 0, 0, 0, 390, 391, 6, 31, 6, 0, 391, 67, 1, 0, 0, 0, 392, 394, 7, 10, 0, 0, 393, 392, 1, 0, 0, 0, 393, 394, 1, 0, 0, 0, 394, 395, 1, 0, 0, 0, 395, 396, 5, 110, 0, 0, 396, 397, 5, 97, 0, 0, 397, 398, 5, 110, 0, 0, 398, 399, 1, 0, 0, 0, 399, 400, 6, 32, 6, 0, 400, 69, 1, 0, 0, 0, 401, 404, 7, 11, 0, 0, 402, 404, 3, 24, 10, 0, 403, 401, 1, 0, 0, 0, 403, 402, 1, 0, 0, 0, 404, 71, 1, 0, 0, 0, 405, 406, 7, 12, 0, 0, 406, 73, 1, 0, 0, 0, 407, 408, 7, 13, 0, 0, 408, 75, 1, 0, 0, 0, 409, 410, 7, 14, 0, 0, 410, 77, 1, 0, 0, 0, 411, 413, 7, 10, 0, 0, 412, 411, 1, 0, 0, 0, 412, 413, 1, 0, 0, 0, 413, 423, 1, 0, 0, 0, 414, 424, 3, 24, 10, 0, 415, 419, 3, 72, 34, 0, 416, 420, 3, 24, 10, 0, 417, 418, 5, 95, 0, 0, 418, 420, 3, 24, 10, 0, 419, 416, 1, 0, 0, 0, 419, 417, 1, 0, 0, 0, 420, 421, 1, 0, 0, 0, 421, 419, 1, 0, 0, 0, 421, 422, 1, 0, 0, 0, 422, 424, 1, 0, 0, 0, 423, 414, 1, 0, 0, 0, 423, 415, 1, 0, 0, 0, 424, 425, 1, 0, 0, 0, 425, 426, 6, 37, 6, 0, 426, 79, 1, 0, 0, 0, 427, 428, 5, 48, 0, 0, 428, 429, 5, 120, 0, 0, 429, 430, 1, 0, 0, 0, 430, 436, 3, 70, 33, 0, 431, 435, 3, 70, 33, 0, 432, 433, 5, 95, 0, 0, 433, 435, 3, 70, 33, 0, 434, 431, 1, 0, 0, 0, 434, 432, 1, 0, 0, 0, 435, 438, 1, 0, 0, 0, 436, 434, 1, 0, 0, 0, 436, 437, 1, 0, 0, 0, 437, 439, 1, 0, 0, 0, 438, 436, 1, 0, 0, 0, 439, 440, 6, 38, 6, 0, 440, 81, 1, 0, 0, 0, 441, 442, 5, 48, 0, 0, 442, 443, 5, 111, 0, 0, 443, 444, 1, 0, 0, 0, 444, 450, 3, 74, 35, 0, 445, 449, 3, 74, 35, 0, 446, 447, 5, 95, 0, 0, 447, 449, 3, 74, 35, 0, 448, 445, 1, 0, 0, 0, 448, 446, 1, 0, 0, 0, 449, 452, 1, 0, 0, 0, 450, 448, 1, 0, 0, 0, 450, 451, 1, 0, 0, 0, 451, 453, 1, 0, 0, 0, 452, 450, 1, 0, 0, 0, 453, 454, 6, 39, 6, 0, 454, 83, 1, 0, 0, 0, 455, 456, 5, 48, 0, 0, 456, 457, 5, 98, 0, 0, 457, 458, 1, 0, 0, 0, 458, 464, 3, 76, 36, 0, 459, 463, 3, 76, 36, 0, 460, 461, 5, 95, 0, 0, 461, 463, 3, 76, 36, 0, 462, 459, 1, 0, 0, 0, 462, 460, 1, 0, 0, 0, 463, 466, 1, 0, 0, 0, 464, 462, 1, 0, 0, 0, 464, 465, 1, 0, 0, 0, 465, 467, 1, 0, 0, 0, 466, 464, 1, 0, 0, 0, 467, 468, 6, 40, 6, 0, 468, 85, 1, 0, 0, 0, 469, 470, 3, 24, 10, 0, 470, 471, 3, 24, 10, 0, 471, 472, 3, 24, 10, 0, 472, 473, 3, 24, 10, 0, 473, 87, 1, 0, 0, 0, 474, 475, 3, 24, 10, 0, 475, 476, 3, 24, 10, 0, 476, 89, 1, 0, 0, 0, 477, 478, 3, 24, 10, 0, 478, 479, 3, 24, 10, 0, 479, 91, 1, 0, 0, 0, 480, 481, 7, 15, 0, 0, 481, 93, 1, 0, 0, 0, 482, 483, 3, 24, 10, 0, 483, 484, 3, 24, 10, 0, 484, 95, 1, 0, 0, 0, 485, 486, 3, 24, 10, 0, 486, 487, 3, 24, 10, 0, 487, 97, 1, 0, 0, 0, 488, 489, 3, 24, 10, 0, 489, 490, 3, 24, 10, 0, 490, 99, 1, 0, 0, 0, 491, 493, 5, 46, 0, 0, 492, 494, 3, 24, 10, 0, 493, 492, 1, 0, 0, 0, 494, 495, 1, 0, 0, 0, 495, 493, 1, 0, 0, 0, 495, 496, 1, 0, 0, 0, 496, 101, 1, 0, 0, 0, 497, 498, 7, 10, 0, 0, 498, 499, 3, 94, 45, 0, 499, 500, 5, 58, 0, 0, 500, 501, 3, 96, 46, 0, 501, 103, 1, 0, 0, 0, 502, 505, 5, 90, 0, 0, 503, 505, 3, 102, 49, 0, 504, 502, 1, 0, 0, 0, 504, 503, 1, 0, 0, 0, 505, 105, 1, 0, 0, 0, 506, 507, 3, 94, 45, 0, 507, 508, 5, 58, 0, 0, 508, 509, 3, 96, 46, 0, 509, 510, 5, 58, 0, 0, 510, 512, 3, 98, 47, 0, 511, 513, 3, 100, 48, 0, 512, 511, 1, 0, 0, 0, 512, 513, 1, 0, 0, 0, 513, 107, 1, 0, 0, 0, 514, 515, 3, 86, 41, 0, 515, 516, 5, 45, 0, 0, 516, 517, 3, 88, 42, 0, 517, 518, 5, 45, 0, 0, 518, 519, 3, 90, 43, 0, 519, 109, 1, 0, 0, 0, 520, 521, 3, 106, 51, 0, 521, 522, 3, 104, 50, 0, 522, 111, 1, 0, 0, 0, 523, 524, 3, 108, 52, 0, 524, 525, 3, 92, 44, 0, 525, 526, 3, 110, 53, 0, 526, 527, 1, 0, 0, 0, 527, 528, 6, 54, 6, 0, 528, 113, 1, 0, 0, 0, 529, 530, 3, 108, 52, 0, 530, 531, 3, 92, 44, 0, 531, 532, 3, 106, 51, 0, 532, 533, 1, 0, 0, 0, 533, 534, 6, 55, 6, 0, 534, 115, 1, 0, 0, 0, 535, 536, 3, 108, 52, 0, 536, 537, 1, 0, 0, 0, 537, 538, 6, 56, 6, 0, 538, 117, 1, 0, 0, 0, 539, 540, 3, 106, 51, 0, 540, 541, 1, 0, 0, 0, 541, 542, 6, 57, 6, 0, 542, 119, 1, 0, 0, 0, 543, 544, 3, 4, 0, 0, 544, 545, 1, 0, 0, 0, 545, 546, 6, 58, 0, 0, 546, 121, 1, 0, 0, 0, 547, 548, 3, 20, 8, 0, 548, 549, 1, 0, 0, 0, 549, 550, 6, 59, 9, 0, 550, 123, 1, 0, 0, 0, 551, 552, 3, 22, 9, 0, 552, 553, 1, 0, 0, 0, 553, 554, 6, 60, 10, 0, 554, 125, 1, 0, 0, 0, 555, 556, 5, 125, 0, 0, 556, 557, 1, 0, 0, 0, 557, 558, 6, 61, 6, 0, 558, 127, 1, 0, 0, 0, 559, 560, 3, 34, 15, 0, 560, 561, 1, 0, 0, 0, 561, 562, 6, 62, 7, 0, 562, 129, 1, 0, 0, 0, 563, 564, 3, 36, 16, 0, 564, 565, 1, 0, 0, 0, 565, 566, 6, 63, 8, 0, 566, 131, 1, 0, 0, 0, 567, 568, 3, 38, 17, 0, 568, 569, 1, 0, 0, 0, 569, 570, 6, 64, 11, 0, 570, 133, 1, 0, 0, 0, 571, 572, 3, 18, 7, 0, 572, 573, 1, 0, 0, 0, 573, 574, 6, 65, 12, 0, 574, 575, 6, 65, 2, 0, 575, 135, 1, 0, 0, 0, 576, 577, 3, 4, 0, 0, 577, 578, 1, 0, 0, 0, 578, 579, 6, 66, 0, 0, 579, 137, 1, 0, 0, 0, 580, 581, 3, 6, 1, 0, 581, 582, 1, 0, 0, 0, 582, 583, 6, 67, 13, 0, 583, 139, 1, 0, 0, 0, 584, 585, 3, 8, 2, 0, 585, 586, 1, 0, 0, 0, 586, 587, 6, 68, 14, 0, 587, 141, 1, 0, 0, 0, 588, 589, 3, 22, 9, 0, 589, 590, 1, 0, 0, 0, 590, 591, 6, 69, 10, 0, 591, 143, 1, 0, 0, 0, 592, 593, 3, 42, 19, 0, 593, 594, 1, 0, 0, 0, 594, 595, 6, 70, 15, 0, 595, 596, 6, 70, 16, 0, 596, 145, 1, 0, 0, 0, 597, 598, 3, 10, 3, 0, 598, 599, 1, 0, 0, 0, 599, 600, 6, 71, 4, 0, 600, 601, 6, 71, 17, 0, 601, 147, 1, 0, 0, 0, 602, 603, 3, 14, 5, 0, 603, 604, 1, 0, 0, 0, 604, 605, 6, 72, 18, 0, 605, 606, 6, 72, 6, 0, 606, 149, 1, 0, 0, 0, 607, 608, 3, 46, 21, 0, 608, 609, 1, 0, 0, 0, 609, 610, 6, 73, 19, 0, 610, 151, 1, 0, 0, 0, 611, 612, 3, 34, 15, 0, 612, 613, 1, 0, 0, 0, 613, 614, 6, 74, 7, 0, 614, 153, 1, 0, 0, 0, 615, 616, 3, 52, 24, 0, 616, 617, 1, 0, 0, 0, 617, 618, 6, 75, 20, 0, 618, 155, 1, 0, 0, 0, 619, 620, 3, 36, 16, 0, 620, 621, 1, 0, 0, 0, 621, 622, 6, 76, 8, 0, 622, 157, 1, 0, 0, 0, 623, 624, 3, 56, 26, 0, 624, 625, 1, 0, 0, 0, 625, 626, 6, 77, 21, 0, 626, 159, 1, 0, 0, 0, 627, 628, 3, 64, 30, 0, 628, 629, 1, 0, 0, 0, 629, 630, 6, 78, 22, 0, 630, 161, 1, 0, 0, 0, 631, 632, 3, 66, 31, 0, 632, 633, 1, 0, 0, 0, 633, 634, 6, 79, 23, 0, 634, 163, 1, 0, 0, 0, 635, 636, 3, 68, 32, 0, 636, 637, 1, 0, 0, 0, 637, 638, 6, 80, 24, 0, 638, 165, 1, 0, 0, 0, 639, 640, 3, 78, 37, 0, 640, 641, 1, 0, 0, 0, 641, 642, 6, 81, 25, 0, 642, 167, 1, 0, 0, 0, 643, 644, 3, 80, 38, 0, 644, 645, 1, 0, 0, 0, 645, 646, 6, 82, 26, 0, 646, 169, 1, 0, 0, 0, 647, 648, 3, 82, 39, 0, 648, 649, 1, 0, 0, 0, 649, 650, 6, 83, 27, 0, 650, 171, 1, 0, 0, 0, 651, 652, 3, 84, 40, 0, 652, 653, 1, 0, 0, 0, 653, 654, 6, 84, 28, 0, 654, 173, 1, 0, 0, 0, 655, 656, 3, 112, 54, 0, 656, 657, 1, 0, 0, 0, 657, 658, 6, 85, 29, 0, 658, 175, 1, 0, 0, 0, 659, 660, 3, 114, 55, 0, 660, 661, 1, 0, 0, 0, 661, 662, 6, 86, 30, 0, 662, 177, 1, 0, 0, 0, 663, 664, 3, 116, 56, 0, 664, 665, 1, 0, 0, 0, 665, 666, 6, 87, 31, 0, 666, 179, 1, 0, 0, 0, 667, 668, 3, 118, 57, 0, 668, 669, 1, 0, 0, 0, 669, 670, 6, 88, 32, 0, 670, 181, 1, 0, 0, 0, 41, 0, 1, 2, 3, 185, 190, 195, 201, 234, 255, 257, 266, 274, 276, 300, 306, 310, 323, 325, 346, 357, 365, 367, 377, 379, 384, 393, 403, 412, 419, 421, 423, 434, 436, 448, 450, 462, 464, 495, 504, 512, 33, 6, 0, 0, 0, 2, 0, 5, 1, 0, 2, 2, 0, 7, 4, 0, 2, 3, 0, 4, 0, 0, 7, 11, 0, 7, 12, 0, 7, 9, 0, 7, 10, 0, 7, 13, 0, 7, 8, 0, 7, 2, 0, 7, 3, 0, 7, 15, 0, 5, 2, 0, 5, 3, 0, 7, 6, 0, 7, 16, 0, 7, 17, 0, 7, 18, 0, 7, 19, 0, 7, 20, 0, 7, 21, 0, 7, 22, 0, 7, 23, 0, 7, 24, 0, 7, 25, 0, 7, 26, 0, 7, 27, 0, 7, 28, 0, 7, 29, 0] \ No newline at end of file +[4, 0, 32, 669, 6, -1, 6, -1, 6, -1, 6, -1, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 2, 21, 7, 21, 2, 22, 7, 22, 2, 23, 7, 23, 2, 24, 7, 24, 2, 25, 7, 25, 2, 26, 7, 26, 2, 27, 7, 27, 2, 28, 7, 28, 2, 29, 7, 29, 2, 30, 7, 30, 2, 31, 7, 31, 2, 32, 7, 32, 2, 33, 7, 33, 2, 34, 7, 34, 2, 35, 7, 35, 2, 36, 7, 36, 2, 37, 7, 37, 2, 38, 7, 38, 2, 39, 7, 39, 2, 40, 7, 40, 2, 41, 7, 41, 2, 42, 7, 42, 2, 43, 7, 43, 2, 44, 7, 44, 2, 45, 7, 45, 2, 46, 7, 46, 2, 47, 7, 47, 2, 48, 7, 48, 2, 49, 7, 49, 2, 50, 7, 50, 2, 51, 7, 51, 2, 52, 7, 52, 2, 53, 7, 53, 2, 54, 7, 54, 2, 55, 7, 55, 2, 56, 7, 56, 2, 57, 7, 57, 2, 58, 7, 58, 2, 59, 7, 59, 2, 60, 7, 60, 2, 61, 7, 61, 2, 62, 7, 62, 2, 63, 7, 63, 2, 64, 7, 64, 2, 65, 7, 65, 2, 66, 7, 66, 2, 67, 7, 67, 2, 68, 7, 68, 2, 69, 7, 69, 2, 70, 7, 70, 2, 71, 7, 71, 2, 72, 7, 72, 2, 73, 7, 73, 2, 74, 7, 74, 2, 75, 7, 75, 2, 76, 7, 76, 2, 77, 7, 77, 2, 78, 7, 78, 2, 79, 7, 79, 2, 80, 7, 80, 2, 81, 7, 81, 2, 82, 7, 82, 2, 83, 7, 83, 2, 84, 7, 84, 2, 85, 7, 85, 2, 86, 7, 86, 2, 87, 7, 87, 2, 88, 7, 88, 1, 0, 4, 0, 184, 8, 0, 11, 0, 12, 0, 185, 1, 0, 1, 0, 1, 1, 3, 1, 191, 8, 1, 1, 1, 4, 1, 194, 8, 1, 11, 1, 12, 1, 195, 1, 2, 1, 2, 5, 2, 200, 8, 2, 10, 2, 12, 2, 203, 9, 2, 1, 3, 1, 3, 1, 4, 1, 4, 1, 4, 1, 5, 1, 5, 1, 6, 1, 6, 1, 6, 1, 7, 1, 7, 1, 7, 1, 7, 1, 8, 1, 8, 1, 9, 1, 9, 1, 9, 1, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 12, 1, 12, 3, 12, 233, 8, 12, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 13, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 5, 15, 254, 8, 15, 10, 15, 12, 15, 257, 9, 15, 1, 15, 1, 15, 1, 16, 1, 16, 5, 16, 263, 8, 16, 10, 16, 12, 16, 266, 9, 16, 1, 16, 1, 16, 1, 17, 1, 17, 1, 17, 4, 17, 273, 8, 17, 11, 17, 12, 17, 274, 1, 18, 1, 18, 1, 18, 1, 18, 1, 19, 1, 19, 1, 19, 1, 19, 1, 20, 1, 20, 1, 20, 1, 20, 1, 20, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 1, 21, 3, 21, 299, 8, 21, 1, 21, 1, 21, 1, 22, 1, 22, 3, 22, 305, 8, 22, 1, 22, 1, 22, 3, 22, 309, 8, 22, 1, 23, 1, 23, 1, 23, 1, 23, 1, 23, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 5, 24, 322, 8, 24, 10, 24, 12, 24, 325, 9, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 24, 1, 25, 1, 25, 1, 25, 1, 25, 1, 25, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 5, 26, 343, 8, 26, 10, 26, 12, 26, 346, 9, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 26, 1, 27, 1, 27, 3, 27, 356, 8, 27, 1, 27, 1, 27, 1, 28, 1, 28, 1, 28, 1, 28, 5, 28, 364, 8, 28, 10, 28, 12, 28, 367, 9, 28, 1, 29, 1, 29, 1, 29, 1, 30, 1, 30, 1, 30, 1, 30, 3, 30, 376, 8, 30, 3, 30, 378, 8, 30, 1, 30, 1, 30, 1, 31, 3, 31, 383, 8, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 31, 1, 32, 3, 32, 392, 8, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 32, 1, 33, 1, 33, 3, 33, 402, 8, 33, 1, 34, 1, 34, 1, 35, 1, 35, 1, 36, 1, 36, 1, 37, 3, 37, 411, 8, 37, 1, 37, 1, 37, 1, 37, 1, 37, 1, 37, 4, 37, 418, 8, 37, 11, 37, 12, 37, 419, 3, 37, 422, 8, 37, 1, 37, 1, 37, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 1, 38, 5, 38, 433, 8, 38, 10, 38, 12, 38, 436, 9, 38, 1, 38, 1, 38, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 1, 39, 5, 39, 447, 8, 39, 10, 39, 12, 39, 450, 9, 39, 1, 39, 1, 39, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 1, 40, 5, 40, 461, 8, 40, 10, 40, 12, 40, 464, 9, 40, 1, 40, 1, 40, 1, 41, 1, 41, 1, 41, 1, 41, 1, 41, 1, 42, 1, 42, 1, 42, 1, 43, 1, 43, 1, 43, 1, 44, 1, 44, 1, 45, 1, 45, 1, 45, 1, 46, 1, 46, 1, 46, 1, 47, 1, 47, 1, 47, 1, 48, 1, 48, 4, 48, 492, 8, 48, 11, 48, 12, 48, 493, 1, 49, 1, 49, 1, 49, 1, 49, 1, 49, 1, 50, 1, 50, 3, 50, 503, 8, 50, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 1, 51, 3, 51, 511, 8, 51, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 52, 1, 53, 1, 53, 1, 53, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 54, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 55, 1, 56, 1, 56, 1, 56, 1, 56, 1, 57, 1, 57, 1, 57, 1, 57, 1, 58, 1, 58, 1, 58, 1, 58, 1, 59, 1, 59, 1, 59, 1, 59, 1, 60, 1, 60, 1, 60, 1, 60, 1, 61, 1, 61, 1, 61, 1, 61, 1, 62, 1, 62, 1, 62, 1, 62, 1, 63, 1, 63, 1, 63, 1, 63, 1, 64, 1, 64, 1, 64, 1, 64, 1, 65, 1, 65, 1, 65, 1, 65, 1, 65, 1, 66, 1, 66, 1, 66, 1, 66, 1, 67, 1, 67, 1, 67, 1, 67, 1, 68, 1, 68, 1, 68, 1, 68, 1, 69, 1, 69, 1, 69, 1, 69, 1, 70, 1, 70, 1, 70, 1, 70, 1, 70, 1, 71, 1, 71, 1, 71, 1, 71, 1, 71, 1, 72, 1, 72, 1, 72, 1, 72, 1, 72, 1, 73, 1, 73, 1, 73, 1, 73, 1, 74, 1, 74, 1, 74, 1, 74, 1, 75, 1, 75, 1, 75, 1, 75, 1, 76, 1, 76, 1, 76, 1, 76, 1, 77, 1, 77, 1, 77, 1, 77, 1, 78, 1, 78, 1, 78, 1, 78, 1, 79, 1, 79, 1, 79, 1, 79, 1, 80, 1, 80, 1, 80, 1, 80, 1, 81, 1, 81, 1, 81, 1, 81, 1, 82, 1, 82, 1, 82, 1, 82, 1, 83, 1, 83, 1, 83, 1, 83, 1, 84, 1, 84, 1, 84, 1, 84, 1, 85, 1, 85, 1, 85, 1, 85, 1, 86, 1, 86, 1, 86, 1, 86, 1, 87, 1, 87, 1, 87, 1, 87, 1, 88, 1, 88, 1, 88, 1, 88, 4, 255, 264, 323, 344, 0, 89, 4, 1, 6, 2, 8, 3, 10, 4, 12, 5, 14, 6, 16, 7, 18, 8, 20, 9, 22, 10, 24, 0, 26, 0, 28, 0, 30, 0, 32, 0, 34, 11, 36, 12, 38, 13, 40, 14, 42, 15, 44, 0, 46, 16, 48, 0, 50, 0, 52, 17, 54, 0, 56, 18, 58, 0, 60, 0, 62, 0, 64, 19, 66, 20, 68, 21, 70, 0, 72, 0, 74, 0, 76, 0, 78, 22, 80, 23, 82, 24, 84, 25, 86, 0, 88, 0, 90, 0, 92, 0, 94, 0, 96, 0, 98, 0, 100, 0, 102, 0, 104, 0, 106, 0, 108, 0, 110, 0, 112, 26, 114, 27, 116, 28, 118, 29, 120, 30, 122, 0, 124, 0, 126, 31, 128, 0, 130, 0, 132, 0, 134, 0, 136, 32, 138, 0, 140, 0, 142, 0, 144, 0, 146, 0, 148, 0, 150, 0, 152, 0, 154, 0, 156, 0, 158, 0, 160, 0, 162, 0, 164, 0, 166, 0, 168, 0, 170, 0, 172, 0, 174, 0, 176, 0, 178, 0, 180, 0, 4, 0, 1, 2, 3, 16, 2, 0, 9, 9, 32, 32, 2, 0, 10, 10, 13, 13, 1, 0, 48, 57, 2, 0, 65, 90, 97, 122, 8, 0, 34, 34, 47, 47, 92, 92, 98, 98, 102, 102, 110, 110, 114, 114, 116, 116, 3, 0, 10, 10, 34, 34, 92, 92, 2, 0, 10, 10, 39, 39, 2, 0, 45, 45, 95, 95, 2, 0, 34, 34, 92, 92, 2, 0, 69, 69, 101, 101, 2, 0, 43, 43, 45, 45, 2, 0, 65, 70, 97, 102, 1, 0, 49, 57, 1, 0, 48, 55, 1, 0, 48, 49, 3, 0, 32, 32, 84, 84, 116, 116, 678, 0, 4, 1, 0, 0, 0, 0, 6, 1, 0, 0, 0, 0, 8, 1, 0, 0, 0, 0, 10, 1, 0, 0, 0, 0, 12, 1, 0, 0, 0, 0, 14, 1, 0, 0, 0, 0, 16, 1, 0, 0, 0, 0, 18, 1, 0, 0, 0, 0, 20, 1, 0, 0, 0, 0, 22, 1, 0, 0, 0, 0, 34, 1, 0, 0, 0, 0, 36, 1, 0, 0, 0, 0, 38, 1, 0, 0, 0, 1, 40, 1, 0, 0, 0, 1, 42, 1, 0, 0, 0, 1, 44, 1, 0, 0, 0, 1, 46, 1, 0, 0, 0, 1, 50, 1, 0, 0, 0, 1, 52, 1, 0, 0, 0, 1, 54, 1, 0, 0, 0, 1, 56, 1, 0, 0, 0, 1, 64, 1, 0, 0, 0, 1, 66, 1, 0, 0, 0, 1, 68, 1, 0, 0, 0, 1, 78, 1, 0, 0, 0, 1, 80, 1, 0, 0, 0, 1, 82, 1, 0, 0, 0, 1, 84, 1, 0, 0, 0, 1, 112, 1, 0, 0, 0, 1, 114, 1, 0, 0, 0, 1, 116, 1, 0, 0, 0, 1, 118, 1, 0, 0, 0, 2, 120, 1, 0, 0, 0, 2, 122, 1, 0, 0, 0, 2, 124, 1, 0, 0, 0, 2, 126, 1, 0, 0, 0, 2, 128, 1, 0, 0, 0, 2, 130, 1, 0, 0, 0, 2, 132, 1, 0, 0, 0, 2, 134, 1, 0, 0, 0, 3, 136, 1, 0, 0, 0, 3, 138, 1, 0, 0, 0, 3, 140, 1, 0, 0, 0, 3, 142, 1, 0, 0, 0, 3, 144, 1, 0, 0, 0, 3, 146, 1, 0, 0, 0, 3, 148, 1, 0, 0, 0, 3, 150, 1, 0, 0, 0, 3, 152, 1, 0, 0, 0, 3, 154, 1, 0, 0, 0, 3, 156, 1, 0, 0, 0, 3, 158, 1, 0, 0, 0, 3, 160, 1, 0, 0, 0, 3, 162, 1, 0, 0, 0, 3, 164, 1, 0, 0, 0, 3, 166, 1, 0, 0, 0, 3, 168, 1, 0, 0, 0, 3, 170, 1, 0, 0, 0, 3, 172, 1, 0, 0, 0, 3, 174, 1, 0, 0, 0, 3, 176, 1, 0, 0, 0, 3, 178, 1, 0, 0, 0, 3, 180, 1, 0, 0, 0, 4, 183, 1, 0, 0, 0, 6, 193, 1, 0, 0, 0, 8, 197, 1, 0, 0, 0, 10, 204, 1, 0, 0, 0, 12, 206, 1, 0, 0, 0, 14, 209, 1, 0, 0, 0, 16, 211, 1, 0, 0, 0, 18, 214, 1, 0, 0, 0, 20, 218, 1, 0, 0, 0, 22, 220, 1, 0, 0, 0, 24, 224, 1, 0, 0, 0, 26, 226, 1, 0, 0, 0, 28, 228, 1, 0, 0, 0, 30, 234, 1, 0, 0, 0, 32, 240, 1, 0, 0, 0, 34, 250, 1, 0, 0, 0, 36, 260, 1, 0, 0, 0, 38, 272, 1, 0, 0, 0, 40, 276, 1, 0, 0, 0, 42, 280, 1, 0, 0, 0, 44, 284, 1, 0, 0, 0, 46, 298, 1, 0, 0, 0, 48, 308, 1, 0, 0, 0, 50, 310, 1, 0, 0, 0, 52, 315, 1, 0, 0, 0, 54, 332, 1, 0, 0, 0, 56, 337, 1, 0, 0, 0, 58, 353, 1, 0, 0, 0, 60, 359, 1, 0, 0, 0, 62, 368, 1, 0, 0, 0, 64, 371, 1, 0, 0, 0, 66, 382, 1, 0, 0, 0, 68, 391, 1, 0, 0, 0, 70, 401, 1, 0, 0, 0, 72, 403, 1, 0, 0, 0, 74, 405, 1, 0, 0, 0, 76, 407, 1, 0, 0, 0, 78, 410, 1, 0, 0, 0, 80, 425, 1, 0, 0, 0, 82, 439, 1, 0, 0, 0, 84, 453, 1, 0, 0, 0, 86, 467, 1, 0, 0, 0, 88, 472, 1, 0, 0, 0, 90, 475, 1, 0, 0, 0, 92, 478, 1, 0, 0, 0, 94, 480, 1, 0, 0, 0, 96, 483, 1, 0, 0, 0, 98, 486, 1, 0, 0, 0, 100, 489, 1, 0, 0, 0, 102, 495, 1, 0, 0, 0, 104, 502, 1, 0, 0, 0, 106, 504, 1, 0, 0, 0, 108, 512, 1, 0, 0, 0, 110, 518, 1, 0, 0, 0, 112, 521, 1, 0, 0, 0, 114, 527, 1, 0, 0, 0, 116, 533, 1, 0, 0, 0, 118, 537, 1, 0, 0, 0, 120, 541, 1, 0, 0, 0, 122, 545, 1, 0, 0, 0, 124, 549, 1, 0, 0, 0, 126, 553, 1, 0, 0, 0, 128, 557, 1, 0, 0, 0, 130, 561, 1, 0, 0, 0, 132, 565, 1, 0, 0, 0, 134, 569, 1, 0, 0, 0, 136, 574, 1, 0, 0, 0, 138, 578, 1, 0, 0, 0, 140, 582, 1, 0, 0, 0, 142, 586, 1, 0, 0, 0, 144, 590, 1, 0, 0, 0, 146, 595, 1, 0, 0, 0, 148, 600, 1, 0, 0, 0, 150, 605, 1, 0, 0, 0, 152, 609, 1, 0, 0, 0, 154, 613, 1, 0, 0, 0, 156, 617, 1, 0, 0, 0, 158, 621, 1, 0, 0, 0, 160, 625, 1, 0, 0, 0, 162, 629, 1, 0, 0, 0, 164, 633, 1, 0, 0, 0, 166, 637, 1, 0, 0, 0, 168, 641, 1, 0, 0, 0, 170, 645, 1, 0, 0, 0, 172, 649, 1, 0, 0, 0, 174, 653, 1, 0, 0, 0, 176, 657, 1, 0, 0, 0, 178, 661, 1, 0, 0, 0, 180, 665, 1, 0, 0, 0, 182, 184, 7, 0, 0, 0, 183, 182, 1, 0, 0, 0, 184, 185, 1, 0, 0, 0, 185, 183, 1, 0, 0, 0, 185, 186, 1, 0, 0, 0, 186, 187, 1, 0, 0, 0, 187, 188, 6, 0, 0, 0, 188, 5, 1, 0, 0, 0, 189, 191, 5, 13, 0, 0, 190, 189, 1, 0, 0, 0, 190, 191, 1, 0, 0, 0, 191, 192, 1, 0, 0, 0, 192, 194, 5, 10, 0, 0, 193, 190, 1, 0, 0, 0, 194, 195, 1, 0, 0, 0, 195, 193, 1, 0, 0, 0, 195, 196, 1, 0, 0, 0, 196, 7, 1, 0, 0, 0, 197, 201, 5, 35, 0, 0, 198, 200, 8, 1, 0, 0, 199, 198, 1, 0, 0, 0, 200, 203, 1, 0, 0, 0, 201, 199, 1, 0, 0, 0, 201, 202, 1, 0, 0, 0, 202, 9, 1, 0, 0, 0, 203, 201, 1, 0, 0, 0, 204, 205, 5, 91, 0, 0, 205, 11, 1, 0, 0, 0, 206, 207, 5, 91, 0, 0, 207, 208, 5, 91, 0, 0, 208, 13, 1, 0, 0, 0, 209, 210, 5, 93, 0, 0, 210, 15, 1, 0, 0, 0, 211, 212, 5, 93, 0, 0, 212, 213, 5, 93, 0, 0, 213, 17, 1, 0, 0, 0, 214, 215, 5, 61, 0, 0, 215, 216, 1, 0, 0, 0, 216, 217, 6, 7, 1, 0, 217, 19, 1, 0, 0, 0, 218, 219, 5, 46, 0, 0, 219, 21, 1, 0, 0, 0, 220, 221, 5, 44, 0, 0, 221, 222, 1, 0, 0, 0, 222, 223, 6, 9, 0, 0, 223, 23, 1, 0, 0, 0, 224, 225, 7, 2, 0, 0, 225, 25, 1, 0, 0, 0, 226, 227, 7, 3, 0, 0, 227, 27, 1, 0, 0, 0, 228, 232, 5, 92, 0, 0, 229, 233, 7, 4, 0, 0, 230, 233, 3, 30, 13, 0, 231, 233, 3, 32, 14, 0, 232, 229, 1, 0, 0, 0, 232, 230, 1, 0, 0, 0, 232, 231, 1, 0, 0, 0, 233, 29, 1, 0, 0, 0, 234, 235, 5, 117, 0, 0, 235, 236, 3, 70, 33, 0, 236, 237, 3, 70, 33, 0, 237, 238, 3, 70, 33, 0, 238, 239, 3, 70, 33, 0, 239, 31, 1, 0, 0, 0, 240, 241, 5, 85, 0, 0, 241, 242, 3, 70, 33, 0, 242, 243, 3, 70, 33, 0, 243, 244, 3, 70, 33, 0, 244, 245, 3, 70, 33, 0, 245, 246, 3, 70, 33, 0, 246, 247, 3, 70, 33, 0, 247, 248, 3, 70, 33, 0, 248, 249, 3, 70, 33, 0, 249, 33, 1, 0, 0, 0, 250, 255, 5, 34, 0, 0, 251, 254, 3, 28, 12, 0, 252, 254, 8, 5, 0, 0, 253, 251, 1, 0, 0, 0, 253, 252, 1, 0, 0, 0, 254, 257, 1, 0, 0, 0, 255, 256, 1, 0, 0, 0, 255, 253, 1, 0, 0, 0, 256, 258, 1, 0, 0, 0, 257, 255, 1, 0, 0, 0, 258, 259, 5, 34, 0, 0, 259, 35, 1, 0, 0, 0, 260, 264, 5, 39, 0, 0, 261, 263, 8, 6, 0, 0, 262, 261, 1, 0, 0, 0, 263, 266, 1, 0, 0, 0, 264, 265, 1, 0, 0, 0, 264, 262, 1, 0, 0, 0, 265, 267, 1, 0, 0, 0, 266, 264, 1, 0, 0, 0, 267, 268, 5, 39, 0, 0, 268, 37, 1, 0, 0, 0, 269, 273, 3, 26, 11, 0, 270, 273, 3, 24, 10, 0, 271, 273, 7, 7, 0, 0, 272, 269, 1, 0, 0, 0, 272, 270, 1, 0, 0, 0, 272, 271, 1, 0, 0, 0, 273, 274, 1, 0, 0, 0, 274, 272, 1, 0, 0, 0, 274, 275, 1, 0, 0, 0, 275, 39, 1, 0, 0, 0, 276, 277, 3, 4, 0, 0, 277, 278, 1, 0, 0, 0, 278, 279, 6, 18, 0, 0, 279, 41, 1, 0, 0, 0, 280, 281, 5, 123, 0, 0, 281, 282, 1, 0, 0, 0, 282, 283, 6, 19, 2, 0, 283, 43, 1, 0, 0, 0, 284, 285, 3, 10, 3, 0, 285, 286, 1, 0, 0, 0, 286, 287, 6, 20, 3, 0, 287, 288, 6, 20, 4, 0, 288, 45, 1, 0, 0, 0, 289, 290, 5, 116, 0, 0, 290, 291, 5, 114, 0, 0, 291, 292, 5, 117, 0, 0, 292, 299, 5, 101, 0, 0, 293, 294, 5, 102, 0, 0, 294, 295, 5, 97, 0, 0, 295, 296, 5, 108, 0, 0, 296, 297, 5, 115, 0, 0, 297, 299, 5, 101, 0, 0, 298, 289, 1, 0, 0, 0, 298, 293, 1, 0, 0, 0, 299, 300, 1, 0, 0, 0, 300, 301, 6, 21, 5, 0, 301, 47, 1, 0, 0, 0, 302, 304, 5, 92, 0, 0, 303, 305, 5, 13, 0, 0, 304, 303, 1, 0, 0, 0, 304, 305, 1, 0, 0, 0, 305, 306, 1, 0, 0, 0, 306, 309, 5, 10, 0, 0, 307, 309, 3, 28, 12, 0, 308, 302, 1, 0, 0, 0, 308, 307, 1, 0, 0, 0, 309, 49, 1, 0, 0, 0, 310, 311, 3, 34, 15, 0, 311, 312, 1, 0, 0, 0, 312, 313, 6, 23, 6, 0, 313, 314, 6, 23, 5, 0, 314, 51, 1, 0, 0, 0, 315, 316, 5, 34, 0, 0, 316, 317, 5, 34, 0, 0, 317, 318, 5, 34, 0, 0, 318, 323, 1, 0, 0, 0, 319, 322, 3, 48, 22, 0, 320, 322, 8, 8, 0, 0, 321, 319, 1, 0, 0, 0, 321, 320, 1, 0, 0, 0, 322, 325, 1, 0, 0, 0, 323, 324, 1, 0, 0, 0, 323, 321, 1, 0, 0, 0, 324, 326, 1, 0, 0, 0, 325, 323, 1, 0, 0, 0, 326, 327, 5, 34, 0, 0, 327, 328, 5, 34, 0, 0, 328, 329, 5, 34, 0, 0, 329, 330, 1, 0, 0, 0, 330, 331, 6, 24, 5, 0, 331, 53, 1, 0, 0, 0, 332, 333, 3, 36, 16, 0, 333, 334, 1, 0, 0, 0, 334, 335, 6, 25, 7, 0, 335, 336, 6, 25, 5, 0, 336, 55, 1, 0, 0, 0, 337, 338, 5, 39, 0, 0, 338, 339, 5, 39, 0, 0, 339, 340, 5, 39, 0, 0, 340, 344, 1, 0, 0, 0, 341, 343, 9, 0, 0, 0, 342, 341, 1, 0, 0, 0, 343, 346, 1, 0, 0, 0, 344, 345, 1, 0, 0, 0, 344, 342, 1, 0, 0, 0, 345, 347, 1, 0, 0, 0, 346, 344, 1, 0, 0, 0, 347, 348, 5, 39, 0, 0, 348, 349, 5, 39, 0, 0, 349, 350, 5, 39, 0, 0, 350, 351, 1, 0, 0, 0, 351, 352, 6, 26, 5, 0, 352, 57, 1, 0, 0, 0, 353, 355, 7, 9, 0, 0, 354, 356, 7, 10, 0, 0, 355, 354, 1, 0, 0, 0, 355, 356, 1, 0, 0, 0, 356, 357, 1, 0, 0, 0, 357, 358, 3, 60, 28, 0, 358, 59, 1, 0, 0, 0, 359, 365, 3, 24, 10, 0, 360, 364, 3, 24, 10, 0, 361, 362, 5, 95, 0, 0, 362, 364, 3, 24, 10, 0, 363, 360, 1, 0, 0, 0, 363, 361, 1, 0, 0, 0, 364, 367, 1, 0, 0, 0, 365, 363, 1, 0, 0, 0, 365, 366, 1, 0, 0, 0, 366, 61, 1, 0, 0, 0, 367, 365, 1, 0, 0, 0, 368, 369, 5, 46, 0, 0, 369, 370, 3, 60, 28, 0, 370, 63, 1, 0, 0, 0, 371, 377, 3, 78, 37, 0, 372, 378, 3, 58, 27, 0, 373, 375, 3, 62, 29, 0, 374, 376, 3, 58, 27, 0, 375, 374, 1, 0, 0, 0, 375, 376, 1, 0, 0, 0, 376, 378, 1, 0, 0, 0, 377, 372, 1, 0, 0, 0, 377, 373, 1, 0, 0, 0, 378, 379, 1, 0, 0, 0, 379, 380, 6, 30, 5, 0, 380, 65, 1, 0, 0, 0, 381, 383, 7, 10, 0, 0, 382, 381, 1, 0, 0, 0, 382, 383, 1, 0, 0, 0, 383, 384, 1, 0, 0, 0, 384, 385, 5, 105, 0, 0, 385, 386, 5, 110, 0, 0, 386, 387, 5, 102, 0, 0, 387, 388, 1, 0, 0, 0, 388, 389, 6, 31, 5, 0, 389, 67, 1, 0, 0, 0, 390, 392, 7, 10, 0, 0, 391, 390, 1, 0, 0, 0, 391, 392, 1, 0, 0, 0, 392, 393, 1, 0, 0, 0, 393, 394, 5, 110, 0, 0, 394, 395, 5, 97, 0, 0, 395, 396, 5, 110, 0, 0, 396, 397, 1, 0, 0, 0, 397, 398, 6, 32, 5, 0, 398, 69, 1, 0, 0, 0, 399, 402, 7, 11, 0, 0, 400, 402, 3, 24, 10, 0, 401, 399, 1, 0, 0, 0, 401, 400, 1, 0, 0, 0, 402, 71, 1, 0, 0, 0, 403, 404, 7, 12, 0, 0, 404, 73, 1, 0, 0, 0, 405, 406, 7, 13, 0, 0, 406, 75, 1, 0, 0, 0, 407, 408, 7, 14, 0, 0, 408, 77, 1, 0, 0, 0, 409, 411, 7, 10, 0, 0, 410, 409, 1, 0, 0, 0, 410, 411, 1, 0, 0, 0, 411, 421, 1, 0, 0, 0, 412, 422, 3, 24, 10, 0, 413, 417, 3, 72, 34, 0, 414, 418, 3, 24, 10, 0, 415, 416, 5, 95, 0, 0, 416, 418, 3, 24, 10, 0, 417, 414, 1, 0, 0, 0, 417, 415, 1, 0, 0, 0, 418, 419, 1, 0, 0, 0, 419, 417, 1, 0, 0, 0, 419, 420, 1, 0, 0, 0, 420, 422, 1, 0, 0, 0, 421, 412, 1, 0, 0, 0, 421, 413, 1, 0, 0, 0, 422, 423, 1, 0, 0, 0, 423, 424, 6, 37, 5, 0, 424, 79, 1, 0, 0, 0, 425, 426, 5, 48, 0, 0, 426, 427, 5, 120, 0, 0, 427, 428, 1, 0, 0, 0, 428, 434, 3, 70, 33, 0, 429, 433, 3, 70, 33, 0, 430, 431, 5, 95, 0, 0, 431, 433, 3, 70, 33, 0, 432, 429, 1, 0, 0, 0, 432, 430, 1, 0, 0, 0, 433, 436, 1, 0, 0, 0, 434, 432, 1, 0, 0, 0, 434, 435, 1, 0, 0, 0, 435, 437, 1, 0, 0, 0, 436, 434, 1, 0, 0, 0, 437, 438, 6, 38, 5, 0, 438, 81, 1, 0, 0, 0, 439, 440, 5, 48, 0, 0, 440, 441, 5, 111, 0, 0, 441, 442, 1, 0, 0, 0, 442, 448, 3, 74, 35, 0, 443, 447, 3, 74, 35, 0, 444, 445, 5, 95, 0, 0, 445, 447, 3, 74, 35, 0, 446, 443, 1, 0, 0, 0, 446, 444, 1, 0, 0, 0, 447, 450, 1, 0, 0, 0, 448, 446, 1, 0, 0, 0, 448, 449, 1, 0, 0, 0, 449, 451, 1, 0, 0, 0, 450, 448, 1, 0, 0, 0, 451, 452, 6, 39, 5, 0, 452, 83, 1, 0, 0, 0, 453, 454, 5, 48, 0, 0, 454, 455, 5, 98, 0, 0, 455, 456, 1, 0, 0, 0, 456, 462, 3, 76, 36, 0, 457, 461, 3, 76, 36, 0, 458, 459, 5, 95, 0, 0, 459, 461, 3, 76, 36, 0, 460, 457, 1, 0, 0, 0, 460, 458, 1, 0, 0, 0, 461, 464, 1, 0, 0, 0, 462, 460, 1, 0, 0, 0, 462, 463, 1, 0, 0, 0, 463, 465, 1, 0, 0, 0, 464, 462, 1, 0, 0, 0, 465, 466, 6, 40, 5, 0, 466, 85, 1, 0, 0, 0, 467, 468, 3, 24, 10, 0, 468, 469, 3, 24, 10, 0, 469, 470, 3, 24, 10, 0, 470, 471, 3, 24, 10, 0, 471, 87, 1, 0, 0, 0, 472, 473, 3, 24, 10, 0, 473, 474, 3, 24, 10, 0, 474, 89, 1, 0, 0, 0, 475, 476, 3, 24, 10, 0, 476, 477, 3, 24, 10, 0, 477, 91, 1, 0, 0, 0, 478, 479, 7, 15, 0, 0, 479, 93, 1, 0, 0, 0, 480, 481, 3, 24, 10, 0, 481, 482, 3, 24, 10, 0, 482, 95, 1, 0, 0, 0, 483, 484, 3, 24, 10, 0, 484, 485, 3, 24, 10, 0, 485, 97, 1, 0, 0, 0, 486, 487, 3, 24, 10, 0, 487, 488, 3, 24, 10, 0, 488, 99, 1, 0, 0, 0, 489, 491, 5, 46, 0, 0, 490, 492, 3, 24, 10, 0, 491, 490, 1, 0, 0, 0, 492, 493, 1, 0, 0, 0, 493, 491, 1, 0, 0, 0, 493, 494, 1, 0, 0, 0, 494, 101, 1, 0, 0, 0, 495, 496, 7, 10, 0, 0, 496, 497, 3, 94, 45, 0, 497, 498, 5, 58, 0, 0, 498, 499, 3, 96, 46, 0, 499, 103, 1, 0, 0, 0, 500, 503, 5, 90, 0, 0, 501, 503, 3, 102, 49, 0, 502, 500, 1, 0, 0, 0, 502, 501, 1, 0, 0, 0, 503, 105, 1, 0, 0, 0, 504, 505, 3, 94, 45, 0, 505, 506, 5, 58, 0, 0, 506, 507, 3, 96, 46, 0, 507, 508, 5, 58, 0, 0, 508, 510, 3, 98, 47, 0, 509, 511, 3, 100, 48, 0, 510, 509, 1, 0, 0, 0, 510, 511, 1, 0, 0, 0, 511, 107, 1, 0, 0, 0, 512, 513, 3, 86, 41, 0, 513, 514, 5, 45, 0, 0, 514, 515, 3, 88, 42, 0, 515, 516, 5, 45, 0, 0, 516, 517, 3, 90, 43, 0, 517, 109, 1, 0, 0, 0, 518, 519, 3, 106, 51, 0, 519, 520, 3, 104, 50, 0, 520, 111, 1, 0, 0, 0, 521, 522, 3, 108, 52, 0, 522, 523, 3, 92, 44, 0, 523, 524, 3, 110, 53, 0, 524, 525, 1, 0, 0, 0, 525, 526, 6, 54, 5, 0, 526, 113, 1, 0, 0, 0, 527, 528, 3, 108, 52, 0, 528, 529, 3, 92, 44, 0, 529, 530, 3, 106, 51, 0, 530, 531, 1, 0, 0, 0, 531, 532, 6, 55, 5, 0, 532, 115, 1, 0, 0, 0, 533, 534, 3, 108, 52, 0, 534, 535, 1, 0, 0, 0, 535, 536, 6, 56, 5, 0, 536, 117, 1, 0, 0, 0, 537, 538, 3, 106, 51, 0, 538, 539, 1, 0, 0, 0, 539, 540, 6, 57, 5, 0, 540, 119, 1, 0, 0, 0, 541, 542, 3, 4, 0, 0, 542, 543, 1, 0, 0, 0, 543, 544, 6, 58, 0, 0, 544, 121, 1, 0, 0, 0, 545, 546, 3, 20, 8, 0, 546, 547, 1, 0, 0, 0, 547, 548, 6, 59, 8, 0, 548, 123, 1, 0, 0, 0, 549, 550, 3, 22, 9, 0, 550, 551, 1, 0, 0, 0, 551, 552, 6, 60, 9, 0, 552, 125, 1, 0, 0, 0, 553, 554, 5, 125, 0, 0, 554, 555, 1, 0, 0, 0, 555, 556, 6, 61, 5, 0, 556, 127, 1, 0, 0, 0, 557, 558, 3, 34, 15, 0, 558, 559, 1, 0, 0, 0, 559, 560, 6, 62, 6, 0, 560, 129, 1, 0, 0, 0, 561, 562, 3, 36, 16, 0, 562, 563, 1, 0, 0, 0, 563, 564, 6, 63, 7, 0, 564, 131, 1, 0, 0, 0, 565, 566, 3, 38, 17, 0, 566, 567, 1, 0, 0, 0, 567, 568, 6, 64, 10, 0, 568, 133, 1, 0, 0, 0, 569, 570, 3, 18, 7, 0, 570, 571, 1, 0, 0, 0, 571, 572, 6, 65, 11, 0, 572, 573, 6, 65, 1, 0, 573, 135, 1, 0, 0, 0, 574, 575, 3, 4, 0, 0, 575, 576, 1, 0, 0, 0, 576, 577, 6, 66, 0, 0, 577, 137, 1, 0, 0, 0, 578, 579, 3, 6, 1, 0, 579, 580, 1, 0, 0, 0, 580, 581, 6, 67, 12, 0, 581, 139, 1, 0, 0, 0, 582, 583, 3, 8, 2, 0, 583, 584, 1, 0, 0, 0, 584, 585, 6, 68, 13, 0, 585, 141, 1, 0, 0, 0, 586, 587, 3, 22, 9, 0, 587, 588, 1, 0, 0, 0, 588, 589, 6, 69, 9, 0, 589, 143, 1, 0, 0, 0, 590, 591, 3, 42, 19, 0, 591, 592, 1, 0, 0, 0, 592, 593, 6, 70, 14, 0, 593, 594, 6, 70, 15, 0, 594, 145, 1, 0, 0, 0, 595, 596, 3, 10, 3, 0, 596, 597, 1, 0, 0, 0, 597, 598, 6, 71, 3, 0, 598, 599, 6, 71, 16, 0, 599, 147, 1, 0, 0, 0, 600, 601, 3, 14, 5, 0, 601, 602, 1, 0, 0, 0, 602, 603, 6, 72, 17, 0, 603, 604, 6, 72, 5, 0, 604, 149, 1, 0, 0, 0, 605, 606, 3, 46, 21, 0, 606, 607, 1, 0, 0, 0, 607, 608, 6, 73, 18, 0, 608, 151, 1, 0, 0, 0, 609, 610, 3, 34, 15, 0, 610, 611, 1, 0, 0, 0, 611, 612, 6, 74, 6, 0, 612, 153, 1, 0, 0, 0, 613, 614, 3, 52, 24, 0, 614, 615, 1, 0, 0, 0, 615, 616, 6, 75, 19, 0, 616, 155, 1, 0, 0, 0, 617, 618, 3, 36, 16, 0, 618, 619, 1, 0, 0, 0, 619, 620, 6, 76, 7, 0, 620, 157, 1, 0, 0, 0, 621, 622, 3, 56, 26, 0, 622, 623, 1, 0, 0, 0, 623, 624, 6, 77, 20, 0, 624, 159, 1, 0, 0, 0, 625, 626, 3, 64, 30, 0, 626, 627, 1, 0, 0, 0, 627, 628, 6, 78, 21, 0, 628, 161, 1, 0, 0, 0, 629, 630, 3, 66, 31, 0, 630, 631, 1, 0, 0, 0, 631, 632, 6, 79, 22, 0, 632, 163, 1, 0, 0, 0, 633, 634, 3, 68, 32, 0, 634, 635, 1, 0, 0, 0, 635, 636, 6, 80, 23, 0, 636, 165, 1, 0, 0, 0, 637, 638, 3, 78, 37, 0, 638, 639, 1, 0, 0, 0, 639, 640, 6, 81, 24, 0, 640, 167, 1, 0, 0, 0, 641, 642, 3, 80, 38, 0, 642, 643, 1, 0, 0, 0, 643, 644, 6, 82, 25, 0, 644, 169, 1, 0, 0, 0, 645, 646, 3, 82, 39, 0, 646, 647, 1, 0, 0, 0, 647, 648, 6, 83, 26, 0, 648, 171, 1, 0, 0, 0, 649, 650, 3, 84, 40, 0, 650, 651, 1, 0, 0, 0, 651, 652, 6, 84, 27, 0, 652, 173, 1, 0, 0, 0, 653, 654, 3, 112, 54, 0, 654, 655, 1, 0, 0, 0, 655, 656, 6, 85, 28, 0, 656, 175, 1, 0, 0, 0, 657, 658, 3, 114, 55, 0, 658, 659, 1, 0, 0, 0, 659, 660, 6, 86, 29, 0, 660, 177, 1, 0, 0, 0, 661, 662, 3, 116, 56, 0, 662, 663, 1, 0, 0, 0, 663, 664, 6, 87, 30, 0, 664, 179, 1, 0, 0, 0, 665, 666, 3, 118, 57, 0, 666, 667, 1, 0, 0, 0, 667, 668, 6, 88, 31, 0, 668, 181, 1, 0, 0, 0, 41, 0, 1, 2, 3, 185, 190, 195, 201, 232, 253, 255, 264, 272, 274, 298, 304, 308, 321, 323, 344, 355, 363, 365, 375, 377, 382, 391, 401, 410, 417, 419, 421, 432, 434, 446, 448, 460, 462, 493, 502, 510, 32, 6, 0, 0, 5, 1, 0, 2, 2, 0, 7, 4, 0, 2, 3, 0, 4, 0, 0, 7, 11, 0, 7, 12, 0, 7, 9, 0, 7, 10, 0, 7, 13, 0, 7, 8, 0, 7, 2, 0, 7, 3, 0, 7, 15, 0, 5, 2, 0, 5, 3, 0, 7, 6, 0, 7, 16, 0, 7, 17, 0, 7, 18, 0, 7, 19, 0, 7, 20, 0, 7, 21, 0, 7, 22, 0, 7, 23, 0, 7, 24, 0, 7, 25, 0, 7, 26, 0, 7, 27, 0, 7, 28, 0, 7, 29, 0] \ No newline at end of file diff --git a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.java b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.java index 2a739910ab1..79166aed4f1 100644 --- a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.java +++ b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlLexer.java @@ -37,12 +37,10 @@ public class TomlLexer extends Lexer { FLOAT=19, INF=20, NAN=21, DEC_INT=22, HEX_INT=23, OCT_INT=24, BIN_INT=25, OFFSET_DATE_TIME=26, LOCAL_DATE_TIME=27, LOCAL_DATE=28, LOCAL_TIME=29, INLINE_TABLE_WS=30, R_BRACE=31, ARRAY_WS=32; - public static final int - COMMENTS_CHANNEL=2; public static final int SIMPLE_VALUE_MODE=1, INLINE_TABLE_MODE=2, ARRAY_MODE=3; public static String[] channelNames = { - "DEFAULT_TOKEN_CHANNEL", "HIDDEN", "COMMENTS_CHANNEL" + "DEFAULT_TOKEN_CHANNEL", "HIDDEN" }; public static String[] modeNames = { @@ -150,7 +148,7 @@ public TomlLexer(CharStream input) { public ATN getATN() { return _ATN; } public static final String _serializedATN = - "\u0004\u0000 \u029f\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ + "\u0004\u0000 \u029d\u0006\uffff\uffff\u0006\uffff\uffff\u0006\uffff\uffff"+ "\u0006\uffff\uffff\u0002\u0000\u0007\u0000\u0002\u0001\u0007\u0001\u0002"+ "\u0002\u0007\u0002\u0002\u0003\u0007\u0003\u0002\u0004\u0007\u0004\u0002"+ "\u0005\u0007\u0005\u0002\u0006\u0007\u0006\u0002\u0007\u0007\u0007\u0002"+ @@ -176,404 +174,403 @@ public TomlLexer(CharStream input) { "\u00b8\b\u0000\u000b\u0000\f\u0000\u00b9\u0001\u0000\u0001\u0000\u0001"+ "\u0001\u0003\u0001\u00bf\b\u0001\u0001\u0001\u0004\u0001\u00c2\b\u0001"+ "\u000b\u0001\f\u0001\u00c3\u0001\u0002\u0001\u0002\u0005\u0002\u00c8\b"+ - "\u0002\n\u0002\f\u0002\u00cb\t\u0002\u0001\u0002\u0001\u0002\u0001\u0003"+ - "\u0001\u0003\u0001\u0004\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005"+ - "\u0001\u0006\u0001\u0006\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007"+ - "\u0001\u0007\u0001\b\u0001\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\n\u0001"+ - "\n\u0001\u000b\u0001\u000b\u0001\f\u0001\f\u0001\f\u0001\f\u0003\f\u00eb"+ - "\b\f\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001"+ - "\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001"+ - "\u000e\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u000f\u0005"+ - "\u000f\u0100\b\u000f\n\u000f\f\u000f\u0103\t\u000f\u0001\u000f\u0001\u000f"+ - "\u0001\u0010\u0001\u0010\u0005\u0010\u0109\b\u0010\n\u0010\f\u0010\u010c"+ - "\t\u0010\u0001\u0010\u0001\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0004"+ - "\u0011\u0113\b\u0011\u000b\u0011\f\u0011\u0114\u0001\u0012\u0001\u0012"+ - "\u0001\u0012\u0001\u0012\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0013"+ - "\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0014\u0001\u0015"+ - "\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015"+ - "\u0001\u0015\u0001\u0015\u0003\u0015\u012d\b\u0015\u0001\u0015\u0001\u0015"+ - "\u0001\u0016\u0001\u0016\u0003\u0016\u0133\b\u0016\u0001\u0016\u0001\u0016"+ - "\u0003\u0016\u0137\b\u0016\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017"+ - "\u0001\u0017\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018"+ - "\u0001\u0018\u0005\u0018\u0144\b\u0018\n\u0018\f\u0018\u0147\t\u0018\u0001"+ - "\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001"+ - "\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001"+ - "\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0005\u001a\u0159\b\u001a\n"+ - "\u001a\f\u001a\u015c\t\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ - "\u001a\u0001\u001a\u0001\u001a\u0001\u001b\u0001\u001b\u0003\u001b\u0166"+ - "\b\u001b\u0001\u001b\u0001\u001b\u0001\u001c\u0001\u001c\u0001\u001c\u0001"+ - "\u001c\u0005\u001c\u016e\b\u001c\n\u001c\f\u001c\u0171\t\u001c\u0001\u001d"+ - "\u0001\u001d\u0001\u001d\u0001\u001e\u0001\u001e\u0001\u001e\u0001\u001e"+ - "\u0003\u001e\u017a\b\u001e\u0003\u001e\u017c\b\u001e\u0001\u001e\u0001"+ - "\u001e\u0001\u001f\u0003\u001f\u0181\b\u001f\u0001\u001f\u0001\u001f\u0001"+ - "\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001 \u0003 \u018a\b \u0001"+ - " \u0001 \u0001 \u0001 \u0001 \u0001 \u0001!\u0001!\u0003!\u0194\b!\u0001"+ - "\"\u0001\"\u0001#\u0001#\u0001$\u0001$\u0001%\u0003%\u019d\b%\u0001%\u0001"+ - "%\u0001%\u0001%\u0001%\u0004%\u01a4\b%\u000b%\f%\u01a5\u0003%\u01a8\b"+ - "%\u0001%\u0001%\u0001&\u0001&\u0001&\u0001&\u0001&\u0001&\u0001&\u0005"+ - "&\u01b3\b&\n&\f&\u01b6\t&\u0001&\u0001&\u0001\'\u0001\'\u0001\'\u0001"+ - "\'\u0001\'\u0001\'\u0001\'\u0005\'\u01c1\b\'\n\'\f\'\u01c4\t\'\u0001\'"+ - "\u0001\'\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0001(\u0005(\u01cf"+ - "\b(\n(\f(\u01d2\t(\u0001(\u0001(\u0001)\u0001)\u0001)\u0001)\u0001)\u0001"+ - "*\u0001*\u0001*\u0001+\u0001+\u0001+\u0001,\u0001,\u0001-\u0001-\u0001"+ - "-\u0001.\u0001.\u0001.\u0001/\u0001/\u0001/\u00010\u00010\u00040\u01ee"+ - "\b0\u000b0\f0\u01ef\u00011\u00011\u00011\u00011\u00011\u00012\u00012\u0003"+ - "2\u01f9\b2\u00013\u00013\u00013\u00013\u00013\u00013\u00033\u0201\b3\u0001"+ - "4\u00014\u00014\u00014\u00014\u00014\u00015\u00015\u00015\u00016\u0001"+ - "6\u00016\u00016\u00016\u00016\u00017\u00017\u00017\u00017\u00017\u0001"+ - "7\u00018\u00018\u00018\u00018\u00019\u00019\u00019\u00019\u0001:\u0001"+ - ":\u0001:\u0001:\u0001;\u0001;\u0001;\u0001;\u0001<\u0001<\u0001<\u0001"+ - "<\u0001=\u0001=\u0001=\u0001=\u0001>\u0001>\u0001>\u0001>\u0001?\u0001"+ - "?\u0001?\u0001?\u0001@\u0001@\u0001@\u0001@\u0001A\u0001A\u0001A\u0001"+ - "A\u0001A\u0001B\u0001B\u0001B\u0001B\u0001C\u0001C\u0001C\u0001C\u0001"+ - "D\u0001D\u0001D\u0001D\u0001E\u0001E\u0001E\u0001E\u0001F\u0001F\u0001"+ - "F\u0001F\u0001F\u0001G\u0001G\u0001G\u0001G\u0001G\u0001H\u0001H\u0001"+ - "H\u0001H\u0001H\u0001I\u0001I\u0001I\u0001I\u0001J\u0001J\u0001J\u0001"+ - "J\u0001K\u0001K\u0001K\u0001K\u0001L\u0001L\u0001L\u0001L\u0001M\u0001"+ - "M\u0001M\u0001M\u0001N\u0001N\u0001N\u0001N\u0001O\u0001O\u0001O\u0001"+ - "O\u0001P\u0001P\u0001P\u0001P\u0001Q\u0001Q\u0001Q\u0001Q\u0001R\u0001"+ - "R\u0001R\u0001R\u0001S\u0001S\u0001S\u0001S\u0001T\u0001T\u0001T\u0001"+ - "T\u0001U\u0001U\u0001U\u0001U\u0001V\u0001V\u0001V\u0001V\u0001W\u0001"+ - "W\u0001W\u0001W\u0001X\u0001X\u0001X\u0001X\u0004\u0101\u010a\u0145\u015a"+ - "\u0000Y\u0004\u0001\u0006\u0002\b\u0003\n\u0004\f\u0005\u000e\u0006\u0010"+ - "\u0007\u0012\b\u0014\t\u0016\n\u0018\u0000\u001a\u0000\u001c\u0000\u001e"+ - "\u0000 \u0000\"\u000b$\f&\r(\u000e*\u000f,\u0000.\u00100\u00002\u0000"+ - "4\u00116\u00008\u0012:\u0000<\u0000>\u0000@\u0013B\u0014D\u0015F\u0000"+ - "H\u0000J\u0000L\u0000N\u0016P\u0017R\u0018T\u0019V\u0000X\u0000Z\u0000"+ - "\\\u0000^\u0000`\u0000b\u0000d\u0000f\u0000h\u0000j\u0000l\u0000n\u0000"+ - "p\u001ar\u001bt\u001cv\u001dx\u001ez\u0000|\u0000~\u001f\u0080\u0000\u0082"+ - "\u0000\u0084\u0000\u0086\u0000\u0088 \u008a\u0000\u008c\u0000\u008e\u0000"+ - "\u0090\u0000\u0092\u0000\u0094\u0000\u0096\u0000\u0098\u0000\u009a\u0000"+ - "\u009c\u0000\u009e\u0000\u00a0\u0000\u00a2\u0000\u00a4\u0000\u00a6\u0000"+ - "\u00a8\u0000\u00aa\u0000\u00ac\u0000\u00ae\u0000\u00b0\u0000\u00b2\u0000"+ - "\u00b4\u0000\u0004\u0000\u0001\u0002\u0003\u0010\u0002\u0000\t\t \u0002"+ - "\u0000\n\n\r\r\u0001\u000009\u0002\u0000AZaz\b\u0000\"\"//\\\\bbffnnr"+ - "rtt\u0003\u0000\n\n\"\"\\\\\u0002\u0000\n\n\'\'\u0002\u0000--__\u0002"+ - "\u0000\"\"\\\\\u0002\u0000EEee\u0002\u0000++--\u0002\u0000AFaf\u0001\u0000"+ - "19\u0001\u000007\u0001\u000001\u0003\u0000 TTtt\u02a8\u0000\u0004\u0001"+ - "\u0000\u0000\u0000\u0000\u0006\u0001\u0000\u0000\u0000\u0000\b\u0001\u0000"+ - "\u0000\u0000\u0000\n\u0001\u0000\u0000\u0000\u0000\f\u0001\u0000\u0000"+ - "\u0000\u0000\u000e\u0001\u0000\u0000\u0000\u0000\u0010\u0001\u0000\u0000"+ - "\u0000\u0000\u0012\u0001\u0000\u0000\u0000\u0000\u0014\u0001\u0000\u0000"+ - "\u0000\u0000\u0016\u0001\u0000\u0000\u0000\u0000\"\u0001\u0000\u0000\u0000"+ - "\u0000$\u0001\u0000\u0000\u0000\u0000&\u0001\u0000\u0000\u0000\u0001("+ - "\u0001\u0000\u0000\u0000\u0001*\u0001\u0000\u0000\u0000\u0001,\u0001\u0000"+ - "\u0000\u0000\u0001.\u0001\u0000\u0000\u0000\u00012\u0001\u0000\u0000\u0000"+ - "\u00014\u0001\u0000\u0000\u0000\u00016\u0001\u0000\u0000\u0000\u00018"+ - "\u0001\u0000\u0000\u0000\u0001@\u0001\u0000\u0000\u0000\u0001B\u0001\u0000"+ - "\u0000\u0000\u0001D\u0001\u0000\u0000\u0000\u0001N\u0001\u0000\u0000\u0000"+ - "\u0001P\u0001\u0000\u0000\u0000\u0001R\u0001\u0000\u0000\u0000\u0001T"+ - "\u0001\u0000\u0000\u0000\u0001p\u0001\u0000\u0000\u0000\u0001r\u0001\u0000"+ - "\u0000\u0000\u0001t\u0001\u0000\u0000\u0000\u0001v\u0001\u0000\u0000\u0000"+ - "\u0002x\u0001\u0000\u0000\u0000\u0002z\u0001\u0000\u0000\u0000\u0002|"+ - "\u0001\u0000\u0000\u0000\u0002~\u0001\u0000\u0000\u0000\u0002\u0080\u0001"+ - "\u0000\u0000\u0000\u0002\u0082\u0001\u0000\u0000\u0000\u0002\u0084\u0001"+ - "\u0000\u0000\u0000\u0002\u0086\u0001\u0000\u0000\u0000\u0003\u0088\u0001"+ - "\u0000\u0000\u0000\u0003\u008a\u0001\u0000\u0000\u0000\u0003\u008c\u0001"+ - "\u0000\u0000\u0000\u0003\u008e\u0001\u0000\u0000\u0000\u0003\u0090\u0001"+ - "\u0000\u0000\u0000\u0003\u0092\u0001\u0000\u0000\u0000\u0003\u0094\u0001"+ - "\u0000\u0000\u0000\u0003\u0096\u0001\u0000\u0000\u0000\u0003\u0098\u0001"+ - "\u0000\u0000\u0000\u0003\u009a\u0001\u0000\u0000\u0000\u0003\u009c\u0001"+ - "\u0000\u0000\u0000\u0003\u009e\u0001\u0000\u0000\u0000\u0003\u00a0\u0001"+ - "\u0000\u0000\u0000\u0003\u00a2\u0001\u0000\u0000\u0000\u0003\u00a4\u0001"+ - "\u0000\u0000\u0000\u0003\u00a6\u0001\u0000\u0000\u0000\u0003\u00a8\u0001"+ - "\u0000\u0000\u0000\u0003\u00aa\u0001\u0000\u0000\u0000\u0003\u00ac\u0001"+ - "\u0000\u0000\u0000\u0003\u00ae\u0001\u0000\u0000\u0000\u0003\u00b0\u0001"+ - "\u0000\u0000\u0000\u0003\u00b2\u0001\u0000\u0000\u0000\u0003\u00b4\u0001"+ - "\u0000\u0000\u0000\u0004\u00b7\u0001\u0000\u0000\u0000\u0006\u00c1\u0001"+ - "\u0000\u0000\u0000\b\u00c5\u0001\u0000\u0000\u0000\n\u00ce\u0001\u0000"+ - "\u0000\u0000\f\u00d0\u0001\u0000\u0000\u0000\u000e\u00d3\u0001\u0000\u0000"+ - "\u0000\u0010\u00d5\u0001\u0000\u0000\u0000\u0012\u00d8\u0001\u0000\u0000"+ - "\u0000\u0014\u00dc\u0001\u0000\u0000\u0000\u0016\u00de\u0001\u0000\u0000"+ - "\u0000\u0018\u00e2\u0001\u0000\u0000\u0000\u001a\u00e4\u0001\u0000\u0000"+ - "\u0000\u001c\u00e6\u0001\u0000\u0000\u0000\u001e\u00ec\u0001\u0000\u0000"+ - "\u0000 \u00f2\u0001\u0000\u0000\u0000\"\u00fc\u0001\u0000\u0000\u0000"+ - "$\u0106\u0001\u0000\u0000\u0000&\u0112\u0001\u0000\u0000\u0000(\u0116"+ - "\u0001\u0000\u0000\u0000*\u011a\u0001\u0000\u0000\u0000,\u011e\u0001\u0000"+ - "\u0000\u0000.\u012c\u0001\u0000\u0000\u00000\u0136\u0001\u0000\u0000\u0000"+ - "2\u0138\u0001\u0000\u0000\u00004\u013d\u0001\u0000\u0000\u00006\u014e"+ - "\u0001\u0000\u0000\u00008\u0153\u0001\u0000\u0000\u0000:\u0163\u0001\u0000"+ - "\u0000\u0000<\u0169\u0001\u0000\u0000\u0000>\u0172\u0001\u0000\u0000\u0000"+ - "@\u0175\u0001\u0000\u0000\u0000B\u0180\u0001\u0000\u0000\u0000D\u0189"+ - "\u0001\u0000\u0000\u0000F\u0193\u0001\u0000\u0000\u0000H\u0195\u0001\u0000"+ - "\u0000\u0000J\u0197\u0001\u0000\u0000\u0000L\u0199\u0001\u0000\u0000\u0000"+ - "N\u019c\u0001\u0000\u0000\u0000P\u01ab\u0001\u0000\u0000\u0000R\u01b9"+ - "\u0001\u0000\u0000\u0000T\u01c7\u0001\u0000\u0000\u0000V\u01d5\u0001\u0000"+ - "\u0000\u0000X\u01da\u0001\u0000\u0000\u0000Z\u01dd\u0001\u0000\u0000\u0000"+ - "\\\u01e0\u0001\u0000\u0000\u0000^\u01e2\u0001\u0000\u0000\u0000`\u01e5"+ - "\u0001\u0000\u0000\u0000b\u01e8\u0001\u0000\u0000\u0000d\u01eb\u0001\u0000"+ - "\u0000\u0000f\u01f1\u0001\u0000\u0000\u0000h\u01f8\u0001\u0000\u0000\u0000"+ - "j\u01fa\u0001\u0000\u0000\u0000l\u0202\u0001\u0000\u0000\u0000n\u0208"+ - "\u0001\u0000\u0000\u0000p\u020b\u0001\u0000\u0000\u0000r\u0211\u0001\u0000"+ - "\u0000\u0000t\u0217\u0001\u0000\u0000\u0000v\u021b\u0001\u0000\u0000\u0000"+ - "x\u021f\u0001\u0000\u0000\u0000z\u0223\u0001\u0000\u0000\u0000|\u0227"+ - "\u0001\u0000\u0000\u0000~\u022b\u0001\u0000\u0000\u0000\u0080\u022f\u0001"+ - "\u0000\u0000\u0000\u0082\u0233\u0001\u0000\u0000\u0000\u0084\u0237\u0001"+ - "\u0000\u0000\u0000\u0086\u023b\u0001\u0000\u0000\u0000\u0088\u0240\u0001"+ - "\u0000\u0000\u0000\u008a\u0244\u0001\u0000\u0000\u0000\u008c\u0248\u0001"+ - "\u0000\u0000\u0000\u008e\u024c\u0001\u0000\u0000\u0000\u0090\u0250\u0001"+ - "\u0000\u0000\u0000\u0092\u0255\u0001\u0000\u0000\u0000\u0094\u025a\u0001"+ - "\u0000\u0000\u0000\u0096\u025f\u0001\u0000\u0000\u0000\u0098\u0263\u0001"+ - "\u0000\u0000\u0000\u009a\u0267\u0001\u0000\u0000\u0000\u009c\u026b\u0001"+ - "\u0000\u0000\u0000\u009e\u026f\u0001\u0000\u0000\u0000\u00a0\u0273\u0001"+ - "\u0000\u0000\u0000\u00a2\u0277\u0001\u0000\u0000\u0000\u00a4\u027b\u0001"+ - "\u0000\u0000\u0000\u00a6\u027f\u0001\u0000\u0000\u0000\u00a8\u0283\u0001"+ - "\u0000\u0000\u0000\u00aa\u0287\u0001\u0000\u0000\u0000\u00ac\u028b\u0001"+ - "\u0000\u0000\u0000\u00ae\u028f\u0001\u0000\u0000\u0000\u00b0\u0293\u0001"+ - "\u0000\u0000\u0000\u00b2\u0297\u0001\u0000\u0000\u0000\u00b4\u029b\u0001"+ - "\u0000\u0000\u0000\u00b6\u00b8\u0007\u0000\u0000\u0000\u00b7\u00b6\u0001"+ - "\u0000\u0000\u0000\u00b8\u00b9\u0001\u0000\u0000\u0000\u00b9\u00b7\u0001"+ - "\u0000\u0000\u0000\u00b9\u00ba\u0001\u0000\u0000\u0000\u00ba\u00bb\u0001"+ - "\u0000\u0000\u0000\u00bb\u00bc\u0006\u0000\u0000\u0000\u00bc\u0005\u0001"+ - "\u0000\u0000\u0000\u00bd\u00bf\u0005\r\u0000\u0000\u00be\u00bd\u0001\u0000"+ - "\u0000\u0000\u00be\u00bf\u0001\u0000\u0000\u0000\u00bf\u00c0\u0001\u0000"+ - "\u0000\u0000\u00c0\u00c2\u0005\n\u0000\u0000\u00c1\u00be\u0001\u0000\u0000"+ - "\u0000\u00c2\u00c3\u0001\u0000\u0000\u0000\u00c3\u00c1\u0001\u0000\u0000"+ - "\u0000\u00c3\u00c4\u0001\u0000\u0000\u0000\u00c4\u0007\u0001\u0000\u0000"+ - "\u0000\u00c5\u00c9\u0005#\u0000\u0000\u00c6\u00c8\b\u0001\u0000\u0000"+ - "\u00c7\u00c6\u0001\u0000\u0000\u0000\u00c8\u00cb\u0001\u0000\u0000\u0000"+ - "\u00c9\u00c7\u0001\u0000\u0000\u0000\u00c9\u00ca\u0001\u0000\u0000\u0000"+ - "\u00ca\u00cc\u0001\u0000\u0000\u0000\u00cb\u00c9\u0001\u0000\u0000\u0000"+ - "\u00cc\u00cd\u0006\u0002\u0001\u0000\u00cd\t\u0001\u0000\u0000\u0000\u00ce"+ - "\u00cf\u0005[\u0000\u0000\u00cf\u000b\u0001\u0000\u0000\u0000\u00d0\u00d1"+ - "\u0005[\u0000\u0000\u00d1\u00d2\u0005[\u0000\u0000\u00d2\r\u0001\u0000"+ - "\u0000\u0000\u00d3\u00d4\u0005]\u0000\u0000\u00d4\u000f\u0001\u0000\u0000"+ - "\u0000\u00d5\u00d6\u0005]\u0000\u0000\u00d6\u00d7\u0005]\u0000\u0000\u00d7"+ - "\u0011\u0001\u0000\u0000\u0000\u00d8\u00d9\u0005=\u0000\u0000\u00d9\u00da"+ - "\u0001\u0000\u0000\u0000\u00da\u00db\u0006\u0007\u0002\u0000\u00db\u0013"+ - "\u0001\u0000\u0000\u0000\u00dc\u00dd\u0005.\u0000\u0000\u00dd\u0015\u0001"+ - "\u0000\u0000\u0000\u00de\u00df\u0005,\u0000\u0000\u00df\u00e0\u0001\u0000"+ - "\u0000\u0000\u00e0\u00e1\u0006\t\u0000\u0000\u00e1\u0017\u0001\u0000\u0000"+ - "\u0000\u00e2\u00e3\u0007\u0002\u0000\u0000\u00e3\u0019\u0001\u0000\u0000"+ - "\u0000\u00e4\u00e5\u0007\u0003\u0000\u0000\u00e5\u001b\u0001\u0000\u0000"+ - "\u0000\u00e6\u00ea\u0005\\\u0000\u0000\u00e7\u00eb\u0007\u0004\u0000\u0000"+ - "\u00e8\u00eb\u0003\u001e\r\u0000\u00e9\u00eb\u0003 \u000e\u0000\u00ea"+ - "\u00e7\u0001\u0000\u0000\u0000\u00ea\u00e8\u0001\u0000\u0000\u0000\u00ea"+ - "\u00e9\u0001\u0000\u0000\u0000\u00eb\u001d\u0001\u0000\u0000\u0000\u00ec"+ - "\u00ed\u0005u\u0000\u0000\u00ed\u00ee\u0003F!\u0000\u00ee\u00ef\u0003"+ - "F!\u0000\u00ef\u00f0\u0003F!\u0000\u00f0\u00f1\u0003F!\u0000\u00f1\u001f"+ - "\u0001\u0000\u0000\u0000\u00f2\u00f3\u0005U\u0000\u0000\u00f3\u00f4\u0003"+ - "F!\u0000\u00f4\u00f5\u0003F!\u0000\u00f5\u00f6\u0003F!\u0000\u00f6\u00f7"+ - "\u0003F!\u0000\u00f7\u00f8\u0003F!\u0000\u00f8\u00f9\u0003F!\u0000\u00f9"+ - "\u00fa\u0003F!\u0000\u00fa\u00fb\u0003F!\u0000\u00fb!\u0001\u0000\u0000"+ - "\u0000\u00fc\u0101\u0005\"\u0000\u0000\u00fd\u0100\u0003\u001c\f\u0000"+ - "\u00fe\u0100\b\u0005\u0000\u0000\u00ff\u00fd\u0001\u0000\u0000\u0000\u00ff"+ - "\u00fe\u0001\u0000\u0000\u0000\u0100\u0103\u0001\u0000\u0000\u0000\u0101"+ - "\u0102\u0001\u0000\u0000\u0000\u0101\u00ff\u0001\u0000\u0000\u0000\u0102"+ - "\u0104\u0001\u0000\u0000\u0000\u0103\u0101\u0001\u0000\u0000\u0000\u0104"+ - "\u0105\u0005\"\u0000\u0000\u0105#\u0001\u0000\u0000\u0000\u0106\u010a"+ - "\u0005\'\u0000\u0000\u0107\u0109\b\u0006\u0000\u0000\u0108\u0107\u0001"+ - "\u0000\u0000\u0000\u0109\u010c\u0001\u0000\u0000\u0000\u010a\u010b\u0001"+ - "\u0000\u0000\u0000\u010a\u0108\u0001\u0000\u0000\u0000\u010b\u010d\u0001"+ - "\u0000\u0000\u0000\u010c\u010a\u0001\u0000\u0000\u0000\u010d\u010e\u0005"+ - "\'\u0000\u0000\u010e%\u0001\u0000\u0000\u0000\u010f\u0113\u0003\u001a"+ - "\u000b\u0000\u0110\u0113\u0003\u0018\n\u0000\u0111\u0113\u0007\u0007\u0000"+ - "\u0000\u0112\u010f\u0001\u0000\u0000\u0000\u0112\u0110\u0001\u0000\u0000"+ - "\u0000\u0112\u0111\u0001\u0000\u0000\u0000\u0113\u0114\u0001\u0000\u0000"+ - "\u0000\u0114\u0112\u0001\u0000\u0000\u0000\u0114\u0115\u0001\u0000\u0000"+ - "\u0000\u0115\'\u0001\u0000\u0000\u0000\u0116\u0117\u0003\u0004\u0000\u0000"+ - "\u0117\u0118\u0001\u0000\u0000\u0000\u0118\u0119\u0006\u0012\u0000\u0000"+ - "\u0119)\u0001\u0000\u0000\u0000\u011a\u011b\u0005{\u0000\u0000\u011b\u011c"+ - "\u0001\u0000\u0000\u0000\u011c\u011d\u0006\u0013\u0003\u0000\u011d+\u0001"+ - "\u0000\u0000\u0000\u011e\u011f\u0003\n\u0003\u0000\u011f\u0120\u0001\u0000"+ - "\u0000\u0000\u0120\u0121\u0006\u0014\u0004\u0000\u0121\u0122\u0006\u0014"+ - "\u0005\u0000\u0122-\u0001\u0000\u0000\u0000\u0123\u0124\u0005t\u0000\u0000"+ - "\u0124\u0125\u0005r\u0000\u0000\u0125\u0126\u0005u\u0000\u0000\u0126\u012d"+ - "\u0005e\u0000\u0000\u0127\u0128\u0005f\u0000\u0000\u0128\u0129\u0005a"+ - "\u0000\u0000\u0129\u012a\u0005l\u0000\u0000\u012a\u012b\u0005s\u0000\u0000"+ - "\u012b\u012d\u0005e\u0000\u0000\u012c\u0123\u0001\u0000\u0000\u0000\u012c"+ - "\u0127\u0001\u0000\u0000\u0000\u012d\u012e\u0001\u0000\u0000\u0000\u012e"+ - "\u012f\u0006\u0015\u0006\u0000\u012f/\u0001\u0000\u0000\u0000\u0130\u0132"+ - "\u0005\\\u0000\u0000\u0131\u0133\u0005\r\u0000\u0000\u0132\u0131\u0001"+ - "\u0000\u0000\u0000\u0132\u0133\u0001\u0000\u0000\u0000\u0133\u0134\u0001"+ - "\u0000\u0000\u0000\u0134\u0137\u0005\n\u0000\u0000\u0135\u0137\u0003\u001c"+ - "\f\u0000\u0136\u0130\u0001\u0000\u0000\u0000\u0136\u0135\u0001\u0000\u0000"+ - "\u0000\u01371\u0001\u0000\u0000\u0000\u0138\u0139\u0003\"\u000f\u0000"+ - "\u0139\u013a\u0001\u0000\u0000\u0000\u013a\u013b\u0006\u0017\u0007\u0000"+ - "\u013b\u013c\u0006\u0017\u0006\u0000\u013c3\u0001\u0000\u0000\u0000\u013d"+ - "\u013e\u0005\"\u0000\u0000\u013e\u013f\u0005\"\u0000\u0000\u013f\u0140"+ - "\u0005\"\u0000\u0000\u0140\u0145\u0001\u0000\u0000\u0000\u0141\u0144\u0003"+ - "0\u0016\u0000\u0142\u0144\b\b\u0000\u0000\u0143\u0141\u0001\u0000\u0000"+ - "\u0000\u0143\u0142\u0001\u0000\u0000\u0000\u0144\u0147\u0001\u0000\u0000"+ - "\u0000\u0145\u0146\u0001\u0000\u0000\u0000\u0145\u0143\u0001\u0000\u0000"+ - "\u0000\u0146\u0148\u0001\u0000\u0000\u0000\u0147\u0145\u0001\u0000\u0000"+ - "\u0000\u0148\u0149\u0005\"\u0000\u0000\u0149\u014a\u0005\"\u0000\u0000"+ - "\u014a\u014b\u0005\"\u0000\u0000\u014b\u014c\u0001\u0000\u0000\u0000\u014c"+ - "\u014d\u0006\u0018\u0006\u0000\u014d5\u0001\u0000\u0000\u0000\u014e\u014f"+ - "\u0003$\u0010\u0000\u014f\u0150\u0001\u0000\u0000\u0000\u0150\u0151\u0006"+ - "\u0019\b\u0000\u0151\u0152\u0006\u0019\u0006\u0000\u01527\u0001\u0000"+ - "\u0000\u0000\u0153\u0154\u0005\'\u0000\u0000\u0154\u0155\u0005\'\u0000"+ - "\u0000\u0155\u0156\u0005\'\u0000\u0000\u0156\u015a\u0001\u0000\u0000\u0000"+ - "\u0157\u0159\t\u0000\u0000\u0000\u0158\u0157\u0001\u0000\u0000\u0000\u0159"+ - "\u015c\u0001\u0000\u0000\u0000\u015a\u015b\u0001\u0000\u0000\u0000\u015a"+ - "\u0158\u0001\u0000\u0000\u0000\u015b\u015d\u0001\u0000\u0000\u0000\u015c"+ - "\u015a\u0001\u0000\u0000\u0000\u015d\u015e\u0005\'\u0000\u0000\u015e\u015f"+ - "\u0005\'\u0000\u0000\u015f\u0160\u0005\'\u0000\u0000\u0160\u0161\u0001"+ - "\u0000\u0000\u0000\u0161\u0162\u0006\u001a\u0006\u0000\u01629\u0001\u0000"+ - "\u0000\u0000\u0163\u0165\u0007\t\u0000\u0000\u0164\u0166\u0007\n\u0000"+ - "\u0000\u0165\u0164\u0001\u0000\u0000\u0000\u0165\u0166\u0001\u0000\u0000"+ - "\u0000\u0166\u0167\u0001\u0000\u0000\u0000\u0167\u0168\u0003<\u001c\u0000"+ - "\u0168;\u0001\u0000\u0000\u0000\u0169\u016f\u0003\u0018\n\u0000\u016a"+ - "\u016e\u0003\u0018\n\u0000\u016b\u016c\u0005_\u0000\u0000\u016c\u016e"+ - "\u0003\u0018\n\u0000\u016d\u016a\u0001\u0000\u0000\u0000\u016d\u016b\u0001"+ - "\u0000\u0000\u0000\u016e\u0171\u0001\u0000\u0000\u0000\u016f\u016d\u0001"+ - "\u0000\u0000\u0000\u016f\u0170\u0001\u0000\u0000\u0000\u0170=\u0001\u0000"+ - "\u0000\u0000\u0171\u016f\u0001\u0000\u0000\u0000\u0172\u0173\u0005.\u0000"+ - "\u0000\u0173\u0174\u0003<\u001c\u0000\u0174?\u0001\u0000\u0000\u0000\u0175"+ - "\u017b\u0003N%\u0000\u0176\u017c\u0003:\u001b\u0000\u0177\u0179\u0003"+ - ">\u001d\u0000\u0178\u017a\u0003:\u001b\u0000\u0179\u0178\u0001\u0000\u0000"+ - "\u0000\u0179\u017a\u0001\u0000\u0000\u0000\u017a\u017c\u0001\u0000\u0000"+ - "\u0000\u017b\u0176\u0001\u0000\u0000\u0000\u017b\u0177\u0001\u0000\u0000"+ - "\u0000\u017c\u017d\u0001\u0000\u0000\u0000\u017d\u017e\u0006\u001e\u0006"+ - "\u0000\u017eA\u0001\u0000\u0000\u0000\u017f\u0181\u0007\n\u0000\u0000"+ - "\u0180\u017f\u0001\u0000\u0000\u0000\u0180\u0181\u0001\u0000\u0000\u0000"+ - "\u0181\u0182\u0001\u0000\u0000\u0000\u0182\u0183\u0005i\u0000\u0000\u0183"+ - "\u0184\u0005n\u0000\u0000\u0184\u0185\u0005f\u0000\u0000\u0185\u0186\u0001"+ - "\u0000\u0000\u0000\u0186\u0187\u0006\u001f\u0006\u0000\u0187C\u0001\u0000"+ - "\u0000\u0000\u0188\u018a\u0007\n\u0000\u0000\u0189\u0188\u0001\u0000\u0000"+ - "\u0000\u0189\u018a\u0001\u0000\u0000\u0000\u018a\u018b\u0001\u0000\u0000"+ - "\u0000\u018b\u018c\u0005n\u0000\u0000\u018c\u018d\u0005a\u0000\u0000\u018d"+ - "\u018e\u0005n\u0000\u0000\u018e\u018f\u0001\u0000\u0000\u0000\u018f\u0190"+ - "\u0006 \u0006\u0000\u0190E\u0001\u0000\u0000\u0000\u0191\u0194\u0007\u000b"+ - "\u0000\u0000\u0192\u0194\u0003\u0018\n\u0000\u0193\u0191\u0001\u0000\u0000"+ - "\u0000\u0193\u0192\u0001\u0000\u0000\u0000\u0194G\u0001\u0000\u0000\u0000"+ - "\u0195\u0196\u0007\f\u0000\u0000\u0196I\u0001\u0000\u0000\u0000\u0197"+ - "\u0198\u0007\r\u0000\u0000\u0198K\u0001\u0000\u0000\u0000\u0199\u019a"+ - "\u0007\u000e\u0000\u0000\u019aM\u0001\u0000\u0000\u0000\u019b\u019d\u0007"+ - "\n\u0000\u0000\u019c\u019b\u0001\u0000\u0000\u0000\u019c\u019d\u0001\u0000"+ - "\u0000\u0000\u019d\u01a7\u0001\u0000\u0000\u0000\u019e\u01a8\u0003\u0018"+ - "\n\u0000\u019f\u01a3\u0003H\"\u0000\u01a0\u01a4\u0003\u0018\n\u0000\u01a1"+ - "\u01a2\u0005_\u0000\u0000\u01a2\u01a4\u0003\u0018\n\u0000\u01a3\u01a0"+ - "\u0001\u0000\u0000\u0000\u01a3\u01a1\u0001\u0000\u0000\u0000\u01a4\u01a5"+ - "\u0001\u0000\u0000\u0000\u01a5\u01a3\u0001\u0000\u0000\u0000\u01a5\u01a6"+ - "\u0001\u0000\u0000\u0000\u01a6\u01a8\u0001\u0000\u0000\u0000\u01a7\u019e"+ - "\u0001\u0000\u0000\u0000\u01a7\u019f\u0001\u0000\u0000\u0000\u01a8\u01a9"+ - "\u0001\u0000\u0000\u0000\u01a9\u01aa\u0006%\u0006\u0000\u01aaO\u0001\u0000"+ - "\u0000\u0000\u01ab\u01ac\u00050\u0000\u0000\u01ac\u01ad\u0005x\u0000\u0000"+ - "\u01ad\u01ae\u0001\u0000\u0000\u0000\u01ae\u01b4\u0003F!\u0000\u01af\u01b3"+ - "\u0003F!\u0000\u01b0\u01b1\u0005_\u0000\u0000\u01b1\u01b3\u0003F!\u0000"+ - "\u01b2\u01af\u0001\u0000\u0000\u0000\u01b2\u01b0\u0001\u0000\u0000\u0000"+ - "\u01b3\u01b6\u0001\u0000\u0000\u0000\u01b4\u01b2\u0001\u0000\u0000\u0000"+ - "\u01b4\u01b5\u0001\u0000\u0000\u0000\u01b5\u01b7\u0001\u0000\u0000\u0000"+ - "\u01b6\u01b4\u0001\u0000\u0000\u0000\u01b7\u01b8\u0006&\u0006\u0000\u01b8"+ - "Q\u0001\u0000\u0000\u0000\u01b9\u01ba\u00050\u0000\u0000\u01ba\u01bb\u0005"+ - "o\u0000\u0000\u01bb\u01bc\u0001\u0000\u0000\u0000\u01bc\u01c2\u0003J#"+ - "\u0000\u01bd\u01c1\u0003J#\u0000\u01be\u01bf\u0005_\u0000\u0000\u01bf"+ - "\u01c1\u0003J#\u0000\u01c0\u01bd\u0001\u0000\u0000\u0000\u01c0\u01be\u0001"+ - "\u0000\u0000\u0000\u01c1\u01c4\u0001\u0000\u0000\u0000\u01c2\u01c0\u0001"+ - "\u0000\u0000\u0000\u01c2\u01c3\u0001\u0000\u0000\u0000\u01c3\u01c5\u0001"+ - "\u0000\u0000\u0000\u01c4\u01c2\u0001\u0000\u0000\u0000\u01c5\u01c6\u0006"+ - "\'\u0006\u0000\u01c6S\u0001\u0000\u0000\u0000\u01c7\u01c8\u00050\u0000"+ - "\u0000\u01c8\u01c9\u0005b\u0000\u0000\u01c9\u01ca\u0001\u0000\u0000\u0000"+ - "\u01ca\u01d0\u0003L$\u0000\u01cb\u01cf\u0003L$\u0000\u01cc\u01cd\u0005"+ - "_\u0000\u0000\u01cd\u01cf\u0003L$\u0000\u01ce\u01cb\u0001\u0000\u0000"+ - "\u0000\u01ce\u01cc\u0001\u0000\u0000\u0000\u01cf\u01d2\u0001\u0000\u0000"+ - "\u0000\u01d0\u01ce\u0001\u0000\u0000\u0000\u01d0\u01d1\u0001\u0000\u0000"+ - "\u0000\u01d1\u01d3\u0001\u0000\u0000\u0000\u01d2\u01d0\u0001\u0000\u0000"+ - "\u0000\u01d3\u01d4\u0006(\u0006\u0000\u01d4U\u0001\u0000\u0000\u0000\u01d5"+ - "\u01d6\u0003\u0018\n\u0000\u01d6\u01d7\u0003\u0018\n\u0000\u01d7\u01d8"+ - "\u0003\u0018\n\u0000\u01d8\u01d9\u0003\u0018\n\u0000\u01d9W\u0001\u0000"+ - "\u0000\u0000\u01da\u01db\u0003\u0018\n\u0000\u01db\u01dc\u0003\u0018\n"+ - "\u0000\u01dcY\u0001\u0000\u0000\u0000\u01dd\u01de\u0003\u0018\n\u0000"+ - "\u01de\u01df\u0003\u0018\n\u0000\u01df[\u0001\u0000\u0000\u0000\u01e0"+ - "\u01e1\u0007\u000f\u0000\u0000\u01e1]\u0001\u0000\u0000\u0000\u01e2\u01e3"+ - "\u0003\u0018\n\u0000\u01e3\u01e4\u0003\u0018\n\u0000\u01e4_\u0001\u0000"+ - "\u0000\u0000\u01e5\u01e6\u0003\u0018\n\u0000\u01e6\u01e7\u0003\u0018\n"+ - "\u0000\u01e7a\u0001\u0000\u0000\u0000\u01e8\u01e9\u0003\u0018\n\u0000"+ - "\u01e9\u01ea\u0003\u0018\n\u0000\u01eac\u0001\u0000\u0000\u0000\u01eb"+ - "\u01ed\u0005.\u0000\u0000\u01ec\u01ee\u0003\u0018\n\u0000\u01ed\u01ec"+ - "\u0001\u0000\u0000\u0000\u01ee\u01ef\u0001\u0000\u0000\u0000\u01ef\u01ed"+ - "\u0001\u0000\u0000\u0000\u01ef\u01f0\u0001\u0000\u0000\u0000\u01f0e\u0001"+ - "\u0000\u0000\u0000\u01f1\u01f2\u0007\n\u0000\u0000\u01f2\u01f3\u0003^"+ - "-\u0000\u01f3\u01f4\u0005:\u0000\u0000\u01f4\u01f5\u0003`.\u0000\u01f5"+ - "g\u0001\u0000\u0000\u0000\u01f6\u01f9\u0005Z\u0000\u0000\u01f7\u01f9\u0003"+ - "f1\u0000\u01f8\u01f6\u0001\u0000\u0000\u0000\u01f8\u01f7\u0001\u0000\u0000"+ - "\u0000\u01f9i\u0001\u0000\u0000\u0000\u01fa\u01fb\u0003^-\u0000\u01fb"+ - "\u01fc\u0005:\u0000\u0000\u01fc\u01fd\u0003`.\u0000\u01fd\u01fe\u0005"+ - ":\u0000\u0000\u01fe\u0200\u0003b/\u0000\u01ff\u0201\u0003d0\u0000\u0200"+ - "\u01ff\u0001\u0000\u0000\u0000\u0200\u0201\u0001\u0000\u0000\u0000\u0201"+ - "k\u0001\u0000\u0000\u0000\u0202\u0203\u0003V)\u0000\u0203\u0204\u0005"+ - "-\u0000\u0000\u0204\u0205\u0003X*\u0000\u0205\u0206\u0005-\u0000\u0000"+ - "\u0206\u0207\u0003Z+\u0000\u0207m\u0001\u0000\u0000\u0000\u0208\u0209"+ - "\u0003j3\u0000\u0209\u020a\u0003h2\u0000\u020ao\u0001\u0000\u0000\u0000"+ - "\u020b\u020c\u0003l4\u0000\u020c\u020d\u0003\\,\u0000\u020d\u020e\u0003"+ - "n5\u0000\u020e\u020f\u0001\u0000\u0000\u0000\u020f\u0210\u00066\u0006"+ - "\u0000\u0210q\u0001\u0000\u0000\u0000\u0211\u0212\u0003l4\u0000\u0212"+ - "\u0213\u0003\\,\u0000\u0213\u0214\u0003j3\u0000\u0214\u0215\u0001\u0000"+ - "\u0000\u0000\u0215\u0216\u00067\u0006\u0000\u0216s\u0001\u0000\u0000\u0000"+ - "\u0217\u0218\u0003l4\u0000\u0218\u0219\u0001\u0000\u0000\u0000\u0219\u021a"+ - "\u00068\u0006\u0000\u021au\u0001\u0000\u0000\u0000\u021b\u021c\u0003j"+ - "3\u0000\u021c\u021d\u0001\u0000\u0000\u0000\u021d\u021e\u00069\u0006\u0000"+ - "\u021ew\u0001\u0000\u0000\u0000\u021f\u0220\u0003\u0004\u0000\u0000\u0220"+ - "\u0221\u0001\u0000\u0000\u0000\u0221\u0222\u0006:\u0000\u0000\u0222y\u0001"+ - "\u0000\u0000\u0000\u0223\u0224\u0003\u0014\b\u0000\u0224\u0225\u0001\u0000"+ - "\u0000\u0000\u0225\u0226\u0006;\t\u0000\u0226{\u0001\u0000\u0000\u0000"+ - "\u0227\u0228\u0003\u0016\t\u0000\u0228\u0229\u0001\u0000\u0000\u0000\u0229"+ - "\u022a\u0006<\n\u0000\u022a}\u0001\u0000\u0000\u0000\u022b\u022c\u0005"+ - "}\u0000\u0000\u022c\u022d\u0001\u0000\u0000\u0000\u022d\u022e\u0006=\u0006"+ - "\u0000\u022e\u007f\u0001\u0000\u0000\u0000\u022f\u0230\u0003\"\u000f\u0000"+ - "\u0230\u0231\u0001\u0000\u0000\u0000\u0231\u0232\u0006>\u0007\u0000\u0232"+ - "\u0081\u0001\u0000\u0000\u0000\u0233\u0234\u0003$\u0010\u0000\u0234\u0235"+ - "\u0001\u0000\u0000\u0000\u0235\u0236\u0006?\b\u0000\u0236\u0083\u0001"+ - "\u0000\u0000\u0000\u0237\u0238\u0003&\u0011\u0000\u0238\u0239\u0001\u0000"+ - "\u0000\u0000\u0239\u023a\u0006@\u000b\u0000\u023a\u0085\u0001\u0000\u0000"+ - "\u0000\u023b\u023c\u0003\u0012\u0007\u0000\u023c\u023d\u0001\u0000\u0000"+ - "\u0000\u023d\u023e\u0006A\f\u0000\u023e\u023f\u0006A\u0002\u0000\u023f"+ - "\u0087\u0001\u0000\u0000\u0000\u0240\u0241\u0003\u0004\u0000\u0000\u0241"+ - "\u0242\u0001\u0000\u0000\u0000\u0242\u0243\u0006B\u0000\u0000\u0243\u0089"+ - "\u0001\u0000\u0000\u0000\u0244\u0245\u0003\u0006\u0001\u0000\u0245\u0246"+ - "\u0001\u0000\u0000\u0000\u0246\u0247\u0006C\r\u0000\u0247\u008b\u0001"+ - "\u0000\u0000\u0000\u0248\u0249\u0003\b\u0002\u0000\u0249\u024a\u0001\u0000"+ - "\u0000\u0000\u024a\u024b\u0006D\u000e\u0000\u024b\u008d\u0001\u0000\u0000"+ - "\u0000\u024c\u024d\u0003\u0016\t\u0000\u024d\u024e\u0001\u0000\u0000\u0000"+ - "\u024e\u024f\u0006E\n\u0000\u024f\u008f\u0001\u0000\u0000\u0000\u0250"+ - "\u0251\u0003*\u0013\u0000\u0251\u0252\u0001\u0000\u0000\u0000\u0252\u0253"+ - "\u0006F\u000f\u0000\u0253\u0254\u0006F\u0010\u0000\u0254\u0091\u0001\u0000"+ - "\u0000\u0000\u0255\u0256\u0003\n\u0003\u0000\u0256\u0257\u0001\u0000\u0000"+ - "\u0000\u0257\u0258\u0006G\u0004\u0000\u0258\u0259\u0006G\u0011\u0000\u0259"+ - "\u0093\u0001\u0000\u0000\u0000\u025a\u025b\u0003\u000e\u0005\u0000\u025b"+ - "\u025c\u0001\u0000\u0000\u0000\u025c\u025d\u0006H\u0012\u0000\u025d\u025e"+ - "\u0006H\u0006\u0000\u025e\u0095\u0001\u0000\u0000\u0000\u025f\u0260\u0003"+ - ".\u0015\u0000\u0260\u0261\u0001\u0000\u0000\u0000\u0261\u0262\u0006I\u0013"+ - "\u0000\u0262\u0097\u0001\u0000\u0000\u0000\u0263\u0264\u0003\"\u000f\u0000"+ - "\u0264\u0265\u0001\u0000\u0000\u0000\u0265\u0266\u0006J\u0007\u0000\u0266"+ - "\u0099\u0001\u0000\u0000\u0000\u0267\u0268\u00034\u0018\u0000\u0268\u0269"+ - "\u0001\u0000\u0000\u0000\u0269\u026a\u0006K\u0014\u0000\u026a\u009b\u0001"+ - "\u0000\u0000\u0000\u026b\u026c\u0003$\u0010\u0000\u026c\u026d\u0001\u0000"+ - "\u0000\u0000\u026d\u026e\u0006L\b\u0000\u026e\u009d\u0001\u0000\u0000"+ - "\u0000\u026f\u0270\u00038\u001a\u0000\u0270\u0271\u0001\u0000\u0000\u0000"+ - "\u0271\u0272\u0006M\u0015\u0000\u0272\u009f\u0001\u0000\u0000\u0000\u0273"+ - "\u0274\u0003@\u001e\u0000\u0274\u0275\u0001\u0000\u0000\u0000\u0275\u0276"+ - "\u0006N\u0016\u0000\u0276\u00a1\u0001\u0000\u0000\u0000\u0277\u0278\u0003"+ - "B\u001f\u0000\u0278\u0279\u0001\u0000\u0000\u0000\u0279\u027a\u0006O\u0017"+ - "\u0000\u027a\u00a3\u0001\u0000\u0000\u0000\u027b\u027c\u0003D \u0000\u027c"+ - "\u027d\u0001\u0000\u0000\u0000\u027d\u027e\u0006P\u0018\u0000\u027e\u00a5"+ - "\u0001\u0000\u0000\u0000\u027f\u0280\u0003N%\u0000\u0280\u0281\u0001\u0000"+ - "\u0000\u0000\u0281\u0282\u0006Q\u0019\u0000\u0282\u00a7\u0001\u0000\u0000"+ - "\u0000\u0283\u0284\u0003P&\u0000\u0284\u0285\u0001\u0000\u0000\u0000\u0285"+ - "\u0286\u0006R\u001a\u0000\u0286\u00a9\u0001\u0000\u0000\u0000\u0287\u0288"+ - "\u0003R\'\u0000\u0288\u0289\u0001\u0000\u0000\u0000\u0289\u028a\u0006"+ - "S\u001b\u0000\u028a\u00ab\u0001\u0000\u0000\u0000\u028b\u028c\u0003T("+ - "\u0000\u028c\u028d\u0001\u0000\u0000\u0000\u028d\u028e\u0006T\u001c\u0000"+ - "\u028e\u00ad\u0001\u0000\u0000\u0000\u028f\u0290\u0003p6\u0000\u0290\u0291"+ - "\u0001\u0000\u0000\u0000\u0291\u0292\u0006U\u001d\u0000\u0292\u00af\u0001"+ - "\u0000\u0000\u0000\u0293\u0294\u0003r7\u0000\u0294\u0295\u0001\u0000\u0000"+ - "\u0000\u0295\u0296\u0006V\u001e\u0000\u0296\u00b1\u0001\u0000\u0000\u0000"+ - "\u0297\u0298\u0003t8\u0000\u0298\u0299\u0001\u0000\u0000\u0000\u0299\u029a"+ - "\u0006W\u001f\u0000\u029a\u00b3\u0001\u0000\u0000\u0000\u029b\u029c\u0003"+ - "v9\u0000\u029c\u029d\u0001\u0000\u0000\u0000\u029d\u029e\u0006X \u0000"+ - "\u029e\u00b5\u0001\u0000\u0000\u0000)\u0000\u0001\u0002\u0003\u00b9\u00be"+ - "\u00c3\u00c9\u00ea\u00ff\u0101\u010a\u0112\u0114\u012c\u0132\u0136\u0143"+ - "\u0145\u015a\u0165\u016d\u016f\u0179\u017b\u0180\u0189\u0193\u019c\u01a3"+ - "\u01a5\u01a7\u01b2\u01b4\u01c0\u01c2\u01ce\u01d0\u01ef\u01f8\u0200!\u0006"+ - "\u0000\u0000\u0000\u0002\u0000\u0005\u0001\u0000\u0002\u0002\u0000\u0007"+ - "\u0004\u0000\u0002\u0003\u0000\u0004\u0000\u0000\u0007\u000b\u0000\u0007"+ - "\f\u0000\u0007\t\u0000\u0007\n\u0000\u0007\r\u0000\u0007\b\u0000\u0007"+ - "\u0002\u0000\u0007\u0003\u0000\u0007\u000f\u0000\u0005\u0002\u0000\u0005"+ - "\u0003\u0000\u0007\u0006\u0000\u0007\u0010\u0000\u0007\u0011\u0000\u0007"+ - "\u0012\u0000\u0007\u0013\u0000\u0007\u0014\u0000\u0007\u0015\u0000\u0007"+ - "\u0016\u0000\u0007\u0017\u0000\u0007\u0018\u0000\u0007\u0019\u0000\u0007"+ - "\u001a\u0000\u0007\u001b\u0000\u0007\u001c\u0000\u0007\u001d\u0000"; + "\u0002\n\u0002\f\u0002\u00cb\t\u0002\u0001\u0003\u0001\u0003\u0001\u0004"+ + "\u0001\u0004\u0001\u0004\u0001\u0005\u0001\u0005\u0001\u0006\u0001\u0006"+ + "\u0001\u0006\u0001\u0007\u0001\u0007\u0001\u0007\u0001\u0007\u0001\b\u0001"+ + "\b\u0001\t\u0001\t\u0001\t\u0001\t\u0001\n\u0001\n\u0001\u000b\u0001\u000b"+ + "\u0001\f\u0001\f\u0001\f\u0001\f\u0003\f\u00e9\b\f\u0001\r\u0001\r\u0001"+ + "\r\u0001\r\u0001\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e"+ + "\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e\u0001\u000e"+ + "\u0001\u000f\u0001\u000f\u0001\u000f\u0005\u000f\u00fe\b\u000f\n\u000f"+ + "\f\u000f\u0101\t\u000f\u0001\u000f\u0001\u000f\u0001\u0010\u0001\u0010"+ + "\u0005\u0010\u0107\b\u0010\n\u0010\f\u0010\u010a\t\u0010\u0001\u0010\u0001"+ + "\u0010\u0001\u0011\u0001\u0011\u0001\u0011\u0004\u0011\u0111\b\u0011\u000b"+ + "\u0011\f\u0011\u0112\u0001\u0012\u0001\u0012\u0001\u0012\u0001\u0012\u0001"+ + "\u0013\u0001\u0013\u0001\u0013\u0001\u0013\u0001\u0014\u0001\u0014\u0001"+ + "\u0014\u0001\u0014\u0001\u0014\u0001\u0015\u0001\u0015\u0001\u0015\u0001"+ + "\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0001\u0015\u0003"+ + "\u0015\u012b\b\u0015\u0001\u0015\u0001\u0015\u0001\u0016\u0001\u0016\u0003"+ + "\u0016\u0131\b\u0016\u0001\u0016\u0001\u0016\u0003\u0016\u0135\b\u0016"+ + "\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0017\u0001\u0018"+ + "\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0005\u0018"+ + "\u0142\b\u0018\n\u0018\f\u0018\u0145\t\u0018\u0001\u0018\u0001\u0018\u0001"+ + "\u0018\u0001\u0018\u0001\u0018\u0001\u0018\u0001\u0019\u0001\u0019\u0001"+ + "\u0019\u0001\u0019\u0001\u0019\u0001\u001a\u0001\u001a\u0001\u001a\u0001"+ + "\u001a\u0001\u001a\u0005\u001a\u0157\b\u001a\n\u001a\f\u001a\u015a\t\u001a"+ + "\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a\u0001\u001a"+ + "\u0001\u001b\u0001\u001b\u0003\u001b\u0164\b\u001b\u0001\u001b\u0001\u001b"+ + "\u0001\u001c\u0001\u001c\u0001\u001c\u0001\u001c\u0005\u001c\u016c\b\u001c"+ + "\n\u001c\f\u001c\u016f\t\u001c\u0001\u001d\u0001\u001d\u0001\u001d\u0001"+ + "\u001e\u0001\u001e\u0001\u001e\u0001\u001e\u0003\u001e\u0178\b\u001e\u0003"+ + "\u001e\u017a\b\u001e\u0001\u001e\u0001\u001e\u0001\u001f\u0003\u001f\u017f"+ + "\b\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001\u001f\u0001"+ + "\u001f\u0001 \u0003 \u0188\b \u0001 \u0001 \u0001 \u0001 \u0001 \u0001"+ + " \u0001!\u0001!\u0003!\u0192\b!\u0001\"\u0001\"\u0001#\u0001#\u0001$\u0001"+ + "$\u0001%\u0003%\u019b\b%\u0001%\u0001%\u0001%\u0001%\u0001%\u0004%\u01a2"+ + "\b%\u000b%\f%\u01a3\u0003%\u01a6\b%\u0001%\u0001%\u0001&\u0001&\u0001"+ + "&\u0001&\u0001&\u0001&\u0001&\u0005&\u01b1\b&\n&\f&\u01b4\t&\u0001&\u0001"+ + "&\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'\u0001\'\u0005\'\u01bf"+ + "\b\'\n\'\f\'\u01c2\t\'\u0001\'\u0001\'\u0001(\u0001(\u0001(\u0001(\u0001"+ + "(\u0001(\u0001(\u0005(\u01cd\b(\n(\f(\u01d0\t(\u0001(\u0001(\u0001)\u0001"+ + ")\u0001)\u0001)\u0001)\u0001*\u0001*\u0001*\u0001+\u0001+\u0001+\u0001"+ + ",\u0001,\u0001-\u0001-\u0001-\u0001.\u0001.\u0001.\u0001/\u0001/\u0001"+ + "/\u00010\u00010\u00040\u01ec\b0\u000b0\f0\u01ed\u00011\u00011\u00011\u0001"+ + "1\u00011\u00012\u00012\u00032\u01f7\b2\u00013\u00013\u00013\u00013\u0001"+ + "3\u00013\u00033\u01ff\b3\u00014\u00014\u00014\u00014\u00014\u00014\u0001"+ + "5\u00015\u00015\u00016\u00016\u00016\u00016\u00016\u00016\u00017\u0001"+ + "7\u00017\u00017\u00017\u00017\u00018\u00018\u00018\u00018\u00019\u0001"+ + "9\u00019\u00019\u0001:\u0001:\u0001:\u0001:\u0001;\u0001;\u0001;\u0001"+ + ";\u0001<\u0001<\u0001<\u0001<\u0001=\u0001=\u0001=\u0001=\u0001>\u0001"+ + ">\u0001>\u0001>\u0001?\u0001?\u0001?\u0001?\u0001@\u0001@\u0001@\u0001"+ + "@\u0001A\u0001A\u0001A\u0001A\u0001A\u0001B\u0001B\u0001B\u0001B\u0001"+ + "C\u0001C\u0001C\u0001C\u0001D\u0001D\u0001D\u0001D\u0001E\u0001E\u0001"+ + "E\u0001E\u0001F\u0001F\u0001F\u0001F\u0001F\u0001G\u0001G\u0001G\u0001"+ + "G\u0001G\u0001H\u0001H\u0001H\u0001H\u0001H\u0001I\u0001I\u0001I\u0001"+ + "I\u0001J\u0001J\u0001J\u0001J\u0001K\u0001K\u0001K\u0001K\u0001L\u0001"+ + "L\u0001L\u0001L\u0001M\u0001M\u0001M\u0001M\u0001N\u0001N\u0001N\u0001"+ + "N\u0001O\u0001O\u0001O\u0001O\u0001P\u0001P\u0001P\u0001P\u0001Q\u0001"+ + "Q\u0001Q\u0001Q\u0001R\u0001R\u0001R\u0001R\u0001S\u0001S\u0001S\u0001"+ + "S\u0001T\u0001T\u0001T\u0001T\u0001U\u0001U\u0001U\u0001U\u0001V\u0001"+ + "V\u0001V\u0001V\u0001W\u0001W\u0001W\u0001W\u0001X\u0001X\u0001X\u0001"+ + "X\u0004\u00ff\u0108\u0143\u0158\u0000Y\u0004\u0001\u0006\u0002\b\u0003"+ + "\n\u0004\f\u0005\u000e\u0006\u0010\u0007\u0012\b\u0014\t\u0016\n\u0018"+ + "\u0000\u001a\u0000\u001c\u0000\u001e\u0000 \u0000\"\u000b$\f&\r(\u000e"+ + "*\u000f,\u0000.\u00100\u00002\u00004\u00116\u00008\u0012:\u0000<\u0000"+ + ">\u0000@\u0013B\u0014D\u0015F\u0000H\u0000J\u0000L\u0000N\u0016P\u0017"+ + "R\u0018T\u0019V\u0000X\u0000Z\u0000\\\u0000^\u0000`\u0000b\u0000d\u0000"+ + "f\u0000h\u0000j\u0000l\u0000n\u0000p\u001ar\u001bt\u001cv\u001dx\u001e"+ + "z\u0000|\u0000~\u001f\u0080\u0000\u0082\u0000\u0084\u0000\u0086\u0000"+ + "\u0088 \u008a\u0000\u008c\u0000\u008e\u0000\u0090\u0000\u0092\u0000\u0094"+ + "\u0000\u0096\u0000\u0098\u0000\u009a\u0000\u009c\u0000\u009e\u0000\u00a0"+ + "\u0000\u00a2\u0000\u00a4\u0000\u00a6\u0000\u00a8\u0000\u00aa\u0000\u00ac"+ + "\u0000\u00ae\u0000\u00b0\u0000\u00b2\u0000\u00b4\u0000\u0004\u0000\u0001"+ + "\u0002\u0003\u0010\u0002\u0000\t\t \u0002\u0000\n\n\r\r\u0001\u00000"+ + "9\u0002\u0000AZaz\b\u0000\"\"//\\\\bbffnnrrtt\u0003\u0000\n\n\"\"\\\\"+ + "\u0002\u0000\n\n\'\'\u0002\u0000--__\u0002\u0000\"\"\\\\\u0002\u0000E"+ + "Eee\u0002\u0000++--\u0002\u0000AFaf\u0001\u000019\u0001\u000007\u0001"+ + "\u000001\u0003\u0000 TTtt\u02a6\u0000\u0004\u0001\u0000\u0000\u0000\u0000"+ + "\u0006\u0001\u0000\u0000\u0000\u0000\b\u0001\u0000\u0000\u0000\u0000\n"+ + "\u0001\u0000\u0000\u0000\u0000\f\u0001\u0000\u0000\u0000\u0000\u000e\u0001"+ + "\u0000\u0000\u0000\u0000\u0010\u0001\u0000\u0000\u0000\u0000\u0012\u0001"+ + "\u0000\u0000\u0000\u0000\u0014\u0001\u0000\u0000\u0000\u0000\u0016\u0001"+ + "\u0000\u0000\u0000\u0000\"\u0001\u0000\u0000\u0000\u0000$\u0001\u0000"+ + "\u0000\u0000\u0000&\u0001\u0000\u0000\u0000\u0001(\u0001\u0000\u0000\u0000"+ + "\u0001*\u0001\u0000\u0000\u0000\u0001,\u0001\u0000\u0000\u0000\u0001."+ + "\u0001\u0000\u0000\u0000\u00012\u0001\u0000\u0000\u0000\u00014\u0001\u0000"+ + "\u0000\u0000\u00016\u0001\u0000\u0000\u0000\u00018\u0001\u0000\u0000\u0000"+ + "\u0001@\u0001\u0000\u0000\u0000\u0001B\u0001\u0000\u0000\u0000\u0001D"+ + "\u0001\u0000\u0000\u0000\u0001N\u0001\u0000\u0000\u0000\u0001P\u0001\u0000"+ + "\u0000\u0000\u0001R\u0001\u0000\u0000\u0000\u0001T\u0001\u0000\u0000\u0000"+ + "\u0001p\u0001\u0000\u0000\u0000\u0001r\u0001\u0000\u0000\u0000\u0001t"+ + "\u0001\u0000\u0000\u0000\u0001v\u0001\u0000\u0000\u0000\u0002x\u0001\u0000"+ + "\u0000\u0000\u0002z\u0001\u0000\u0000\u0000\u0002|\u0001\u0000\u0000\u0000"+ + "\u0002~\u0001\u0000\u0000\u0000\u0002\u0080\u0001\u0000\u0000\u0000\u0002"+ + "\u0082\u0001\u0000\u0000\u0000\u0002\u0084\u0001\u0000\u0000\u0000\u0002"+ + "\u0086\u0001\u0000\u0000\u0000\u0003\u0088\u0001\u0000\u0000\u0000\u0003"+ + "\u008a\u0001\u0000\u0000\u0000\u0003\u008c\u0001\u0000\u0000\u0000\u0003"+ + "\u008e\u0001\u0000\u0000\u0000\u0003\u0090\u0001\u0000\u0000\u0000\u0003"+ + "\u0092\u0001\u0000\u0000\u0000\u0003\u0094\u0001\u0000\u0000\u0000\u0003"+ + "\u0096\u0001\u0000\u0000\u0000\u0003\u0098\u0001\u0000\u0000\u0000\u0003"+ + "\u009a\u0001\u0000\u0000\u0000\u0003\u009c\u0001\u0000\u0000\u0000\u0003"+ + "\u009e\u0001\u0000\u0000\u0000\u0003\u00a0\u0001\u0000\u0000\u0000\u0003"+ + "\u00a2\u0001\u0000\u0000\u0000\u0003\u00a4\u0001\u0000\u0000\u0000\u0003"+ + "\u00a6\u0001\u0000\u0000\u0000\u0003\u00a8\u0001\u0000\u0000\u0000\u0003"+ + "\u00aa\u0001\u0000\u0000\u0000\u0003\u00ac\u0001\u0000\u0000\u0000\u0003"+ + "\u00ae\u0001\u0000\u0000\u0000\u0003\u00b0\u0001\u0000\u0000\u0000\u0003"+ + "\u00b2\u0001\u0000\u0000\u0000\u0003\u00b4\u0001\u0000\u0000\u0000\u0004"+ + "\u00b7\u0001\u0000\u0000\u0000\u0006\u00c1\u0001\u0000\u0000\u0000\b\u00c5"+ + "\u0001\u0000\u0000\u0000\n\u00cc\u0001\u0000\u0000\u0000\f\u00ce\u0001"+ + "\u0000\u0000\u0000\u000e\u00d1\u0001\u0000\u0000\u0000\u0010\u00d3\u0001"+ + "\u0000\u0000\u0000\u0012\u00d6\u0001\u0000\u0000\u0000\u0014\u00da\u0001"+ + "\u0000\u0000\u0000\u0016\u00dc\u0001\u0000\u0000\u0000\u0018\u00e0\u0001"+ + "\u0000\u0000\u0000\u001a\u00e2\u0001\u0000\u0000\u0000\u001c\u00e4\u0001"+ + "\u0000\u0000\u0000\u001e\u00ea\u0001\u0000\u0000\u0000 \u00f0\u0001\u0000"+ + "\u0000\u0000\"\u00fa\u0001\u0000\u0000\u0000$\u0104\u0001\u0000\u0000"+ + "\u0000&\u0110\u0001\u0000\u0000\u0000(\u0114\u0001\u0000\u0000\u0000*"+ + "\u0118\u0001\u0000\u0000\u0000,\u011c\u0001\u0000\u0000\u0000.\u012a\u0001"+ + "\u0000\u0000\u00000\u0134\u0001\u0000\u0000\u00002\u0136\u0001\u0000\u0000"+ + "\u00004\u013b\u0001\u0000\u0000\u00006\u014c\u0001\u0000\u0000\u00008"+ + "\u0151\u0001\u0000\u0000\u0000:\u0161\u0001\u0000\u0000\u0000<\u0167\u0001"+ + "\u0000\u0000\u0000>\u0170\u0001\u0000\u0000\u0000@\u0173\u0001\u0000\u0000"+ + "\u0000B\u017e\u0001\u0000\u0000\u0000D\u0187\u0001\u0000\u0000\u0000F"+ + "\u0191\u0001\u0000\u0000\u0000H\u0193\u0001\u0000\u0000\u0000J\u0195\u0001"+ + "\u0000\u0000\u0000L\u0197\u0001\u0000\u0000\u0000N\u019a\u0001\u0000\u0000"+ + "\u0000P\u01a9\u0001\u0000\u0000\u0000R\u01b7\u0001\u0000\u0000\u0000T"+ + "\u01c5\u0001\u0000\u0000\u0000V\u01d3\u0001\u0000\u0000\u0000X\u01d8\u0001"+ + "\u0000\u0000\u0000Z\u01db\u0001\u0000\u0000\u0000\\\u01de\u0001\u0000"+ + "\u0000\u0000^\u01e0\u0001\u0000\u0000\u0000`\u01e3\u0001\u0000\u0000\u0000"+ + "b\u01e6\u0001\u0000\u0000\u0000d\u01e9\u0001\u0000\u0000\u0000f\u01ef"+ + "\u0001\u0000\u0000\u0000h\u01f6\u0001\u0000\u0000\u0000j\u01f8\u0001\u0000"+ + "\u0000\u0000l\u0200\u0001\u0000\u0000\u0000n\u0206\u0001\u0000\u0000\u0000"+ + "p\u0209\u0001\u0000\u0000\u0000r\u020f\u0001\u0000\u0000\u0000t\u0215"+ + "\u0001\u0000\u0000\u0000v\u0219\u0001\u0000\u0000\u0000x\u021d\u0001\u0000"+ + "\u0000\u0000z\u0221\u0001\u0000\u0000\u0000|\u0225\u0001\u0000\u0000\u0000"+ + "~\u0229\u0001\u0000\u0000\u0000\u0080\u022d\u0001\u0000\u0000\u0000\u0082"+ + "\u0231\u0001\u0000\u0000\u0000\u0084\u0235\u0001\u0000\u0000\u0000\u0086"+ + "\u0239\u0001\u0000\u0000\u0000\u0088\u023e\u0001\u0000\u0000\u0000\u008a"+ + "\u0242\u0001\u0000\u0000\u0000\u008c\u0246\u0001\u0000\u0000\u0000\u008e"+ + "\u024a\u0001\u0000\u0000\u0000\u0090\u024e\u0001\u0000\u0000\u0000\u0092"+ + "\u0253\u0001\u0000\u0000\u0000\u0094\u0258\u0001\u0000\u0000\u0000\u0096"+ + "\u025d\u0001\u0000\u0000\u0000\u0098\u0261\u0001\u0000\u0000\u0000\u009a"+ + "\u0265\u0001\u0000\u0000\u0000\u009c\u0269\u0001\u0000\u0000\u0000\u009e"+ + "\u026d\u0001\u0000\u0000\u0000\u00a0\u0271\u0001\u0000\u0000\u0000\u00a2"+ + "\u0275\u0001\u0000\u0000\u0000\u00a4\u0279\u0001\u0000\u0000\u0000\u00a6"+ + "\u027d\u0001\u0000\u0000\u0000\u00a8\u0281\u0001\u0000\u0000\u0000\u00aa"+ + "\u0285\u0001\u0000\u0000\u0000\u00ac\u0289\u0001\u0000\u0000\u0000\u00ae"+ + "\u028d\u0001\u0000\u0000\u0000\u00b0\u0291\u0001\u0000\u0000\u0000\u00b2"+ + "\u0295\u0001\u0000\u0000\u0000\u00b4\u0299\u0001\u0000\u0000\u0000\u00b6"+ + "\u00b8\u0007\u0000\u0000\u0000\u00b7\u00b6\u0001\u0000\u0000\u0000\u00b8"+ + "\u00b9\u0001\u0000\u0000\u0000\u00b9\u00b7\u0001\u0000\u0000\u0000\u00b9"+ + "\u00ba\u0001\u0000\u0000\u0000\u00ba\u00bb\u0001\u0000\u0000\u0000\u00bb"+ + "\u00bc\u0006\u0000\u0000\u0000\u00bc\u0005\u0001\u0000\u0000\u0000\u00bd"+ + "\u00bf\u0005\r\u0000\u0000\u00be\u00bd\u0001\u0000\u0000\u0000\u00be\u00bf"+ + "\u0001\u0000\u0000\u0000\u00bf\u00c0\u0001\u0000\u0000\u0000\u00c0\u00c2"+ + "\u0005\n\u0000\u0000\u00c1\u00be\u0001\u0000\u0000\u0000\u00c2\u00c3\u0001"+ + "\u0000\u0000\u0000\u00c3\u00c1\u0001\u0000\u0000\u0000\u00c3\u00c4\u0001"+ + "\u0000\u0000\u0000\u00c4\u0007\u0001\u0000\u0000\u0000\u00c5\u00c9\u0005"+ + "#\u0000\u0000\u00c6\u00c8\b\u0001\u0000\u0000\u00c7\u00c6\u0001\u0000"+ + "\u0000\u0000\u00c8\u00cb\u0001\u0000\u0000\u0000\u00c9\u00c7\u0001\u0000"+ + "\u0000\u0000\u00c9\u00ca\u0001\u0000\u0000\u0000\u00ca\t\u0001\u0000\u0000"+ + "\u0000\u00cb\u00c9\u0001\u0000\u0000\u0000\u00cc\u00cd\u0005[\u0000\u0000"+ + "\u00cd\u000b\u0001\u0000\u0000\u0000\u00ce\u00cf\u0005[\u0000\u0000\u00cf"+ + "\u00d0\u0005[\u0000\u0000\u00d0\r\u0001\u0000\u0000\u0000\u00d1\u00d2"+ + "\u0005]\u0000\u0000\u00d2\u000f\u0001\u0000\u0000\u0000\u00d3\u00d4\u0005"+ + "]\u0000\u0000\u00d4\u00d5\u0005]\u0000\u0000\u00d5\u0011\u0001\u0000\u0000"+ + "\u0000\u00d6\u00d7\u0005=\u0000\u0000\u00d7\u00d8\u0001\u0000\u0000\u0000"+ + "\u00d8\u00d9\u0006\u0007\u0001\u0000\u00d9\u0013\u0001\u0000\u0000\u0000"+ + "\u00da\u00db\u0005.\u0000\u0000\u00db\u0015\u0001\u0000\u0000\u0000\u00dc"+ + "\u00dd\u0005,\u0000\u0000\u00dd\u00de\u0001\u0000\u0000\u0000\u00de\u00df"+ + "\u0006\t\u0000\u0000\u00df\u0017\u0001\u0000\u0000\u0000\u00e0\u00e1\u0007"+ + "\u0002\u0000\u0000\u00e1\u0019\u0001\u0000\u0000\u0000\u00e2\u00e3\u0007"+ + "\u0003\u0000\u0000\u00e3\u001b\u0001\u0000\u0000\u0000\u00e4\u00e8\u0005"+ + "\\\u0000\u0000\u00e5\u00e9\u0007\u0004\u0000\u0000\u00e6\u00e9\u0003\u001e"+ + "\r\u0000\u00e7\u00e9\u0003 \u000e\u0000\u00e8\u00e5\u0001\u0000\u0000"+ + "\u0000\u00e8\u00e6\u0001\u0000\u0000\u0000\u00e8\u00e7\u0001\u0000\u0000"+ + "\u0000\u00e9\u001d\u0001\u0000\u0000\u0000\u00ea\u00eb\u0005u\u0000\u0000"+ + "\u00eb\u00ec\u0003F!\u0000\u00ec\u00ed\u0003F!\u0000\u00ed\u00ee\u0003"+ + "F!\u0000\u00ee\u00ef\u0003F!\u0000\u00ef\u001f\u0001\u0000\u0000\u0000"+ + "\u00f0\u00f1\u0005U\u0000\u0000\u00f1\u00f2\u0003F!\u0000\u00f2\u00f3"+ + "\u0003F!\u0000\u00f3\u00f4\u0003F!\u0000\u00f4\u00f5\u0003F!\u0000\u00f5"+ + "\u00f6\u0003F!\u0000\u00f6\u00f7\u0003F!\u0000\u00f7\u00f8\u0003F!\u0000"+ + "\u00f8\u00f9\u0003F!\u0000\u00f9!\u0001\u0000\u0000\u0000\u00fa\u00ff"+ + "\u0005\"\u0000\u0000\u00fb\u00fe\u0003\u001c\f\u0000\u00fc\u00fe\b\u0005"+ + "\u0000\u0000\u00fd\u00fb\u0001\u0000\u0000\u0000\u00fd\u00fc\u0001\u0000"+ + "\u0000\u0000\u00fe\u0101\u0001\u0000\u0000\u0000\u00ff\u0100\u0001\u0000"+ + "\u0000\u0000\u00ff\u00fd\u0001\u0000\u0000\u0000\u0100\u0102\u0001\u0000"+ + "\u0000\u0000\u0101\u00ff\u0001\u0000\u0000\u0000\u0102\u0103\u0005\"\u0000"+ + "\u0000\u0103#\u0001\u0000\u0000\u0000\u0104\u0108\u0005\'\u0000\u0000"+ + "\u0105\u0107\b\u0006\u0000\u0000\u0106\u0105\u0001\u0000\u0000\u0000\u0107"+ + "\u010a\u0001\u0000\u0000\u0000\u0108\u0109\u0001\u0000\u0000\u0000\u0108"+ + "\u0106\u0001\u0000\u0000\u0000\u0109\u010b\u0001\u0000\u0000\u0000\u010a"+ + "\u0108\u0001\u0000\u0000\u0000\u010b\u010c\u0005\'\u0000\u0000\u010c%"+ + "\u0001\u0000\u0000\u0000\u010d\u0111\u0003\u001a\u000b\u0000\u010e\u0111"+ + "\u0003\u0018\n\u0000\u010f\u0111\u0007\u0007\u0000\u0000\u0110\u010d\u0001"+ + "\u0000\u0000\u0000\u0110\u010e\u0001\u0000\u0000\u0000\u0110\u010f\u0001"+ + "\u0000\u0000\u0000\u0111\u0112\u0001\u0000\u0000\u0000\u0112\u0110\u0001"+ + "\u0000\u0000\u0000\u0112\u0113\u0001\u0000\u0000\u0000\u0113\'\u0001\u0000"+ + "\u0000\u0000\u0114\u0115\u0003\u0004\u0000\u0000\u0115\u0116\u0001\u0000"+ + "\u0000\u0000\u0116\u0117\u0006\u0012\u0000\u0000\u0117)\u0001\u0000\u0000"+ + "\u0000\u0118\u0119\u0005{\u0000\u0000\u0119\u011a\u0001\u0000\u0000\u0000"+ + "\u011a\u011b\u0006\u0013\u0002\u0000\u011b+\u0001\u0000\u0000\u0000\u011c"+ + "\u011d\u0003\n\u0003\u0000\u011d\u011e\u0001\u0000\u0000\u0000\u011e\u011f"+ + "\u0006\u0014\u0003\u0000\u011f\u0120\u0006\u0014\u0004\u0000\u0120-\u0001"+ + "\u0000\u0000\u0000\u0121\u0122\u0005t\u0000\u0000\u0122\u0123\u0005r\u0000"+ + "\u0000\u0123\u0124\u0005u\u0000\u0000\u0124\u012b\u0005e\u0000\u0000\u0125"+ + "\u0126\u0005f\u0000\u0000\u0126\u0127\u0005a\u0000\u0000\u0127\u0128\u0005"+ + "l\u0000\u0000\u0128\u0129\u0005s\u0000\u0000\u0129\u012b\u0005e\u0000"+ + "\u0000\u012a\u0121\u0001\u0000\u0000\u0000\u012a\u0125\u0001\u0000\u0000"+ + "\u0000\u012b\u012c\u0001\u0000\u0000\u0000\u012c\u012d\u0006\u0015\u0005"+ + "\u0000\u012d/\u0001\u0000\u0000\u0000\u012e\u0130\u0005\\\u0000\u0000"+ + "\u012f\u0131\u0005\r\u0000\u0000\u0130\u012f\u0001\u0000\u0000\u0000\u0130"+ + "\u0131\u0001\u0000\u0000\u0000\u0131\u0132\u0001\u0000\u0000\u0000\u0132"+ + "\u0135\u0005\n\u0000\u0000\u0133\u0135\u0003\u001c\f\u0000\u0134\u012e"+ + "\u0001\u0000\u0000\u0000\u0134\u0133\u0001\u0000\u0000\u0000\u01351\u0001"+ + "\u0000\u0000\u0000\u0136\u0137\u0003\"\u000f\u0000\u0137\u0138\u0001\u0000"+ + "\u0000\u0000\u0138\u0139\u0006\u0017\u0006\u0000\u0139\u013a\u0006\u0017"+ + "\u0005\u0000\u013a3\u0001\u0000\u0000\u0000\u013b\u013c\u0005\"\u0000"+ + "\u0000\u013c\u013d\u0005\"\u0000\u0000\u013d\u013e\u0005\"\u0000\u0000"+ + "\u013e\u0143\u0001\u0000\u0000\u0000\u013f\u0142\u00030\u0016\u0000\u0140"+ + "\u0142\b\b\u0000\u0000\u0141\u013f\u0001\u0000\u0000\u0000\u0141\u0140"+ + "\u0001\u0000\u0000\u0000\u0142\u0145\u0001\u0000\u0000\u0000\u0143\u0144"+ + "\u0001\u0000\u0000\u0000\u0143\u0141\u0001\u0000\u0000\u0000\u0144\u0146"+ + "\u0001\u0000\u0000\u0000\u0145\u0143\u0001\u0000\u0000\u0000\u0146\u0147"+ + "\u0005\"\u0000\u0000\u0147\u0148\u0005\"\u0000\u0000\u0148\u0149\u0005"+ + "\"\u0000\u0000\u0149\u014a\u0001\u0000\u0000\u0000\u014a\u014b\u0006\u0018"+ + "\u0005\u0000\u014b5\u0001\u0000\u0000\u0000\u014c\u014d\u0003$\u0010\u0000"+ + "\u014d\u014e\u0001\u0000\u0000\u0000\u014e\u014f\u0006\u0019\u0007\u0000"+ + "\u014f\u0150\u0006\u0019\u0005\u0000\u01507\u0001\u0000\u0000\u0000\u0151"+ + "\u0152\u0005\'\u0000\u0000\u0152\u0153\u0005\'\u0000\u0000\u0153\u0154"+ + "\u0005\'\u0000\u0000\u0154\u0158\u0001\u0000\u0000\u0000\u0155\u0157\t"+ + "\u0000\u0000\u0000\u0156\u0155\u0001\u0000\u0000\u0000\u0157\u015a\u0001"+ + "\u0000\u0000\u0000\u0158\u0159\u0001\u0000\u0000\u0000\u0158\u0156\u0001"+ + "\u0000\u0000\u0000\u0159\u015b\u0001\u0000\u0000\u0000\u015a\u0158\u0001"+ + "\u0000\u0000\u0000\u015b\u015c\u0005\'\u0000\u0000\u015c\u015d\u0005\'"+ + "\u0000\u0000\u015d\u015e\u0005\'\u0000\u0000\u015e\u015f\u0001\u0000\u0000"+ + "\u0000\u015f\u0160\u0006\u001a\u0005\u0000\u01609\u0001\u0000\u0000\u0000"+ + "\u0161\u0163\u0007\t\u0000\u0000\u0162\u0164\u0007\n\u0000\u0000\u0163"+ + "\u0162\u0001\u0000\u0000\u0000\u0163\u0164\u0001\u0000\u0000\u0000\u0164"+ + "\u0165\u0001\u0000\u0000\u0000\u0165\u0166\u0003<\u001c\u0000\u0166;\u0001"+ + "\u0000\u0000\u0000\u0167\u016d\u0003\u0018\n\u0000\u0168\u016c\u0003\u0018"+ + "\n\u0000\u0169\u016a\u0005_\u0000\u0000\u016a\u016c\u0003\u0018\n\u0000"+ + "\u016b\u0168\u0001\u0000\u0000\u0000\u016b\u0169\u0001\u0000\u0000\u0000"+ + "\u016c\u016f\u0001\u0000\u0000\u0000\u016d\u016b\u0001\u0000\u0000\u0000"+ + "\u016d\u016e\u0001\u0000\u0000\u0000\u016e=\u0001\u0000\u0000\u0000\u016f"+ + "\u016d\u0001\u0000\u0000\u0000\u0170\u0171\u0005.\u0000\u0000\u0171\u0172"+ + "\u0003<\u001c\u0000\u0172?\u0001\u0000\u0000\u0000\u0173\u0179\u0003N"+ + "%\u0000\u0174\u017a\u0003:\u001b\u0000\u0175\u0177\u0003>\u001d\u0000"+ + "\u0176\u0178\u0003:\u001b\u0000\u0177\u0176\u0001\u0000\u0000\u0000\u0177"+ + "\u0178\u0001\u0000\u0000\u0000\u0178\u017a\u0001\u0000\u0000\u0000\u0179"+ + "\u0174\u0001\u0000\u0000\u0000\u0179\u0175\u0001\u0000\u0000\u0000\u017a"+ + "\u017b\u0001\u0000\u0000\u0000\u017b\u017c\u0006\u001e\u0005\u0000\u017c"+ + "A\u0001\u0000\u0000\u0000\u017d\u017f\u0007\n\u0000\u0000\u017e\u017d"+ + "\u0001\u0000\u0000\u0000\u017e\u017f\u0001\u0000\u0000\u0000\u017f\u0180"+ + "\u0001\u0000\u0000\u0000\u0180\u0181\u0005i\u0000\u0000\u0181\u0182\u0005"+ + "n\u0000\u0000\u0182\u0183\u0005f\u0000\u0000\u0183\u0184\u0001\u0000\u0000"+ + "\u0000\u0184\u0185\u0006\u001f\u0005\u0000\u0185C\u0001\u0000\u0000\u0000"+ + "\u0186\u0188\u0007\n\u0000\u0000\u0187\u0186\u0001\u0000\u0000\u0000\u0187"+ + "\u0188\u0001\u0000\u0000\u0000\u0188\u0189\u0001\u0000\u0000\u0000\u0189"+ + "\u018a\u0005n\u0000\u0000\u018a\u018b\u0005a\u0000\u0000\u018b\u018c\u0005"+ + "n\u0000\u0000\u018c\u018d\u0001\u0000\u0000\u0000\u018d\u018e\u0006 \u0005"+ + "\u0000\u018eE\u0001\u0000\u0000\u0000\u018f\u0192\u0007\u000b\u0000\u0000"+ + "\u0190\u0192\u0003\u0018\n\u0000\u0191\u018f\u0001\u0000\u0000\u0000\u0191"+ + "\u0190\u0001\u0000\u0000\u0000\u0192G\u0001\u0000\u0000\u0000\u0193\u0194"+ + "\u0007\f\u0000\u0000\u0194I\u0001\u0000\u0000\u0000\u0195\u0196\u0007"+ + "\r\u0000\u0000\u0196K\u0001\u0000\u0000\u0000\u0197\u0198\u0007\u000e"+ + "\u0000\u0000\u0198M\u0001\u0000\u0000\u0000\u0199\u019b\u0007\n\u0000"+ + "\u0000\u019a\u0199\u0001\u0000\u0000\u0000\u019a\u019b\u0001\u0000\u0000"+ + "\u0000\u019b\u01a5\u0001\u0000\u0000\u0000\u019c\u01a6\u0003\u0018\n\u0000"+ + "\u019d\u01a1\u0003H\"\u0000\u019e\u01a2\u0003\u0018\n\u0000\u019f\u01a0"+ + "\u0005_\u0000\u0000\u01a0\u01a2\u0003\u0018\n\u0000\u01a1\u019e\u0001"+ + "\u0000\u0000\u0000\u01a1\u019f\u0001\u0000\u0000\u0000\u01a2\u01a3\u0001"+ + "\u0000\u0000\u0000\u01a3\u01a1\u0001\u0000\u0000\u0000\u01a3\u01a4\u0001"+ + "\u0000\u0000\u0000\u01a4\u01a6\u0001\u0000\u0000\u0000\u01a5\u019c\u0001"+ + "\u0000\u0000\u0000\u01a5\u019d\u0001\u0000\u0000\u0000\u01a6\u01a7\u0001"+ + "\u0000\u0000\u0000\u01a7\u01a8\u0006%\u0005\u0000\u01a8O\u0001\u0000\u0000"+ + "\u0000\u01a9\u01aa\u00050\u0000\u0000\u01aa\u01ab\u0005x\u0000\u0000\u01ab"+ + "\u01ac\u0001\u0000\u0000\u0000\u01ac\u01b2\u0003F!\u0000\u01ad\u01b1\u0003"+ + "F!\u0000\u01ae\u01af\u0005_\u0000\u0000\u01af\u01b1\u0003F!\u0000\u01b0"+ + "\u01ad\u0001\u0000\u0000\u0000\u01b0\u01ae\u0001\u0000\u0000\u0000\u01b1"+ + "\u01b4\u0001\u0000\u0000\u0000\u01b2\u01b0\u0001\u0000\u0000\u0000\u01b2"+ + "\u01b3\u0001\u0000\u0000\u0000\u01b3\u01b5\u0001\u0000\u0000\u0000\u01b4"+ + "\u01b2\u0001\u0000\u0000\u0000\u01b5\u01b6\u0006&\u0005\u0000\u01b6Q\u0001"+ + "\u0000\u0000\u0000\u01b7\u01b8\u00050\u0000\u0000\u01b8\u01b9\u0005o\u0000"+ + "\u0000\u01b9\u01ba\u0001\u0000\u0000\u0000\u01ba\u01c0\u0003J#\u0000\u01bb"+ + "\u01bf\u0003J#\u0000\u01bc\u01bd\u0005_\u0000\u0000\u01bd\u01bf\u0003"+ + "J#\u0000\u01be\u01bb\u0001\u0000\u0000\u0000\u01be\u01bc\u0001\u0000\u0000"+ + "\u0000\u01bf\u01c2\u0001\u0000\u0000\u0000\u01c0\u01be\u0001\u0000\u0000"+ + "\u0000\u01c0\u01c1\u0001\u0000\u0000\u0000\u01c1\u01c3\u0001\u0000\u0000"+ + "\u0000\u01c2\u01c0\u0001\u0000\u0000\u0000\u01c3\u01c4\u0006\'\u0005\u0000"+ + "\u01c4S\u0001\u0000\u0000\u0000\u01c5\u01c6\u00050\u0000\u0000\u01c6\u01c7"+ + "\u0005b\u0000\u0000\u01c7\u01c8\u0001\u0000\u0000\u0000\u01c8\u01ce\u0003"+ + "L$\u0000\u01c9\u01cd\u0003L$\u0000\u01ca\u01cb\u0005_\u0000\u0000\u01cb"+ + "\u01cd\u0003L$\u0000\u01cc\u01c9\u0001\u0000\u0000\u0000\u01cc\u01ca\u0001"+ + "\u0000\u0000\u0000\u01cd\u01d0\u0001\u0000\u0000\u0000\u01ce\u01cc\u0001"+ + "\u0000\u0000\u0000\u01ce\u01cf\u0001\u0000\u0000\u0000\u01cf\u01d1\u0001"+ + "\u0000\u0000\u0000\u01d0\u01ce\u0001\u0000\u0000\u0000\u01d1\u01d2\u0006"+ + "(\u0005\u0000\u01d2U\u0001\u0000\u0000\u0000\u01d3\u01d4\u0003\u0018\n"+ + "\u0000\u01d4\u01d5\u0003\u0018\n\u0000\u01d5\u01d6\u0003\u0018\n\u0000"+ + "\u01d6\u01d7\u0003\u0018\n\u0000\u01d7W\u0001\u0000\u0000\u0000\u01d8"+ + "\u01d9\u0003\u0018\n\u0000\u01d9\u01da\u0003\u0018\n\u0000\u01daY\u0001"+ + "\u0000\u0000\u0000\u01db\u01dc\u0003\u0018\n\u0000\u01dc\u01dd\u0003\u0018"+ + "\n\u0000\u01dd[\u0001\u0000\u0000\u0000\u01de\u01df\u0007\u000f\u0000"+ + "\u0000\u01df]\u0001\u0000\u0000\u0000\u01e0\u01e1\u0003\u0018\n\u0000"+ + "\u01e1\u01e2\u0003\u0018\n\u0000\u01e2_\u0001\u0000\u0000\u0000\u01e3"+ + "\u01e4\u0003\u0018\n\u0000\u01e4\u01e5\u0003\u0018\n\u0000\u01e5a\u0001"+ + "\u0000\u0000\u0000\u01e6\u01e7\u0003\u0018\n\u0000\u01e7\u01e8\u0003\u0018"+ + "\n\u0000\u01e8c\u0001\u0000\u0000\u0000\u01e9\u01eb\u0005.\u0000\u0000"+ + "\u01ea\u01ec\u0003\u0018\n\u0000\u01eb\u01ea\u0001\u0000\u0000\u0000\u01ec"+ + "\u01ed\u0001\u0000\u0000\u0000\u01ed\u01eb\u0001\u0000\u0000\u0000\u01ed"+ + "\u01ee\u0001\u0000\u0000\u0000\u01eee\u0001\u0000\u0000\u0000\u01ef\u01f0"+ + "\u0007\n\u0000\u0000\u01f0\u01f1\u0003^-\u0000\u01f1\u01f2\u0005:\u0000"+ + "\u0000\u01f2\u01f3\u0003`.\u0000\u01f3g\u0001\u0000\u0000\u0000\u01f4"+ + "\u01f7\u0005Z\u0000\u0000\u01f5\u01f7\u0003f1\u0000\u01f6\u01f4\u0001"+ + "\u0000\u0000\u0000\u01f6\u01f5\u0001\u0000\u0000\u0000\u01f7i\u0001\u0000"+ + "\u0000\u0000\u01f8\u01f9\u0003^-\u0000\u01f9\u01fa\u0005:\u0000\u0000"+ + "\u01fa\u01fb\u0003`.\u0000\u01fb\u01fc\u0005:\u0000\u0000\u01fc\u01fe"+ + "\u0003b/\u0000\u01fd\u01ff\u0003d0\u0000\u01fe\u01fd\u0001\u0000\u0000"+ + "\u0000\u01fe\u01ff\u0001\u0000\u0000\u0000\u01ffk\u0001\u0000\u0000\u0000"+ + "\u0200\u0201\u0003V)\u0000\u0201\u0202\u0005-\u0000\u0000\u0202\u0203"+ + "\u0003X*\u0000\u0203\u0204\u0005-\u0000\u0000\u0204\u0205\u0003Z+\u0000"+ + "\u0205m\u0001\u0000\u0000\u0000\u0206\u0207\u0003j3\u0000\u0207\u0208"+ + "\u0003h2\u0000\u0208o\u0001\u0000\u0000\u0000\u0209\u020a\u0003l4\u0000"+ + "\u020a\u020b\u0003\\,\u0000\u020b\u020c\u0003n5\u0000\u020c\u020d\u0001"+ + "\u0000\u0000\u0000\u020d\u020e\u00066\u0005\u0000\u020eq\u0001\u0000\u0000"+ + "\u0000\u020f\u0210\u0003l4\u0000\u0210\u0211\u0003\\,\u0000\u0211\u0212"+ + "\u0003j3\u0000\u0212\u0213\u0001\u0000\u0000\u0000\u0213\u0214\u00067"+ + "\u0005\u0000\u0214s\u0001\u0000\u0000\u0000\u0215\u0216\u0003l4\u0000"+ + "\u0216\u0217\u0001\u0000\u0000\u0000\u0217\u0218\u00068\u0005\u0000\u0218"+ + "u\u0001\u0000\u0000\u0000\u0219\u021a\u0003j3\u0000\u021a\u021b\u0001"+ + "\u0000\u0000\u0000\u021b\u021c\u00069\u0005\u0000\u021cw\u0001\u0000\u0000"+ + "\u0000\u021d\u021e\u0003\u0004\u0000\u0000\u021e\u021f\u0001\u0000\u0000"+ + "\u0000\u021f\u0220\u0006:\u0000\u0000\u0220y\u0001\u0000\u0000\u0000\u0221"+ + "\u0222\u0003\u0014\b\u0000\u0222\u0223\u0001\u0000\u0000\u0000\u0223\u0224"+ + "\u0006;\b\u0000\u0224{\u0001\u0000\u0000\u0000\u0225\u0226\u0003\u0016"+ + "\t\u0000\u0226\u0227\u0001\u0000\u0000\u0000\u0227\u0228\u0006<\t\u0000"+ + "\u0228}\u0001\u0000\u0000\u0000\u0229\u022a\u0005}\u0000\u0000\u022a\u022b"+ + "\u0001\u0000\u0000\u0000\u022b\u022c\u0006=\u0005\u0000\u022c\u007f\u0001"+ + "\u0000\u0000\u0000\u022d\u022e\u0003\"\u000f\u0000\u022e\u022f\u0001\u0000"+ + "\u0000\u0000\u022f\u0230\u0006>\u0006\u0000\u0230\u0081\u0001\u0000\u0000"+ + "\u0000\u0231\u0232\u0003$\u0010\u0000\u0232\u0233\u0001\u0000\u0000\u0000"+ + "\u0233\u0234\u0006?\u0007\u0000\u0234\u0083\u0001\u0000\u0000\u0000\u0235"+ + "\u0236\u0003&\u0011\u0000\u0236\u0237\u0001\u0000\u0000\u0000\u0237\u0238"+ + "\u0006@\n\u0000\u0238\u0085\u0001\u0000\u0000\u0000\u0239\u023a\u0003"+ + "\u0012\u0007\u0000\u023a\u023b\u0001\u0000\u0000\u0000\u023b\u023c\u0006"+ + "A\u000b\u0000\u023c\u023d\u0006A\u0001\u0000\u023d\u0087\u0001\u0000\u0000"+ + "\u0000\u023e\u023f\u0003\u0004\u0000\u0000\u023f\u0240\u0001\u0000\u0000"+ + "\u0000\u0240\u0241\u0006B\u0000\u0000\u0241\u0089\u0001\u0000\u0000\u0000"+ + "\u0242\u0243\u0003\u0006\u0001\u0000\u0243\u0244\u0001\u0000\u0000\u0000"+ + "\u0244\u0245\u0006C\f\u0000\u0245\u008b\u0001\u0000\u0000\u0000\u0246"+ + "\u0247\u0003\b\u0002\u0000\u0247\u0248\u0001\u0000\u0000\u0000\u0248\u0249"+ + "\u0006D\r\u0000\u0249\u008d\u0001\u0000\u0000\u0000\u024a\u024b\u0003"+ + "\u0016\t\u0000\u024b\u024c\u0001\u0000\u0000\u0000\u024c\u024d\u0006E"+ + "\t\u0000\u024d\u008f\u0001\u0000\u0000\u0000\u024e\u024f\u0003*\u0013"+ + "\u0000\u024f\u0250\u0001\u0000\u0000\u0000\u0250\u0251\u0006F\u000e\u0000"+ + "\u0251\u0252\u0006F\u000f\u0000\u0252\u0091\u0001\u0000\u0000\u0000\u0253"+ + "\u0254\u0003\n\u0003\u0000\u0254\u0255\u0001\u0000\u0000\u0000\u0255\u0256"+ + "\u0006G\u0003\u0000\u0256\u0257\u0006G\u0010\u0000\u0257\u0093\u0001\u0000"+ + "\u0000\u0000\u0258\u0259\u0003\u000e\u0005\u0000\u0259\u025a\u0001\u0000"+ + "\u0000\u0000\u025a\u025b\u0006H\u0011\u0000\u025b\u025c\u0006H\u0005\u0000"+ + "\u025c\u0095\u0001\u0000\u0000\u0000\u025d\u025e\u0003.\u0015\u0000\u025e"+ + "\u025f\u0001\u0000\u0000\u0000\u025f\u0260\u0006I\u0012\u0000\u0260\u0097"+ + "\u0001\u0000\u0000\u0000\u0261\u0262\u0003\"\u000f\u0000\u0262\u0263\u0001"+ + "\u0000\u0000\u0000\u0263\u0264\u0006J\u0006\u0000\u0264\u0099\u0001\u0000"+ + "\u0000\u0000\u0265\u0266\u00034\u0018\u0000\u0266\u0267\u0001\u0000\u0000"+ + "\u0000\u0267\u0268\u0006K\u0013\u0000\u0268\u009b\u0001\u0000\u0000\u0000"+ + "\u0269\u026a\u0003$\u0010\u0000\u026a\u026b\u0001\u0000\u0000\u0000\u026b"+ + "\u026c\u0006L\u0007\u0000\u026c\u009d\u0001\u0000\u0000\u0000\u026d\u026e"+ + "\u00038\u001a\u0000\u026e\u026f\u0001\u0000\u0000\u0000\u026f\u0270\u0006"+ + "M\u0014\u0000\u0270\u009f\u0001\u0000\u0000\u0000\u0271\u0272\u0003@\u001e"+ + "\u0000\u0272\u0273\u0001\u0000\u0000\u0000\u0273\u0274\u0006N\u0015\u0000"+ + "\u0274\u00a1\u0001\u0000\u0000\u0000\u0275\u0276\u0003B\u001f\u0000\u0276"+ + "\u0277\u0001\u0000\u0000\u0000\u0277\u0278\u0006O\u0016\u0000\u0278\u00a3"+ + "\u0001\u0000\u0000\u0000\u0279\u027a\u0003D \u0000\u027a\u027b\u0001\u0000"+ + "\u0000\u0000\u027b\u027c\u0006P\u0017\u0000\u027c\u00a5\u0001\u0000\u0000"+ + "\u0000\u027d\u027e\u0003N%\u0000\u027e\u027f\u0001\u0000\u0000\u0000\u027f"+ + "\u0280\u0006Q\u0018\u0000\u0280\u00a7\u0001\u0000\u0000\u0000\u0281\u0282"+ + "\u0003P&\u0000\u0282\u0283\u0001\u0000\u0000\u0000\u0283\u0284\u0006R"+ + "\u0019\u0000\u0284\u00a9\u0001\u0000\u0000\u0000\u0285\u0286\u0003R\'"+ + "\u0000\u0286\u0287\u0001\u0000\u0000\u0000\u0287\u0288\u0006S\u001a\u0000"+ + "\u0288\u00ab\u0001\u0000\u0000\u0000\u0289\u028a\u0003T(\u0000\u028a\u028b"+ + "\u0001\u0000\u0000\u0000\u028b\u028c\u0006T\u001b\u0000\u028c\u00ad\u0001"+ + "\u0000\u0000\u0000\u028d\u028e\u0003p6\u0000\u028e\u028f\u0001\u0000\u0000"+ + "\u0000\u028f\u0290\u0006U\u001c\u0000\u0290\u00af\u0001\u0000\u0000\u0000"+ + "\u0291\u0292\u0003r7\u0000\u0292\u0293\u0001\u0000\u0000\u0000\u0293\u0294"+ + "\u0006V\u001d\u0000\u0294\u00b1\u0001\u0000\u0000\u0000\u0295\u0296\u0003"+ + "t8\u0000\u0296\u0297\u0001\u0000\u0000\u0000\u0297\u0298\u0006W\u001e"+ + "\u0000\u0298\u00b3\u0001\u0000\u0000\u0000\u0299\u029a\u0003v9\u0000\u029a"+ + "\u029b\u0001\u0000\u0000\u0000\u029b\u029c\u0006X\u001f\u0000\u029c\u00b5"+ + "\u0001\u0000\u0000\u0000)\u0000\u0001\u0002\u0003\u00b9\u00be\u00c3\u00c9"+ + "\u00e8\u00fd\u00ff\u0108\u0110\u0112\u012a\u0130\u0134\u0141\u0143\u0158"+ + "\u0163\u016b\u016d\u0177\u0179\u017e\u0187\u0191\u019a\u01a1\u01a3\u01a5"+ + "\u01b0\u01b2\u01be\u01c0\u01cc\u01ce\u01ed\u01f6\u01fe \u0006\u0000\u0000"+ + "\u0005\u0001\u0000\u0002\u0002\u0000\u0007\u0004\u0000\u0002\u0003\u0000"+ + "\u0004\u0000\u0000\u0007\u000b\u0000\u0007\f\u0000\u0007\t\u0000\u0007"+ + "\n\u0000\u0007\r\u0000\u0007\b\u0000\u0007\u0002\u0000\u0007\u0003\u0000"+ + "\u0007\u000f\u0000\u0005\u0002\u0000\u0005\u0003\u0000\u0007\u0006\u0000"+ + "\u0007\u0010\u0000\u0007\u0011\u0000\u0007\u0012\u0000\u0007\u0013\u0000"+ + "\u0007\u0014\u0000\u0007\u0015\u0000\u0007\u0016\u0000\u0007\u0017\u0000"+ + "\u0007\u0018\u0000\u0007\u0019\u0000\u0007\u001a\u0000\u0007\u001b\u0000"+ + "\u0007\u001c\u0000\u0007\u001d\u0000"; public static final ATN _ATN = new ATNDeserializer().deserialize(_serializedATN.toCharArray()); static { diff --git a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.interp b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.interp index 826b7607270..314ece3ce49 100644 --- a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.interp +++ b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.interp @@ -93,4 +93,4 @@ arrayTable atn: -[4, 1, 32, 235, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 1, 0, 3, 0, 44, 8, 0, 1, 0, 1, 0, 3, 0, 48, 8, 0, 5, 0, 50, 8, 0, 10, 0, 12, 0, 53, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 3, 1, 59, 8, 1, 1, 1, 1, 1, 3, 1, 63, 8, 1, 1, 1, 3, 1, 66, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 3, 4, 76, 8, 4, 1, 5, 1, 5, 3, 5, 80, 8, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 4, 8, 89, 8, 8, 11, 8, 12, 8, 90, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 100, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 1, 15, 1, 15, 3, 15, 115, 8, 15, 1, 16, 1, 16, 5, 16, 119, 8, 16, 10, 16, 12, 16, 122, 9, 16, 1, 16, 1, 16, 1, 16, 5, 16, 127, 8, 16, 10, 16, 12, 16, 130, 9, 16, 1, 16, 1, 16, 1, 16, 5, 16, 135, 8, 16, 10, 16, 12, 16, 138, 9, 16, 1, 16, 1, 16, 3, 16, 142, 8, 16, 5, 16, 144, 8, 16, 10, 16, 12, 16, 147, 9, 16, 1, 16, 5, 16, 150, 8, 16, 10, 16, 12, 16, 153, 9, 16, 1, 16, 1, 16, 3, 16, 157, 8, 16, 1, 17, 1, 17, 3, 17, 161, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 167, 8, 18, 10, 18, 12, 18, 170, 9, 18, 1, 18, 5, 18, 173, 8, 18, 10, 18, 12, 18, 176, 9, 18, 1, 19, 1, 19, 5, 19, 180, 8, 19, 10, 19, 12, 19, 183, 9, 19, 1, 19, 1, 19, 1, 19, 5, 19, 188, 8, 19, 10, 19, 12, 19, 191, 9, 19, 1, 19, 1, 19, 1, 19, 5, 19, 196, 8, 19, 10, 19, 12, 19, 199, 9, 19, 1, 19, 1, 19, 3, 19, 203, 8, 19, 5, 19, 205, 8, 19, 10, 19, 12, 19, 208, 9, 19, 1, 19, 5, 19, 211, 8, 19, 10, 19, 12, 19, 214, 9, 19, 1, 19, 1, 19, 3, 19, 218, 8, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 224, 8, 20, 10, 20, 12, 20, 227, 9, 20, 1, 20, 5, 20, 230, 8, 20, 10, 20, 12, 20, 233, 9, 20, 1, 20, 0, 0, 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0, 5, 1, 0, 11, 12, 2, 0, 11, 12, 17, 18, 1, 0, 22, 25, 1, 0, 19, 21, 1, 0, 26, 29, 249, 0, 43, 1, 0, 0, 0, 2, 65, 1, 0, 0, 0, 4, 67, 1, 0, 0, 0, 6, 69, 1, 0, 0, 0, 8, 75, 1, 0, 0, 0, 10, 79, 1, 0, 0, 0, 12, 81, 1, 0, 0, 0, 14, 83, 1, 0, 0, 0, 16, 85, 1, 0, 0, 0, 18, 99, 1, 0, 0, 0, 20, 101, 1, 0, 0, 0, 22, 103, 1, 0, 0, 0, 24, 105, 1, 0, 0, 0, 26, 107, 1, 0, 0, 0, 28, 109, 1, 0, 0, 0, 30, 114, 1, 0, 0, 0, 32, 156, 1, 0, 0, 0, 34, 160, 1, 0, 0, 0, 36, 162, 1, 0, 0, 0, 38, 217, 1, 0, 0, 0, 40, 219, 1, 0, 0, 0, 42, 44, 3, 2, 1, 0, 43, 42, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 51, 1, 0, 0, 0, 45, 47, 5, 2, 0, 0, 46, 48, 3, 2, 1, 0, 47, 46, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 50, 1, 0, 0, 0, 49, 45, 1, 0, 0, 0, 50, 53, 1, 0, 0, 0, 51, 49, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 54, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 54, 55, 5, 0, 0, 1, 55, 1, 1, 0, 0, 0, 56, 58, 3, 6, 3, 0, 57, 59, 3, 4, 2, 0, 58, 57, 1, 0, 0, 0, 58, 59, 1, 0, 0, 0, 59, 66, 1, 0, 0, 0, 60, 62, 3, 34, 17, 0, 61, 63, 3, 4, 2, 0, 62, 61, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 66, 1, 0, 0, 0, 64, 66, 3, 4, 2, 0, 65, 56, 1, 0, 0, 0, 65, 60, 1, 0, 0, 0, 65, 64, 1, 0, 0, 0, 66, 3, 1, 0, 0, 0, 67, 68, 5, 3, 0, 0, 68, 5, 1, 0, 0, 0, 69, 70, 3, 8, 4, 0, 70, 71, 5, 8, 0, 0, 71, 72, 3, 18, 9, 0, 72, 7, 1, 0, 0, 0, 73, 76, 3, 10, 5, 0, 74, 76, 3, 16, 8, 0, 75, 73, 1, 0, 0, 0, 75, 74, 1, 0, 0, 0, 76, 9, 1, 0, 0, 0, 77, 80, 3, 14, 7, 0, 78, 80, 3, 12, 6, 0, 79, 77, 1, 0, 0, 0, 79, 78, 1, 0, 0, 0, 80, 11, 1, 0, 0, 0, 81, 82, 5, 13, 0, 0, 82, 13, 1, 0, 0, 0, 83, 84, 7, 0, 0, 0, 84, 15, 1, 0, 0, 0, 85, 88, 3, 10, 5, 0, 86, 87, 5, 9, 0, 0, 87, 89, 3, 10, 5, 0, 88, 86, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 88, 1, 0, 0, 0, 90, 91, 1, 0, 0, 0, 91, 17, 1, 0, 0, 0, 92, 100, 3, 20, 10, 0, 93, 100, 3, 22, 11, 0, 94, 100, 3, 24, 12, 0, 95, 100, 3, 26, 13, 0, 96, 100, 3, 28, 14, 0, 97, 100, 3, 32, 16, 0, 98, 100, 3, 38, 19, 0, 99, 92, 1, 0, 0, 0, 99, 93, 1, 0, 0, 0, 99, 94, 1, 0, 0, 0, 99, 95, 1, 0, 0, 0, 99, 96, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 98, 1, 0, 0, 0, 100, 19, 1, 0, 0, 0, 101, 102, 7, 1, 0, 0, 102, 21, 1, 0, 0, 0, 103, 104, 7, 2, 0, 0, 104, 23, 1, 0, 0, 0, 105, 106, 7, 3, 0, 0, 106, 25, 1, 0, 0, 0, 107, 108, 5, 16, 0, 0, 108, 27, 1, 0, 0, 0, 109, 110, 7, 4, 0, 0, 110, 29, 1, 0, 0, 0, 111, 112, 5, 3, 0, 0, 112, 115, 5, 2, 0, 0, 113, 115, 5, 2, 0, 0, 114, 111, 1, 0, 0, 0, 114, 113, 1, 0, 0, 0, 115, 31, 1, 0, 0, 0, 116, 120, 5, 4, 0, 0, 117, 119, 3, 30, 15, 0, 118, 117, 1, 0, 0, 0, 119, 122, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 123, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 123, 157, 5, 6, 0, 0, 124, 128, 5, 4, 0, 0, 125, 127, 3, 30, 15, 0, 126, 125, 1, 0, 0, 0, 127, 130, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 131, 1, 0, 0, 0, 130, 128, 1, 0, 0, 0, 131, 145, 3, 18, 9, 0, 132, 136, 5, 10, 0, 0, 133, 135, 3, 30, 15, 0, 134, 133, 1, 0, 0, 0, 135, 138, 1, 0, 0, 0, 136, 134, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 1, 0, 0, 0, 138, 136, 1, 0, 0, 0, 139, 141, 3, 18, 9, 0, 140, 142, 5, 10, 0, 0, 141, 140, 1, 0, 0, 0, 141, 142, 1, 0, 0, 0, 142, 144, 1, 0, 0, 0, 143, 132, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 151, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 150, 3, 30, 15, 0, 149, 148, 1, 0, 0, 0, 150, 153, 1, 0, 0, 0, 151, 149, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 154, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 154, 155, 5, 6, 0, 0, 155, 157, 1, 0, 0, 0, 156, 116, 1, 0, 0, 0, 156, 124, 1, 0, 0, 0, 157, 33, 1, 0, 0, 0, 158, 161, 3, 36, 18, 0, 159, 161, 3, 40, 20, 0, 160, 158, 1, 0, 0, 0, 160, 159, 1, 0, 0, 0, 161, 35, 1, 0, 0, 0, 162, 163, 5, 4, 0, 0, 163, 164, 3, 8, 4, 0, 164, 174, 5, 6, 0, 0, 165, 167, 3, 30, 15, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, 3, 2, 1, 0, 172, 168, 1, 0, 0, 0, 173, 176, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 37, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 177, 181, 5, 15, 0, 0, 178, 180, 3, 30, 15, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 184, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 218, 5, 31, 0, 0, 185, 189, 5, 15, 0, 0, 186, 188, 3, 30, 15, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 192, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 206, 3, 6, 3, 0, 193, 197, 5, 10, 0, 0, 194, 196, 3, 30, 15, 0, 195, 194, 1, 0, 0, 0, 196, 199, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 197, 1, 0, 0, 0, 200, 202, 3, 6, 3, 0, 201, 203, 5, 10, 0, 0, 202, 201, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 205, 1, 0, 0, 0, 204, 193, 1, 0, 0, 0, 205, 208, 1, 0, 0, 0, 206, 204, 1, 0, 0, 0, 206, 207, 1, 0, 0, 0, 207, 212, 1, 0, 0, 0, 208, 206, 1, 0, 0, 0, 209, 211, 3, 30, 15, 0, 210, 209, 1, 0, 0, 0, 211, 214, 1, 0, 0, 0, 212, 210, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 215, 1, 0, 0, 0, 214, 212, 1, 0, 0, 0, 215, 216, 5, 31, 0, 0, 216, 218, 1, 0, 0, 0, 217, 177, 1, 0, 0, 0, 217, 185, 1, 0, 0, 0, 218, 39, 1, 0, 0, 0, 219, 220, 5, 5, 0, 0, 220, 221, 3, 8, 4, 0, 221, 231, 5, 7, 0, 0, 222, 224, 3, 30, 15, 0, 223, 222, 1, 0, 0, 0, 224, 227, 1, 0, 0, 0, 225, 223, 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 228, 1, 0, 0, 0, 227, 225, 1, 0, 0, 0, 228, 230, 3, 2, 1, 0, 229, 225, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 41, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 30, 43, 47, 51, 58, 62, 65, 75, 79, 90, 99, 114, 120, 128, 136, 141, 145, 151, 156, 160, 168, 174, 181, 189, 197, 202, 206, 212, 217, 225, 231] \ No newline at end of file +[4, 1, 32, 235, 2, 0, 7, 0, 2, 1, 7, 1, 2, 2, 7, 2, 2, 3, 7, 3, 2, 4, 7, 4, 2, 5, 7, 5, 2, 6, 7, 6, 2, 7, 7, 7, 2, 8, 7, 8, 2, 9, 7, 9, 2, 10, 7, 10, 2, 11, 7, 11, 2, 12, 7, 12, 2, 13, 7, 13, 2, 14, 7, 14, 2, 15, 7, 15, 2, 16, 7, 16, 2, 17, 7, 17, 2, 18, 7, 18, 2, 19, 7, 19, 2, 20, 7, 20, 1, 0, 3, 0, 44, 8, 0, 1, 0, 1, 0, 3, 0, 48, 8, 0, 5, 0, 50, 8, 0, 10, 0, 12, 0, 53, 9, 0, 1, 0, 1, 0, 1, 1, 1, 1, 3, 1, 59, 8, 1, 1, 1, 1, 1, 3, 1, 63, 8, 1, 1, 1, 3, 1, 66, 8, 1, 1, 2, 1, 2, 1, 3, 1, 3, 1, 3, 1, 3, 1, 4, 1, 4, 3, 4, 76, 8, 4, 1, 5, 1, 5, 3, 5, 80, 8, 5, 1, 6, 1, 6, 1, 7, 1, 7, 1, 8, 1, 8, 1, 8, 4, 8, 89, 8, 8, 11, 8, 12, 8, 90, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 1, 9, 3, 9, 100, 8, 9, 1, 10, 1, 10, 1, 11, 1, 11, 1, 12, 1, 12, 1, 13, 1, 13, 1, 14, 1, 14, 1, 15, 3, 15, 113, 8, 15, 1, 15, 1, 15, 1, 16, 1, 16, 5, 16, 119, 8, 16, 10, 16, 12, 16, 122, 9, 16, 1, 16, 1, 16, 1, 16, 5, 16, 127, 8, 16, 10, 16, 12, 16, 130, 9, 16, 1, 16, 1, 16, 1, 16, 5, 16, 135, 8, 16, 10, 16, 12, 16, 138, 9, 16, 1, 16, 1, 16, 3, 16, 142, 8, 16, 5, 16, 144, 8, 16, 10, 16, 12, 16, 147, 9, 16, 1, 16, 5, 16, 150, 8, 16, 10, 16, 12, 16, 153, 9, 16, 1, 16, 1, 16, 3, 16, 157, 8, 16, 1, 17, 1, 17, 3, 17, 161, 8, 17, 1, 18, 1, 18, 1, 18, 1, 18, 5, 18, 167, 8, 18, 10, 18, 12, 18, 170, 9, 18, 1, 18, 5, 18, 173, 8, 18, 10, 18, 12, 18, 176, 9, 18, 1, 19, 1, 19, 5, 19, 180, 8, 19, 10, 19, 12, 19, 183, 9, 19, 1, 19, 1, 19, 1, 19, 5, 19, 188, 8, 19, 10, 19, 12, 19, 191, 9, 19, 1, 19, 1, 19, 1, 19, 5, 19, 196, 8, 19, 10, 19, 12, 19, 199, 9, 19, 1, 19, 1, 19, 3, 19, 203, 8, 19, 5, 19, 205, 8, 19, 10, 19, 12, 19, 208, 9, 19, 1, 19, 5, 19, 211, 8, 19, 10, 19, 12, 19, 214, 9, 19, 1, 19, 1, 19, 3, 19, 218, 8, 19, 1, 20, 1, 20, 1, 20, 1, 20, 5, 20, 224, 8, 20, 10, 20, 12, 20, 227, 9, 20, 1, 20, 5, 20, 230, 8, 20, 10, 20, 12, 20, 233, 9, 20, 1, 20, 0, 0, 21, 0, 2, 4, 6, 8, 10, 12, 14, 16, 18, 20, 22, 24, 26, 28, 30, 32, 34, 36, 38, 40, 0, 5, 1, 0, 11, 12, 2, 0, 11, 12, 17, 18, 1, 0, 22, 25, 1, 0, 19, 21, 1, 0, 26, 29, 249, 0, 43, 1, 0, 0, 0, 2, 65, 1, 0, 0, 0, 4, 67, 1, 0, 0, 0, 6, 69, 1, 0, 0, 0, 8, 75, 1, 0, 0, 0, 10, 79, 1, 0, 0, 0, 12, 81, 1, 0, 0, 0, 14, 83, 1, 0, 0, 0, 16, 85, 1, 0, 0, 0, 18, 99, 1, 0, 0, 0, 20, 101, 1, 0, 0, 0, 22, 103, 1, 0, 0, 0, 24, 105, 1, 0, 0, 0, 26, 107, 1, 0, 0, 0, 28, 109, 1, 0, 0, 0, 30, 112, 1, 0, 0, 0, 32, 156, 1, 0, 0, 0, 34, 160, 1, 0, 0, 0, 36, 162, 1, 0, 0, 0, 38, 217, 1, 0, 0, 0, 40, 219, 1, 0, 0, 0, 42, 44, 3, 2, 1, 0, 43, 42, 1, 0, 0, 0, 43, 44, 1, 0, 0, 0, 44, 51, 1, 0, 0, 0, 45, 47, 5, 2, 0, 0, 46, 48, 3, 2, 1, 0, 47, 46, 1, 0, 0, 0, 47, 48, 1, 0, 0, 0, 48, 50, 1, 0, 0, 0, 49, 45, 1, 0, 0, 0, 50, 53, 1, 0, 0, 0, 51, 49, 1, 0, 0, 0, 51, 52, 1, 0, 0, 0, 52, 54, 1, 0, 0, 0, 53, 51, 1, 0, 0, 0, 54, 55, 5, 0, 0, 1, 55, 1, 1, 0, 0, 0, 56, 58, 3, 6, 3, 0, 57, 59, 3, 4, 2, 0, 58, 57, 1, 0, 0, 0, 58, 59, 1, 0, 0, 0, 59, 66, 1, 0, 0, 0, 60, 62, 3, 34, 17, 0, 61, 63, 3, 4, 2, 0, 62, 61, 1, 0, 0, 0, 62, 63, 1, 0, 0, 0, 63, 66, 1, 0, 0, 0, 64, 66, 3, 4, 2, 0, 65, 56, 1, 0, 0, 0, 65, 60, 1, 0, 0, 0, 65, 64, 1, 0, 0, 0, 66, 3, 1, 0, 0, 0, 67, 68, 5, 3, 0, 0, 68, 5, 1, 0, 0, 0, 69, 70, 3, 8, 4, 0, 70, 71, 5, 8, 0, 0, 71, 72, 3, 18, 9, 0, 72, 7, 1, 0, 0, 0, 73, 76, 3, 10, 5, 0, 74, 76, 3, 16, 8, 0, 75, 73, 1, 0, 0, 0, 75, 74, 1, 0, 0, 0, 76, 9, 1, 0, 0, 0, 77, 80, 3, 14, 7, 0, 78, 80, 3, 12, 6, 0, 79, 77, 1, 0, 0, 0, 79, 78, 1, 0, 0, 0, 80, 11, 1, 0, 0, 0, 81, 82, 5, 13, 0, 0, 82, 13, 1, 0, 0, 0, 83, 84, 7, 0, 0, 0, 84, 15, 1, 0, 0, 0, 85, 88, 3, 10, 5, 0, 86, 87, 5, 9, 0, 0, 87, 89, 3, 10, 5, 0, 88, 86, 1, 0, 0, 0, 89, 90, 1, 0, 0, 0, 90, 88, 1, 0, 0, 0, 90, 91, 1, 0, 0, 0, 91, 17, 1, 0, 0, 0, 92, 100, 3, 20, 10, 0, 93, 100, 3, 22, 11, 0, 94, 100, 3, 24, 12, 0, 95, 100, 3, 26, 13, 0, 96, 100, 3, 28, 14, 0, 97, 100, 3, 32, 16, 0, 98, 100, 3, 38, 19, 0, 99, 92, 1, 0, 0, 0, 99, 93, 1, 0, 0, 0, 99, 94, 1, 0, 0, 0, 99, 95, 1, 0, 0, 0, 99, 96, 1, 0, 0, 0, 99, 97, 1, 0, 0, 0, 99, 98, 1, 0, 0, 0, 100, 19, 1, 0, 0, 0, 101, 102, 7, 1, 0, 0, 102, 21, 1, 0, 0, 0, 103, 104, 7, 2, 0, 0, 104, 23, 1, 0, 0, 0, 105, 106, 7, 3, 0, 0, 106, 25, 1, 0, 0, 0, 107, 108, 5, 16, 0, 0, 108, 27, 1, 0, 0, 0, 109, 110, 7, 4, 0, 0, 110, 29, 1, 0, 0, 0, 111, 113, 5, 3, 0, 0, 112, 111, 1, 0, 0, 0, 112, 113, 1, 0, 0, 0, 113, 114, 1, 0, 0, 0, 114, 115, 5, 2, 0, 0, 115, 31, 1, 0, 0, 0, 116, 120, 5, 4, 0, 0, 117, 119, 3, 30, 15, 0, 118, 117, 1, 0, 0, 0, 119, 122, 1, 0, 0, 0, 120, 118, 1, 0, 0, 0, 120, 121, 1, 0, 0, 0, 121, 123, 1, 0, 0, 0, 122, 120, 1, 0, 0, 0, 123, 157, 5, 6, 0, 0, 124, 128, 5, 4, 0, 0, 125, 127, 3, 30, 15, 0, 126, 125, 1, 0, 0, 0, 127, 130, 1, 0, 0, 0, 128, 126, 1, 0, 0, 0, 128, 129, 1, 0, 0, 0, 129, 131, 1, 0, 0, 0, 130, 128, 1, 0, 0, 0, 131, 145, 3, 18, 9, 0, 132, 136, 5, 10, 0, 0, 133, 135, 3, 30, 15, 0, 134, 133, 1, 0, 0, 0, 135, 138, 1, 0, 0, 0, 136, 134, 1, 0, 0, 0, 136, 137, 1, 0, 0, 0, 137, 139, 1, 0, 0, 0, 138, 136, 1, 0, 0, 0, 139, 141, 3, 18, 9, 0, 140, 142, 5, 10, 0, 0, 141, 140, 1, 0, 0, 0, 141, 142, 1, 0, 0, 0, 142, 144, 1, 0, 0, 0, 143, 132, 1, 0, 0, 0, 144, 147, 1, 0, 0, 0, 145, 143, 1, 0, 0, 0, 145, 146, 1, 0, 0, 0, 146, 151, 1, 0, 0, 0, 147, 145, 1, 0, 0, 0, 148, 150, 3, 30, 15, 0, 149, 148, 1, 0, 0, 0, 150, 153, 1, 0, 0, 0, 151, 149, 1, 0, 0, 0, 151, 152, 1, 0, 0, 0, 152, 154, 1, 0, 0, 0, 153, 151, 1, 0, 0, 0, 154, 155, 5, 6, 0, 0, 155, 157, 1, 0, 0, 0, 156, 116, 1, 0, 0, 0, 156, 124, 1, 0, 0, 0, 157, 33, 1, 0, 0, 0, 158, 161, 3, 36, 18, 0, 159, 161, 3, 40, 20, 0, 160, 158, 1, 0, 0, 0, 160, 159, 1, 0, 0, 0, 161, 35, 1, 0, 0, 0, 162, 163, 5, 4, 0, 0, 163, 164, 3, 8, 4, 0, 164, 174, 5, 6, 0, 0, 165, 167, 3, 30, 15, 0, 166, 165, 1, 0, 0, 0, 167, 170, 1, 0, 0, 0, 168, 166, 1, 0, 0, 0, 168, 169, 1, 0, 0, 0, 169, 171, 1, 0, 0, 0, 170, 168, 1, 0, 0, 0, 171, 173, 3, 6, 3, 0, 172, 168, 1, 0, 0, 0, 173, 176, 1, 0, 0, 0, 174, 172, 1, 0, 0, 0, 174, 175, 1, 0, 0, 0, 175, 37, 1, 0, 0, 0, 176, 174, 1, 0, 0, 0, 177, 181, 5, 15, 0, 0, 178, 180, 3, 30, 15, 0, 179, 178, 1, 0, 0, 0, 180, 183, 1, 0, 0, 0, 181, 179, 1, 0, 0, 0, 181, 182, 1, 0, 0, 0, 182, 184, 1, 0, 0, 0, 183, 181, 1, 0, 0, 0, 184, 218, 5, 31, 0, 0, 185, 189, 5, 15, 0, 0, 186, 188, 3, 30, 15, 0, 187, 186, 1, 0, 0, 0, 188, 191, 1, 0, 0, 0, 189, 187, 1, 0, 0, 0, 189, 190, 1, 0, 0, 0, 190, 192, 1, 0, 0, 0, 191, 189, 1, 0, 0, 0, 192, 206, 3, 6, 3, 0, 193, 197, 5, 10, 0, 0, 194, 196, 3, 30, 15, 0, 195, 194, 1, 0, 0, 0, 196, 199, 1, 0, 0, 0, 197, 195, 1, 0, 0, 0, 197, 198, 1, 0, 0, 0, 198, 200, 1, 0, 0, 0, 199, 197, 1, 0, 0, 0, 200, 202, 3, 6, 3, 0, 201, 203, 5, 10, 0, 0, 202, 201, 1, 0, 0, 0, 202, 203, 1, 0, 0, 0, 203, 205, 1, 0, 0, 0, 204, 193, 1, 0, 0, 0, 205, 208, 1, 0, 0, 0, 206, 204, 1, 0, 0, 0, 206, 207, 1, 0, 0, 0, 207, 212, 1, 0, 0, 0, 208, 206, 1, 0, 0, 0, 209, 211, 3, 30, 15, 0, 210, 209, 1, 0, 0, 0, 211, 214, 1, 0, 0, 0, 212, 210, 1, 0, 0, 0, 212, 213, 1, 0, 0, 0, 213, 215, 1, 0, 0, 0, 214, 212, 1, 0, 0, 0, 215, 216, 5, 31, 0, 0, 216, 218, 1, 0, 0, 0, 217, 177, 1, 0, 0, 0, 217, 185, 1, 0, 0, 0, 218, 39, 1, 0, 0, 0, 219, 220, 5, 5, 0, 0, 220, 221, 3, 8, 4, 0, 221, 231, 5, 7, 0, 0, 222, 224, 3, 30, 15, 0, 223, 222, 1, 0, 0, 0, 224, 227, 1, 0, 0, 0, 225, 223, 1, 0, 0, 0, 225, 226, 1, 0, 0, 0, 226, 228, 1, 0, 0, 0, 227, 225, 1, 0, 0, 0, 228, 230, 3, 6, 3, 0, 229, 225, 1, 0, 0, 0, 230, 233, 1, 0, 0, 0, 231, 229, 1, 0, 0, 0, 231, 232, 1, 0, 0, 0, 232, 41, 1, 0, 0, 0, 233, 231, 1, 0, 0, 0, 30, 43, 47, 51, 58, 62, 65, 75, 79, 90, 99, 112, 120, 128, 136, 141, 145, 151, 156, 160, 168, 174, 181, 189, 197, 202, 206, 212, 217, 225, 231] \ No newline at end of file diff --git a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.java b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.java index 36f1d699925..13f6a167f1b 100644 --- a/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.java +++ b/rewrite-toml/src/main/java/org/openrewrite/toml/internal/grammar/TomlParser.java @@ -249,6 +249,7 @@ public T accept(ParseTreeVisitor visitor) { public final ExpressionContext expression() throws RecognitionException { ExpressionContext _localctx = new ExpressionContext(_ctx, getState()); enterRule(_localctx, 2, RULE_expression); + int _la; try { setState(65); _errHandler.sync(this); @@ -262,14 +263,14 @@ public final ExpressionContext expression() throws RecognitionException { keyValue(); setState(58); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,3,_ctx) ) { - case 1: + _la = _input.LA(1); + if (_la==COMMENT) { { setState(57); comment(); } - break; } + } break; case L_BRACKET: @@ -280,14 +281,14 @@ public final ExpressionContext expression() throws RecognitionException { table(); setState(62); _errHandler.sync(this); - switch ( getInterpreter().adaptivePredict(_input,4,_ctx) ) { - case 1: + _la = _input.LA(1); + if (_la==COMMENT) { { setState(61); comment(); } - break; } + } break; case COMMENT: @@ -1086,8 +1087,8 @@ public final DateTimeContext dateTime() throws RecognitionException { @SuppressWarnings("CheckReturnValue") public static class CommentOrNlContext extends ParserRuleContext { - public TerminalNode COMMENT() { return getToken(TomlParser.COMMENT, 0); } public TerminalNode NL() { return getToken(TomlParser.NL, 0); } + public TerminalNode COMMENT() { return getToken(TomlParser.COMMENT, 0); } public CommentOrNlContext(ParserRuleContext parent, int invokingState) { super(parent, invokingState); } @@ -1110,28 +1111,22 @@ public T accept(ParseTreeVisitor visitor) { public final CommentOrNlContext commentOrNl() throws RecognitionException { CommentOrNlContext _localctx = new CommentOrNlContext(_ctx, getState()); enterRule(_localctx, 30, RULE_commentOrNl); + int _la; try { - setState(114); + enterOuterAlt(_localctx, 1); + { + setState(112); _errHandler.sync(this); - switch (_input.LA(1)) { - case COMMENT: - enterOuterAlt(_localctx, 1); + _la = _input.LA(1); + if (_la==COMMENT) { { setState(111); match(COMMENT); - setState(112); - match(NL); } - break; - case NL: - enterOuterAlt(_localctx, 2); - { - setState(113); - match(NL); - } - break; - default: - throw new NoViableAltException(this); + } + + setState(114); + match(NL); } } catch (RecognitionException re) { @@ -1377,11 +1372,11 @@ public KeyContext key() { return getRuleContext(KeyContext.class,0); } public TerminalNode R_BRACKET() { return getToken(TomlParser.R_BRACKET, 0); } - public List expression() { - return getRuleContexts(ExpressionContext.class); + public List keyValue() { + return getRuleContexts(KeyValueContext.class); } - public ExpressionContext expression(int i) { - return getRuleContext(ExpressionContext.class,i); + public KeyValueContext keyValue(int i) { + return getRuleContext(KeyValueContext.class,i); } public List commentOrNl() { return getRuleContexts(CommentOrNlContext.class); @@ -1411,6 +1406,7 @@ public T accept(ParseTreeVisitor visitor) { public final StandardTableContext standardTable() throws RecognitionException { StandardTableContext _localctx = new StandardTableContext(_ctx, getState()); enterRule(_localctx, 36, RULE_standardTable); + int _la; try { int _alt; enterOuterAlt(_localctx, 1); @@ -1430,22 +1426,20 @@ public final StandardTableContext standardTable() throws RecognitionException { { setState(168); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,19,_ctx); - while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { - if ( _alt==1 ) { - { - { - setState(165); - commentOrNl(); - } - } + _la = _input.LA(1); + while (_la==NL || _la==COMMENT) { + { + { + setState(165); + commentOrNl(); + } } setState(170); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,19,_ctx); + _la = _input.LA(1); } setState(171); - expression(); + keyValue(); } } } @@ -1635,11 +1629,11 @@ public KeyContext key() { return getRuleContext(KeyContext.class,0); } public TerminalNode DOUBLE_R_BRACKET() { return getToken(TomlParser.DOUBLE_R_BRACKET, 0); } - public List expression() { - return getRuleContexts(ExpressionContext.class); + public List keyValue() { + return getRuleContexts(KeyValueContext.class); } - public ExpressionContext expression(int i) { - return getRuleContext(ExpressionContext.class,i); + public KeyValueContext keyValue(int i) { + return getRuleContext(KeyValueContext.class,i); } public List commentOrNl() { return getRuleContexts(CommentOrNlContext.class); @@ -1669,6 +1663,7 @@ public T accept(ParseTreeVisitor visitor) { public final ArrayTableContext arrayTable() throws RecognitionException { ArrayTableContext _localctx = new ArrayTableContext(_ctx, getState()); enterRule(_localctx, 40, RULE_arrayTable); + int _la; try { int _alt; enterOuterAlt(_localctx, 1); @@ -1688,22 +1683,20 @@ public final ArrayTableContext arrayTable() throws RecognitionException { { setState(225); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,28,_ctx); - while ( _alt!=2 && _alt!=org.antlr.v4.runtime.atn.ATN.INVALID_ALT_NUMBER ) { - if ( _alt==1 ) { - { - { - setState(222); - commentOrNl(); - } - } + _la = _input.LA(1); + while (_la==NL || _la==COMMENT) { + { + { + setState(222); + commentOrNl(); + } } setState(227); _errHandler.sync(this); - _alt = getInterpreter().adaptivePredict(_input,28,_ctx); + _la = _input.LA(1); } setState(228); - expression(); + keyValue(); } } } @@ -1741,8 +1734,8 @@ public final ArrayTableContext arrayTable() throws RecognitionException { "\u0006\u0001\u0007\u0001\u0007\u0001\b\u0001\b\u0001\b\u0004\bY\b\b\u000b"+ "\b\f\bZ\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0001\t\u0003"+ "\td\b\t\u0001\n\u0001\n\u0001\u000b\u0001\u000b\u0001\f\u0001\f\u0001"+ - "\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0001\u000f\u0001\u000f"+ - "\u0003\u000fs\b\u000f\u0001\u0010\u0001\u0010\u0005\u0010w\b\u0010\n\u0010"+ + "\r\u0001\r\u0001\u000e\u0001\u000e\u0001\u000f\u0003\u000fq\b\u000f\u0001"+ + "\u000f\u0001\u000f\u0001\u0010\u0001\u0010\u0005\u0010w\b\u0010\n\u0010"+ "\f\u0010z\t\u0010\u0001\u0010\u0001\u0010\u0001\u0010\u0005\u0010\u007f"+ "\b\u0010\n\u0010\f\u0010\u0082\t\u0010\u0001\u0010\u0001\u0010\u0001\u0010"+ "\u0005\u0010\u0087\b\u0010\n\u0010\f\u0010\u008a\t\u0010\u0001\u0010\u0001"+ @@ -1771,7 +1764,7 @@ public final ArrayTableContext arrayTable() throws RecognitionException { "U\u0001\u0000\u0000\u0000\u0012c\u0001\u0000\u0000\u0000\u0014e\u0001"+ "\u0000\u0000\u0000\u0016g\u0001\u0000\u0000\u0000\u0018i\u0001\u0000\u0000"+ "\u0000\u001ak\u0001\u0000\u0000\u0000\u001cm\u0001\u0000\u0000\u0000\u001e"+ - "r\u0001\u0000\u0000\u0000 \u009c\u0001\u0000\u0000\u0000\"\u00a0\u0001"+ + "p\u0001\u0000\u0000\u0000 \u009c\u0001\u0000\u0000\u0000\"\u00a0\u0001"+ "\u0000\u0000\u0000$\u00a2\u0001\u0000\u0000\u0000&\u00d9\u0001\u0000\u0000"+ "\u0000(\u00db\u0001\u0000\u0000\u0000*,\u0003\u0002\u0001\u0000+*\u0001"+ "\u0000\u0000\u0000+,\u0001\u0000\u0000\u0000,3\u0001\u0000\u0000\u0000"+ @@ -1804,9 +1797,9 @@ public final ArrayTableContext arrayTable() throws RecognitionException { "f\u0015\u0001\u0000\u0000\u0000gh\u0007\u0002\u0000\u0000h\u0017\u0001"+ "\u0000\u0000\u0000ij\u0007\u0003\u0000\u0000j\u0019\u0001\u0000\u0000"+ "\u0000kl\u0005\u0010\u0000\u0000l\u001b\u0001\u0000\u0000\u0000mn\u0007"+ - "\u0004\u0000\u0000n\u001d\u0001\u0000\u0000\u0000op\u0005\u0003\u0000"+ - "\u0000ps\u0005\u0002\u0000\u0000qs\u0005\u0002\u0000\u0000ro\u0001\u0000"+ - "\u0000\u0000rq\u0001\u0000\u0000\u0000s\u001f\u0001\u0000\u0000\u0000"+ + "\u0004\u0000\u0000n\u001d\u0001\u0000\u0000\u0000oq\u0005\u0003\u0000"+ + "\u0000po\u0001\u0000\u0000\u0000pq\u0001\u0000\u0000\u0000qr\u0001\u0000"+ + "\u0000\u0000rs\u0005\u0002\u0000\u0000s\u001f\u0001\u0000\u0000\u0000"+ "tx\u0005\u0004\u0000\u0000uw\u0003\u001e\u000f\u0000vu\u0001\u0000\u0000"+ "\u0000wz\u0001\u0000\u0000\u0000xv\u0001\u0000\u0000\u0000xy\u0001\u0000"+ "\u0000\u0000y{\u0001\u0000\u0000\u0000zx\u0001\u0000\u0000\u0000{\u009d"+ @@ -1836,7 +1829,7 @@ public final ArrayTableContext arrayTable() throws RecognitionException { "\u0000\u00a5\u00a7\u0003\u001e\u000f\u0000\u00a6\u00a5\u0001\u0000\u0000"+ "\u0000\u00a7\u00aa\u0001\u0000\u0000\u0000\u00a8\u00a6\u0001\u0000\u0000"+ "\u0000\u00a8\u00a9\u0001\u0000\u0000\u0000\u00a9\u00ab\u0001\u0000\u0000"+ - "\u0000\u00aa\u00a8\u0001\u0000\u0000\u0000\u00ab\u00ad\u0003\u0002\u0001"+ + "\u0000\u00aa\u00a8\u0001\u0000\u0000\u0000\u00ab\u00ad\u0003\u0006\u0003"+ "\u0000\u00ac\u00a8\u0001\u0000\u0000\u0000\u00ad\u00b0\u0001\u0000\u0000"+ "\u0000\u00ae\u00ac\u0001\u0000\u0000\u0000\u00ae\u00af\u0001\u0000\u0000"+ "\u0000\u00af%\u0001\u0000\u0000\u0000\u00b0\u00ae\u0001\u0000\u0000\u0000"+ @@ -1869,10 +1862,10 @@ public final ArrayTableContext arrayTable() throws RecognitionException { "\u000f\u0000\u00df\u00de\u0001\u0000\u0000\u0000\u00e0\u00e3\u0001\u0000"+ "\u0000\u0000\u00e1\u00df\u0001\u0000\u0000\u0000\u00e1\u00e2\u0001\u0000"+ "\u0000\u0000\u00e2\u00e4\u0001\u0000\u0000\u0000\u00e3\u00e1\u0001\u0000"+ - "\u0000\u0000\u00e4\u00e6\u0003\u0002\u0001\u0000\u00e5\u00e1\u0001\u0000"+ + "\u0000\u0000\u00e4\u00e6\u0003\u0006\u0003\u0000\u00e5\u00e1\u0001\u0000"+ "\u0000\u0000\u00e6\u00e9\u0001\u0000\u0000\u0000\u00e7\u00e5\u0001\u0000"+ "\u0000\u0000\u00e7\u00e8\u0001\u0000\u0000\u0000\u00e8)\u0001\u0000\u0000"+ - "\u0000\u00e9\u00e7\u0001\u0000\u0000\u0000\u001e+/3:>AKOZcrx\u0080\u0088"+ + "\u0000\u00e9\u00e7\u0001\u0000\u0000\u0000\u001e+/3:>AKOZcpx\u0080\u0088"+ "\u008d\u0091\u0097\u009c\u00a0\u00a8\u00ae\u00b5\u00bd\u00c5\u00ca\u00ce"+ "\u00d4\u00d9\u00e1\u00e7"; public static final ATN _ATN = diff --git a/rewrite-toml/src/test/java/org/openrewrite/toml/TomlParserTest.java b/rewrite-toml/src/test/java/org/openrewrite/toml/TomlParserTest.java index 2693151c649..d466abf86e2 100644 --- a/rewrite-toml/src/test/java/org/openrewrite/toml/TomlParserTest.java +++ b/rewrite-toml/src/test/java/org/openrewrite/toml/TomlParserTest.java @@ -17,7 +17,13 @@ import org.junit.jupiter.api.Test; import org.openrewrite.test.RewriteTest; +import org.openrewrite.toml.tree.Toml; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import static org.assertj.core.api.Assertions.assertThat; import static org.openrewrite.toml.Assertions.toml; class TomlParserTest implements RewriteTest { @@ -198,7 +204,13 @@ void table() { [dog."tater.man"] type.name = "pug" - """ + """, + spec -> spec.afterRecipe(doc -> { + assertThat(doc.getValues()).hasSize(3); + assertThat(doc.getValues()).allSatisfy( + v -> assertThat(v).isInstanceOf(Toml.Table.class) + ); + }) ) ); } From 36efb73d894b14440f7955d9aaf67a615ce41cd6 Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Thu, 16 Jan 2025 01:44:22 -0800 Subject: [PATCH 004/173] Add a test validation that execution context is not mutated during recipe execution (#4879) * Add a test validation that execution context is not mutated during the recipe run. * Allow messages from MavenExecutionContextView --- .../CursorValidatingExecutionContextView.java | 22 ++++++++++++ .../org/openrewrite/ExecutionContextTest.java | 4 ++- .../org/openrewrite/test/RewriteTest.java | 6 ++-- .../org/openrewrite/test/TypeValidation.java | 10 +++++- .../test/internal/RewriteTestTest.java | 36 +++++++++++++++++++ 5 files changed, 73 insertions(+), 5 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/CursorValidatingExecutionContextView.java b/rewrite-core/src/main/java/org/openrewrite/CursorValidatingExecutionContextView.java index 35fd3616483..cb8be5ce807 100644 --- a/rewrite-core/src/main/java/org/openrewrite/CursorValidatingExecutionContextView.java +++ b/rewrite-core/src/main/java/org/openrewrite/CursorValidatingExecutionContextView.java @@ -15,8 +15,11 @@ */ package org.openrewrite; +import org.jspecify.annotations.Nullable; + public class CursorValidatingExecutionContextView extends DelegatingExecutionContext { private static final String VALIDATE_CURSOR_ACYCLIC = "org.openrewrite.CursorValidatingExecutionContextView.ValidateCursorAcyclic"; + private static final String VALIDATE_CTX_MUTATION = "org.openrewrite.CursorValidatingExecutionContextView.ValidateExecutionContextImmutability"; public CursorValidatingExecutionContextView(ExecutionContext delegate) { super(delegate); @@ -38,4 +41,23 @@ public CursorValidatingExecutionContextView setValidateCursorAcyclic(boolean val putMessage(VALIDATE_CURSOR_ACYCLIC, validateCursorAcyclic); return this; } + + public CursorValidatingExecutionContextView setValidateImmutableExecutionContext(boolean allowExecutionContextMutation) { + putMessage(VALIDATE_CTX_MUTATION, allowExecutionContextMutation); + return this; + } + + @Override + public void putMessage(String key, @Nullable Object value) { + boolean mutationAllowed = !getMessage(VALIDATE_CTX_MUTATION, false) || key.equals(VALIDATE_CURSOR_ACYCLIC) || key.equals(VALIDATE_CTX_MUTATION) + || key.equals(ExecutionContext.CURRENT_CYCLE) || key.equals(ExecutionContext.CURRENT_RECIPE) || key.equals(ExecutionContext.DATA_TABLES) + || key.startsWith("org.openrewrite.maven"); // MavenExecutionContextView stores metrics + assert mutationAllowed + : "Recipe mutated execution context key \"" + key + "\". " + + "Recipes should not mutate the contents of the ExecutionContext as it allows mutable state to leak between " + + "recipes, opening the door for difficult to debug recipe composition errors. " + + "If you need to store state within the execution of a single recipe use Cursor messaging. " + + "If you want to pass state between recipes, use a ScanningRecipe instead."; + super.putMessage(key, value); + } } diff --git a/rewrite-core/src/test/java/org/openrewrite/ExecutionContextTest.java b/rewrite-core/src/test/java/org/openrewrite/ExecutionContextTest.java index ab9ad0ef731..fa7aaa25d7c 100644 --- a/rewrite-core/src/test/java/org/openrewrite/ExecutionContextTest.java +++ b/rewrite-core/src/test/java/org/openrewrite/ExecutionContextTest.java @@ -17,6 +17,7 @@ import org.junit.jupiter.api.Test; import org.openrewrite.test.RewriteTest; +import org.openrewrite.test.TypeValidation; import org.openrewrite.text.PlainText; import org.openrewrite.text.PlainTextVisitor; @@ -41,7 +42,8 @@ public PlainText visitText(PlainText text, ExecutionContext ctx) { cycles.incrementAndGet(); return text; } - }).withCausesAnotherCycle(true)), + }).withCausesAnotherCycle(true)) + .typeValidationOptions(TypeValidation.all().immutableExecutionContext(false)), text("hello world") ); assertThat(cycles.get()).isEqualTo(2); diff --git a/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java b/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java index 11c218c6495..073da655b1e 100644 --- a/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java +++ b/rewrite-test/src/main/java/org/openrewrite/test/RewriteTest.java @@ -367,9 +367,9 @@ default void rewriteRun(Consumer spec, SourceSpec... sourceSpecs) lss = new LargeSourceSetCheckingExpectedCycles(expectedCyclesThatMakeChanges, runnableSourceFiles); } - CursorValidatingExecutionContextView.view(recipeCtx) - .setValidateCursorAcyclic(TypeValidation.before(testMethodSpec, testClassSpec) - .cursorAcyclic()); + recipeCtx = CursorValidatingExecutionContextView.view(recipeCtx) + .setValidateCursorAcyclic(TypeValidation.before(testMethodSpec, testClassSpec).cursorAcyclic()) + .setValidateImmutableExecutionContext(TypeValidation.before(testMethodSpec, testClassSpec).immutableExecutionContext()); RecipeRun recipeRun = recipe.run( lss, recipeCtx, diff --git a/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java b/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java index 9d78cd0a33a..e395db403da 100644 --- a/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java +++ b/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java @@ -103,6 +103,14 @@ public class TypeValidation { @Builder.Default private boolean erroneous = true; + /** + * Adding messages to execution context is a side effect which makes the recipe run itself stateful. + * Potentially allows recipes to interfere with each other in surprising and hard to debug ways. + * Problematic for all the same reasons mutable global variables or singletons are. + */ + @Builder.Default + private boolean immutableExecutionContext = true; + /** * Enable all invariant validation checks. */ @@ -114,7 +122,7 @@ public static TypeValidation all() { * Skip all invariant validation checks. */ public static TypeValidation none() { - return new TypeValidation(false, false, false, false, false, false, false, false, o -> false, false); + return new TypeValidation(false, false, false, false, false, false, false, false, o -> false, false, false); } static TypeValidation before(RecipeSpec testMethodSpec, RecipeSpec testClassSpec) { diff --git a/rewrite-test/src/test/java/org/openrewrite/test/internal/RewriteTestTest.java b/rewrite-test/src/test/java/org/openrewrite/test/internal/RewriteTestTest.java index 343fe976074..aacab205113 100644 --- a/rewrite-test/src/test/java/org/openrewrite/test/internal/RewriteTestTest.java +++ b/rewrite-test/src/test/java/org/openrewrite/test/internal/RewriteTestTest.java @@ -112,6 +112,42 @@ void rejectRecipeValidationFailure() { """, "org.openrewrite.RefersToNonExistentRecipe") )); } + + @Test + void rejectExecutionContextMutation() { + assertThrows(AssertionError.class, () -> + rewriteRun( + spec -> spec.recipe(new MutateExecutionContext()), + text("irrelevant") + )); + } +} + +@Value +@EqualsAndHashCode(callSuper = false) +@NullMarked +class MutateExecutionContext extends Recipe { + + @Override + public String getDisplayName() { + return "Mutate execution context"; + } + + @Override + public String getDescription() { + return "Mutates the execution context to trigger a validation failure."; + } + + @Override + public TreeVisitor getVisitor() { + return new TreeVisitor<>() { + @Override + public @Nullable Tree visit(@Nullable Tree tree, ExecutionContext ctx) { + ctx.putMessage("mutated", true); + return tree; + } + }; + } } @Value From 68f86ee0af22206b5578e458a651835cefd3d3e3 Mon Sep 17 00:00:00 2001 From: JesseEstum Date: Thu, 16 Jan 2025 03:59:23 -0600 Subject: [PATCH 005/173] Optionally update maven plugin version in ChangePluginGroupIdAndArtifactId (#4905) * Remove deprecated newArtifact Option * Add newVersion Option to ChangePluginGroupIdAndArtifactId * Apply formatter --------- Co-authored-by: jestum_uhg Co-authored-by: Tim te Beek --- .../ChangePluginGroupIdAndArtifactId.java | 22 +- .../ChangePluginGroupIdAndArtifactIdTest.java | 214 +++++++++++++++++- 2 files changed, 212 insertions(+), 24 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactId.java b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactId.java index ba633f1dd9e..3ca0e66448e 100755 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactId.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactId.java @@ -58,17 +58,12 @@ public class ChangePluginGroupIdAndArtifactId extends Recipe { @Nullable String newArtifactId; - /** - * Mistakenly introduced, we restored newArtifactId but let's not break recipes abruptly. - */ - @Option(displayName = "New artifact ID", - description = "The new artifact ID to use. Defaults to the existing artifact ID. This property is deprecated, use newArtifactId instead.", - example = "my-new-maven-plugin", - required = false) + @Option(displayName = "New version", + description = "An exact version number or node-style semver selector used to select the version number.", + example = "29.X", + required = false) @Nullable - @Deprecated - @SuppressWarnings("DeprecatedIsStillUsed") - String newArtifact; + String newVersion; @Override public String getDisplayName() { @@ -82,7 +77,7 @@ public String getInstanceNameSuffix() { @Override public String getDescription() { - return "Change the groupId and/or the artifactId of a specified Maven plugin."; + return "Change the groupId and/or the artifactId of a specified Maven plugin. Optionally update the plugin version."; } @Override @@ -98,8 +93,9 @@ public Xml visitTag(Xml.Tag tag, ExecutionContext ctx) { } if (newArtifactId != null) { t = changeChildTagValue(t, "artifactId", newArtifactId, ctx); - } else if (newArtifact != null) { - t = changeChildTagValue(t, "artifactId", newArtifact, ctx); + } + if (newVersion != null) { + t = changeChildTagValue(t, "version", newVersion, ctx); } if (t != tag) { maybeUpdateModel(); diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactIdTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactIdTest.java index 55147edecf3..1de416271d6 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactIdTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/ChangePluginGroupIdAndArtifactIdTest.java @@ -103,14 +103,14 @@ void changePluginGroupIdAndArtifactId() { @DocumentExample @Test - void changePluginGroupIdAndArtifactIdDeprecatedNewArtifact() { + void changePluginGroupIdAndArtifactIdWithVersion() { rewriteRun( spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( "io.quarkus", "quarkus-bootstrap-maven-plugin", null, - null, - "quarkus-extension-maven-plugin" + "quarkus-extension-maven-plugin", + "4.0.0" )), pomXml( """ @@ -128,6 +128,55 @@ void changePluginGroupIdAndArtifactIdDeprecatedNewArtifact() { + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + io.quarkus + quarkus-extension-maven-plugin + 4.0.0 + + + + + """ + ) + ); + } + + @Test + void changePluginGroupIdAndArtifactIdNoChange() { + rewriteRun( + spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( + "io.quarkus", + "quarkus-bootstrap-maven-plugin", + null, + "quarkus-extension-maven-plugin", + null + )), + pomXml( + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + io.quarkus + quarkus-extension-maven-plugin + 3.0.0.Beta1 + + + profile @@ -135,7 +184,7 @@ void changePluginGroupIdAndArtifactIdDeprecatedNewArtifact() { io.quarkus - quarkus-bootstrap-maven-plugin + quarkus-extension-maven-plugin 3.0.0.Beta1 @@ -143,7 +192,22 @@ void changePluginGroupIdAndArtifactIdDeprecatedNewArtifact() { - """, + """ + ) + ); + } + + @Test + void changePluginGroupIdAndArtifactIdNoChangeWithVersion() { + rewriteRun( + spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( + "io.quarkus", + "quarkus-bootstrap-maven-plugin", + null, + "quarkus-extension-maven-plugin", + "4.0.0" + )), + pomXml( """ 4.0.0 @@ -180,7 +244,7 @@ void changePluginGroupIdAndArtifactIdDeprecatedNewArtifact() { } @Test - void changePluginGroupIdAndArtifactIdNoChange() { + void changeManagedPluginGroupIdAndArtifactId() { rewriteRun( spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( "io.quarkus", @@ -197,6 +261,63 @@ void changePluginGroupIdAndArtifactIdNoChange() { my-app 1 + + + + io.quarkus + quarkus-bootstrap-maven-plugin + 3.0.0.Beta1 + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + 3.0.0.Beta1 + + + + + + profile + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + 3.0.0.Beta1 + + + + + + io.quarkus + quarkus-bootstrap-maven-plugin + + + + + + + """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + + io.quarkus + quarkus-extension-maven-plugin + 3.0.0.Beta1 + + + io.quarkus @@ -209,11 +330,19 @@ void changePluginGroupIdAndArtifactIdNoChange() { profile + + + + io.quarkus + quarkus-extension-maven-plugin + 3.0.0.Beta1 + + + io.quarkus quarkus-extension-maven-plugin - 3.0.0.Beta1 @@ -226,14 +355,14 @@ void changePluginGroupIdAndArtifactIdNoChange() { } @Test - void changeManagedPluginGroupIdAndArtifactId() { + void changeManagedPluginGroupIdAndArtifactIdWithVersion() { rewriteRun( spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( "io.quarkus", "quarkus-bootstrap-maven-plugin", null, "quarkus-extension-maven-plugin", - null + "4.0.0" )), pomXml( """ @@ -284,6 +413,69 @@ void changeManagedPluginGroupIdAndArtifactId() { """, + """ + + 4.0.0 + com.mycompany.app + my-app + 1 + + + + + io.quarkus + quarkus-extension-maven-plugin + 4.0.0 + + + + + + io.quarkus + quarkus-extension-maven-plugin + 4.0.0 + + + + + + profile + + + + + io.quarkus + quarkus-extension-maven-plugin + 4.0.0 + + + + + + io.quarkus + quarkus-extension-maven-plugin + + + + + + + """ + ) + ); + } + + @Test + void changeManagedPluginGroupIdAndArtifactIdNoChange() { + rewriteRun( + spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( + "io.quarkus", + "quarkus-bootstrap-maven-plugin", + null, + "quarkus-extension-maven-plugin", + null + )), + pomXml( """ 4.0.0 @@ -337,14 +529,14 @@ void changeManagedPluginGroupIdAndArtifactId() { } @Test - void changeManagedPluginGroupIdAndArtifactIdNoChange() { + void changeManagedPluginGroupIdAndArtifactIdNoChangeWithVersion() { rewriteRun( spec -> spec.recipe(new ChangePluginGroupIdAndArtifactId( "io.quarkus", "quarkus-bootstrap-maven-plugin", null, "quarkus-extension-maven-plugin", - null + "4.0.0" )), pomXml( """ From 1fd511c3b31787ba6517b8b2db137d73fa05e6bb Mon Sep 17 00:00:00 2001 From: SiBorea <108953913+SiBorea@users.noreply.github.com> Date: Thu, 16 Jan 2025 18:20:35 +0800 Subject: [PATCH 006/173] Fix AddOrUpdateAnnotationAttribute unable to handle FieldAccess (#4898) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fix AddOrUpdateAnnotationAttribute unable to handle FieldAccess (cherry picked from commit 7d7451acfb6d939694f8d1cffc967affc5077710) * Fix AddOrUpdateAnnotationAttribute unable to handle FieldAccess (cherry picked from commit 7d7451acfb6d939694f8d1cffc967affc5077710) * Fix omitting addOnly and code style * Use getCursor() for JavaTemplate --------- Co-authored-by: Merlin Bögershausen --- .../AddOrUpdateAnnotationAttributeTest.java | 41 +++++++++++++++++++ .../java/AddOrUpdateAnnotationAttribute.java | 29 +++++++++---- 2 files changed, 62 insertions(+), 8 deletions(-) diff --git a/rewrite-java-test/src/test/java/org/openrewrite/java/AddOrUpdateAnnotationAttributeTest.java b/rewrite-java-test/src/test/java/org/openrewrite/java/AddOrUpdateAnnotationAttributeTest.java index fc520e7f8ab..fa9c34deb28 100755 --- a/rewrite-java-test/src/test/java/org/openrewrite/java/AddOrUpdateAnnotationAttributeTest.java +++ b/rewrite-java-test/src/test/java/org/openrewrite/java/AddOrUpdateAnnotationAttributeTest.java @@ -907,6 +907,47 @@ public class A { ); } + @Test + void updateFieldAccessAttribute() { + rewriteRun( + spec -> spec.recipe(new AddOrUpdateAnnotationAttribute("org.example.Foo", "value", "hello", null, false, null)), + java( + """ + package org.example; + + public class Const { + public static final String HI = "hi"; + } + """), + java( + """ + package org.example; + public @interface Foo { + String value() default ""; + } + """ + ), + java( + """ + import org.example.Foo; + import org.example.Const; + + @Foo(value = Const.HI) + public class A { + } + """, + """ + import org.example.Foo; + import org.example.Const; + + @Foo(value = "hello") + public class A { + } + """ + ) + ); + } + @Test void addAttributeToNestedAnnotationArray() { rewriteRun( diff --git a/rewrite-java/src/main/java/org/openrewrite/java/AddOrUpdateAnnotationAttribute.java b/rewrite-java/src/main/java/org/openrewrite/java/AddOrUpdateAnnotationAttribute.java index 38cb78f8d66..2f7a8858857 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/AddOrUpdateAnnotationAttribute.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/AddOrUpdateAnnotationAttribute.java @@ -23,7 +23,10 @@ import org.openrewrite.*; import org.openrewrite.internal.ListUtils; import org.openrewrite.java.search.UsesType; -import org.openrewrite.java.tree.*; +import org.openrewrite.java.tree.Expression; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.TypeUtils; import org.openrewrite.marker.Marker; import org.openrewrite.marker.Markers; @@ -208,14 +211,24 @@ public J.Annotation visitAnnotation(J.Annotation a, ExecutionContext ctx) { return as.withAssignment(((J.NewArray) as.getAssignment()).withInitializer(jLiteralList)); } else { - J.Literal value = (J.Literal) as.getAssignment(); - if (newAttributeValue.equals(value.getValueSource()) || Boolean.TRUE.equals(addOnly)) { - return it; - } - if (!valueMatches(value, oldAttributeValue)) { - return it; + Expression exp = as.getAssignment(); + if (exp instanceof J.Literal) { + J.Literal value = (J.Literal) exp; + if (newAttributeValue.equals(value.getValueSource()) || Boolean.TRUE.equals(addOnly)) { + return it; + } + if (!valueMatches(value, oldAttributeValue)) { + return it; + } + return as.withAssignment(value.withValue(newAttributeValue).withValueSource(newAttributeValue)); + } else if (exp instanceof J.FieldAccess) { + if (Boolean.TRUE.equals(addOnly)) { + return it; + } + int index = finalA.getArguments().indexOf(as); + as = (J.Assignment) ((J.Annotation) JavaTemplate.apply("#{} = #{}", getCursor(), as.getCoordinates().replace(), var.getSimpleName(), newAttributeValue)).getArguments().get(index); + return as; } - return as.withAssignment(value.withValue(newAttributeValue).withValueSource(newAttributeValue)); } } else if (it instanceof J.Literal) { // The only way anything except an assignment can appear is if there's an implicit assignment to "value" From 3d9653d441e90f46be502765b449aff251dcb5e6 Mon Sep 17 00:00:00 2001 From: t-huebner-id <161744488+t-huebner-id@users.noreply.github.com> Date: Thu, 16 Jan 2025 21:15:07 +0100 Subject: [PATCH 007/173] =?UTF-8?q?Fixed=20missing=20version=20on=20multip?= =?UTF-8?q?le=20dependency=20management=20sections=20in=20m=E2=80=A6=20(#4?= =?UTF-8?q?888)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Fixed missing version on multiple dependency management sections in multi-module projects and fixed ignored classifiers when choosing snapshot timestamp * Formatted code, add unit test * Added issue annotation to test * Formatted * Minor polish * Further polish * Generalize comment on continue * Test for snapshot downloading issue * Minor polish --------- Co-authored-by: Tobias Hübner Co-authored-by: Tim te Beek --- .../maven/internal/MavenPomDownloader.java | 76 ++++-- .../openrewrite/maven/tree/MavenMetadata.java | 2 + .../openrewrite/maven/tree/ResolvedPom.java | 4 +- .../internal/MavenPomDownloaderTest.java | 246 +++++++++++++----- .../maven/tree/ResolvedPomTest.java | 140 +++++++++- 5 files changed, 378 insertions(+), 90 deletions(-) diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/internal/MavenPomDownloader.java b/rewrite-maven/src/main/java/org/openrewrite/maven/internal/MavenPomDownloader.java index 26e59770b35..175cdb7a9a0 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/internal/MavenPomDownloader.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/internal/MavenPomDownloader.java @@ -219,7 +219,7 @@ private List getAncestryWithinProject(Pom projectPom, Map projec .normalize(); Pom parentPom = projectPoms.get(parentPath); return parentPom != null && parentPom.getGav().getGroupId().equals(parent.getGav().getGroupId()) && - parentPom.getGav().getArtifactId().equals(parent.getGav().getArtifactId()) ? parentPom : null; + parentPom.getGav().getArtifactId().equals(parent.getGav().getArtifactId()) ? parentPom : null; } public MavenMetadata downloadMetadata(GroupArtifact groupArtifact, @Nullable ResolvedPom containingPom, List repositories) throws MavenDownloadingException { @@ -259,9 +259,9 @@ public MavenMetadata downloadMetadata(GroupArtifactVersion gav, @Nullable Resolv try { String scheme = URI.create(repo.getUri()).getScheme(); String baseUri = repo.getUri() + (repo.getUri().endsWith("/") ? "" : "/") + - requireNonNull(gav.getGroupId()).replace('.', '/') + '/' + - gav.getArtifactId() + '/' + - (gav.getVersion() == null ? "" : gav.getVersion() + '/'); + requireNonNull(gav.getGroupId()).replace('.', '/') + '/' + + gav.getArtifactId() + '/' + + (gav.getVersion() == null ? "" : gav.getVersion() + '/'); if ("file".equals(scheme)) { // A maven repository can be expressed as a URI with a file scheme @@ -356,8 +356,8 @@ public MavenMetadata downloadMetadata(GroupArtifactVersion gav, @Nullable Resolv String scheme = URI.create(repo.getUri()).getScheme(); String uri = repo.getUri() + (repo.getUri().endsWith("/") ? "" : "/") + - requireNonNull(gav.getGroupId()).replace('.', '/') + '/' + - gav.getArtifactId() + '/'; + requireNonNull(gav.getGroupId()).replace('.', '/') + '/' + + gav.getArtifactId() + '/'; try { MavenMetadata.Versioning versioning; @@ -496,7 +496,7 @@ public Pom download(GroupArtifactVersion gav, // The requested gav might itself have an unresolved placeholder in the version, so also check raw values for (Pom projectPom : projectPoms.values()) { if (!projectPom.getGroupId().equals(gav.getGroupId()) || - !projectPom.getArtifactId().equals(gav.getArtifactId())) { + !projectPom.getArtifactId().equals(gav.getArtifactId())) { continue; } @@ -512,7 +512,7 @@ public Pom download(GroupArtifactVersion gav, } if (containingPom != null && containingPom.getRequested().getSourcePath() != null && - !StringUtils.isBlank(relativePath) && !relativePath.contains(":")) { + !StringUtils.isBlank(relativePath) && !relativePath.contains(":")) { Path folderContainingPom = containingPom.getRequested().getSourcePath().getParent(); if (folderContainingPom != null) { Pom maybeLocalPom = projectPoms.get(folderContainingPom.resolve(Paths.get(relativePath, "pom.xml")) @@ -521,9 +521,9 @@ public Pom download(GroupArtifactVersion gav, // So double check that the GAV coordinates match so that we don't get a relative path from a remote // pom like ".." or "../.." which coincidentally _happens_ to have led to an unrelated pom on the local filesystem if (maybeLocalPom != null && - gav.getGroupId().equals(maybeLocalPom.getGroupId()) && - gav.getArtifactId().equals(maybeLocalPom.getArtifactId()) && - gav.getVersion().equals(maybeLocalPom.getVersion())) { + gav.getGroupId().equals(maybeLocalPom.getGroupId()) && + gav.getArtifactId().equals(maybeLocalPom.getArtifactId()) && + gav.getVersion().equals(maybeLocalPom.getVersion())) { return maybeLocalPom; } } @@ -552,10 +552,10 @@ public Pom download(GroupArtifactVersion gav, if (result == null) { URI uri = URI.create(repo.getUri() + (repo.getUri().endsWith("/") ? "" : "/") + - requireNonNull(gav.getGroupId()).replace('.', '/') + '/' + - gav.getArtifactId() + '/' + - gav.getVersion() + '/' + - gav.getArtifactId() + '-' + versionMaybeDatedSnapshot + ".pom"); + requireNonNull(gav.getGroupId()).replace('.', '/') + '/' + + gav.getArtifactId() + '/' + + gav.getVersion() + '/' + + gav.getArtifactId() + '-' + versionMaybeDatedSnapshot + ".pom"); uris.add(uri.toString()); if ("file".equals(uri.getScheme())) { Path inputPath = Paths.get(gav.getGroupId(), gav.getArtifactId(), gav.getVersion()); @@ -688,9 +688,9 @@ private GroupArtifactVersion handleSnapshotTimestampVersion(GroupArtifactVersion if (gav.getVersion() != null && gav.getVersion().endsWith("-SNAPSHOT")) { for (ResolvedGroupArtifactVersion pinnedSnapshotVersion : new MavenExecutionContextView(ctx).getPinnedSnapshotVersions()) { if (pinnedSnapshotVersion.getDatedSnapshotVersion() != null && - pinnedSnapshotVersion.getGroupId().equals(gav.getGroupId()) && - pinnedSnapshotVersion.getArtifactId().equals(gav.getArtifactId()) && - pinnedSnapshotVersion.getVersion().equals(gav.getVersion())) { + pinnedSnapshotVersion.getGroupId().equals(gav.getGroupId()) && + pinnedSnapshotVersion.getArtifactId().equals(gav.getArtifactId()) && + pinnedSnapshotVersion.getVersion().equals(gav.getVersion())) { return pinnedSnapshotVersion.getDatedSnapshotVersion(); } } @@ -702,6 +702,23 @@ private GroupArtifactVersion handleSnapshotTimestampVersion(GroupArtifactVersion //This can happen if the artifact only exists in the local maven cache. In this case, just return the original return gav.getVersion(); } + + // Find the newest with a matching classifier - the latest snapshot may not have artifacts for all classifiers. + List snapshotVersions = mavenMetadata.getVersioning().getSnapshotVersions(); + if (snapshotVersions != null) { + // Try to get requested classifier (this is unfortunately not present in 'gav' structure) + String classifier = getClassifierFromContainingPom(gav, containingPom); + MavenMetadata.SnapshotVersion snapshotVersion = snapshotVersions.stream() + .sorted(Comparator.comparing(MavenMetadata.SnapshotVersion::getUpdated).reversed()) + .filter(s -> Objects.equals(s.getClassifier(), classifier)) + .findFirst() + .orElse(null); + if (snapshotVersion != null) { + return snapshotVersion.getValue(); + } + } + + // Replace SNAPSHOT suffix with timestamp and build number MavenMetadata.Snapshot snapshot = mavenMetadata.getVersioning().getSnapshot(); if (snapshot != null && snapshot.getTimestamp() != null) { return gav.getVersion().replaceFirst("SNAPSHOT$", snapshot.getTimestamp() + "-" + snapshot.getBuildNumber()); @@ -1054,4 +1071,27 @@ private static boolean hasPomFile(Path dir, Path versionPath, GroupArtifactVersi String artifactPomFile = gav.getArtifactId() + "-" + versionPath.getFileName() + ".pom"; return Files.exists(dir.resolve(versionPath.resolve(artifactPomFile))); } + + /** + * Retrieves the classifier of a dependency from a provided resolved POM, if it exists. + * + * @param gav The group, artifact, and version information of the dependency to locate. + * @param containingPom The resolved POM that potentially contains the dependency information. + * If null, the method will return null. + * @return The classifier of the dependency within the provided POM, or null if no matching + * dependency or classifier is found. + */ + private static @Nullable String getClassifierFromContainingPom(GroupArtifactVersion gav, @Nullable ResolvedPom containingPom) { + if (containingPom != null) { + for (Dependency dep : containingPom.getRequestedDependencies()) { + if (Objects.equals(dep.getGroupId(), gav.getGroupId())) { + if (Objects.equals(dep.getArtifactId(), gav.getArtifactId())) { + return dep.getClassifier(); + } + } + } + } + return null; + } + } diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/tree/MavenMetadata.java b/rewrite-maven/src/main/java/org/openrewrite/maven/tree/MavenMetadata.java index 2ece965a7f5..8d94d2dd036 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/tree/MavenMetadata.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/tree/MavenMetadata.java @@ -101,5 +101,7 @@ public static class SnapshotVersion { String extension; String value; String updated; + @Nullable + String classifier; } } diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java b/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java index 7f5a0d343e1..7b9b00721d3 100644 --- a/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/tree/ResolvedPom.java @@ -320,11 +320,13 @@ public String getPackaging() { public @Nullable String getManagedVersion(@Nullable String groupId, String artifactId, @Nullable String type, @Nullable String classifier) { for (ResolvedManagedDependency dm : dependencyManagement) { + if (dm.getVersion() == null) { + continue; // Unclear why this happens; just ignore those entries, because a valid version is requested + } if (dm.matches(groupId, artifactId, type, classifier)) { return getValue(dm.getVersion()); } } - return null; } diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java index 4c19fc87f33..b641f835b64 100755 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/internal/MavenPomDownloaderTest.java @@ -33,11 +33,11 @@ import org.openrewrite.*; import org.openrewrite.ipc.http.HttpSender; import org.openrewrite.ipc.http.HttpUrlConnectionSender; -import org.openrewrite.maven.http.OkHttpSender; import org.openrewrite.maven.MavenDownloadingException; import org.openrewrite.maven.MavenExecutionContextView; import org.openrewrite.maven.MavenParser; import org.openrewrite.maven.MavenSettings; +import org.openrewrite.maven.http.OkHttpSender; import org.openrewrite.maven.tree.*; import javax.net.ssl.SSLSocketFactory; @@ -314,7 +314,7 @@ void useHttpWhenHttpsFails() throws IOException { @Test @Disabled - void dontFetchSnapshotsFromReleaseRepos() { + void dontFetchSnapshotsFromReleaseRepos() throws Exception { try (MockWebServer snapshotRepo = new MockWebServer(); MockWebServer releaseRepo = new MockWebServer()) { snapshotRepo.setDispatcher(new Dispatcher() { @@ -322,39 +322,39 @@ void dontFetchSnapshotsFromReleaseRepos() { public MockResponse dispatch(RecordedRequest request) { MockResponse response = new MockResponse().setResponseCode(200); if (request.getPath() != null && request.getPath().contains("maven-metadata")) { + //language=xml response.setBody( - //language=xml """ - - org.springframework.cloud - spring-cloud-dataflow-build - 2.10.0-SNAPSHOT - - - 20220201.001946 - 85 - - 20220201001950 - - - pom - 2.10.0-20220201.001946-85 - 20220201001946 - - - - + + org.springframework.cloud + spring-cloud-dataflow-build + 2.10.0-SNAPSHOT + + + 20220201.001946 + 85 + + 20220201001950 + + + pom + 2.10.0-20220201.001946-85 + 20220201001946 + + + + """ ); } else if (request.getPath() != null && request.getPath().endsWith(".pom")) { + //language=xml response.setBody( - //language=xml """ - - org.springframework.cloud - spring-cloud-dataflow-build - 2.10.0-SNAPSHOT - + + org.springframework.cloud + spring-cloud-dataflow-build + 2.10.0-SNAPSHOT + """ ); } @@ -380,45 +380,173 @@ public MockResponse dispatch(RecordedRequest request) { MavenParser.builder().build().parse(ctx, //language=xml """ - - 4.0.0 + + 4.0.0 - org.openrewrite.test - foo - 0.1.0-SNAPSHOT + org.openrewrite.test + foo + 0.1.0-SNAPSHOT - - - snapshot - - true - - http://%s:%d - - - release - - false - - http://%s:%d - - + + + snapshot + + true + + http://%s:%d + + + release + + false + + http://%s:%d + + - - - org.springframework.cloud - spring-cloud-dataflow-build - 2.10.0-SNAPSHOT - - - + + + org.springframework.cloud + spring-cloud-dataflow-build + 2.10.0-SNAPSHOT + + + """.formatted(snapshotRepo.getHostName(), snapshotRepo.getPort(), releaseRepo.getHostName(), releaseRepo.getPort()) ); assertThat(snapshotRepo.getRequestCount()).isGreaterThan(1); assertThat(metadataPaths.get()).isEqualTo(0); - } catch (IOException e) { - throw new RuntimeException(e); + } + } + + @Issue("https://github.com/openrewrite/rewrite-maven-plugin/issues/862") + @Test + void fetchSnapshotWithCorrectClassifier() throws Exception { + try (MockWebServer snapshotServer = new MockWebServer()) { + snapshotServer.setDispatcher(new Dispatcher() { + @Override + public MockResponse dispatch(RecordedRequest request) { + MockResponse response = new MockResponse().setResponseCode(200); + if (request.getPath() != null && request.getPath().contains("maven-metadata")) { + //language=xml + response.setBody( + """ + + com.some + an-artifact + 10.5.0-SNAPSHOT + + + 20250113.114247 + 36 + + 20250113114247 + + + javadoc + jar + 10.5.0-20250113.114247-36 + 20250113114247 + + + tests + jar + 10.5.0-20250113.114244-35 + 20250113114244 + + + sources + jar + 10.5.0-20250113.114242-34 + 20250113114242 + + + jar + 10.5.0-20250113.114227-33 + 20250113114227 + + + pom + 10.5.0-20250113.114227-33 + 20250113114227 + + + + + """ + ); + } else if (request.getPath() != null && request.getPath().endsWith(".pom")) { + //language=xml + response.setBody( + """ + + com.some + an-artifact + 10.5.0-SNAPSHOT + + """ + ); + } + return response; + } + }); + + snapshotServer.start(); + + //language=xml + MavenParser.builder().build().parse(ctx, + """ + + 4.0.0 + org.openrewrite.test + foo + 0.1.0-SNAPSHOT + + + snapshot + + true + + http://%s:%d + + + + + com.some + an-artifact + 10.5.0-SNAPSHOT + + + + """.formatted(snapshotServer.getHostName(), snapshotServer.getPort()) + ); + + MavenRepository snapshotRepo = MavenRepository.builder() + .id("id") + .uri("http://%s:%d/maven/".formatted(snapshotServer.getHostName(), snapshotServer.getPort())) + .build(); + + var gav = new GroupArtifactVersion("com.some", "an-artifact", "10.5.0-SNAPSHOT"); + var mavenPomDownloader = new MavenPomDownloader(emptyMap(), ctx); + + var pomPath = Paths.get("pom.xml"); + var pom = Pom.builder() + .sourcePath(pomPath) + .repository(snapshotRepo) + .properties(singletonMap("REPO_URL", snapshotRepo.getUri())) + .gav(new ResolvedGroupArtifactVersion( + "${REPO_URL}", gav.getGroupId(), gav.getArtifactId(), gav.getVersion(), null)) + .build(); + var resolvedPom = ResolvedPom.builder() + .requested(pom) + .properties(singletonMap("REPO_URL", snapshotRepo.getUri())) + .repositories(singletonList(snapshotRepo)) + .build(); + + // Ensure that classifier 'javadoc', 'tests' and 'sources' are not used + var downloadedPom = mavenPomDownloader.download(gav, null, resolvedPom, List.of(snapshotRepo)); + assertThat(downloadedPom).returns("10.5.0-20250113.114227-33", Pom::getDatedSnapshotVersion); } } diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/tree/ResolvedPomTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/tree/ResolvedPomTest.java index b1c0e12f1bd..ea52800af59 100644 --- a/rewrite-maven/src/test/java/org/openrewrite/maven/tree/ResolvedPomTest.java +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/tree/ResolvedPomTest.java @@ -367,19 +367,135 @@ public void downloadError(GroupArtifactVersion gav, List attemptedUris, assertThat(downloadErrorArgs).hasSize(1); } - private static void createJarFile(Path localRepository1) throws IOException { - Path localJar = localRepository1.resolve("com/some/some-artifact/1/some-artifact-1.jar"); - assertThat(localJar.getParent().toFile().mkdirs()).isTrue(); - Files.writeString(localJar, "some content not to be empty"); - } + } - private static MavenRepository createMavenRepository(Path localRepository, String name) { - return MavenRepository.builder() - .id(name) - .uri(localRepository.toUri().toString()) - .snapshots(false) - .knownToExist(true) - .build(); + @Nested + class DependencyManagement { + + @Issue("https://github.com/openrewrite/rewrite-maven-plugin/issues/862") + @Test + void resolveVersionFromParentDependencyManagement(@TempDir Path localRepository) throws IOException { + MavenRepository mavenLocal = createMavenRepository(localRepository, "local"); + createJarFile(localRepository); + createJarFile(localRepository, "org.openrewrite.test", "lib", "1.0"); + + List> downloadErrorArgs = new ArrayList<>(); + MavenExecutionContextView ctx = MavenExecutionContextView.view(new InMemoryExecutionContext(Throwable::printStackTrace)); + ctx.setRepositories(List.of(mavenLocal)); + ctx.setResolutionListener(new ResolutionEventListener() { + @Override + public void downloadError(GroupArtifactVersion gav, List attemptedUris, @Nullable Pom containing) { + List list = new ArrayList<>(); + list.add(gav); + list.add(attemptedUris); + list.add(containing); + downloadErrorArgs.add(list); + } + }); + + String father = """ + + 4.0.0 + org.example + father + 1.0.0-SNAPSHOT + pom + + childA + childB + + + + + com.some + some-artifact + 1 + + + + + """; + String childA = """ + + 4.0.0 + + org.example + father + 1.0.0-SNAPSHOT + + childA + + + + org.openrewrite.test + lib + 1.0 + pom + import + + + + + + com.some + some-artifact + + + + """; + String childB = """ + + 4.0.0 + + org.example + father + 1.0.0-SNAPSHOT + + childB + + + + com.some + some-artifact + compile + + + + + """; + + rewriteRun( + spec -> spec.executionContext(ctx), + pomXml(father, spec -> spec.path("pom.xml")), + pomXml(childA, spec -> spec.path("childA/pom.xml")), + pomXml(childB, spec -> spec.path("childB/pom.xml").afterRecipe(doc -> { + ResolvedPom pom = doc.getMarkers().findFirst(MavenResolutionResult.class).get().getPom(); + String version = pom.getManagedVersion("com.some", "some-artifact", null, null); + // Assert that version is not null! + assertThat(version).isEqualTo("1"); + }) + ) + ); } } + + private static void createJarFile(Path localRepository1) throws IOException { + createJarFile(localRepository1, "com/some", "some-artifact", "1"); + } + + private static void createJarFile(Path localRepository, String groupId, String artifactId, String version) throws IOException { + Path localJar = localRepository.resolve("%s/%s/%s/%s-%s.jar".formatted( + groupId.replace('.', '/'), artifactId, version, artifactId, version)); + assertThat(localJar.getParent().toFile().mkdirs()).isTrue(); + Files.writeString(localJar, "some content not to be empty"); + } + + private static MavenRepository createMavenRepository(Path localRepository, String name) { + return MavenRepository.builder() + .id(name) + .uri(localRepository.toUri().toString()) + .snapshots(false) + .knownToExist(true) + .build(); + } } From a6afce055efd0274e86ea26b2eecb9d7cc4d56fe Mon Sep 17 00:00:00 2001 From: Sam Snyder Date: Thu, 16 Jan 2025 12:33:58 -0800 Subject: [PATCH 008/173] Tweak AddDependency to be a bit more permissive when adding a dependency without onlyIfUsing constraint. --- .../org/openrewrite/gradle/AddDependency.java | 24 ++++++++++++------- .../openrewrite/gradle/AddDependencyTest.java | 3 --- 2 files changed, 15 insertions(+), 12 deletions(-) diff --git a/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java b/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java index 990a0606d65..59084bd7cec 100644 --- a/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java +++ b/rewrite-gradle/src/main/java/org/openrewrite/gradle/AddDependency.java @@ -34,6 +34,7 @@ import java.util.*; +import static java.util.Collections.*; import static java.util.Objects.requireNonNull; @Value @@ -171,14 +172,14 @@ private boolean usesType(SourceFile sourceFile, ExecutionContext ctx) { return tree; } SourceFile sourceFile = (SourceFile) tree; - sourceFile.getMarkers().findFirst(JavaProject.class).ifPresent(javaProject -> - sourceFile.getMarkers().findFirst(JavaSourceSet.class).ifPresent(sourceSet -> { - if (usesType(sourceFile, ctx)) { - acc.usingType = true; - } - Set configurations = acc.configurationsByProject.computeIfAbsent(javaProject, ignored -> new HashSet<>()); - configurations.add("main".equals(sourceSet.getName()) ? "implementation" : sourceSet.getName() + "Implementation"); - })); + sourceFile.getMarkers().findFirst(JavaProject.class).ifPresent(javaProject -> { + if (usesType(sourceFile, ctx)) { + acc.usingType = true; + } + Set configurations = acc.configurationsByProject.computeIfAbsent(javaProject, ignored -> new HashSet<>()); + sourceFile.getMarkers().findFirst(JavaSourceSet.class).ifPresent(sourceSet -> + configurations.add("main".equals(sourceSet.getName()) ? "implementation" : sourceSet.getName() + "Implementation")); + }); return tree; } }; @@ -216,7 +217,12 @@ public TreeVisitor getVisitor(Scanned acc) { GradleProject gp = maybeGp.get(); - Set resolvedConfigurations = StringUtils.isBlank(configuration) ? acc.configurationsByProject.get(jp) : new HashSet<>(Collections.singletonList(configuration)); + Set resolvedConfigurations = StringUtils.isBlank(configuration) ? + acc.configurationsByProject.getOrDefault(jp, new HashSet<>()) : + new HashSet<>(singletonList(configuration)); + if (resolvedConfigurations.isEmpty()) { + resolvedConfigurations.add("implementation"); + } Set tmpConfigurations = new HashSet<>(resolvedConfigurations); for (String tmpConfiguration : tmpConfigurations) { GradleDependencyConfiguration gdc = gp.getConfiguration(tmpConfiguration); diff --git a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java index 6330f931018..cb1da2ffe4a 100644 --- a/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java +++ b/rewrite-gradle/src/test/java/org/openrewrite/gradle/AddDependencyTest.java @@ -1317,9 +1317,6 @@ void addUnconditionally() { rewriteRun( spec -> spec.recipe(addDependency("org.apache.logging.log4j:log4j-core:2.22.1")), mavenProject("project", - srcMainJava( - java(usingGuavaIntMath) - ), buildGradle(""" plugins { id "java-library" From c1b258eef30f430104c733575da99b99e8d1eaba Mon Sep 17 00:00:00 2001 From: Ralph Sanders <59902221+rlsanders4@users.noreply.github.com> Date: Fri, 17 Jan 2025 02:24:31 -0600 Subject: [PATCH 009/173] Fix issue parsing string with Java8ReloadableParser (#4914) * Fix parser * restore build files * Restore build file * Put arguments on new line for readability * Add test case (even though not reproducible) --------- Co-authored-by: Tim te Beek Co-authored-by: Knut Wannheden --- .../java/ReloadableJava8Parser.java | 7 ++- .../org/openrewrite/java/tree/ParserTest.java | 43 +++++++++++++++++++ 2 files changed, 48 insertions(+), 2 deletions(-) create mode 100644 rewrite-java-tck/src/main/java/org/openrewrite/java/tree/ParserTest.java diff --git a/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8Parser.java b/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8Parser.java index bad6fc19a4d..73fbc46c6ba 100644 --- a/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8Parser.java +++ b/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8Parser.java @@ -113,7 +113,7 @@ class ReloadableJava8Parser implements JavaParser { LOMBOK: if (System.getenv().getOrDefault("REWRITE_LOMBOK", System.getProperty("rewrite.lombok")) != null && - classpath != null && classpath.stream().anyMatch(it -> it.toString().contains("lombok"))) { + classpath != null && classpath.stream().anyMatch(it -> it.toString().contains("lombok"))) { Processor lombokProcessor = null; try { // https://projectlombok.org/contributing/lombok-execution-path @@ -255,7 +255,10 @@ LinkedHashMap parseInputsToCompilerAst(Iterable } try { //noinspection unchecked - com.sun.tools.javac.util.List jcCompilationUnits = compiler.parseFiles((List) (List) inputFileObjects); + com.sun.tools.javac.util.List jcCompilationUnits = com.sun.tools.javac.util.List.from( + inputFileObjects.stream() + .map(input -> compiler.parse(input)) + .toArray(JCTree.JCCompilationUnit[]::new)); for (int i = 0; i < inputFileObjects.size(); i++) { cus.put(inputFileObjects.get(i).getInput(), jcCompilationUnits.get(i)); } diff --git a/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/ParserTest.java b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/ParserTest.java new file mode 100644 index 00000000000..065ef0c22f9 --- /dev/null +++ b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/ParserTest.java @@ -0,0 +1,43 @@ +/* + * Copyright 2025 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.java.tree; + +import org.junit.jupiter.api.Test; +import org.openrewrite.Issue; +import org.openrewrite.SourceFile; +import org.openrewrite.java.JavaParser; +import org.openrewrite.test.RewriteTest; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.List; +import java.util.stream.Collectors; + +class ParserTest implements RewriteTest { + + @Test + @Issue("https://github.com/openrewrite/rewrite/pull/4914") + void parseString() throws IOException { + // path needs to be resolvable from `rewrite-java-8` etc. + Path targetFile = Paths.get("../rewrite-java-tck/src/main/java/org/openrewrite/java/tree/ParserTest.java"); + @SuppressWarnings("SimplifyStreamApiCallChains") List ignore = JavaParser.fromJavaVersion() + .build() + .parse(new String(Files.readAllBytes(targetFile))) + .collect(Collectors.toList()); + } +} From b7746cf85bfa915bb68061a756f11273cfeae98d Mon Sep 17 00:00:00 2001 From: Valentin Delaye Date: Fri, 17 Jan 2025 09:24:55 +0100 Subject: [PATCH 010/173] Groovy parser fail with single line comment (#4887) * Groovy parser fail with Jenkinsfile and single line comment * Minimize example * Update rewrite-groovy/src/test/java/org/openrewrite/groovy/JenkinsFileTest.java Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Fix `StringUtils#indexOfNextNonWhitespace()` A `//` sequence inside a multi-line comment caused trouble. --------- Co-authored-by: Tim te Beek Co-authored-by: Tim te Beek Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Knut Wannheden --- .../org/openrewrite/internal/StringUtils.java | 12 +++++++----- .../org/openrewrite/groovy/JenkinsFileTest.java | 16 ++++++++++++++++ 2 files changed, 23 insertions(+), 5 deletions(-) diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java b/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java index 4f0f76ae578..e06c1d58281 100644 --- a/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java +++ b/rewrite-core/src/main/java/org/openrewrite/internal/StringUtils.java @@ -692,7 +692,13 @@ public static int indexOfNextNonWhitespace(int cursor, String source) { continue; } else if (length > cursor + 1) { char next = source.charAt(cursor + 1); - if (current == '/' && next == '/') { + if (inMultiLineComment) { + if (current == '*' && next == '/') { + inMultiLineComment = false; + cursor++; + continue; + } + } else if (current == '/' && next == '/') { inSingleLineComment = true; cursor++; continue; @@ -700,10 +706,6 @@ public static int indexOfNextNonWhitespace(int cursor, String source) { inMultiLineComment = true; cursor++; continue; - } else if (current == '*' && next == '/') { - inMultiLineComment = false; - cursor++; - continue; } } if (!inMultiLineComment && !Character.isWhitespace(current)) { diff --git a/rewrite-groovy/src/test/java/org/openrewrite/groovy/JenkinsFileTest.java b/rewrite-groovy/src/test/java/org/openrewrite/groovy/JenkinsFileTest.java index f677fb9f019..75ff46b9ffe 100644 --- a/rewrite-groovy/src/test/java/org/openrewrite/groovy/JenkinsFileTest.java +++ b/rewrite-groovy/src/test/java/org/openrewrite/groovy/JenkinsFileTest.java @@ -16,6 +16,7 @@ package org.openrewrite.groovy; import org.junit.jupiter.api.Test; +import org.openrewrite.Issue; import org.openrewrite.test.RewriteTest; import static org.openrewrite.groovy.Assertions.groovy; @@ -119,4 +120,19 @@ void jenkinsfile() { ) ); } + + @Issue("https://github.com/openrewrite/rewrite/pull/4887") + @Test + void jenkinsfileWithComment() { + // the Jenkinsfile adapted from https://github.com/jenkinsci/ssh-plugin/blob/158.ve2a_e90fb_7319/Jenkinsfile + rewriteRun( + groovy( + """ + /* https://github.com */ + foo() + """, + spec -> spec.path("Jenkinsfile") + ) + ); + } } From b2a641dd69a7e846692834760c73e1e279ff61b4 Mon Sep 17 00:00:00 2001 From: Greg Oledzki Date: Fri, 17 Jan 2025 11:07:26 +0100 Subject: [PATCH 011/173] YAML Parser not to take @variables@ in the middle of scalar (#4917) --- .../java/org/openrewrite/yaml/YamlParser.java | 2 +- .../org/openrewrite/yaml/YamlParserTest.java | 16 ++++++++++++++++ 2 files changed, 17 insertions(+), 1 deletion(-) diff --git a/rewrite-yaml/src/main/java/org/openrewrite/yaml/YamlParser.java b/rewrite-yaml/src/main/java/org/openrewrite/yaml/YamlParser.java index ca7685f37ba..deac37d20cd 100644 --- a/rewrite-yaml/src/main/java/org/openrewrite/yaml/YamlParser.java +++ b/rewrite-yaml/src/main/java/org/openrewrite/yaml/YamlParser.java @@ -52,7 +52,7 @@ import static org.openrewrite.Tree.randomId; public class YamlParser implements org.openrewrite.Parser { - private static final Pattern VARIABLE_PATTERN = Pattern.compile(":\\s*(@[^\n\r@]+@)"); + private static final Pattern VARIABLE_PATTERN = Pattern.compile(":\\s+(@[^\n\r@]+@)"); @Override public Stream parse(@Language("yml") String... sources) { diff --git a/rewrite-yaml/src/test/java/org/openrewrite/yaml/YamlParserTest.java b/rewrite-yaml/src/test/java/org/openrewrite/yaml/YamlParserTest.java index e3033a4b827..7b8653cd68a 100644 --- a/rewrite-yaml/src/test/java/org/openrewrite/yaml/YamlParserTest.java +++ b/rewrite-yaml/src/test/java/org/openrewrite/yaml/YamlParserTest.java @@ -216,4 +216,20 @@ void troublesomeYaml() { ) ); } + + @Test + void atSymbols() { + rewriteRun( + yaml( + // BTW, the @ sign is forbidden as the first character of a scalar value by the YAML spec: + // https://github.com/yaml/yaml-spec/blob/1b1a1be43bd6e0cfec45caf0e40af3b5d2bb7f8a/spec/1.2.2/spec.md#L1877 + """ + root: + specifier: npm:@testing-library/vue@5.0.4 + date: @build.timestamp@ + version: @project.version@ + """ + ) + ); + } } From fa191cb152d4aad33f3b1a7c9d97f5a1fbf95655 Mon Sep 17 00:00:00 2001 From: Knut Wannheden Date: Fri, 17 Jan 2025 13:27:05 +0100 Subject: [PATCH 012/173] Add missing `@Contract` to `ListUtils#map()` method --- .../src/main/java/org/openrewrite/internal/ListUtils.java | 1 + 1 file changed, 1 insertion(+) diff --git a/rewrite-core/src/main/java/org/openrewrite/internal/ListUtils.java b/rewrite-core/src/main/java/org/openrewrite/internal/ListUtils.java index a18cc8bf585..5de88dc8c50 100644 --- a/rewrite-core/src/main/java/org/openrewrite/internal/ListUtils.java +++ b/rewrite-core/src/main/java/org/openrewrite/internal/ListUtils.java @@ -261,6 +261,7 @@ public static List insert(@Nullable List ls, @Nullable T t, int index) /** * For backwards compatibility; prefer {@link #map(List, Function)}. */ + @Contract("null, _ -> null; !null, _ -> !null") public static @Nullable List map(@Nullable List ls, UnaryOperator<@Nullable T> map) { return map(ls, (Function) map); } From 9ddbb83f038cd989d4679aa12fe1951b5e0836c2 Mon Sep 17 00:00:00 2001 From: Niels de Bruin Date: Fri, 17 Jan 2025 14:08:21 +0100 Subject: [PATCH 013/173] Support JEP-441: Pattern Matching for switch for Java 21+ (#4661) * Add full blown support for Switch pattern matching * Add print idempotency for Record pattern matching --------- Co-authored-by: Laurens Westerlaken Co-authored-by: Tim te Beek --- .../groovy/GroovyParserVisitor.java | 13 +- .../ReloadableJava11ParserVisitor.java | 2 + .../ReloadableJava17ParserVisitor.java | 2 + .../ReloadableJava21ParserVisitor.java | 28 +++- .../java/ReloadableJava8ParserVisitor.java | 32 ++-- .../java/tree/RecordPatternMatchingTest.java | 74 +++++++++ .../java/tree/SwitchPatternMatchingTest.java | 155 ++++++++++++++++++ .../java/org/openrewrite/java/Assertions.java | 19 ++- .../org/openrewrite/java/JavaPrinter.java | 12 +- .../org/openrewrite/java/JavaVisitor.java | 5 +- .../java/search/SemanticallyEqual.java | 8 +- .../java/org/openrewrite/java/tree/J.java | 77 +++++++-- .../org/openrewrite/java/tree/JContainer.java | 1 + .../openrewrite/java/tree/JRightPadded.java | 1 + .../java/org/openrewrite/java/tree/Space.java | 5 +- .../org/openrewrite/test/TypeValidation.java | 8 +- 16 files changed, 394 insertions(+), 48 deletions(-) create mode 100644 rewrite-java-tck/src/main/java/org/openrewrite/java/tree/RecordPatternMatchingTest.java create mode 100644 rewrite-java-tck/src/main/java/org/openrewrite/java/tree/SwitchPatternMatchingTest.java diff --git a/rewrite-groovy/src/main/java/org/openrewrite/groovy/GroovyParserVisitor.java b/rewrite-groovy/src/main/java/org/openrewrite/groovy/GroovyParserVisitor.java index d38c154ef76..e36026b986a 100644 --- a/rewrite-groovy/src/main/java/org/openrewrite/groovy/GroovyParserVisitor.java +++ b/rewrite-groovy/src/main/java/org/openrewrite/groovy/GroovyParserVisitor.java @@ -650,7 +650,7 @@ public List visitAndGetAnnotations(AnnotatedNode node) { for (AnnotationNode annotationNode : node.getAnnotations()) { // The groovy compiler can add or remove annotations for AST transformations. // Because @groovy.transform.Immutable is discarded in favour of other transform annotations, the removed annotation must be parsed by hand. - if (sourceStartsWith("@" + Immutable.class.getSimpleName()) || sourceStartsWith("@" + Immutable.class.getCanonicalName()) ) { + if (sourceStartsWith("@" + Immutable.class.getSimpleName()) || sourceStartsWith("@" + Immutable.class.getCanonicalName())) { visitAnnotation(new AnnotationNode(new ClassNode(Immutable.class))); paramAnnotations.add(pollQueue()); } @@ -1135,10 +1135,12 @@ public void visitCaseStatement(CaseStatement statement) { J.Case.Type.Statement, null, JContainer.build(singletonList(JRightPadded.build(visit(statement.getExpression())))), + null, + null, statement.getCode() instanceof EmptyStatement ? JContainer.build(sourceBefore(":"), convertStatements(emptyList()), Markers.EMPTY) : - JContainer.build(sourceBefore(":"), convertStatements(((BlockStatement) statement.getCode()).getStatements()), Markers.EMPTY) - , null) + JContainer.build(sourceBefore(":"), convertStatements(((BlockStatement) statement.getCode()).getStatements()), Markers.EMPTY), + null) ); } @@ -1149,6 +1151,8 @@ private J.Case visitDefaultCaseStatement(BlockStatement statement) { J.Case.Type.Statement, null, JContainer.build(singletonList(JRightPadded.build(new J.Identifier(randomId(), EMPTY, Markers.EMPTY, emptyList(), skip("default"), null, null)))), + null, + null, JContainer.build(sourceBefore(":"), convertStatements(statement.getStatements()), Markers.EMPTY), null ); @@ -1609,7 +1613,7 @@ public void visitGStringExpression(GStringExpression gstring) { } } - queue.add(new G.GString(randomId(), fmt, Markers.EMPTY, delimiter, strings,typeMapping.type(gstring.getType()))); + queue.add(new G.GString(randomId(), fmt, Markers.EMPTY, delimiter, strings, typeMapping.type(gstring.getType()))); skip(delimiter); // Closing delim for GString } @@ -2778,6 +2782,7 @@ private static ClassNode staticType(Parameter parameter) { } private static final Map modifierNameToType; + static { modifierNameToType = new LinkedHashMap<>(); modifierNameToType.put("def", J.Modifier.Type.LanguageExtension); diff --git a/rewrite-java-11/src/main/java/org/openrewrite/java/isolated/ReloadableJava11ParserVisitor.java b/rewrite-java-11/src/main/java/org/openrewrite/java/isolated/ReloadableJava11ParserVisitor.java index 8c434c84edd..22648604cd2 100644 --- a/rewrite-java-11/src/main/java/org/openrewrite/java/isolated/ReloadableJava11ParserVisitor.java +++ b/rewrite-java-11/src/main/java/org/openrewrite/java/isolated/ReloadableJava11ParserVisitor.java @@ -346,6 +346,8 @@ public J visitCase(CaseTree node, Space fmt) { ), Markers.EMPTY ), + null, + null, JContainer.build(sourceBefore(":"), convertStatements(node.getStatements()), Markers.EMPTY), null ); diff --git a/rewrite-java-17/src/main/java/org/openrewrite/java/isolated/ReloadableJava17ParserVisitor.java b/rewrite-java-17/src/main/java/org/openrewrite/java/isolated/ReloadableJava17ParserVisitor.java index 7fbd874ed01..4cfa6f14764 100644 --- a/rewrite-java-17/src/main/java/org/openrewrite/java/isolated/ReloadableJava17ParserVisitor.java +++ b/rewrite-java-17/src/main/java/org/openrewrite/java/isolated/ReloadableJava17ParserVisitor.java @@ -355,6 +355,8 @@ public J visitCase(CaseTree node, Space fmt) { convertAll(node.getExpressions(), commaDelim, t -> EMPTY), Markers.EMPTY ), + null, + null, JContainer.build( sourceBefore(type == J.Case.Type.Rule ? "->" : ":"), convertStatements(node.getStatements()), diff --git a/rewrite-java-21/src/main/java/org/openrewrite/java/isolated/ReloadableJava21ParserVisitor.java b/rewrite-java-21/src/main/java/org/openrewrite/java/isolated/ReloadableJava21ParserVisitor.java index 4a6973da177..0614a13714f 100644 --- a/rewrite-java-21/src/main/java/org/openrewrite/java/isolated/ReloadableJava21ParserVisitor.java +++ b/rewrite-java-21/src/main/java/org/openrewrite/java/isolated/ReloadableJava21ParserVisitor.java @@ -348,13 +348,15 @@ public J visitCase(CaseTree node, Space fmt) { Markers.EMPTY, type, null, + null, JContainer.build( - node.getExpressions().isEmpty() ? EMPTY : sourceBefore("case"), - node.getExpressions().isEmpty() ? + node.getLabels().isEmpty() ? EMPTY : sourceBefore("case"), + node.getLabels().isEmpty() || node.getLabels().getFirst() instanceof DefaultCaseLabelTree ? List.of(JRightPadded.build(new J.Identifier(randomId(), Space.EMPTY, Markers.EMPTY, emptyList(), skip("default"), null, null))) : - convertAll(node.getExpressions(), commaDelim, t -> EMPTY), + convertAll(node.getLabels(), commaDelim, ignored -> node.getGuard() != null ? sourceBefore("when", '-') : EMPTY), Markers.EMPTY ), + convert(node.getGuard()), JContainer.build( sourceBefore(type == J.Case.Type.Rule ? "->" : ":"), convertStatements(node.getStatements()), @@ -779,12 +781,26 @@ public J visitInstanceOf(InstanceOfTree node, Space fmt) { return new J.InstanceOf(randomId(), fmt, Markers.EMPTY, convert(node.getExpression(), t -> sourceBefore("instanceof")), convert(node.getType()), - node.getPattern() instanceof JCBindingPattern b ? - new J.Identifier(randomId(), sourceBefore(b.getVariable().getName().toString()), Markers.EMPTY, emptyList(), b.getVariable().getName().toString(), - type, typeMapping.variableType(b.var.sym)) : null, + getNodePattern(node.getPattern(), type), type); } + private @Nullable J getNodePattern(@Nullable PatternTree pattern, JavaType type) { + if (pattern instanceof JCBindingPattern b) { + return new J.Identifier(randomId(), sourceBefore(b.getVariable().getName().toString()), Markers.EMPTY, emptyList(), b.getVariable().getName().toString(), + type, typeMapping.variableType(b.var.sym)); + } else { + if (pattern == null) { + return null; + } + int saveCursor = cursor; + int endCursor = max(endPos(pattern), cursor); + cursor = endCursor; + return new J.Unknown(randomId(), whitespace(), Markers.EMPTY, new J.Unknown.Source(randomId(), whitespace(), Markers.EMPTY, source.substring(saveCursor, endCursor))); + + } + } + @Override public J visitIntersectionType(IntersectionTypeTree node, Space fmt) { JContainer bounds = node.getBounds().isEmpty() ? null : diff --git a/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8ParserVisitor.java b/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8ParserVisitor.java index 0d6cf8309fc..5d35ffcc46a 100644 --- a/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8ParserVisitor.java +++ b/rewrite-java-8/src/main/java/org/openrewrite/java/ReloadableJava8ParserVisitor.java @@ -343,6 +343,8 @@ public J visitCase(CaseTree node, Space fmt) { ), Markers.EMPTY ), + null, + null, JContainer.build(sourceBefore(":"), convertStatements(node.getStatements()), Markers.EMPTY), null ); @@ -1787,17 +1789,17 @@ private List> convertAll(List tr private Space statementDelim(@Nullable Tree t) { if (t instanceof JCAssert || - t instanceof JCAssign || - t instanceof JCAssignOp || - t instanceof JCBreak || - t instanceof JCContinue || - t instanceof JCDoWhileLoop || - t instanceof JCImport || - t instanceof JCMethodInvocation || - t instanceof JCNewClass || - t instanceof JCReturn || - t instanceof JCThrow || - t instanceof JCUnary) { + t instanceof JCAssign || + t instanceof JCAssignOp || + t instanceof JCBreak || + t instanceof JCContinue || + t instanceof JCDoWhileLoop || + t instanceof JCImport || + t instanceof JCMethodInvocation || + t instanceof JCNewClass || + t instanceof JCReturn || + t instanceof JCThrow || + t instanceof JCUnary) { return sourceBefore(";"); } @@ -1808,7 +1810,7 @@ private Space statementDelim(@Nullable Tree t) { if (t instanceof JCExpressionStatement) { ExpressionTree expTree = ((ExpressionStatementTree) t).getExpression(); if (expTree instanceof ErroneousTree) { - return Space.build(source.substring(((JCTree) expTree).getEndPosition(endPosTable),((JCTree) t).getEndPosition(endPosTable)), Collections.emptyList()); + return Space.build(source.substring(((JCTree) expTree).getEndPosition(endPosTable), ((JCTree) t).getEndPosition(endPosTable)), Collections.emptyList()); } else { return sourceBefore(";"); } @@ -1972,7 +1974,7 @@ private int positionOfNext(String untilDelim, @Nullable Character stop) { char c2 = source.charAt(delimIndex + 1); switch (c1) { case '/': - switch(c2) { + switch (c2) { case '/': inSingleLineComment = true; delimIndex++; @@ -1984,7 +1986,7 @@ private int positionOfNext(String untilDelim, @Nullable Character stop) { } break; case '*': - if(c2 == '/') { + if (c2 == '/') { inMultiLineComment = false; delimIndex++; continue; @@ -2051,7 +2053,7 @@ private List listFlags(long flags) { try { // FIXME instanceof probably not right here... return field.get(null) instanceof Long && - field.getName().matches("[A-Z_]+"); + field.getName().matches("[A-Z_]+"); } catch (IllegalAccessException e) { throw new RuntimeException(e); } diff --git a/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/RecordPatternMatchingTest.java b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/RecordPatternMatchingTest.java new file mode 100644 index 00000000000..6af88fe84f1 --- /dev/null +++ b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/RecordPatternMatchingTest.java @@ -0,0 +1,74 @@ +/* + * Copyright 2025 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.java.tree; + +import org.junit.jupiter.api.Test; +import org.openrewrite.java.MinimumJava21; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; +import org.openrewrite.test.TypeValidation; + +import static org.openrewrite.java.Assertions.java; + +@MinimumJava21 +class RecordPatternMatchingTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.typeValidationOptions(TypeValidation.all().unknown(false)); + } + + @Test + void shouldParseJava21PatternMatchForRecords() { + rewriteRun( + java( + //language=java + """ + record Point(int x, int y) {} + class Test { + void printSum(Object obj) { + if (obj instanceof Point(int x, int y)) { + System.out.println(x+y); + } + } + } + """ + )); + } + + @Test + void shouldParseJava21NestedPatternMatchForRecords() { + rewriteRun( + java( + //language=java + """ + record Point(int x, int y) {} + enum Color { RED, GREEN, BLUE } + record ColoredPoint(Point p, Color c) {} + record Rectangle(ColoredPoint upperLeft, ColoredPoint lowerRight) {} + class Test { + void printColorOfUpperLeftPoint(Rectangle r) { + if (r instanceof Rectangle(ColoredPoint(Point p, Color c), + ColoredPoint lr)) { + System.out.println(c); + } + } + } + """ + )); + } + +} diff --git a/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/SwitchPatternMatchingTest.java b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/SwitchPatternMatchingTest.java new file mode 100644 index 00000000000..30d89070966 --- /dev/null +++ b/rewrite-java-tck/src/main/java/org/openrewrite/java/tree/SwitchPatternMatchingTest.java @@ -0,0 +1,155 @@ +/* + * Copyright 2025 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.java.tree; + +import org.junit.jupiter.api.Test; +import org.openrewrite.java.MinimumJava21; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +@MinimumJava21 +class SwitchPatternMatchingTest implements RewriteTest { + + @Test + void shouldParseJava21PatternSwitch() { + rewriteRun( + java( + //language=java + """ + class Test { + String formatterPatternSwitch(Object obj) { + return switch (obj) { + case Integer i -> String.format("int %d", i); + case Long l -> String.format("long %d", l); + case Double d -> String.format("double %f", d); + case String s -> String.format("String %s", s); + default -> obj.toString(); + }; + } + } + """ + )); + } + + @Test + void shouldSupportParsingNullSwitch() { + rewriteRun( + java( + //language=java + """ + class Test { + void fooBarWithNull(String s) { + switch (s) { + case null -> System.out.println("Oops"); + case "Foo", "Bar" -> System.out.println("Great"); + default -> System.out.println("Ok"); + } + } + } + """ + )); + } + + @Test + void shouldParseJava21EnumSupportInSwitch() { + rewriteRun( + java( + //language=java + """ + enum Coin { HEADS, TAILS } + + class Test { + void switchEnum(Coin c) { + switch (c) { + case HEADS -> System.out.println("Heads"); + case Coin.TAILS -> System.out.println("Tails"); + } + } + } + """ + ) + ); + } + + @Test + void shouldParseJava21ImprovedEnumSupportInSwitch() { + rewriteRun( + java( + //language=java + """ + sealed interface I permits Foo, Bar {} + public enum Foo implements I { A, B } + final class Bar implements I {} + + class Test { + void switchEnumExtendedType(I c) { + switch (c) { + case Foo.A -> System.out.println("It's Foo A"); + case Foo.B -> System.out.println("It's Foo B"); + case Bar b -> System.out.println("It's Bar"); + } + } + } + """ + )); + } + + @Test + void shouldParseJava21SwitchWithRelaxedTypeRestrictions() { + rewriteRun( + java( + //language=java + """ + record Point(int i, int j) {} + enum Color { RED, GREEN, BLUE; } + + class Test { + void typeTester(Object obj) { + switch (obj) { + case null -> System.out.println("null"); + case String s -> System.out.println("String"); + case Color c -> System.out.println("Color: " + c.toString()); + case Point p -> System.out.println("Record class: " + p.toString()); + case int[] ia -> System.out.println("Array of ints of length" + ia.length); + default -> System.out.println("Something else"); + } + } + } + """ + )); + } + + @Test + void shouldParseJava21SwitchWithSpecialCases() { + rewriteRun( + java( + //language=java + """ + class Test { + void integerTester(Integer i) { + switch (i) { + case -1, 1 -> System.out.println("special"); + case Integer j when (j - 1) > -1 -> System.out.println("pos"); + case Integer j -> System.out.println("others"); + } + } + } + """ + )); + } + +} diff --git a/rewrite-java/src/main/java/org/openrewrite/java/Assertions.java b/rewrite-java/src/main/java/org/openrewrite/java/Assertions.java index 1524c72188e..4d2196083ca 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/Assertions.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/Assertions.java @@ -74,13 +74,28 @@ public J.Erroneous visitErroneous(J.Erroneous erroneous, List list) .collect(joining("\n\n"))); } } + if (typeValidation.unknown()) { + List allUnknown = new JavaIsoVisitor>() { + @Override + public J.Unknown visitUnknown(J.Unknown unknown, List list) { + J.Unknown err = super.visitUnknown(unknown, list); + list.add(err); + return err; + } + }.reduce(source, new ArrayList<>()); + if (!allUnknown.isEmpty()) { + throw new IllegalStateException("LST contains erroneous nodes\n" + allUnknown.stream() + .map(unknown -> unknown.getSource().getText()) + .collect(joining("\n\n"))); + } + } } return source; } private static void assertValidTypes(TypeValidation typeValidation, J sf) { if (typeValidation.identifiers() || typeValidation.methodInvocations() || typeValidation.methodDeclarations() || typeValidation.classDeclarations() || - typeValidation.constructorInvocations()) { + typeValidation.constructorInvocations()) { List missingTypeResults = FindMissingTypes.findMissingTypes(sf); missingTypeResults = missingTypeResults.stream() .filter(missingType -> { @@ -108,7 +123,7 @@ private static void assertValidTypes(TypeValidation typeValidation, J sf) { .collect(joining("\n\n")); throw new IllegalStateException( "LST contains missing or invalid type information\n" + missingTypes + - "\nhttps://docs.openrewrite.org/reference/faq#im-seeing-lst-contains-missing-or-invalid-type-information-in-my-recipe-unit-tests-how-to-resolve"); + "\nhttps://docs.openrewrite.org/reference/faq#im-seeing-lst-contains-missing-or-invalid-type-information-in-my-recipe-unit-tests-how-to-resolve"); } } } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/JavaPrinter.java b/rewrite-java/src/main/java/org/openrewrite/java/JavaPrinter.java index 9743bb1abcd..38e6fc9715b 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/JavaPrinter.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/JavaPrinter.java @@ -442,8 +442,8 @@ protected void printStatementTerminator(Statement s, PrintOutputCapture

p) { getCursor() .dropParentUntil( c -> c instanceof Switch || - c instanceof SwitchExpression || - c == Cursor.ROOT_VALUE + c instanceof SwitchExpression || + c == Cursor.ROOT_VALUE ) .getValue(); if (aSwitch instanceof SwitchExpression) { @@ -484,11 +484,15 @@ public J visitBreak(Break breakStatement, PrintOutputCapture

p) { @Override public J visitCase(Case case_, PrintOutputCapture

p) { beforeSyntax(case_, Space.Location.CASE_PREFIX, p); - Expression elem = case_.getExpressions().get(0); + J elem = case_.getCaseLabels().get(0); if (!(elem instanceof Identifier) || !((Identifier) elem).getSimpleName().equals("default")) { p.append("case"); } - visitContainer("", case_.getPadding().getExpressions(), JContainer.Location.CASE_EXPRESSION, ",", "", p); + visitContainer("", case_.getPadding().getCaseLabels(), JContainer.Location.CASE_LABEL, ",", "", p); + if (case_.getGuard() != null) { + p.append("when"); + visit(case_.getGuard(), p); + } visitSpace(case_.getPadding().getStatements().getBefore(), Space.Location.CASE, p); p.append(case_.getType() == Case.Type.Statement ? ":" : "->"); visitStatements(case_.getPadding().getStatements().getPadding() diff --git a/rewrite-java/src/main/java/org/openrewrite/java/JavaVisitor.java b/rewrite-java/src/main/java/org/openrewrite/java/JavaVisitor.java index be5ca459848..8f8e05bb1bd 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/JavaVisitor.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/JavaVisitor.java @@ -423,7 +423,8 @@ public J visitCase(J.Case case_, P p) { } else { c = (J.Case) temp; } - c = c.getPadding().withExpressions(visitContainer(c.getPadding().getExpressions(), JContainer.Location.CASE_EXPRESSION, p)); + c = c.getPadding().withCaseLabels(visitContainer(c.getPadding().getCaseLabels(), JContainer.Location.CASE_LABEL, p)); + c = c.withGuard(visitAndCast(c.getGuard(), p)); c = c.getPadding().withBody(visitRightPadded(c.getPadding().getBody(), JRightPadded.Location.CASE_BODY, p)); c = c.getPadding().withStatements(visitContainer(c.getPadding().getStatements(), JContainer.Location.CASE, p)); return c; @@ -1406,7 +1407,7 @@ public J visitYield(J.Yield yield, P p) { } public @Nullable JContainer visitContainer(@Nullable JContainer container, - JContainer.Location loc, P p) { + JContainer.Location loc, P p) { if (container == null) { //noinspection ConstantConditions return null; diff --git a/rewrite-java/src/main/java/org/openrewrite/java/search/SemanticallyEqual.java b/rewrite-java/src/main/java/org/openrewrite/java/search/SemanticallyEqual.java index 6260ae2ec1a..3618a95f763 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/search/SemanticallyEqual.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/search/SemanticallyEqual.java @@ -366,7 +366,13 @@ public J.Case visitCase(J.Case _case, J j) { J.Case compareTo = (J.Case) j; this.visitList(_case.getStatements(), compareTo.getStatements()); visit(_case.getBody(), compareTo.getBody()); - this.visitList(_case.getExpressions(), compareTo.getExpressions()); + this.visitList(_case.getCaseLabels(), compareTo.getCaseLabels()); + if (_case.getGuard() != null && compareTo.getGuard() != null) { + visit(_case.getGuard(), compareTo.getGuard()); + } else if (nullMissMatch(_case.getGuard(), compareTo.getGuard())) { + isEqual.set(false); + return _case; + } } return _case; } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/tree/J.java b/rewrite-java/src/main/java/org/openrewrite/java/tree/J.java index 3c6f581bb8a..592e839a3e3 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/tree/J.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/tree/J.java @@ -1027,14 +1027,36 @@ public Case withPattern(@Nullable Expression pattern) { return withExpressions(ListUtils.mapFirst(getExpressions(), first -> pattern)); } - JContainer expressions; - + /** + * @deprecated As of Java 21 this is referred to as case labels and can be broader than just Expressions. + * Use {@link #getCaseLabels} and {@link #withCaseLabels(List)} instead. + */ + @Deprecated public List getExpressions() { - return expressions.getElements(); + return caseLabels.getElements().stream().filter(Expression.class::isInstance).map(Expression.class::cast).collect(toList()); } + /** + * @deprecated As of Java 21 this is referred to as case labels and can be broader than just Expressions. + * Use {@link #getCaseLabels} and {@link #withCaseLabels(List)} instead. + */ public Case withExpressions(List expressions) { - return getPadding().withExpressions(requireNonNull(JContainer.withElementsNullable(this.expressions, expressions))); + if (caseLabels.getElements().stream().allMatch(Expression.class::isInstance)) { + //noinspection unchecked + return getPadding().withCaseLabels(requireNonNull(JContainer.withElementsNullable(this.caseLabels, (List) (List) expressions))); + } else { + throw new IllegalStateException("caseLabels contains an entry that is not an Expression, use withCaseLabels instead."); + } + } + + JContainer caseLabels; + + public List getCaseLabels() { + return caseLabels.getElements(); + } + + public Case withCaseLabels(List caseLabels) { + return getPadding().withCaseLabels(requireNonNull(JContainer.withElementsNullable(this.caseLabels, caseLabels))); } /** @@ -1067,17 +1089,27 @@ public Case withBody(J body) { return getPadding().withBody(JRightPadded.withElement(this.body, body)); } + @Nullable + @Getter + @With + Expression guard; + @JsonCreator - public Case(UUID id, Space prefix, Markers markers, Type type, @Deprecated @Nullable Expression pattern, JContainer expressions, JContainer statements, @Nullable JRightPadded body) { + public Case(UUID id, Space prefix, Markers markers, Type type, @Deprecated @Nullable Expression pattern, @Nullable JContainer expressions, @Nullable JContainer caseLabels, @Nullable Expression guard, JContainer statements, @Nullable JRightPadded body) { this.id = id; this.prefix = prefix; this.markers = markers; this.type = type; if (pattern != null) { - this.expressions = requireNonNull(JContainer.withElementsNullable(null, singletonList(pattern))); + this.caseLabels = requireNonNull(JContainer.withElementsNullable(null, singletonList(pattern))); + } else if (expressions != null) { + this.caseLabels = JContainer.build(expressions.getBefore(), expressions.getElements().stream().map(J.class::cast).map(JRightPadded::build).collect(toList()), expressions.getMarkers()); + } else if (caseLabels != null) { + this.caseLabels = caseLabels; } else { - this.expressions = expressions; + this.caseLabels = JContainer.empty(); } + this.guard = guard; this.statements = statements; this.body = body; } @@ -1127,7 +1159,7 @@ public static class Padding { } public Case withBody(@Nullable JRightPadded body) { - return t.body == body ? t : new Case(t.id, t.prefix, t.markers, t.type, null, t.expressions, t.statements, body); + return t.body == body ? t : new Case(t.id, t.prefix, t.markers, t.type, null, null, t.caseLabels, t.guard, t.statements, body); } public JContainer getStatements() { @@ -1135,15 +1167,38 @@ public JContainer getStatements() { } public Case withStatements(JContainer statements) { - return t.statements == statements ? t : new Case(t.id, t.prefix, t.markers, t.type, null, t.expressions, statements, t.body); + return t.statements == statements ? t : new Case(t.id, t.prefix, t.markers, t.type, null, null, t.caseLabels, t.guard, statements, t.body); } + /** + * @deprecated As of Java 21 this is referred to as case labels and can be broader than just Expressions. + * Use {@link #getCaseLabels} and {@link #withCaseLabels(JContainer)} instead. + */ + @Deprecated public JContainer getExpressions() { - return t.expressions; + return JContainer.build(t.caseLabels.getBefore(), t.caseLabels.getElements().stream().filter(Expression.class::isInstance).map(Expression.class::cast).map(JRightPadded::build).collect(toList()), t.caseLabels.getMarkers()); } + /** + * @deprecated As of Java 21 this is referred to as case labels and can be broader than just Expressions. + * Use {@link #getCaseLabels} and {@link #withCaseLabels(JContainer)} instead. + */ + @Deprecated public Case withExpressions(JContainer expressions) { - return t.expressions == expressions ? t : new Case(t.id, t.prefix, t.markers, t.type, null, expressions, t.statements, t.body); + if (t.getExpressions() == expressions) { + return t; + } else if (t.caseLabels.getElements().stream().allMatch(Expression.class::isInstance)) { + return new Case(t.id, t.prefix, t.markers, t.type, null, expressions, null, t.guard, t.statements, t.body); + } + throw new IllegalStateException("caseLabels contains an entry that is not an Expression, use withCaseLabels instead."); + } + + public JContainer getCaseLabels() { + return t.caseLabels; + } + + public Case withCaseLabels(JContainer caseLabels) { + return t.caseLabels == caseLabels ? t : new Case(t.id, t.prefix, t.markers, t.type, null, null, caseLabels, t.guard, t.statements, t.body); } } } diff --git a/rewrite-java/src/main/java/org/openrewrite/java/tree/JContainer.java b/rewrite-java/src/main/java/org/openrewrite/java/tree/JContainer.java index a299f98da67..c03505a05d2 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/tree/JContainer.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/tree/JContainer.java @@ -102,6 +102,7 @@ public enum Location { ANNOTATION_ARGUMENTS(Space.Location.ANNOTATION_ARGUMENTS, JRightPadded.Location.ANNOTATION_ARGUMENT), CASE(Space.Location.CASE, JRightPadded.Location.CASE), CASE_EXPRESSION(Space.Location.CASE_EXPRESSION, JRightPadded.Location.CASE_EXPRESSION), + CASE_LABEL(Space.Location.CASE_LABEL, JRightPadded.Location.CASE_LABEL), IMPLEMENTS(Space.Location.IMPLEMENTS, JRightPadded.Location.IMPLEMENTS), PERMITS(Space.Location.PERMITS, JRightPadded.Location.PERMITS), LANGUAGE_EXTENSION(Space.Location.LANGUAGE_EXTENSION, JRightPadded.Location.LANGUAGE_EXTENSION), diff --git a/rewrite-java/src/main/java/org/openrewrite/java/tree/JRightPadded.java b/rewrite-java/src/main/java/org/openrewrite/java/tree/JRightPadded.java index 78c65a04a14..b90a9abc19d 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/tree/JRightPadded.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/tree/JRightPadded.java @@ -47,6 +47,7 @@ public enum Location { BLOCK_STATEMENT(Space.Location.BLOCK_STATEMENT_SUFFIX), CASE(Space.Location.CASE_SUFFIX), CASE_EXPRESSION(Space.Location.CASE_EXPRESSION), + CASE_LABEL(Space.Location.CASE_LABEL), CASE_BODY(Space.Location.CASE_BODY), CATCH_ALTERNATIVE(Space.Location.CATCH_ALTERNATIVE_SUFFIX), DIMENSION(Space.Location.DIMENSION_SUFFIX), diff --git a/rewrite-java/src/main/java/org/openrewrite/java/tree/Space.java b/rewrite-java/src/main/java/org/openrewrite/java/tree/Space.java index a334eafa601..a18deff4ce0 100644 --- a/rewrite-java/src/main/java/org/openrewrite/java/tree/Space.java +++ b/rewrite-java/src/main/java/org/openrewrite/java/tree/Space.java @@ -295,8 +295,8 @@ public String toString() { String whitespaces = printedWs.toString(); return "Space(" + - "comments=<" + (comments.size() == 1 ? "1 comment" : comments.size() + " comments") + ">, " + - "whitespace=" + (whitespaces.isEmpty() ? "" : "'" + whitespaces + "'") + ")"; + "comments=<" + (comments.size() == 1 ? "1 comment" : comments.size() + " comments") + ">, " + + "whitespace=" + (whitespaces.isEmpty() ? "" : "'" + whitespaces + "'") + ")"; } public enum Location { @@ -325,6 +325,7 @@ public enum Location { CASE, CASE_BODY, CASE_EXPRESSION, + CASE_LABEL, CASE_PREFIX, CASE_SUFFIX, CATCH_ALTERNATIVE_SUFFIX, diff --git a/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java b/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java index e395db403da..81bbc478a61 100644 --- a/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java +++ b/rewrite-test/src/main/java/org/openrewrite/test/TypeValidation.java @@ -103,6 +103,12 @@ public class TypeValidation { @Builder.Default private boolean erroneous = true; + /** + * Controls whether the LST is validated not to contain any `J.Unknown` elements. + */ + @Builder.Default + private boolean unknown = true; + /** * Adding messages to execution context is a side effect which makes the recipe run itself stateful. * Potentially allows recipes to interfere with each other in surprising and hard to debug ways. @@ -122,7 +128,7 @@ public static TypeValidation all() { * Skip all invariant validation checks. */ public static TypeValidation none() { - return new TypeValidation(false, false, false, false, false, false, false, false, o -> false, false, false); + return new TypeValidation(false, false, false, false, false, false, false, false, o -> false, false, false, false); } static TypeValidation before(RecipeSpec testMethodSpec, RecipeSpec testClassSpec) { From 1d9685808c9fbad430c9e85c5df69c2b9d12fc89 Mon Sep 17 00:00:00 2001 From: Tim te Beek Date: Fri, 17 Jan 2025 14:33:25 +0100 Subject: [PATCH 014/173] Pull up recipes from rewrite-migrate-java (#4918) * Pull up recipes from rewrite-migrate-java * Also pull up `UpdateMavenProjectPropertyJavaVersion` * Apply formatter --- .../ChangeMethodInvocationReturnType.java | 116 ++++ .../java/ReplaceStringLiteralValue.java | 76 +++ .../ChangeMethodInvocationReturnTypeTest.java | 124 ++++ .../java/ReplaceStringLiteralValueTest.java | 64 ++ ...UpdateMavenProjectPropertyJavaVersion.java | 142 +++++ ...venCompilerPluginReleaseConfiguration.java | 116 ++++ ...teMavenProjectPropertyJavaVersionTest.java | 316 ++++++++++ ...ompilerPluginReleaseConfigurationTest.java | 561 ++++++++++++++++++ 8 files changed, 1515 insertions(+) create mode 100644 rewrite-java/src/main/java/org/openrewrite/java/ChangeMethodInvocationReturnType.java create mode 100644 rewrite-java/src/main/java/org/openrewrite/java/ReplaceStringLiteralValue.java create mode 100644 rewrite-java/src/test/java/org/openrewrite/java/ChangeMethodInvocationReturnTypeTest.java create mode 100644 rewrite-java/src/test/java/org/openrewrite/java/ReplaceStringLiteralValueTest.java create mode 100644 rewrite-maven/src/main/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersion.java create mode 100644 rewrite-maven/src/main/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfiguration.java create mode 100644 rewrite-maven/src/test/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersionTest.java create mode 100644 rewrite-maven/src/test/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfigurationTest.java diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ChangeMethodInvocationReturnType.java b/rewrite-java/src/main/java/org/openrewrite/java/ChangeMethodInvocationReturnType.java new file mode 100644 index 00000000000..6cf60bfc3e8 --- /dev/null +++ b/rewrite-java/src/main/java/org/openrewrite/java/ChangeMethodInvocationReturnType.java @@ -0,0 +1,116 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.java; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.ListUtils; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; +import org.openrewrite.java.tree.TypeUtils; +import org.openrewrite.marker.Markers; + +import static java.util.Collections.emptyList; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ChangeMethodInvocationReturnType extends Recipe { + + @Option(displayName = "Method pattern", + description = "A method pattern that is used to find matching method declarations/invocations.", + example = "org.mockito.Matchers anyVararg()") + String methodPattern; + + @Option(displayName = "New method invocation return type", + description = "The fully qualified new return type of method invocation.", + example = "long") + String newReturnType; + + @Override + public String getDisplayName() { + return "Change method invocation return type"; + } + + @Override + public String getDescription() { + return "Changes the return type of a method invocation."; + } + + @Override + public TreeVisitor getVisitor() { + return new JavaIsoVisitor() { + private final MethodMatcher methodMatcher = new MethodMatcher(methodPattern, false); + + private boolean methodUpdated; + + @Override + public J.MethodInvocation visitMethodInvocation(J.MethodInvocation method, ExecutionContext ctx) { + J.MethodInvocation m = super.visitMethodInvocation(method, ctx); + JavaType.Method type = m.getMethodType(); + if (methodMatcher.matches(method) && type != null && !newReturnType.equals(type.getReturnType().toString())) { + type = type.withReturnType(JavaType.buildType(newReturnType)); + m = m.withMethodType(type); + if (m.getName().getType() != null) { + m = m.withName(m.getName().withType(type)); + } + methodUpdated = true; + } + return m; + } + + @Override + public J.VariableDeclarations visitVariableDeclarations(J.VariableDeclarations multiVariable, ExecutionContext ctx) { + methodUpdated = false; + JavaType.FullyQualified originalType = multiVariable.getTypeAsFullyQualified(); + J.VariableDeclarations mv = super.visitVariableDeclarations(multiVariable, ctx); + + if (methodUpdated) { + JavaType newType = JavaType.buildType(newReturnType); + JavaType.FullyQualified newFieldType = TypeUtils.asFullyQualified(newType); + + maybeAddImport(newFieldType); + maybeRemoveImport(originalType); + + mv = mv.withTypeExpression(mv.getTypeExpression() == null ? + null : + new J.Identifier(mv.getTypeExpression().getId(), + mv.getTypeExpression().getPrefix(), + Markers.EMPTY, + emptyList(), + newReturnType.substring(newReturnType.lastIndexOf('.') + 1), + newType, + null + ) + ); + + mv = mv.withVariables(ListUtils.map(mv.getVariables(), var -> { + JavaType.FullyQualified varType = TypeUtils.asFullyQualified(var.getType()); + if (varType != null && !varType.equals(newType)) { + return var.withType(newType).withName(var.getName().withType(newType)); + } + return var; + })); + } + + return mv; + } + }; + } +} diff --git a/rewrite-java/src/main/java/org/openrewrite/java/ReplaceStringLiteralValue.java b/rewrite-java/src/main/java/org/openrewrite/java/ReplaceStringLiteralValue.java new file mode 100644 index 00000000000..64bea17ed38 --- /dev/null +++ b/rewrite-java/src/main/java/org/openrewrite/java/ReplaceStringLiteralValue.java @@ -0,0 +1,76 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.java; + +import com.fasterxml.jackson.annotation.JsonCreator; +import com.fasterxml.jackson.annotation.JsonProperty; +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.java.tree.J; +import org.openrewrite.java.tree.JavaType; + +@Value +@EqualsAndHashCode(callSuper = false) +public class ReplaceStringLiteralValue extends Recipe { + + @Option(displayName = "Old literal `String` value", + description = "The `String` value to replace.", + example = "apple") + String oldLiteralValue; + + @Option(displayName = "New literal `String` value", + description = "The `String` value to replace with.", + example = "orange") + String newLiteralValue; + + @JsonCreator + public ReplaceStringLiteralValue(@JsonProperty("oldStringValue") String oldStringValue, @JsonProperty("newStringValue") String newStringValue) { + this.oldLiteralValue = oldStringValue; + this.newLiteralValue = newStringValue; + } + + @Override + public String getDisplayName() { + return "Replace `String` literal"; + } + + @Override + public String getDescription() { + return "Replace the value of a complete `String` literal."; + } + + @Override + public TreeVisitor getVisitor() { + return new JavaIsoVisitor() { + @Override + public J.Literal visitLiteral(J.Literal literal, ExecutionContext ctx) { + J.Literal lit = super.visitLiteral(literal, ctx); + if (lit.getType() == JavaType.Primitive.String && + oldLiteralValue.equals(lit.getValue())) { + return lit + .withValue(newLiteralValue) + .withValueSource('"' + newLiteralValue + '"'); + } + return lit; + } + }; + } + +} diff --git a/rewrite-java/src/test/java/org/openrewrite/java/ChangeMethodInvocationReturnTypeTest.java b/rewrite-java/src/test/java/org/openrewrite/java/ChangeMethodInvocationReturnTypeTest.java new file mode 100644 index 00000000000..339e1777c28 --- /dev/null +++ b/rewrite-java/src/test/java/org/openrewrite/java/ChangeMethodInvocationReturnTypeTest.java @@ -0,0 +1,124 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.java; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class ChangeMethodInvocationReturnTypeTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new ChangeMethodInvocationReturnType("java.lang.Integer parseInt(String)", "long")); + } + + @Test + @DocumentExample + void replaceVariableAssignment() { + rewriteRun( + //language=java + java( + """ + class Foo { + void bar() { + int one = Integer.parseInt("1"); + } + } + """, + """ + class Foo { + void bar() { + long one = Integer.parseInt("1"); + } + } + """ + ) + ); + } + + @Test + void shouldOnlyChangeTargetMethodAssignments() { + rewriteRun( + //language=java + java( + """ + class Foo { + void bar() { + int zero = Integer.valueOf("0"); + int one = Integer.parseInt("1"); + int two = Integer.valueOf("2"); + } + } + """, + """ + class Foo { + void bar() { + int zero = Integer.valueOf("0"); + long one = Integer.parseInt("1"); + int two = Integer.valueOf("2"); + } + } + """ + ) + ); + } + + @Test + void replaceVariableAssignmentFullyQualified() { + rewriteRun( + spec -> spec.recipe(new ChangeMethodInvocationReturnType("bar.Bar bar()", "java.math.BigInteger")) + .parser(JavaParser.fromJavaVersion() + //language=java + .dependsOn( + """ + package bar; + public class Bar { + public static Integer bar() { + return null; + } + } + """ + ) + ), + //language=java + java( + """ + import bar.Bar; + class Foo { + void foo() { + Integer one = Bar.bar(); + } + } + """, + """ + import bar.Bar; + + import java.math.BigInteger; + + class Foo { + void foo() { + BigInteger one = Bar.bar(); + } + } + """ + ) + ); + } +} diff --git a/rewrite-java/src/test/java/org/openrewrite/java/ReplaceStringLiteralValueTest.java b/rewrite-java/src/test/java/org/openrewrite/java/ReplaceStringLiteralValueTest.java new file mode 100644 index 00000000000..e40fd0f9f93 --- /dev/null +++ b/rewrite-java/src/test/java/org/openrewrite/java/ReplaceStringLiteralValueTest.java @@ -0,0 +1,64 @@ +/* + * Copyright 2025 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.java; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.java; + +class ReplaceStringLiteralValueTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new ReplaceStringLiteralValue("apple", "orange")); + } + + @DocumentExample + @Test + void replaceAppleWithOrange() { + rewriteRun( + java( + """ + class Test { + String s = "apple"; + } + """, + """ + class Test { + String s = "orange"; + } + """ + ) + ); + } + @Test + void doNotReplacePineapply() { + rewriteRun( + java( + """ + class Test { + // We only match the full String literal value + String s = "pineapple"; + } + """ + ) + ); + } + +} diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersion.java b/rewrite-maven/src/main/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersion.java new file mode 100644 index 00000000000..405ffbb4645 --- /dev/null +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersion.java @@ -0,0 +1,142 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.maven; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.xml.XPathMatcher; +import org.openrewrite.xml.tree.Xml; + +import java.util.Arrays; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + +@Value +@EqualsAndHashCode(callSuper = false) +public class UpdateMavenProjectPropertyJavaVersion extends Recipe { + + private static final List JAVA_VERSION_PROPERTIES = Arrays.asList( + "java.version", + "jdk.version", + "javaVersion", + "jdkVersion", + "maven.compiler.source", + "maven.compiler.target", + "maven.compiler.release", + "release.version"); + + private static final List JAVA_VERSION_XPATH_MATCHERS = + JAVA_VERSION_PROPERTIES.stream() + .map(property -> "/project/properties/" + property) + .map(XPathMatcher::new).collect(Collectors.toList()); + + private static final XPathMatcher PLUGINS_MATCHER = new XPathMatcher("/project/build//plugins"); + + @Option(displayName = "Java version", + description = "The Java version to upgrade to.", + example = "11") + Integer version; + + @Override + public String getDisplayName() { + return "Update Maven Java project properties"; + } + + @Override + public String getDescription() { + //language=markdown + return "The Java version is determined by several project properties, including:\n\n" + + " * `java.version`\n" + + " * `jdk.version`\n" + + " * `javaVersion`\n" + + " * `jdkVersion`\n" + + " * `maven.compiler.source`\n" + + " * `maven.compiler.target`\n" + + " * `maven.compiler.release`\n" + + " * `release.version`\n\n" + + "If none of these properties are in use and the maven compiler plugin is not otherwise configured, adds the `maven.compiler.release` property."; + } + + @Override + public TreeVisitor getVisitor() { + return new MavenIsoVisitor() { + boolean compilerPluginConfiguredExplicitly; + + @Override + public Xml.Document visitDocument(Xml.Document document, ExecutionContext ctx) { + // Update properties already defined in the current pom + Xml.Document d = super.visitDocument(document, ctx); + + // Return early if the parent appears to be within the current repository, as properties defined there will be updated + if (getResolutionResult().parentPomIsProjectPom()) { + return d; + } + + // Otherwise override remote parent's properties locally + Map currentProperties = getResolutionResult().getPom().getProperties(); + boolean foundProperty = false; + for (String property : JAVA_VERSION_PROPERTIES) { + String propertyValue = currentProperties.get(property); + if (propertyValue != null) { + foundProperty = true; + try { + if (Float.parseFloat(propertyValue) < version) { + d = (Xml.Document) new AddProperty(property, String.valueOf(version), null, false) + .getVisitor() + .visitNonNull(d, ctx); + maybeUpdateModel(); + } + } catch (NumberFormatException ex) { + // either an expression or something else, don't touch + } + } + } + + // When none of the relevant properties are explicitly configured Maven defaults to Java 8 + // The release option was added in 9 + // If no properties have yet been updated then set release explicitly + if (!foundProperty && version >= 9 && !compilerPluginConfiguredExplicitly) { + d = (Xml.Document) new AddProperty("maven.compiler.release", String.valueOf(version), null, false) + .getVisitor() + .visitNonNull(d, ctx); + maybeUpdateModel(); + } + + return d; + } + + @Override + public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { + Xml.Tag t = super.visitTag(tag, ctx); + if (isPluginTag("org.apache.maven.plugins", "maven-compiler-plugin")) { + t.getChild("configuration").ifPresent(compilerPluginConfig -> { + if (compilerPluginConfig.getChildValue("source").isPresent() || + compilerPluginConfig.getChildValue("target").isPresent() || + compilerPluginConfig.getChildValue("release").isPresent()) { + compilerPluginConfiguredExplicitly = true; + } + }); + } + return t; + } + }; + } +} diff --git a/rewrite-maven/src/main/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfiguration.java b/rewrite-maven/src/main/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfiguration.java new file mode 100644 index 00000000000..c126accf448 --- /dev/null +++ b/rewrite-maven/src/main/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfiguration.java @@ -0,0 +1,116 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.maven; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.maven.tree.MavenResolutionResult; +import org.openrewrite.xml.XPathMatcher; +import org.openrewrite.xml.tree.Xml; + +import java.util.Optional; + +import static org.openrewrite.xml.AddOrUpdateChild.addOrUpdateChild; +import static org.openrewrite.xml.FilterTagChildrenVisitor.filterTagChildren; + +@Value +@EqualsAndHashCode(callSuper = false) +public class UseMavenCompilerPluginReleaseConfiguration extends Recipe { + private static final XPathMatcher PLUGINS_MATCHER = new XPathMatcher("/project/build//plugins"); + + @Option( + displayName = "Release version", + description = "The new value for the release configuration. This recipe prefers ${java.version} if defined.", + example = "11" + ) + Integer releaseVersion; + + @Override + public String getDisplayName() { + return "Use Maven compiler plugin release configuration"; + } + + @Override + public String getDescription() { + return "Replaces any explicit `source` or `target` configuration (if present) on the `maven-compiler-plugin` with " + + "`release`, and updates the `release` value if needed. Will not downgrade the Java version if the current version is higher."; + } + + @Override + public TreeVisitor getVisitor() { + return new MavenIsoVisitor() { + @Override + public Xml.Tag visitTag(Xml.Tag tag, ExecutionContext ctx) { + Xml.Tag t = super.visitTag(tag, ctx); + if (!PLUGINS_MATCHER.matches(getCursor())) { + return t; + } + Optional maybeCompilerPlugin = t.getChildren().stream() + .filter(plugin -> + "plugin".equals(plugin.getName()) && + "org.apache.maven.plugins".equals(plugin.getChildValue("groupId").orElse("org.apache.maven.plugins")) && + "maven-compiler-plugin".equals(plugin.getChildValue("artifactId").orElse(null))) + .findAny(); + Optional maybeCompilerPluginConfig = maybeCompilerPlugin + .flatMap(it -> it.getChild("configuration")); + if (!maybeCompilerPluginConfig.isPresent()) { + return t; + } + Xml.Tag compilerPluginConfig = maybeCompilerPluginConfig.get(); + Optional source = compilerPluginConfig.getChildValue("source"); + Optional target = compilerPluginConfig.getChildValue("target"); + Optional release = compilerPluginConfig.getChildValue("release"); + if (!source.isPresent() && + !target.isPresent() && + !release.isPresent() || + currentNewerThanProposed(release)) { + return t; + } + Xml.Tag updated = filterTagChildren(t, compilerPluginConfig, + child -> !("source".equals(child.getName()) || "target".equals(child.getName()))); + String releaseVersionValue = hasJavaVersionProperty(getCursor().firstEnclosingOrThrow(Xml.Document.class)) ? + "${java.version}" : releaseVersion.toString(); + updated = addOrUpdateChild(updated, compilerPluginConfig, + Xml.Tag.build("" + releaseVersionValue + ""), getCursor().getParentOrThrow()); + return updated; + } + + }; + } + + private boolean currentNewerThanProposed(@SuppressWarnings("OptionalUsedAsFieldOrParameterType") Optional maybeRelease) { + if (!maybeRelease.isPresent()) { + return false; + } + try { + float currentVersion = Float.parseFloat(maybeRelease.get()); + float proposedVersion = Float.parseFloat(releaseVersion.toString()); + return proposedVersion < currentVersion; + } catch (NumberFormatException e) { + return false; + } + } + + private boolean hasJavaVersionProperty(Xml.Document xml) { + return xml.getMarkers().findFirst(MavenResolutionResult.class) + .map(r -> r.getPom().getProperties().get("java.version") != null) + .orElse(false); + } +} diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersionTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersionTest.java new file mode 100644 index 00000000000..6fc6a2fca0b --- /dev/null +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/UpdateMavenProjectPropertyJavaVersionTest.java @@ -0,0 +1,316 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.maven; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.Issue; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.mavenProject; +import static org.openrewrite.maven.Assertions.pomXml; + +@Deprecated(forRemoval = true) +class UpdateMavenProjectPropertyJavaVersionTest implements RewriteTest { + + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new UpdateMavenProjectPropertyJavaVersion(17)); + } + + @DocumentExample + @Test + void basic() { + rewriteRun( + //language=xml + pomXml( + """ + + com.example + foo + 1.0.0 + 4.0 + + 11 + 11 + 11 + 11 + 11 + 11 + 11 + 11 + + + """, + """ + + com.example + foo + 1.0.0 + 4.0 + + 17 + 17 + 17 + 17 + 17 + 17 + 17 + 17 + + + """ + ) + ); + } + + @Test + void basicWithVariables() { + rewriteRun( + //language=xml + pomXml( + """ + + com.example + foo + 1.0.0 + 4.0 + + ${release.version} + 11 + ${release.version} + ${jdk.version} + ${maven.compiler.release} + ${maven.compiler.release} + 11 + 11 + + + """, + """ + + com.example + foo + 1.0.0 + 4.0 + + ${release.version} + 17 + ${release.version} + ${jdk.version} + ${maven.compiler.release} + ${maven.compiler.release} + 17 + 17 + + + """) + ); + } + + @Test + void updateLocalParent() { + rewriteRun( + //language=xml + pomXml( + """ + + com.example + example-parent + 1.0.0 + 4.0 + + 11 + 11 + 11 + 11 + 11 + 11 + 11 + 11 + + + """, + """ + + com.example + example-parent + 1.0.0 + 4.0 + + 17 + 17 + 17 + 17 + 17 + 17 + 17 + 17 + + + """), + mavenProject("example-child", + //language=xml + pomXml( + """ + + + com.example + example-parent + 1.0.0 + + com.example + example-child + 1.0.0 + 4.0 + + """ + ) + ) + ); + } + + @Test + void doNothingForExplicitPluginConfiguration() { + // Use UseMavenCompilerPluginReleaseConfiguration for this case + rewriteRun( + //language=xml + pomXml( + """ + + com.example + example-child + 1.0.0 + 4.0 + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + 11 + 11 + + + + + + """ + ) + ); + } + + @Test + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/514") + void addReleaseIfNoOtherChangeIsMade() { + rewriteRun( + //language=xml + pomXml( + """ + + com.example + example-child + 1.0.0 + 4.0 + + """, + """ + + com.example + example-child + 1.0.0 + 4.0 + + 17 + + + """ + ) + ); + } + + @Test + void springBoot3ParentToJava17() { + // Spring Boot Starter Parent already enforces Java 17 + rewriteRun( + pomXml( + //language=xml + """ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.3 + + + + com.mycompany.app + my-app + 1 + + """ + ) + ); + } + + @Test + void springBoot3ParentToJava21() { + rewriteRun( + spec -> spec.recipe(new UpdateMavenProjectPropertyJavaVersion(21)), + pomXml( + //language=xml + """ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.3 + + + + com.mycompany.app + my-app + 1 + + """, + //language=xml + """ + + 4.0.0 + + org.springframework.boot + spring-boot-starter-parent + 3.3.3 + + + + com.mycompany.app + my-app + 1 + + 21 + + + """ + ) + ); + } +} diff --git a/rewrite-maven/src/test/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfigurationTest.java b/rewrite-maven/src/test/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfigurationTest.java new file mode 100644 index 00000000000..ce23a97daa5 --- /dev/null +++ b/rewrite-maven/src/test/java/org/openrewrite/maven/UseMavenCompilerPluginReleaseConfigurationTest.java @@ -0,0 +1,561 @@ +/* + * Copyright 2024 the original author or authors. + *

+ * Licensed under the Moderne Source Available License (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + *

+ * https://docs.moderne.io/licensing/moderne-source-available-license + *

+ * 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.maven; + +import org.junit.jupiter.api.Test; +import org.openrewrite.DocumentExample; +import org.openrewrite.Issue; +import org.openrewrite.test.RecipeSpec; +import org.openrewrite.test.RewriteTest; + +import static org.openrewrite.java.Assertions.mavenProject; +import static org.openrewrite.maven.Assertions.pomXml; + +class UseMavenCompilerPluginReleaseConfigurationTest implements RewriteTest { + @Override + public void defaults(RecipeSpec spec) { + spec.recipe(new UseMavenCompilerPluginReleaseConfiguration(11)); + } + + @DocumentExample + @Test + void replacesSourceAndTargetConfig() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 1.8 + 1.8 + + + + + + + """, + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + + + + + + + """ + ) + ); + } + + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/514") + @Test + void replaceSourceAndTargetConfigIfDefault() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + true + ${maven.compiler.source} + ${maven.compiler.target} + + + + + + + """, + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + true + 11 + + + + + + + """ + ) + ); + } + + @Test + void reusesJavaVersionVariableIfAvailable() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + 11 + + + + + + maven-compiler-plugin + 3.8.0 + + ${java.version} + ${java.version} + + + + + + + """, + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + 11 + + + + + + maven-compiler-plugin + 3.8.0 + + ${java.version} + + + + + + + """ + ) + ); + } + + @Test + void upgradesExistingReleaseConfig() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 10 + + + + + + + """, + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + + + + + + + """ + ) + ); + } + + @Test + void prefersJavaVersionIfAvailable() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + 11 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 10 + + + + + + + """, + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + 11 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + ${java.version} + + + + + + + """ + ) + ); + } + + @Test + void notMisledByUnrelatedProperty() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + 11 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 10 + ${foobar} + + + + + + + """, + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + 11 + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 11 + ${foobar} + + + + + + + """ + ) + ); + } + + @Issue("https://github.com/openrewrite/rewrite-migrate-java/issues/169") + @Test + void noVersionDowngrade() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + sample + 1.0.0 + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.8.0 + + 17 + + + + + + + """) + ); + } + + @Test + void reusesJavaVersionVariableIfDefinedInParentPom() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + parent + 1.0.0 + + + 11 + + + pom + + """), + mavenProject( + "sample", + //language=xml + pomXml(""" + + + 4.0.0 + + + org.sample + parent + 1.0.0 + + + sample + 1.0.0 + + + + + maven-compiler-plugin + 3.8.0 + + ${java.version} + ${java.version} + + + + + + """, + """ + + + 4.0.0 + + + org.sample + parent + 1.0.0 + + + sample + 1.0.0 + + + + + maven-compiler-plugin + 3.8.0 + + ${java.version} + + + + + + """ + ) + ) + ); + } + + @Test + void pluginManagement() { + rewriteRun( + //language=xml + pomXml( + """ + + + 4.0.0 + org.sample + parent + 1.0.0 + + + + + maven-compiler-plugin + 3.8.0 + + 8 + + + + + + + """, + """ + + + 4.0.0 + org.sample + parent + 1.0.0 + + + + + maven-compiler-plugin + 3.8.0 + + 11 + + + + + + + """ + ) + ); + } +} From afa160e7e7dd6a066a4b84d04764bdc7bcef1a0a Mon Sep 17 00:00:00 2001 From: Greg Oledzki Date: Fri, 17 Jan 2025 17:10:55 +0100 Subject: [PATCH 015/173] Autodetect formatting style of JSON code (#4916) * feat: recipe for adding a key value pair to a json * Slight polish * Slight polish * Strive for better formatting after insertion * Improve some existing cases already * Update test as suggested * Refactoring, extract normalizeNewLines() * Autoformat visitor for JSON * Removing @NotNull annotations * Basic tests for Autodetect * Basic tests for NormalizeLineBreaksVisitor * No public classifier Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Copy&paste typo Co-authored-by: Knut Wannheden * Copy&paste typo Co-authored-by: Knut Wannheden * Rename FindLineFormatJsonVisitor * Adding package-info.java files * Parsing the value parameter to JSON * Fixed description * Removing unneeded unQuote method --------- Co-authored-by: dpozinen Co-authored-by: Tim te Beek Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Knut Wannheden --- .../org/openrewrite/json/AddKeyValue.java | 135 ++++++++++ .../org/openrewrite/json/JsonVisitor.java | 30 +++ .../json/format/AutoFormatVisitor.java | 93 +++++++ .../org/openrewrite/json/format/Indents.java | 57 +++++ .../format/NormalizeLineBreaksVisitor.java | 60 +++++ .../json/format/TabsAndIndentsVisitor.java | 89 +++++++ .../openrewrite/json/format/package-info.java | 21 ++ .../openrewrite/json/style/Autodetect.java | 237 ++++++++++++++++++ .../org/openrewrite/json/style/JsonStyle.java | 21 ++ .../json/style/TabsAndIndentsStyle.java | 55 ++++ .../openrewrite/json/style/package-info.java | 21 ++ .../json/tree/JsonRightPadded.java | 22 +- .../org/openrewrite/json/AddKeyValueTest.java | 170 +++++++++++++ .../NormalizeLineBreaksVisitorTest.java | 92 +++++++ .../json/style/AutodetectTest.java | 102 ++++++++ 15 files changed, 1199 insertions(+), 6 deletions(-) create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/AddKeyValue.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/format/AutoFormatVisitor.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/format/Indents.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/format/NormalizeLineBreaksVisitor.java create mode 100755 rewrite-json/src/main/java/org/openrewrite/json/format/TabsAndIndentsVisitor.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/format/package-info.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/style/Autodetect.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/style/JsonStyle.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/style/TabsAndIndentsStyle.java create mode 100644 rewrite-json/src/main/java/org/openrewrite/json/style/package-info.java create mode 100644 rewrite-json/src/test/java/org/openrewrite/json/AddKeyValueTest.java create mode 100644 rewrite-json/src/test/java/org/openrewrite/json/format/NormalizeLineBreaksVisitorTest.java create mode 100644 rewrite-json/src/test/java/org/openrewrite/json/style/AutodetectTest.java diff --git a/rewrite-json/src/main/java/org/openrewrite/json/AddKeyValue.java b/rewrite-json/src/main/java/org/openrewrite/json/AddKeyValue.java new file mode 100644 index 00000000000..4fc66417797 --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/AddKeyValue.java @@ -0,0 +1,135 @@ +/* + * Copyright 2024 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.json; + +import lombok.EqualsAndHashCode; +import lombok.Value; +import org.intellij.lang.annotations.Language; +import org.openrewrite.ExecutionContext; +import org.openrewrite.Option; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.internal.ListUtils; +import org.openrewrite.json.tree.*; +import org.openrewrite.marker.Markers; + +import java.util.Collections; +import java.util.List; + +import static java.util.Collections.emptyList; +import static org.openrewrite.Tree.randomId; + +@Value +@EqualsAndHashCode(callSuper = false) +public class AddKeyValue extends Recipe { + + @Option(displayName = "Key path", + description = "A JsonPath expression to locate the *parent* JSON entry.", + example = "'$.subjects.*' or '$.' or '$.x[1].y.*' etc.") + String keyPath; + + @Option(displayName = "Key", + description = "The key to create.", + example = "myKey") + String key; + + @Option(displayName = "Value", + description = "The value to add to the document at the specified key. Can be of any type representing JSON value." + + " String values should be quoted to be inserted as Strings.", + example = "`\"myValue\"` or `{\"a\": 1}` or `[ 123 ]`") + @Language("Json") + String value; + + @Option(displayName = "Prepend", + required = false, + description = "If set to `true` the value will be added to the beginning of the object") + boolean prepend; + + @Override + public String getDisplayName() { + return "Add value to JSON Object"; + } + + @Override + public String getDescription() { + return "Adds a `value` at the specified `keyPath` with the specified `key`, if the key doesn't already exist."; + } + + + @Override + public TreeVisitor getVisitor() { + return new JsonIsoVisitor() { + private final JsonPathMatcher pathMatcher = new JsonPathMatcher(keyPath); + + @Override + public Json.JsonObject visitObject(Json.JsonObject obj, ExecutionContext ctx) { + obj = super.visitObject(obj, ctx); + + if (pathMatcher.matches(getCursor()) && objectDoesNotContainKey(obj, key)) { + List originalMembers = obj.getMembers(); + boolean jsonIsEmpty = originalMembers.isEmpty() || originalMembers.get(0) instanceof Json.Empty; + Space space = jsonIsEmpty || prepend ? originalMembers.get(0).getPrefix() : Space.build("\n", emptyList()); + + Json newMember = new Json.Member(randomId(), space, Markers.EMPTY, rightPaddedKey(), parsedValue()); + + if (jsonIsEmpty) { + return autoFormat(obj.withMembers(Collections.singletonList(newMember)), ctx, getCursor().getParent()); + } + + List newMembers = prepend ? + ListUtils.concat(newMember, originalMembers) : + ListUtils.concat(originalMembers, newMember); + return autoFormat(obj.withMembers(newMembers), ctx, getCursor().getParent()); + } + return obj; + } + + private JsonValue parsedValue() { + Json.Document parsedDoc = (Json.Document) JsonParser.builder().build() + .parse(value.trim()).findFirst().get(); + JsonValue value = parsedDoc.getValue(); + return value.withPrefix(value.getPrefix().withWhitespace(" ")); + } + + private JsonRightPadded rightPaddedKey() { + return new JsonRightPadded<>( + new Json.Literal(randomId(), Space.EMPTY, Markers.EMPTY, "\"" + key + "\"", key), + Space.EMPTY, Markers.EMPTY + ); + } + + private boolean objectDoesNotContainKey(Json.JsonObject obj, String key) { + for (Json member : obj.getMembers()) { + if (member instanceof Json.Member) { + if (keyMatches(((Json.Member) member).getKey(), key)) { + return false; + } + } + } + return true; + } + + private boolean keyMatches(JsonKey jsonKey, String key) { + if (jsonKey instanceof Json.Literal) { + return key.equals(((Json.Literal) jsonKey).getValue()); + } else if (jsonKey instanceof Json.Identifier) { + return key.equals(((Json.Identifier) jsonKey).getName()); + } + return false; + } + }; + } +} diff --git a/rewrite-json/src/main/java/org/openrewrite/json/JsonVisitor.java b/rewrite-json/src/main/java/org/openrewrite/json/JsonVisitor.java index ad1980f5b8b..2389969407e 100755 --- a/rewrite-json/src/main/java/org/openrewrite/json/JsonVisitor.java +++ b/rewrite-json/src/main/java/org/openrewrite/json/JsonVisitor.java @@ -20,6 +20,7 @@ import org.openrewrite.SourceFile; import org.openrewrite.TreeVisitor; import org.openrewrite.internal.ListUtils; +import org.openrewrite.json.format.AutoFormatVisitor; import org.openrewrite.json.tree.Json; import org.openrewrite.json.tree.JsonRightPadded; import org.openrewrite.json.tree.JsonValue; @@ -37,6 +38,35 @@ public String getLanguage() { return "json"; } + public Y2 maybeAutoFormat(Y2 before, Y2 after, P p) { + return maybeAutoFormat(before, after, p, getCursor()); + } + + public Y2 maybeAutoFormat(Y2 before, Y2 after, P p, Cursor cursor) { + return maybeAutoFormat(before, after, null, p, cursor); + } + + @SuppressWarnings({"unchecked", "ConstantConditions"}) + public Y2 maybeAutoFormat(Y2 before, Y2 after, @Nullable Json stopAfter, P p, Cursor cursor) { + if (before != after) { + return (Y2) new AutoFormatVisitor<>(stopAfter).visit(after, p, cursor); + } + return after; + } + + public Y2 autoFormat(Y2 y, P p) { + return autoFormat(y, p, getCursor()); + } + + public Y2 autoFormat(Y2 y, P p, Cursor cursor) { + return autoFormat(y, null, p, cursor); + } + + @SuppressWarnings({"ConstantConditions", "unchecked"}) + public Y2 autoFormat(Y2 y, @Nullable Json stopAfter, P p, Cursor cursor) { + return (Y2) new AutoFormatVisitor<>(stopAfter).visit(y, p, cursor); + } + public Json visitArray(Json.Array array, P p) { Json.Array a = array; a = a.withPrefix(visitSpace(a.getPrefix(), p)); diff --git a/rewrite-json/src/main/java/org/openrewrite/json/format/AutoFormatVisitor.java b/rewrite-json/src/main/java/org/openrewrite/json/format/AutoFormatVisitor.java new file mode 100644 index 00000000000..f161c95c20e --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/format/AutoFormatVisitor.java @@ -0,0 +1,93 @@ +/* + * Copyright 2025 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.json.format; + +import org.jspecify.annotations.Nullable; +import org.openrewrite.Cursor; +import org.openrewrite.Tree; +import org.openrewrite.json.JsonIsoVisitor; +import org.openrewrite.json.style.Autodetect; +import org.openrewrite.json.style.TabsAndIndentsStyle; +import org.openrewrite.json.tree.Json; +import org.openrewrite.style.GeneralFormatStyle; +import org.openrewrite.style.NamedStyles; + +import java.util.Optional; + +import static java.util.Collections.singletonList; + +public class AutoFormatVisitor

extends JsonIsoVisitor

{ + @Nullable + private final Tree stopAfter; + + public AutoFormatVisitor(@Nullable Tree stopAfter) { + this.stopAfter = stopAfter; + } + + @Override + public Json preVisit(Json tree, P p) { + stopAfterPreVisit(); + Json.Document doc = getCursor().firstEnclosingOrThrow(Json.Document.class); + Cursor cursor = getCursor().getParentOrThrow(); + Autodetect autodetectedStyle = Autodetect.detector().sample(doc).build(); + Json js = tree; + + TabsAndIndentsStyle taiStyle = Optional.ofNullable(doc.getStyle(TabsAndIndentsStyle.class)) + .orElseGet(() -> NamedStyles.merge(TabsAndIndentsStyle.class, singletonList(autodetectedStyle))); + assert(taiStyle != null); + js = new TabsAndIndentsVisitor<>(taiStyle, stopAfter).visitNonNull(js, p, cursor.fork()); + + GeneralFormatStyle gfStyle = Optional.ofNullable(doc.getStyle(GeneralFormatStyle.class)) + .orElseGet(() -> NamedStyles.merge(GeneralFormatStyle.class, singletonList(autodetectedStyle))); + assert(gfStyle != null); + js = new NormalizeLineBreaksVisitor<>(gfStyle, stopAfter).visitNonNull(js, p, cursor.fork()); + + return js; + } + + @Override + public Json.Document visitDocument(Json.Document js, P p) { + Autodetect autodetectedStyle = Autodetect.detector().sample(js).build(); + + TabsAndIndentsStyle taiStyle = Optional.ofNullable(js.getStyle(TabsAndIndentsStyle.class)) + .orElseGet(() -> NamedStyles.merge(TabsAndIndentsStyle.class, singletonList(autodetectedStyle))); + assert(taiStyle != null); + js = (Json.Document) new TabsAndIndentsVisitor<>(taiStyle, stopAfter).visitNonNull(js, p); + + GeneralFormatStyle gfStyle = Optional.ofNullable(js.getStyle(GeneralFormatStyle.class)) + .orElseGet(() -> NamedStyles.merge(GeneralFormatStyle.class, singletonList(autodetectedStyle))); + assert(gfStyle != null); + js = (Json.Document) new NormalizeLineBreaksVisitor<>(gfStyle, stopAfter).visitNonNull(js, p); + + return js; + } + + @Override + public @Nullable Json postVisit(Json tree, P p) { + if (stopAfter != null && stopAfter.isScope(tree)) { + getCursor().putMessageOnFirstEnclosing(Json.Document.class, "stop", true); + } + return super.postVisit(tree, p); + } + + @Override + public @Nullable Json visit(@Nullable Tree tree, P p) { + if (getCursor().getNearestMessage("stop") != null) { + return (Json) tree; + } + return super.visit(tree, p); + } +} diff --git a/rewrite-json/src/main/java/org/openrewrite/json/format/Indents.java b/rewrite-json/src/main/java/org/openrewrite/json/format/Indents.java new file mode 100644 index 00000000000..d636ea9e07d --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/format/Indents.java @@ -0,0 +1,57 @@ +/* + * Copyright 2025 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.json.format; + +import org.openrewrite.ExecutionContext; +import org.openrewrite.Recipe; +import org.openrewrite.TreeVisitor; +import org.openrewrite.json.JsonIsoVisitor; +import org.openrewrite.json.style.Autodetect; +import org.openrewrite.json.style.TabsAndIndentsStyle; +import org.openrewrite.json.tree.Json; +import org.openrewrite.style.NamedStyles; + +import static java.util.Collections.singletonList; + +public class Indents extends Recipe { + @Override + public String getDisplayName() { + return "JSON indent"; + } + + @Override + public String getDescription() { + return "Format tabs and indents in JSON."; + } + + @Override + public TreeVisitor getVisitor() { + return new TabsAndIndentsFromCompilationUnitStyle(); + } + + private static class TabsAndIndentsFromCompilationUnitStyle extends JsonIsoVisitor { + @Override + public Json. Document visitDocument(Json.Document docs, ExecutionContext ctx) { + TabsAndIndentsStyle style = docs.getStyle(TabsAndIndentsStyle.class); + if (style == null) { + style = NamedStyles.merge(TabsAndIndentsStyle.class, singletonList(Autodetect.detector().sample(docs).build())); + assert(style != null); + } + doAfterVisit(new TabsAndIndentsVisitor<>(style, null)); + return docs; + } + } +} diff --git a/rewrite-json/src/main/java/org/openrewrite/json/format/NormalizeLineBreaksVisitor.java b/rewrite-json/src/main/java/org/openrewrite/json/format/NormalizeLineBreaksVisitor.java new file mode 100644 index 00000000000..34f19d6829f --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/format/NormalizeLineBreaksVisitor.java @@ -0,0 +1,60 @@ +/* + * Copyright 2025 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.json.format; + +import org.jspecify.annotations.Nullable; +import org.openrewrite.Tree; +import org.openrewrite.style.GeneralFormatStyle; +import org.openrewrite.json.JsonIsoVisitor; +import org.openrewrite.json.tree.Json; + +import static org.openrewrite.format.LineBreaks.normalizeNewLines; + +public class NormalizeLineBreaksVisitor

extends JsonIsoVisitor

{ + private final GeneralFormatStyle generalFormatStyle; + + @Nullable + private final Tree stopAfter; + + public NormalizeLineBreaksVisitor(GeneralFormatStyle generalFormatStyle, @Nullable Tree stopAfter) { + this.generalFormatStyle = generalFormatStyle; + this.stopAfter = stopAfter; + } + + @Override + public @Nullable Json postVisit(Json tree, P p) { + if (stopAfter != null && stopAfter.isScope(tree)) { + getCursor().putMessageOnFirstEnclosing(Json.Document.class, "stop", true); + } + return super.postVisit(tree, p); + } + + @Override + public @Nullable Json visit(@Nullable Tree tree, P p) { + if (getCursor().getNearestMessage("stop") != null) { + return (Json) tree; + } + + Json y = super.visit(tree, p); + if (y != null) { + String modifiedWs = normalizeNewLines(y.getPrefix().getWhitespace(), generalFormatStyle.isUseCRLFNewLines()); + if (!y.getPrefix().getWhitespace().equals(modifiedWs)) { + y = y.withPrefix(y.getPrefix().withWhitespace(modifiedWs)); + } + } + return y; + } +} diff --git a/rewrite-json/src/main/java/org/openrewrite/json/format/TabsAndIndentsVisitor.java b/rewrite-json/src/main/java/org/openrewrite/json/format/TabsAndIndentsVisitor.java new file mode 100755 index 00000000000..bd17823efaa --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/format/TabsAndIndentsVisitor.java @@ -0,0 +1,89 @@ +/* + * Copyright 2025 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.json.format; + +import org.jspecify.annotations.Nullable; +import org.openrewrite.Cursor; +import org.openrewrite.Tree; +import org.openrewrite.internal.StringUtils; +import org.openrewrite.json.JsonIsoVisitor; +import org.openrewrite.json.style.TabsAndIndentsStyle; +import org.openrewrite.json.tree.Json; + +import java.util.Iterator; +import java.util.concurrent.atomic.AtomicReference; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +public class TabsAndIndentsVisitor

extends JsonIsoVisitor

{ + + private final TabsAndIndentsStyle style; + + @Nullable + private final Tree stopAfter; + + public TabsAndIndentsVisitor(TabsAndIndentsStyle style, @Nullable Tree stopAfter) { + this.style = style; + this.stopAfter = stopAfter; + } + + @Override + public Json preVisit(Json tree, P p) { + Json json = super.preVisit(tree, p); + if (json != null) { + final String ws = json.getPrefix().getWhitespace(); + if (ws.contains("\n")) { + int indentMultiple = (int) getCursor().getPathAsStream().filter(Json.JsonObject.class::isInstance).count(); + String shiftedPrefix = createIndent(ws, indentMultiple); + if (!shiftedPrefix.equals(ws)) { + return json.withPrefix(json.getPrefix().withWhitespace(shiftedPrefix)); + } + } + } + return json; + } + + @Override + public @Nullable Json postVisit(Json tree, P p) { + if (stopAfter != null && stopAfter.isScope(tree)) { + getCursor().putMessageOnFirstEnclosing(Json.Document.class, "stop", true); + } + return super.postVisit(tree, p); + } + + @Override + public @Nullable Json visit(@Nullable Tree tree, P p) { + if (getCursor().getNearestMessage("stop") != null) { + return (Json) tree; + } + return super.visit(tree, p); + } + + private String createIndent(String ws, int indentMultiple) { + StringBuilder shiftedPrefixBuilder = new StringBuilder(ws.substring(0, ws.lastIndexOf('\n') + 1)); + for (int i = 0; i < indentMultiple; i++) { + if (style.getUseTabCharacter()) { + shiftedPrefixBuilder.append("\t"); + } else { + for (int j = 0; j < style.getIndentSize(); j++) { + shiftedPrefixBuilder.append(" "); + } + } + } + + return shiftedPrefixBuilder.toString(); + } +} diff --git a/rewrite-json/src/main/java/org/openrewrite/json/format/package-info.java b/rewrite-json/src/main/java/org/openrewrite/json/format/package-info.java new file mode 100644 index 00000000000..cfab9d193b9 --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/format/package-info.java @@ -0,0 +1,21 @@ +/* + * Copyright 2020 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. + */ +@NullMarked +@NonNullFields +package org.openrewrite.json.format; + +import org.jspecify.annotations.NullMarked; +import org.openrewrite.internal.lang.NonNullFields; diff --git a/rewrite-json/src/main/java/org/openrewrite/json/style/Autodetect.java b/rewrite-json/src/main/java/org/openrewrite/json/style/Autodetect.java new file mode 100644 index 00000000000..c07657d42e6 --- /dev/null +++ b/rewrite-json/src/main/java/org/openrewrite/json/style/Autodetect.java @@ -0,0 +1,237 @@ +/* + * Copyright 2025 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.json.style; + +import com.fasterxml.jackson.annotation.JsonCreator; +import org.jspecify.annotations.Nullable; +import org.openrewrite.SourceFile; +import org.openrewrite.Tree; +import org.openrewrite.json.JsonVisitor; +import org.openrewrite.style.GeneralFormatStyle; +import org.openrewrite.style.NamedStyles; +import org.openrewrite.style.Style; +import org.openrewrite.json.tree.Json; + +import java.util.*; +import java.util.concurrent.atomic.AtomicBoolean; +import java.util.stream.Collectors; + +import static java.util.Collections.emptySet; +import static java.util.function.Function.identity; +import static java.util.stream.Collectors.counting; + +public class Autodetect extends NamedStyles { + @JsonCreator + public Autodetect(UUID id, Collection