From d77e4b946a882737a9016c083215e330abd6ee9e Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Wed, 16 Mar 2022 13:45:27 +0100 Subject: [PATCH 01/51] build: temporarily change test matrix to include Scala 3 --- .github/workflows/validate-and-test.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/validate-and-test.yml b/.github/workflows/validate-and-test.yml index 197fae0b8d7..868d25690f8 100644 --- a/.github/workflows/validate-and-test.yml +++ b/.github/workflows/validate-and-test.yml @@ -53,8 +53,8 @@ jobs: strategy: fail-fast: false matrix: - SCALA_VERSION: [2.12, 2.13] - JABBA_JDK: [1.8, 1.11] + SCALA_VERSION: [2.12, 2.13, 3] + JABBA_JDK: [1.8] steps: - name: Checkout uses: actions/checkout@v2 From 890c7bd69b3424d4239719340a41b281c5c71c05 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 11:26:44 +0100 Subject: [PATCH 02/51] build: setup scala 3 building --- build.sbt | 28 ++++++++++++++++-------- project/Dependencies.scala | 44 +++++++++++++++++++++++++++++--------- project/NoScala3.scala | 10 +++++++++ 3 files changed, 63 insertions(+), 19 deletions(-) create mode 100644 project/NoScala3.scala diff --git a/build.sbt b/build.sbt index f9b0c38d377..f6b45bf44e7 100644 --- a/build.sbt +++ b/build.sbt @@ -105,7 +105,7 @@ def add213CrossDirs(config: Configuration): Seq[Setting[_]] = Seq( config / unmanagedSourceDirectories += { val sourceDir = (config / sourceDirectory).value CrossVersion.partialVersion(scalaVersion.value) match { - case Some((2, n)) if n >= 13 => sourceDir / "scala-2.13+" + case Some((e, n)) if e > 2 || (e == 2 && n >= 13) => sourceDir / "scala-2.13+" case _ => sourceDir / "scala-2.13-" } } @@ -148,7 +148,7 @@ lazy val parsing = project("akka-parsing") lazy val httpCore = project("akka-http-core") .settings(commonSettings) .settings(AutomaticModuleName.settings("akka.http.core")) - .dependsOn(parsing, httpScalafixRules % ScalafixConfig) + .dependsOn(parsing/*, httpScalafixRules % ScalafixConfig*/) .addAkkaModuleDependency("akka-stream", "provided") .addAkkaModuleDependency( "akka-stream-testkit", @@ -157,11 +157,20 @@ lazy val httpCore = project("akka-http-core") if (System.getProperty("akka.http.test-against-akka-main", "false") == "true") AkkaDependency.masterSnapshot else AkkaDependency.default ) + .settings( + scalacOptions ++= { + if (scalaVersion.value startsWith "3") + Seq("-source", "3.0-migration") + else + Nil + }, + ) .settings(Dependencies.httpCore) .settings(VersionGenerator.versionSettings) .settings(scalaMacroSupport) .enablePlugins(BootstrapGenjavadoc) .enablePlugins(ReproducibleBuildsPlugin) + .disablePlugins(ScalafixPlugin) lazy val http = project("akka-http") .settings(commonSettings) @@ -346,22 +355,23 @@ def httpMarshallersJavaSubproject(name: String) = .enablePlugins(ReproducibleBuildsPlugin) lazy val httpScalafix = project("akka-http-scalafix") - .enablePlugins(NoPublish) + .enablePlugins(NoPublish, NoScala3) .disablePlugins(MimaPlugin) .aggregate(httpScalafixRules, httpScalafixTestInput, httpScalafixTestOutput, httpScalafixTests) lazy val httpScalafixRules = Project(id = "akka-http-scalafix-rules", base = file("akka-http-scalafix/scalafix-rules")) .settings( - libraryDependencies += Dependencies.Compile.scalafix + libraryDependencies += Dependencies.Compile.scalafix, ) + .enablePlugins(NoScala3) .disablePlugins(MimaPlugin) // tooling, no bin compat guaranteed lazy val httpScalafixTestInput = Project(id = "akka-http-scalafix-test-input", base = file("akka-http-scalafix/scalafix-test-input")) .dependsOn(http) .addAkkaModuleDependency("akka-stream") - .enablePlugins(NoPublish) + .enablePlugins(NoPublish, NoScala3) .disablePlugins(MimaPlugin, HeaderPlugin /* because it gets confused about metaheader required for tests */) .settings( addCompilerPlugin(scalafixSemanticdb), @@ -376,12 +386,12 @@ lazy val httpScalafixTestOutput = Project(id = "akka-http-scalafix-test-output", base = file("akka-http-scalafix/scalafix-test-output")) .dependsOn(http) .addAkkaModuleDependency("akka-stream") - .enablePlugins(NoPublish) + .enablePlugins(NoPublish, NoScala3) .disablePlugins(MimaPlugin, HeaderPlugin /* because it gets confused about metaheader required for tests */) lazy val httpScalafixTests = Project(id = "akka-http-scalafix-tests", base = file("akka-http-scalafix/scalafix-tests")) - .enablePlugins(NoPublish) + .enablePlugins(NoPublish, NoScala3) .disablePlugins(MimaPlugin) .settings( publish / skip := true, @@ -472,7 +482,7 @@ lazy val docs = project("docs") .settings(ParadoxSupport.paradoxWithCustomDirectives) lazy val compatibilityTests = Project("akka-http-compatibility-tests", file("akka-http-compatibility-tests")) - .enablePlugins(NoPublish) + .enablePlugins(NoPublish, NoScala3) .disablePlugins(MimaPlugin) .addAkkaModuleDependency("akka-stream", "provided") .settings( @@ -484,7 +494,7 @@ lazy val compatibilityTests = Project("akka-http-compatibility-tests", file("akk // current version but that fails. So, this is a manual `dependsOn` which works as expected. (Test / dependencyClasspath).value.filterNot(_.data.getName contains "akka") ++ (httpTests / Test / fullClasspath).value - } + }, ) lazy val billOfMaterials = Project("bill-of-materials", file("akka-http-bill-of-materials")) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index bbf3c8e5cf1..1718a98a77b 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -19,15 +19,22 @@ object Dependencies { val h2specExe = "h2spec" + DependencyHelpers.exeIfWindows val h2specUrl = s"https://github.com/summerwind/h2spec/releases/download/v${h2specVersion}/${h2specName}.zip" - val scalaTestVersion = "3.1.4" + val scalaTestVersion = "3.2.9" val specs2Version = "4.10.6" - val scalaCheckVersion = "1.14.3" + val scalaCheckVersion = "1.15.4" val scalafixVersion = _root_.scalafix.sbt.BuildInfo.scalafixVersion // grab from plugin val scala212Version = "2.12.15" val scala213Version = "2.13.8" - val allScalaVersions = Seq(scala213Version, scala212Version) + val scala3Version = "3.1.1" + val allScalaVersions = + // FIXME: can be simplified when Akka 2.5 is dropped + if (AkkaDependency.akkaVersion startsWith "2.6.") + // Scala 3 only for Akka 2.6 + Seq(scala213Version, scala212Version, scala3Version) + else + Seq(scala213Version, scala212Version) val Versions = Seq( crossScalaVersions := allScalaVersions, @@ -36,11 +43,20 @@ object Dependencies { object Provided { val jsr305 = "com.google.code.findbugs" % "jsr305" % "3.0.2" % "provided" // ApacheV2 - val scalaReflect = ScalaVersionDependentModuleID.versioned("org.scala-lang" % "scala-reflect" % _ % "provided") // Scala License + val scalaReflect = ScalaVersionDependentModuleID.fromPF { + case v if v startsWith "2." => "org.scala-lang" % "scala-reflect" % v % "provided" // Scala License + } } object Compile { - val scalaXml = "org.scala-lang.modules" %% "scala-xml" % "1.3.0" // Scala License + val scalaXml = { + val xml = "org.scala-lang.modules" %% "scala-xml" // Scala License + ScalaVersionDependentModuleID.versioned { + case v if v.startsWith("2.") => xml % "1.3.0" + case _ => xml % "2.0.1" + } + } + // For akka-http spray-json support val sprayJson = "io.spray" %% "spray-json" % "1.3.6" // ApacheV2 @@ -70,7 +86,7 @@ object Dependencies { val junitIntf = "com.github.sbt" % "junit-interface" % "0.13.3" % "test" // MIT val scalatest = "org.scalatest" %% "scalatest" % scalaTestVersion % "test" // ApacheV2 - val scalatestplusScalacheck = "org.scalatestplus" %% "scalacheck-1-14" % (scalaTestVersion + ".0") % "test" + val scalatestplusScalacheck = "org.scalatestplus" %% "scalacheck-1-15" % (scalaTestVersion + ".0") % "test" val scalatestplusJUnit = "org.scalatestplus" %% "junit-4-13" % (scalaTestVersion + ".0") % "test" // HTTP/2 @@ -105,10 +121,18 @@ object Dependencies { lazy val http2Support = l ++= Seq(Test.h2spec) - lazy val httpTestkit = l ++= Seq( - Test.junit, Test.junitIntf, Compile.junit % "provided", - Test.scalatest.withConfigurations(Some("provided; test")), - Test.specs2.withConfigurations(Some("provided; test")) + lazy val httpTestkit = Seq( + versionDependentDeps( + ScalaVersionDependentModuleID.fromPF { + // FIXME: ultimately, we might update to a Scala 3 compatible version of specs2 + // for now disable specs2 support in the Scala 3 akka-http-testkit + case v if v startsWith "2." => Test.specs2.withConfigurations(Some("provided; test")) + } + ), + l ++= Seq( + Test.junit, Test.junitIntf, Compile.junit % "provided", + Test.scalatest.withConfigurations(Some("provided; test")), + ) ) lazy val httpTests = l ++= Seq(Test.junit, Test.scalatest, Test.junitIntf) diff --git a/project/NoScala3.scala b/project/NoScala3.scala new file mode 100644 index 00000000000..75fc6f597cf --- /dev/null +++ b/project/NoScala3.scala @@ -0,0 +1,10 @@ +package akka + +import sbt.{Def, _} +import Keys._ + +object NoScala3 extends AutoPlugin { + override def projectSettings: Seq[Def.Setting[_]] = Seq( + crossScalaVersions := crossScalaVersions.value.filterNot(_.startsWith("3.")), + ) +} From d7ead4681c3395daa066cc235e1e5484b7f0dbd1 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 13:12:11 +0100 Subject: [PATCH 03/51] parboiled: import latest scala-3 parboiled2 code --- .../impl/model/parser/Base64Parsing.scala | 4 +- .../model/parser/CacheControlHeader.scala | 2 +- .../http/impl/model/parser/CommonRules.scala | 2 +- .../http/impl/model/parser/HeaderParser.scala | 2 +- .../java/akka/parboiled2/util/Base64.java | 672 ---- .../parboiled2/DynamicRuleDispatchMacro.scala | 65 + .../akka/parboiled2/ParserMacros.scala | 99 + .../akka/parboiled2/support/HListable.scala | 6 +- .../parboiled2/support/OpTreeContext.scala | 207 +- .../akka/parboiled2/support/TailSwitch.scala | 26 +- .../parboiled2/DynamicRuleDispatchMacro.scala | 76 + .../akka/parboiled2/ParserMacros.scala | 1127 ++++++ .../akka/parboiled2/support/HListable.scala} | 25 +- .../akka/parboiled2/support/TailSwitch.scala | 79 + .../scala/akka/parboiled2/CharPredicate.scala | 217 +- .../scala/akka/parboiled2/CharUtils.scala | 38 +- .../akka/parboiled2/DynamicRuleDispatch.scala | 51 +- .../akka/parboiled2/ErrorFormatter.scala | 36 +- .../scala/akka/parboiled2/ParseError.scala | 11 +- .../main/scala/akka/parboiled2/Parser.scala | 179 +- .../scala/akka/parboiled2/ParserInput.scala | 27 +- .../src/main/scala/akka/parboiled2/Rule.scala | 28 +- .../akka/parboiled2/RuleDSLActions.scala | 11 +- .../scala/akka/parboiled2/RuleDSLBasics.scala | 20 +- .../akka/parboiled2/RuleDSLCombinators.scala | 15 +- .../scala/akka/parboiled2/ValueStack.scala | 8 +- .../main/scala/akka/parboiled2/package.scala | 6 +- .../akka/parboiled2/support/ActionOps.scala | 3052 ++++++++--------- .../parboiled2/support/ActionOpsSupport.scala | 53 +- .../akka/parboiled2/support/Lifter.scala | 13 +- .../akka/parboiled2/support/RunResult.scala | 15 +- .../akka/parboiled2/support/Unpack.scala | 20 +- .../support/hlist}/hlists.scala | 22 +- .../support/hlist}/ops/hlists.scala | 67 +- .../support/hlist}/syntax/hlists.scala | 11 +- .../akka/parboiled2/support/package.scala | 4 +- .../scala/akka/parboiled2/util/Base64.scala | 342 ++ 37 files changed, 3876 insertions(+), 2762 deletions(-) delete mode 100644 akka-parsing/src/main/java/akka/parboiled2/util/Base64.java create mode 100644 akka-parsing/src/main/scala-2/akka/parboiled2/DynamicRuleDispatchMacro.scala create mode 100644 akka-parsing/src/main/scala-2/akka/parboiled2/ParserMacros.scala rename akka-parsing/src/main/{scala => scala-2}/akka/parboiled2/support/HListable.scala (87%) rename akka-parsing/src/main/{scala => scala-2}/akka/parboiled2/support/OpTreeContext.scala (85%) rename akka-parsing/src/main/{scala => scala-2}/akka/parboiled2/support/TailSwitch.scala (82%) create mode 100644 akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala create mode 100644 akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala rename akka-parsing/src/main/{scala/akka/shapeless/package.scala => scala-3/akka/parboiled2/support/HListable.scala} (59%) create mode 100644 akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala rename akka-parsing/src/main/scala/akka/{shapeless => parboiled2/support/hlist}/hlists.scala (72%) rename akka-parsing/src/main/scala/akka/{shapeless => parboiled2/support/hlist}/ops/hlists.scala (73%) rename akka-parsing/src/main/scala/akka/{shapeless => parboiled2/support/hlist}/syntax/hlists.scala (79%) create mode 100644 akka-parsing/src/main/scala/akka/parboiled2/util/Base64.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala index 7a3b72a868d..ae1f9ecaf9c 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala @@ -40,12 +40,12 @@ private[parser] trait Base64Parsing { this: Parser => def rfc2045Block: Rule1[Array[Byte]] = base64StringOrBlock(rfc2045Alphabet, rfc2045BlockDecoder) /** - * Parses a org.parboiled2.util.Base64.custom()-encoded string and decodes it onto the value stack. + * Parses a akka.parboiled2.util.Base64.custom()-encoded string and decodes it onto the value stack. */ def base64CustomString: Rule1[Array[Byte]] = base64StringOrBlock(customAlphabet, customStringDecoder) /** - * Parses a org.parboiled2.util.Base64.custom()-encoded string potentially containing newlines + * Parses a akka.parboiled2.util.Base64.custom()-encoded string potentially containing newlines * and decodes it onto the value stack. */ def base64CustomBlock: Rule1[Array[Byte]] = base64StringOrBlock(customAlphabet, customBlockDecoder) diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala index 01b56253b7c..2af2d142c0c 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala @@ -8,7 +8,7 @@ import akka.parboiled2.Parser import akka.http.scaladsl.model.headers._ import CacheDirectives._ -private[parser] trait CacheControlHeader { this: Parser with CommonRules with CommonActions with StringBuilding => +private[parser] trait CacheControlHeader { this: HeaderParser => // http://tools.ietf.org/html/rfc7234#section-5.2 def `cache-control` = rule { diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala index 2af146e2179..5bcb8d4f05f 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala @@ -10,7 +10,7 @@ import scala.collection.immutable.TreeMap import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers._ import akka.parboiled2._ -import akka.shapeless._ +import akka.parboiled2.support.hlist._ private[parser] trait CommonRules { this: HeaderParser with Parser with StringBuilding => import CharacterClasses._ diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala index 25f748ac63a..56d88424676 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala @@ -14,7 +14,7 @@ import akka.util.ConstantFun import scala.util.control.NonFatal import akka.http.impl.util.SingletonException import akka.parboiled2._ -import akka.shapeless._ +import akka.parboiled2.support.hlist._ import akka.http.scaladsl.model._ /** diff --git a/akka-parsing/src/main/java/akka/parboiled2/util/Base64.java b/akka-parsing/src/main/java/akka/parboiled2/util/Base64.java deleted file mode 100644 index 5bd36d33096..00000000000 --- a/akka-parsing/src/main/java/akka/parboiled2/util/Base64.java +++ /dev/null @@ -1,672 +0,0 @@ -/** - * A very fast and memory efficient class to encode and decode to and from BASE64 in full accordance - * with RFC 2045.

- * On Windows XP sp1 with 1.4.2_04 and later ;), this encoder and decoder is about 10 times faster - * on small arrays (10 - 1000 bytes) and 2-3 times as fast on larger arrays (10000 - 1000000 bytes) - * compared to sun.misc.Encoder()/Decoder().

- * - * On byte arrays the encoder is about 20% faster than Jakarta Commons Base64 Codec for encode and - * about 50% faster for decoding large arrays. This implementation is about twice as fast on very small - * arrays (< 30 bytes). If source/destination is a String this - * version is about three times as fast due to the fact that the Commons Codec result has to be recoded - * to a String from byte[], which is very expensive.

- * - * This encode/decode algorithm doesn't create any temporary arrays as many other codecs do, it only - * allocates the resulting array. This produces less garbage and it is possible to handle arrays twice - * as large as algorithms that create a temporary array. (E.g. Jakarta Commons Codec). It is unknown - * whether Sun's sun.misc.Encoder()/Decoder() produce temporary arrays but since performance - * is quite low it probably does.

- * - * The encoder produces the same output as the Sun one except that the Sun's encoder appends - * a trailing line separator if the last character isn't a pad. Unclear why but it only adds to the - * length and is probably a side effect. Both are in conformance with RFC 2045 though.
- * Commons codec seem to always att a trailing line separator.

- * - * Note! - * The encode/decode method pairs (types) come in three versions with the exact same algorithm and - * thus a lot of code redundancy. This is to not create any temporary arrays for transcoding to/from different - * format types. The methods not used can simply be commented out.

- * - * There is also a "fast" version of all decode methods that works the same way as the normal ones, but - * har a few demands on the decoded input. Normally though, these fast verions should be used if the source if - * the input is known and it hasn't bee tampered with.

- * - * If you find the code useful or you find a bug, please send me a note at base64 @ miginfocom . com. - * - * Licence (BSD): - * ============== - * - * Copyright (c) 2004, Mikael Grev, MiG InfoCom AB. (base64 @ miginfocom . com) - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without modification, - * are permitted provided that the following conditions are met: - * Redistributions of source code must retain the above copyright notice, this list - * of conditions and the following disclaimer. - * Redistributions in binary form must reproduce the above copyright notice, this - * list of conditions and the following disclaimer in the documentation and/or other - * materials provided with the distribution. - * Neither the name of the MiG InfoCom AB nor the names of its contributors may be - * used to endorse or promote products derived from this software without specific - * prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED - * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. - * IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, - * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, - * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, - * OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, - * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) - * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY - * OF SUCH DAMAGE. - * - * @version 2.2 - * @author Mikael Grev - * Date: 2004-aug-02 - * Time: 11:31:11 - * - * Adapted in 2009 by Mathias Doenitz. - */ - -package akka.parboiled2.util; - -import java.util.Arrays; - -public class Base64 { - - // -------- FIELDS ------------------------------------------------------------------------------------------------- - - private static Base64 RFC2045; - private static Base64 CUSTOM; - - private final char[] CA; - private final int[] IA; - private final char fillChar; - - // -------- STATIC METHODS ----------------------------------------------------------------------------------------- - - public static Base64 custom() { - if (CUSTOM == null) { - CUSTOM = new Base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_"); - } - return CUSTOM; - } - - public static Base64 rfc2045() { - if (RFC2045 == null) { - RFC2045 = new Base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/="); - } - return RFC2045; - } - - // -------- CONSTRUCTORS ------------------------------------------------------------------------------------------- - - public Base64(String alphabet) { - if (alphabet == null || alphabet.length() != 65) throw new IllegalArgumentException(); - CA = alphabet.substring(0, 64).toCharArray(); - IA = new int[256]; - Arrays.fill(IA, -1); - for (int i = 0, iS = CA.length; i < iS; i++) { - IA[CA[i]] = i; - } - fillChar = alphabet.charAt(64); - IA[fillChar] = 0; - } - - // -------- OTHER METHODS ------------------------------------------------------------------------------------------ - - /** - * Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with - * and without line separators. - * - * @param sArr The source array. null or length 0 will return an empty array. - * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters - * (including '=') isn't divideable by 4. (I.e. definitely corrupted). - */ - public final byte[] decode(char[] sArr) { - // Check special case - int sLen = sArr != null ? sArr.length : 0; - if (sLen == 0) { - return new byte[0]; - } - - // Count illegal characters (including '\r', '\n') to know what size the returned array will be, - // so we don't have to reallocate & copy it later. - int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) - for ( - int i = 0; i < - sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. - { - if (IA[sArr[i]] < 0) { - sepCnt++; - } - } - - // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. - if ((sLen - sepCnt) % 4 != 0) { - return null; - } - - int pad = 0; - for (int i = sLen; i > 1 && IA[sArr[--i]] <= 0;) { - if (sArr[i] == fillChar) { - pad++; - } - } - - int len = ((sLen - sepCnt) * 6 >> 3) - pad; - - byte[] dArr = new byte[len]; // Preallocate byte[] of exact length - - for (int s = 0, d = 0; d < len;) { - // Assemble three bytes into an int from four "valid" characters. - int i = 0; - for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. - int c = IA[sArr[s++]]; - if (c >= 0) { - i |= c << (18 - j * 6); - } else { - j--; - } - } - // Add the bytes - dArr[d++] = (byte) (i >> 16); - if (d < len) { - dArr[d++] = (byte) (i >> 8); - if (d < len) { - dArr[d++] = (byte) i; - } - } - } - return dArr; - } - - /** - * Decodes a BASE64 encoded byte array. All illegal characters will be ignored and can handle both arrays with - * and without line separators. - * - * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. - * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters - * (including '=') isn't divideable by 4. (I.e. definitely corrupted). - */ - public final byte[] decode(byte[] sArr) { - // Check special case - int sLen = sArr.length; - - // Count illegal characters (including '\r', '\n') to know what size the returned array will be, - // so we don't have to reallocate & copy it later. - int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) - for ( - int i = 0; i < - sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. - { - if (IA[sArr[i] & 0xff] < 0) { - sepCnt++; - } - } - - // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. - if ((sLen - sepCnt) % 4 != 0) { - return null; - } - - int pad = 0; - for (int i = sLen; i > 1 && IA[sArr[--i] & 0xff] <= 0;) { - if (sArr[i] == fillChar) { - pad++; - } - } - - int len = ((sLen - sepCnt) * 6 >> 3) - pad; - - byte[] dArr = new byte[len]; // Preallocate byte[] of exact length - - for (int s = 0, d = 0; d < len;) { - // Assemble three bytes into an int from four "valid" characters. - int i = 0; - for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. - int c = IA[sArr[s++] & 0xff]; - if (c >= 0) { - i |= c << (18 - j * 6); - } else { - j--; - } - } - - // Add the bytes - dArr[d++] = (byte) (i >> 16); - if (d < len) { - dArr[d++] = (byte) (i >> 8); - if (d < len) { - dArr[d++] = (byte) i; - } - } - } - - return dArr; - } - - /** - * Decodes a BASE64 encoded String. All illegal characters will be ignored and can handle both strings with - * and without line separators.
- * Note! It can be up to about 2x the speed to call decode(str.toCharArray()) instead. That - * will create a temporary array though. This version will use str.charAt(i) to iterate the string. - * - * @param str The source string. null or length 0 will return an empty array. - * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters - * (including '=') isn't divideable by 4. (I.e. definitely corrupted). - */ - public final byte[] decode(String str) { - // Check special case - int sLen = str != null ? str.length() : 0; - if (sLen == 0) { - return new byte[0]; - } - - // Count illegal characters (including '\r', '\n') to know what size the returned array will be, - // so we don't have to reallocate & copy it later. - int sepCnt = 0; // Number of separator characters. (Actually illegal characters, but that's a bonus...) - for ( - int i = 0; i < - sLen; i++) // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. - { - if (IA[str.charAt(i)] < 0) { - sepCnt++; - } - } - - // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. - if ((sLen - sepCnt) % 4 != 0) { - return null; - } - - // Count '=' at end - int pad = 0; - for (int i = sLen; i > 1 && IA[str.charAt(--i)] <= 0;) { - if (str.charAt(i) == fillChar) { - pad++; - } - } - - int len = ((sLen - sepCnt) * 6 >> 3) - pad; - - byte[] dArr = new byte[len]; // Preallocate byte[] of exact length - - for (int s = 0, d = 0; d < len;) { - // Assemble three bytes into an int from four "valid" characters. - int i = 0; - for (int j = 0; j < 4; j++) { // j only increased if a valid char was found. - int c = IA[str.charAt(s++)]; - if (c >= 0) { - i |= c << (18 - j * 6); - } else { - j--; - } - } - // Add the bytes - dArr[d++] = (byte) (i >> 16); - if (d < len) { - dArr[d++] = (byte) (i >> 8); - if (d < len) { - dArr[d++] = (byte) i; - } - } - } - return dArr; - } - - /** - * Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as - * fast as {@link #decode(char[])}. The preconditions are:
- * + The array must have a line length of 76 chars OR no line separators at all (one line).
- * + Line separator must be "\r\n", as specified in RFC 2045 - * + The array must not contain illegal characters within the encoded string
- * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
- * - * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. - * @return The decoded array of bytes. May be of length 0. - */ - public final byte[] decodeFast(char[] sArr) { - // Check special case - int sLen = sArr.length; - if (sLen == 0) { - return new byte[0]; - } - - int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. - - // Trim illegal chars from start - while (sIx < eIx && IA[sArr[sIx]] < 0) { - sIx++; - } - - // Trim illegal chars from end - while (eIx > 0 && IA[sArr[eIx]] < 0) { - eIx--; - } - - // get the padding count (=) (0, 1 or 2) - int pad = sArr[eIx] == fillChar ? (sArr[eIx - 1] == fillChar ? 2 : 1) : 0; // Count '=' at end. - int cCnt = eIx - sIx + 1; // Content count including possible separators - int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; - - int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes - byte[] dArr = new byte[len]; // Preallocate byte[] of exact length - - // Decode all but the last 0 - 2 bytes. - int d = 0; - for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { - // Assemble three bytes into an int from four "valid" characters. - int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; - - // Add the bytes - dArr[d++] = (byte) (i >> 16); - dArr[d++] = (byte) (i >> 8); - dArr[d++] = (byte) i; - - // If line separator, jump over it. - if (sepCnt > 0 && ++cc == 19) { - sIx += 2; - cc = 0; - } - } - - if (d < len) { - // Decode last 1-3 bytes (incl '=') into 1-3 bytes - int i = 0; - for (int j = 0; sIx <= eIx - pad; j++) { - i |= IA[sArr[sIx++]] << (18 - j * 6); - } - - for (int r = 16; d < len; r -= 8) { - dArr[d++] = (byte) (i >> r); - } - } - - return dArr; - } - - /** - * Decodes a BASE64 encoded byte array that is known to be resonably well formatted. The method is about twice as - * fast as {@link #decode(byte[])}. The preconditions are:
- * + The array must have a line length of 76 chars OR no line separators at all (one line).
- * + Line separator must be "\r\n", as specified in RFC 2045 - * + The array must not contain illegal characters within the encoded string
- * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
- * - * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. - * @return The decoded array of bytes. May be of length 0. - */ - public final byte[] decodeFast(byte[] sArr) { - // Check special case - int sLen = sArr.length; - if (sLen == 0) { - return new byte[0]; - } - - int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. - - // Trim illegal chars from start - while (sIx < eIx && IA[sArr[sIx] & 0xff] < 0) { - sIx++; - } - - // Trim illegal chars from end - while (eIx > 0 && IA[sArr[eIx] & 0xff] < 0) { - eIx--; - } - - // get the padding count (=) (0, 1 or 2) - int pad = sArr[eIx] == fillChar ? (sArr[eIx - 1] == fillChar ? 2 : 1) : 0; // Count '=' at end. - int cCnt = eIx - sIx + 1; // Content count including possible separators - int sepCnt = sLen > 76 ? (sArr[76] == '\r' ? cCnt / 78 : 0) << 1 : 0; - - int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes - byte[] dArr = new byte[len]; // Preallocate byte[] of exact length - - // Decode all but the last 0 - 2 bytes. - int d = 0; - for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { - // Assemble three bytes into an int from four "valid" characters. - int i = IA[sArr[sIx++]] << 18 | IA[sArr[sIx++]] << 12 | IA[sArr[sIx++]] << 6 | IA[sArr[sIx++]]; - - // Add the bytes - dArr[d++] = (byte) (i >> 16); - dArr[d++] = (byte) (i >> 8); - dArr[d++] = (byte) i; - - // If line separator, jump over it. - if (sepCnt > 0 && ++cc == 19) { - sIx += 2; - cc = 0; - } - } - - if (d < len) { - // Decode last 1-3 bytes (incl '=') into 1-3 bytes - int i = 0; - for (int j = 0; sIx <= eIx - pad; j++) { - i |= IA[sArr[sIx++]] << (18 - j * 6); - } - - for (int r = 16; d < len; r -= 8) { - dArr[d++] = (byte) (i >> r); - } - } - - return dArr; - } - - /** - * Decodes a BASE64 encoded string that is known to be resonably well formatted. The method is about twice as - * fast as {@link #decode(String)}. The preconditions are:
- * + The array must have a line length of 76 chars OR no line separators at all (one line).
- * + Line separator must be "\r\n", as specified in RFC 2045 - * + The array must not contain illegal characters within the encoded string
- * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
- * - * @param s The source string. Length 0 will return an empty array. null will throw an exception. - * @return The decoded array of bytes. May be of length 0. - */ - public final byte[] decodeFast(String s) { - // Check special case - int sLen = s.length(); - if (sLen == 0) { - return new byte[0]; - } - - int sIx = 0, eIx = sLen - 1; // Start and end index after trimming. - - // Trim illegal chars from start - while (sIx < eIx && IA[s.charAt(sIx) & 0xff] < 0) { - sIx++; - } - - // Trim illegal chars from end - while (eIx > 0 && IA[s.charAt(eIx) & 0xff] < 0) { - eIx--; - } - - // get the padding count (=) (0, 1 or 2) - int pad = s.charAt(eIx) == fillChar ? (s.charAt(eIx - 1) == fillChar ? 2 : 1) : 0; // Count '=' at end. - int cCnt = eIx - sIx + 1; // Content count including possible separators - int sepCnt = sLen > 76 ? (s.charAt(76) == '\r' ? cCnt / 78 : 0) << 1 : 0; - - int len = ((cCnt - sepCnt) * 6 >> 3) - pad; // The number of decoded bytes - byte[] dArr = new byte[len]; // Preallocate byte[] of exact length - - // Decode all but the last 0 - 2 bytes. - int d = 0; - for (int cc = 0, eLen = (len / 3) * 3; d < eLen;) { - // Assemble three bytes into an int from four "valid" characters. - int i = IA[s.charAt(sIx++)] << 18 | IA[s.charAt(sIx++)] << 12 | IA[s.charAt(sIx++)] << 6 | IA[s - .charAt(sIx++)]; - - // Add the bytes - dArr[d++] = (byte) (i >> 16); - dArr[d++] = (byte) (i >> 8); - dArr[d++] = (byte) i; - - // If line separator, jump over it. - if (sepCnt > 0 && ++cc == 19) { - sIx += 2; - cc = 0; - } - } - - if (d < len) { - // Decode last 1-3 bytes (incl '=') into 1-3 bytes - int i = 0; - for (int j = 0; sIx <= eIx - pad; j++) { - i |= IA[s.charAt(sIx++)] << (18 - j * 6); - } - - for (int r = 16; d < len; r -= 8) { - dArr[d++] = (byte) (i >> r); - } - } - - return dArr; - } - - // **************************************************************************************** - // * byte[] version - // **************************************************************************************** - - /** - * Encodes a raw byte array into a BASE64 byte[] representation i accordance with RFC 2045. - * - * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. - * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
- * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a - * little faster. - * @return A BASE64 encoded array. Never null. - */ - public final byte[] encodeToByte(byte[] sArr, boolean lineSep) { - // Check special case - int sLen = sArr != null ? sArr.length : 0; - if (sLen == 0) { - return new byte[0]; - } - - int eLen = (sLen / 3) * 3; // Length of even 24-bits. - int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count - int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array - byte[] dArr = new byte[dLen]; - - // Encode even 24-bits - for (int s = 0, d = 0, cc = 0; s < eLen;) { - // Copy next three bytes into lower 24 bits of int, paying attention to sign. - int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); - - // Encode the int into four chars - dArr[d++] = (byte) CA[(i >>> 18) & 0x3f]; - dArr[d++] = (byte) CA[(i >>> 12) & 0x3f]; - dArr[d++] = (byte) CA[(i >>> 6) & 0x3f]; - dArr[d++] = (byte) CA[i & 0x3f]; - - // Add optional line separator - if (lineSep && ++cc == 19 && d < dLen - 2) { - dArr[d++] = '\r'; - dArr[d++] = '\n'; - cc = 0; - } - } - - // Pad and encode last bits if source isn't an even 24 bits. - int left = sLen - eLen; // 0 - 2. - if (left > 0) { - // Prepare the int - int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); - - // Set last four chars - dArr[dLen - 4] = (byte) CA[i >> 12]; - dArr[dLen - 3] = (byte) CA[(i >>> 6) & 0x3f]; - dArr[dLen - 2] = left == 2 ? (byte) CA[i & 0x3f] : (byte) fillChar; - dArr[dLen - 1] = (byte) fillChar; - } - return dArr; - } - - // **************************************************************************************** - // * String version - // **************************************************************************************** - - /** - * Encodes a raw byte array into a BASE64 String representation in accordance with RFC 2045. - * - * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. - * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
- * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a - * little faster. - * @return A BASE64 encoded array. Never null. - */ - public final String encodeToString(byte[] sArr, boolean lineSep) { - // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower. - return new String(encodeToChar(sArr, lineSep)); - } - - // **************************************************************************************** - // * char[] version - // **************************************************************************************** - - /** - * Encodes a raw byte array into a BASE64 char[] representation i accordance with RFC 2045. - * - * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. - * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
- * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a - * little faster. - * @return A BASE64 encoded array. Never null. - */ - public final char[] encodeToChar(byte[] sArr, boolean lineSep) { - // Check special case - int sLen = sArr != null ? sArr.length : 0; - if (sLen == 0) { - return new char[0]; - } - - int eLen = (sLen / 3) * 3; // Length of even 24-bits. - int cCnt = ((sLen - 1) / 3 + 1) << 2; // Returned character count - int dLen = cCnt + (lineSep ? (cCnt - 1) / 76 << 1 : 0); // Length of returned array - char[] dArr = new char[dLen]; - - // Encode even 24-bits - for (int s = 0, d = 0, cc = 0; s < eLen;) { - // Copy next three bytes into lower 24 bits of int, paying attention to sign. - int i = (sArr[s++] & 0xff) << 16 | (sArr[s++] & 0xff) << 8 | (sArr[s++] & 0xff); - - // Encode the int into four chars - dArr[d++] = CA[(i >>> 18) & 0x3f]; - dArr[d++] = CA[(i >>> 12) & 0x3f]; - dArr[d++] = CA[(i >>> 6) & 0x3f]; - dArr[d++] = CA[i & 0x3f]; - - // Add optional line separator - if (lineSep && ++cc == 19 && d < dLen - 2) { - dArr[d++] = '\r'; - dArr[d++] = '\n'; - cc = 0; - } - } - - // Pad and encode last bits if source isn't even 24 bits. - int left = sLen - eLen; // 0 - 2. - if (left > 0) { - // Prepare the int - int i = ((sArr[eLen] & 0xff) << 10) | (left == 2 ? ((sArr[sLen - 1] & 0xff) << 2) : 0); - - // Set last four chars - dArr[dLen - 4] = CA[i >> 12]; - dArr[dLen - 3] = CA[(i >>> 6) & 0x3f]; - dArr[dLen - 2] = left == 2 ? CA[i & 0x3f] : fillChar; - dArr[dLen - 1] = fillChar; - } - return dArr; - } - - public char[] getAlphabet() { - return CA; - } -} diff --git a/akka-parsing/src/main/scala-2/akka/parboiled2/DynamicRuleDispatchMacro.scala b/akka-parsing/src/main/scala-2/akka/parboiled2/DynamicRuleDispatchMacro.scala new file mode 100644 index 00000000000..9e8c8f1d940 --- /dev/null +++ b/akka-parsing/src/main/scala-2/akka/parboiled2/DynamicRuleDispatchMacro.scala @@ -0,0 +1,65 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2 + +import scala.reflect.macros.whitebox +import akka.parboiled2.support.hlist.HList + +import scala.collection.immutable + +trait DynamicRuleDispatchMacro { _: DynamicRuleDispatch.type => + + /** + * Implements efficient runtime dispatch to a predefined set of parser rules. + * Given a number of rule names this macro-supported method creates a `DynamicRuleDispatch` instance along with + * a sequence of the given rule names. + * Note that there is no reflection involved and compilation will fail, if one of the given rule names + * does not constitute a method of parser type `P` or has a type different from `RuleN[L]`. + */ + def apply[P <: Parser, L <: HList](ruleNames: String*): (DynamicRuleDispatch[P, L], immutable.Seq[String]) = macro DynamicRuleDispatch.__create[P, L] + + ///////////////////// INTERNAL //////////////////////// + + def __create[P <: Parser, L <: HList](c: whitebox.Context)(ruleNames: c.Expr[String]*)(implicit P: c.WeakTypeTag[P], L: c.WeakTypeTag[L]): c.Expr[(DynamicRuleDispatch[P, L], immutable.Seq[String])] = { + import c.universe._ + val names = ruleNames.map { + _.tree match { + case Literal(Constant(s: String)) => s + case x => c.abort(x.pos, s"Invalid `String` argument `x`, only `String` literals are supported!") + } + } + + def ruleEntry(name: String): Tree = + q"""($name, new RuleRunner[$P, $L] { + def apply(handler: DynamicRuleHandler[$P, $L]): handler.Result = { + val p = handler.parser + p.__run[$L](p.${TermName(name).encodedName.toTermName})(handler) + } + })""" + val ruleEntries: Seq[Tree] = names.map(ruleEntry(_)) + + c.Expr[(DynamicRuleDispatch[P, L], immutable.Seq[String])] { + q"""val map: Map[String, RuleRunner[$P, $L]] = Map(..$ruleEntries) + val drd = + new akka.parboiled2.DynamicRuleDispatch[$P, $L] { + def lookup(ruleName: String): Option[RuleRunner[$P, $L]] = + map.get(ruleName) + } + (drd, scala.collection.immutable.Seq(..$ruleNames))""" + } + } +} diff --git a/akka-parsing/src/main/scala-2/akka/parboiled2/ParserMacros.scala b/akka-parsing/src/main/scala-2/akka/parboiled2/ParserMacros.scala new file mode 100644 index 00000000000..b0712739b83 --- /dev/null +++ b/akka-parsing/src/main/scala-2/akka/parboiled2/ParserMacros.scala @@ -0,0 +1,99 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2 + +import akka.parboiled2.support.OpTreeContext +import akka.parboiled2.support.hlist.HList + +private[parboiled2] trait ParserMacroMethods { + + /** + * Converts a compile-time only rule definition into the corresponding rule method implementation. + */ + def rule[I <: HList, O <: HList](r: Rule[I, O]): Rule[I, O] = macro ParserMacros.ruleImpl[I, O] + + /** + * Converts a compile-time only rule definition into the corresponding rule method implementation + * with an explicitly given name. + */ + def namedRule[I <: HList, O <: HList](name: String)(r: Rule[I, O]): Rule[I, O] = macro ParserMacros.namedRuleImpl[I, O] + +} + +private[parboiled2] trait RuleRunnable { + + /** + * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! + */ + implicit class Runnable[L <: HList](rule: RuleN[L]) { + def run()(implicit scheme: Parser.DeliveryScheme[L]): scheme.Result = macro ParserMacros.runImpl[L] + } +} + +object ParserMacros { + import scala.reflect.macros.whitebox.Context + + /** + * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! + */ + type RunnableRuleContext[L <: HList] = Context { type PrefixType = Rule.Runnable[L] } + + def runImpl[L <: HList: c.WeakTypeTag]( + c: RunnableRuleContext[L] + )()(scheme: c.Expr[Parser.DeliveryScheme[L]]): c.Expr[scheme.value.Result] = { + import c.universe._ + val runCall = c.prefix.tree match { + case q"parboiled2.this.Rule.Runnable[$l]($ruleExpr)" => + ruleExpr match { + case q"$p.$r[..$ts](...$argss)" if p.tpe <:< typeOf[Parser] => + q"val p = $p; p.__run[$l](p.$r[..$ts](...$argss))($scheme)" + case rule if rule.tpe <:< typeOf[RuleX] => q"__run[$l]($ruleExpr)($scheme)" + case x => c.abort(x.pos, "Illegal `.run()` call base: " + x) + } + case x => c.abort(x.pos, "Illegal `Runnable.apply` call: " + x) + } + c.Expr[scheme.value.Result](runCall) + } + + /** + * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! + */ + type ParserContext = Context { type PrefixType = Parser } + + def ruleImpl[I <: HList: ctx.WeakTypeTag, O <: HList: ctx.WeakTypeTag]( + ctx: ParserContext + )(r: ctx.Expr[Rule[I, O]]): ctx.Expr[Rule[I, O]] = { + import ctx.universe._ + namedRuleImpl(ctx)(ctx.Expr[String](Literal(Constant(ctx.internal.enclosingOwner.name.decodedName.toString))))(r) + } + + def namedRuleImpl[I <: HList: ctx.WeakTypeTag, O <: HList: ctx.WeakTypeTag]( + ctx: ParserContext + )(name: ctx.Expr[String])(r: ctx.Expr[Rule[I, O]]): ctx.Expr[Rule[I, O]] = { + val opTreeCtx = new OpTreeContext[ctx.type] { val c: ctx.type = ctx } + val opTree = opTreeCtx.RuleCall(Left(opTreeCtx.OpTree(r.tree)), name.tree) + import ctx.universe._ + val ruleTree = q""" + def wrapped: Boolean = ${opTree.render(wrapped = true)} + val matched = + if (__inErrorAnalysis) wrapped + else ${opTree.render(wrapped = false)} + if (matched) akka.parboiled2.Rule else null""" // we encode the "matched" boolean as 'ruleResult ne null' + + reify(ctx.Expr[RuleX](ruleTree).splice.asInstanceOf[Rule[I, O]]) + } +} diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/HListable.scala b/akka-parsing/src/main/scala-2/akka/parboiled2/support/HListable.scala similarity index 87% rename from akka-parsing/src/main/scala/akka/parboiled2/support/HListable.scala rename to akka-parsing/src/main/scala-2/akka/parboiled2/support/HListable.scala index d03b211d02f..62e174f751b 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/HListable.scala +++ b/akka-parsing/src/main/scala-2/akka/parboiled2/support/HListable.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,7 +16,7 @@ package akka.parboiled2.support -import akka.shapeless._ +import akka.parboiled2.support.hlist._ trait HListable[T] { type Out <: HList diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/OpTreeContext.scala b/akka-parsing/src/main/scala-2/akka/parboiled2/support/OpTreeContext.scala similarity index 85% rename from akka-parsing/src/main/scala/akka/parboiled2/support/OpTreeContext.scala rename to akka-parsing/src/main/scala-2/akka/parboiled2/support/OpTreeContext.scala index b555632bc79..53215b8751f 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/OpTreeContext.scala +++ b/akka-parsing/src/main/scala-2/akka/parboiled2/support/OpTreeContext.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -64,10 +64,13 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } sealed abstract class PotentiallyNamedTerminalOpTree(arg: Tree) extends TerminalOpTree { - override def bubbleUp = callName(arg) match { - case Some(name) => q"__bubbleUp(akka.parboiled2.RuleTrace.NonTerminal(akka.parboiled2.RuleTrace.Named($name), 0) :: Nil, $ruleTraceTerminal)" - case None => super.bubbleUp - } + + override def bubbleUp = + callName(arg) match { + case Some(name) => + q"__bubbleUp(akka.parboiled2.RuleTrace.NonTerminal(akka.parboiled2.RuleTrace.Named($name), 0) :: Nil, $ruleTraceTerminal)" + case None => super.bubbleUp + } def ruleTraceTerminal: Tree } @@ -85,7 +88,8 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case q"$lhs.|[$a, $b]($rhs)" => FirstOf(OpTree(lhs), OpTree(rhs)) case q"$a.this.ch($c)" => CharMatch(c) case q"$a.this.str($s)" => StringMatch(s) - case q"$a.this.valueMap[$b]($m)($hl)" => MapMatch(m) + case q"$a.this.valueMap[$b]($m)($hl)" => MapMatch(m, q"false") + case q"$a.this.valueMap[$b]($m, $ic)($hl)" => MapMatch(m, ic) case q"$a.this.ignoreCase($t)" => IgnoreCase(t) case q"$a.this.predicate($p)" => CharPredicateMatch(p) case q"$a.this.anyOf($s)" => AnyOf(s) @@ -114,9 +118,9 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case q"$a.this.failX[$b, $c]($m)" => Fail(m) case q"$a.named($name)" => Named(OpTree(a), name) case x @ q"$a.this.str2CharRangeSupport($l).-($r)" => CharRange(l, r) - case q"$a.this.charAndValue[$t]($b.any2ArrowAssoc[$t1]($c).->[$t2]($v))($hl)" => + case q"$a.this.charAndValue[$t]($b.ArrowAssoc[$t1]($c).->[$t2]($v))($hl)" => Sequence(CharMatch(c), PushAction(v, hl)) - case q"$a.this.stringAndValue[$t]($b.any2ArrowAssoc[$t1]($s).->[$t2]($v))($hl)" => + case q"$a.this.stringAndValue[$t]($b.ArrowAssoc[$t1]($s).->[$t2]($v))($hl)" => Sequence(StringMatch(s), PushAction(v, hl)) case q"$a.this.rule2ActionOperator[$b1, $b2]($r)($o).~>.apply[..$e]($f)($g, support.this.FCapture.apply[$ts])" => Sequence(OpTree(r), Action(f, ts)) @@ -143,9 +147,13 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class Sequence(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { require(ops.size >= 2) def ruleTraceNonTerminalKey = reify(RuleTrace.Sequence).tree + def renderInner(wrapped: Boolean): Tree = - ops.map(_.render(wrapped)).reduceLeft((l, r) => - q"val l = $l; if (l) $r else false") // work-around for https://issues.scala-lang.org/browse/SI-8657" + ops + .map(_.render(wrapped)) + .reduceLeft((l, r) => + q"val l = $l; if (l) $r else false" + ) // work-around for https://issues.scala-lang.org/browse/SI-8657" } case class Cut(lhs: OpTree, rhs: OpTree) extends DefaultNonTerminalOpTree { @@ -169,15 +177,20 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class FirstOf(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { def ruleTraceNonTerminalKey = reify(RuleTrace.FirstOf).tree + def renderInner(wrapped: Boolean): Tree = q"""val mark = __saveState; ${ - ops.map(_.render(wrapped)).reduceLeft((l, r) => - q"val l = $l; if (!l) { __restoreState(mark); $r } else true // work-around for https://issues.scala-lang.org/browse/SI-8657") + ops + .map(_.render(wrapped)) + .reduceLeft((l, r) => + q"val l = $l; if (!l) { __restoreState(mark); $r } else true // work-around for https://issues.scala-lang.org/browse/SI-8657" + ) }""" } case class CharMatch(charTree: Tree) extends TerminalOpTree { def ruleTraceTerminal = q"akka.parboiled2.RuleTrace.CharMatch($charTree)" + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q"cursorChar == $charTree && __advance()" if (wrapped) q"$unwrappedTree && __updateMaxCursor() || __registerMismatch()" else unwrappedTree @@ -186,6 +199,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class StringMatch(stringTree: Tree) extends OpTree { final private val autoExpandMaxStringLength = 8 + def render(wrapped: Boolean): Tree = { def unrollUnwrapped(s: String, ix: Int = 0): Tree = if (ix < s.length) q""" @@ -221,8 +235,11 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } } - case class MapMatch(mapTree: Tree) extends OpTree { - def render(wrapped: Boolean): Tree = if (wrapped) q"__matchMapWrapped($mapTree)" else q"__matchMap($mapTree)" + case class MapMatch(mapTree: Tree, ignoreCaseTree: Tree) extends OpTree { + + def render(wrapped: Boolean): Tree = + if (wrapped) q"__matchMapWrapped($mapTree, $ignoreCaseTree)" + else q"__matchMap($mapTree, $ignoreCaseTree)" } def IgnoreCase(argTree: Tree): OpTree = { @@ -234,6 +251,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class IgnoreCaseChar(charTree: Tree) extends TerminalOpTree { def ruleTraceTerminal = q"akka.parboiled2.RuleTrace.IgnoreCaseChar($charTree)" + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q"_root_.java.lang.Character.toLowerCase(cursorChar) == $charTree && __advance()" if (wrapped) q"$unwrappedTree && __updateMaxCursor() || __registerMismatch()" else unwrappedTree @@ -242,6 +260,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class IgnoreCaseString(stringTree: Tree) extends OpTree { final private val autoExpandMaxStringLength = 8 + def render(wrapped: Boolean): Tree = { def unrollUnwrapped(s: String, ix: Int = 0): Tree = if (ix < s.length) q""" @@ -279,6 +298,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class CharPredicateMatch(predicateTree: Tree) extends PotentiallyNamedTerminalOpTree(predicateTree) { def ruleTraceTerminal = q"akka.parboiled2.RuleTrace.CharPredicateMatch($predicateTree)" + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q"$predicateTree(cursorChar) && __advance()" if (wrapped) q"$unwrappedTree && __updateMaxCursor() || __registerMismatch()" else unwrappedTree @@ -287,6 +307,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class AnyOf(stringTree: Tree) extends TerminalOpTree { def ruleTraceTerminal = q"akka.parboiled2.RuleTrace.AnyOf($stringTree)" + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q"__matchAnyOf($stringTree)" if (wrapped) q"$unwrappedTree && __updateMaxCursor() || __registerMismatch()" else unwrappedTree @@ -295,6 +316,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class NoneOf(stringTree: Tree) extends TerminalOpTree { def ruleTraceTerminal = q"akka.parboiled2.RuleTrace.NoneOf($stringTree)" + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q"__matchNoneOf($stringTree)" if (wrapped) q"$unwrappedTree && __updateMaxCursor() || __registerMismatch()" else unwrappedTree @@ -303,6 +325,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case object ANY extends TerminalOpTree { def ruleTraceTerminal = reify(RuleTrace.ANY).tree + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q"cursorChar != EOI && __advance()" if (wrapped) q"$unwrappedTree && __updateMaxCursor() || __registerMismatch()" else unwrappedTree @@ -330,6 +353,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class ZeroOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { def withSeparator(sep: Separator) = copy(separator = sep) def ruleTraceNonTerminalKey = reify(RuleTrace.ZeroOrMore).tree + def renderInner(wrapped: Boolean): Tree = { val recurse = if (separator eq null) q"rec(__saveState)" @@ -354,6 +378,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class OneOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { def withSeparator(sep: Separator) = copy(separator = sep) def ruleTraceNonTerminalKey = reify(RuleTrace.OneOrMore).tree + def renderInner(wrapped: Boolean): Tree = { val recurse = if (separator eq null) q"rec(__saveState)" @@ -379,42 +404,48 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } } - def Times(base: Tree, rule: OpTree, collector: Collector, separator: Separator = null): OpTree = { - def handleRange(mn: Tree, mx: Tree, r: Tree) = (mn, mx) match { - case (Literal(Constant(min: Int)), Literal(Constant(max: Int))) => - if (min <= 0) c.abort(mn.pos, "`min` in `(min to max).times` must be positive") - else if (max <= 0) c.abort(mx.pos, "`max` in `(min to max).times` must be positive") - else if (max < min) c.abort(mx.pos, "`max` in `(min to max).times` must be >= `min`") - else Times(rule, q"val min = $mn; val max = $mx", collector, separator) - case ((Ident(_) | Select(_, _)), (Ident(_) | Select(_, _))) => - Times(rule, q"val min = $mn; val max = $mx", collector, separator) - case _ => c.abort(r.pos, "Invalid int range expression for `.times(...)`: " + r) - } - + def Times(base: Tree, rule: OpTree, collector: Collector, separator: Separator = null): OpTree = base match { - case q"$a.this.int2NTimes($n)" => n match { - case Literal(Constant(i: Int)) => - if (i <= 0) c.abort(base.pos, "`x` in `x.times` must be positive") - else if (i == 1) rule - else Times(rule, q"val min, max = $n", collector, separator) - case x @ (Ident(_) | Select(_, _)) => Times(rule, q"val min = $n; val max = min", collector, separator) - case _ => c.abort(n.pos, "Invalid int base expression for `.times(...)`: " + n) - } - case q"$a.this.range2NTimes($r)" => r match { - case q"scala.Predef.intWrapper($mn).to($mx)" => handleRange(mn, mx, r) // Scala 2.12 - case q"scala.this.Predef.intWrapper($mn).to($mx)" => handleRange(mn, mx, r) // Scala 2.11 - case x @ (Ident(_) | Select(_, _)) => - Times(rule, q"val r = $r; val min = r.start; val max = r.end", collector, separator) - case _ => c.abort(r.pos, "Invalid range base expression for `.times(...)`: " + r) - } + case q"$a.this.int2NTimes($n)" => + n match { + case Literal(Constant(i: Int)) => + if (i <= 0) c.abort(base.pos, "`x` in `x.times` must be positive") + else if (i == 1) rule + else Times(rule, q"val min, max = $n", collector, separator) + case i => Times(rule, q"val min = $i; val max = min", collector, separator) + } + case q"$a.this.range2NTimes($r)" => + r match { + case q"${ _ }.Predef.intWrapper($mn).to($mx)" => + mn match { + case Literal(Constant(min: Int)) => + if (min <= 0) c.abort(mn.pos, "`min` in `(min to max).times` must be positive") + case (Ident(_) | Select(_, _)) => + case _ => c.abort(r.pos, "Invalid int range expression for `min` in `.times(...)`: " + r) + } + mx match { + case Literal(Constant(max: Int)) => + if (max <= 0) c.abort(mx.pos, "`max` in `(min to max).times` must be positive") + case (Ident(_) | Select(_, _)) => + case _ => c.abort(r.pos, "Invalid int range expression for `max` in `.times(...)`: " + r) + } + (mn, mx) match { + case (Literal(Constant(min: Int)), Literal(Constant(max: Int))) => + if (max < min) c.abort(mx.pos, "`max` in `(min to max).times` must be >= `min`") + case _ => + } + Times(rule, q"val min = $mn; val max = $mx", collector, separator) + case r => + Times(rule, q"val r = $r; val min = r.start; val max = r.end", collector, separator) + } case _ => c.abort(base.pos, "Invalid base expression for `.times(...)`: " + base) } - } case class Times(op: OpTree, init: Tree, collector: Collector, separator: Separator) extends WithSeparator { def withSeparator(sep: Separator) = copy(separator = sep) val Block(inits, _) = init def ruleTraceNonTerminalKey = q"..$inits; akka.parboiled2.RuleTrace.Times(min, max)" + def renderInner(wrapped: Boolean): Tree = { val recurse = if (separator eq null) q"rec(count + 1, __saveState)" @@ -425,6 +456,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { q""" ${collector.valBuilder} ..$inits + require(min <= max, "`max` in `(min to max).times` must be >= `min`") @_root_.scala.annotation.tailrec def rec(count: Int, mark: akka.parboiled2.Parser.Mark): Boolean = { val matched = ${op.render(wrapped)} @@ -448,6 +480,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } case class NotPredicate(op: OpTree) extends OpTree { + def render(wrapped: Boolean): Tree = { val unwrappedTree = q""" val mark = __saveState @@ -461,8 +494,8 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { val base = op match { case x: TerminalOpTree => q"akka.parboiled2.RuleTrace.NotPredicate.Terminal(${x.ruleTraceTerminal})" case x: RuleCall => q"akka.parboiled2.RuleTrace.NotPredicate.RuleCall(${x.calleeNameTree})" - case x: StringMatch => q"""akka.parboiled2.RuleTrace.NotPredicate.Named('"' + ${x.stringTree} + '"')""" - case x: IgnoreCaseString => q"""akka.parboiled2.RuleTrace.NotPredicate.Named('"' + ${x.stringTree} + '"')""" + case x: StringMatch => q"""akka.parboiled2.RuleTrace.NotPredicate.Named("\"" + ${x.stringTree} + '"')""" + case x: IgnoreCaseString => q"""akka.parboiled2.RuleTrace.NotPredicate.Named("\"" + ${x.stringTree} + '"')""" case x: Named => q"akka.parboiled2.RuleTrace.NotPredicate.Named(${x.stringTree})" case _ => q"akka.parboiled2.RuleTrace.NotPredicate.Anonymous" } @@ -480,6 +513,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class Atomic(op: OpTree) extends DefaultNonTerminalOpTree { def ruleTraceNonTerminalKey = reify(RuleTrace.Atomic).tree + def renderInner(wrapped: Boolean): Tree = if (wrapped) q""" val saved = __enterAtomic(start) @@ -491,6 +525,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class Quiet(op: OpTree) extends DefaultNonTerminalOpTree { def ruleTraceNonTerminalKey = reify(RuleTrace.Quiet).tree + def renderInner(wrapped: Boolean): Tree = if (wrapped) q""" val saved = __enterQuiet() @@ -502,6 +537,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class SemanticPredicate(flagTree: Tree) extends TerminalOpTree { def ruleTraceTerminal = reify(RuleTrace.SemanticPredicate).tree + def renderInner(wrapped: Boolean): Tree = if (wrapped) q"$flagTree || __registerMismatch()" else flagTree } @@ -519,6 +555,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class RunAction(argTree: Tree, rrTree: Tree) extends DefaultNonTerminalOpTree { def ruleTraceNonTerminalKey = reify(RuleTrace.Run).tree + def renderInner(wrapped: Boolean): Tree = { def renderFunctionAction(resultTypeTree: Tree, argTypeTrees: Tree*): Tree = { def actionBody(tree: Tree): Tree = @@ -532,7 +569,10 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case x if isSubClass(resultTypeTree.tpe, "akka.parboiled2.Rule") => expand(x, wrapped) case x => q"__push($x)" } - val valDefs = args.zip(argTypeTrees).map { case (a, t) => q"val ${a.name} = valueStack.pop().asInstanceOf[${t.tpe}]" }.reverse + val valDefs = args + .zip(argTypeTrees) + .map { case (a, t) => q"val ${a.name} = valueStack.pop().asInstanceOf[${t.tpe}]" } + .reverse block(valDefs, rewrite(body)) case x => c.abort(argTree.pos, "Unexpected `run` argument: " + show(argTree)) @@ -542,15 +582,16 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } rrTree match { - case q"RunResult.this.Aux.forAny[$t]" => block(argTree, q"true") + case q"RunResult.this.Aux.forAny[$t]" => block(argTree, q"true") - case q"RunResult.this.Aux.forRule[$t]" => expand(argTree, wrapped) + case q"RunResult.this.Aux.forRule[$t]" => expand(argTree, wrapped) - case q"RunResult.this.Aux.forF1[$z, $r, $in, $out]($a)" => renderFunctionAction(r, z) - case q"RunResult.this.Aux.forF2[$y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, y, z) - case q"RunResult.this.Aux.forF3[$x, $y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, x, y, z) - case q"RunResult.this.Aux.forF4[$w, $x, $y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, w, x, y, z) - case q"RunResult.this.Aux.forF5[$v, $w, $x, $y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, v, w, x, y, z) + case q"RunResult.this.Aux.forF1[$z, $r, $in, $out]($a)" => renderFunctionAction(r, z) + case q"RunResult.this.Aux.forF2[$y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, y, z) + case q"RunResult.this.Aux.forF3[$x, $y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, x, y, z) + case q"RunResult.this.Aux.forF4[$w, $x, $y, $z, $r, $in, $out]($a)" => renderFunctionAction(r, w, x, y, z) + case q"RunResult.this.Aux.forF5[$v, $w, $x, $y, $z, $r, $in, $out]($a)" => + renderFunctionAction(r, v, w, x, y, z) case q"RunResult.this.Aux.forFHList[$il, $r, $in, $out]($a)" => c.abort(argTree.pos, "`run` with a function taking an HList is not yet implemented") // TODO: implement @@ -561,25 +602,31 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } case class PushAction(argTree: Tree, hlTree: Tree) extends OpTree { + def render(wrapped: Boolean): Tree = - block(hlTree match { - case q"support.this.HListable.fromUnit" => argTree - case q"support.this.HListable.fromHList[$t]" => q"valueStack.pushAll(${c.untypecheck(argTree)})" - case q"support.this.HListable.fromAnyRef[$t]" => q"valueStack.push(${c.untypecheck(argTree)})" - case x => c.abort(hlTree.pos, "Unexpected HListable: " + show(x)) - }, q"true") + block( + hlTree match { + case q"support.this.HListable.fromUnit" => argTree + case q"support.this.HListable.fromHList[$t]" => q"valueStack.pushAll(${c.untypecheck(argTree)})" + case q"support.this.HListable.fromAnyRef[$t]" => q"valueStack.push(${c.untypecheck(argTree)})" + case x => c.abort(hlTree.pos, "Unexpected HListable: " + show(x)) + }, + q"true" + ) } case class DropAction(hlTree: Tree) extends OpTree { + def render(wrapped: Boolean): Tree = hlTree match { case q"support.this.HListable.fromUnit" => q"true" case q"support.this.HListable.fromAnyRef[$t]" => q"valueStack.pop(); true" case q"support.this.HListable.fromHList[$t]" => @tailrec def rec(t: Type, result: List[Tree] = Nil): List[Tree] = - t match { // TODO: how can we use type quotes here, e.g. tq"shapeless.HNil"? - case TypeRef(_, sym, List(_, tail)) if sym == HListConsTypeSymbol => rec(tail, q"valueStack.pop()" :: result) - case TypeRef(_, sym, _) if sym == HNilTypeSymbol => result + t match { // TODO: how can we use type quotes here, e.g. tq"akka.parboiled2.support.hlist.HNil"? + case TypeRef(_, sym, List(_, tail)) if sym == HListConsTypeSymbol => + rec(tail, q"valueStack.pop()" :: result) + case TypeRef(_, sym, _) if sym == HNilTypeSymbol => result } Block(rec(t.tpe), q"true") case x => c.abort(hlTree.pos, "Unexpected HListable: " + show(x)) @@ -590,11 +637,13 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { def bubbleUp = q""" import akka.parboiled2.RuleTrace._ e.prepend(RuleCall, start).bubbleUp(Named($calleeNameTree), start)""" + override def render(wrapped: Boolean) = call match { case Left(_) => super.render(wrapped) case Right(x) => q"$x ne null" } + def renderInner(wrapped: Boolean) = { val Left(value) = call.asInstanceOf[Left[OpTree, Tree]] value.render(wrapped) @@ -616,6 +665,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class CharacterRange(lowerBound: Char, upperBound: Char) extends TerminalOpTree { def ruleTraceTerminal = q"akka.parboiled2.RuleTrace.CharRange($lowerBound, $upperBound)" + def renderInner(wrapped: Boolean): Tree = { val unwrappedTree = q""" val char = cursorChar @@ -625,11 +675,13 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { } case class Action(actionTree: Tree, actionTypeTree: Tree) extends DefaultNonTerminalOpTree { + val actionType: List[Type] = actionTypeTree.tpe match { case TypeRef(_, _, args) if args.nonEmpty => args case x => c.abort(actionTree.pos, "Unexpected action type: " + x) } def ruleTraceNonTerminalKey = reify(RuleTrace.Action).tree + def renderInner(wrapped: Boolean): Tree = { val argTypes = actionType dropRight 1 @@ -641,7 +693,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case Block(statements, res) => block(statements, actionBody(res)) case x @ (Ident(_) | Select(_, _)) => - val valNames: List[TermName] = argTypes.indices.iterator.map { i => TermName("value" + i) }.toList + val valNames = argTypes.indices.map(i => TermName("value" + i)).toList val args = valNames map Ident.apply block(popToVals(valNames), q"__push($x(..$args))") @@ -661,6 +713,7 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { case class RunSubParser(fTree: Tree) extends DefaultNonTerminalOpTree { def ruleTraceNonTerminalKey = reify(RuleTrace.RunSubParser).tree + def renderInner(wrapped: Boolean): Tree = { def rewrite(arg: TermName, tree: Tree): Tree = tree match { @@ -696,7 +749,8 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { val popToBuilder: Tree, val pushBuilderResult: Tree, val pushSomePop: Tree, - val pushNone: Tree) + val pushNone: Tree + ) lazy val rule0Collector = { val unit = q"()" @@ -708,14 +762,15 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { popToBuilder = q"builder += valueStack.pop()", pushBuilderResult = q"valueStack.push(builder.result()); true", pushSomePop = q"valueStack.push(Some(valueStack.pop()))", - pushNone = q"valueStack.push(None)") + pushNone = q"valueStack.push(None)" + ) type Separator = Boolean => Tree def Separator(op: OpTree): Separator = wrapped => op.render(wrapped) - lazy val HListConsTypeSymbol = c.mirror.staticClass("shapeless.$colon$colon") - lazy val HNilTypeSymbol = c.mirror.staticClass("shapeless.HNil") + lazy val HListConsTypeSymbol = c.mirror.staticClass("akka.parboiled2.support.hlist.$colon$colon") + lazy val HNilTypeSymbol = c.mirror.staticClass("akka.parboiled2.support.hlist.HNil") // tries to match and expand the leaves of the given Tree def expand(tree: Tree, wrapped: Boolean): Tree = @@ -739,14 +794,16 @@ trait OpTreeContext[OpTreeCtx <: ParserMacros.ParserContext] { def block(a: Tree, b: Tree): Tree = a match { - case Block(a1, a2) => b match { - case Block(b1, b2) => Block(a1 ::: a2 :: b1, b2) - case _ => Block(a1 ::: a2 :: Nil, b) - } - case _ => b match { - case Block(b1, b2) => Block(a :: b1, b2) - case _ => Block(a :: Nil, b) - } + case Block(a1, a2) => + b match { + case Block(b1, b2) => Block(a1 ::: a2 :: b1, b2) + case _ => Block(a1 ::: a2 :: Nil, b) + } + case _ => + b match { + case Block(b1, b2) => Block(a :: b1, b2) + case _ => Block(a :: Nil, b) + } } def block(stmts: List[Tree], expr: Tree): Tree = diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/TailSwitch.scala b/akka-parsing/src/main/scala-2/akka/parboiled2/support/TailSwitch.scala similarity index 82% rename from akka-parsing/src/main/scala/akka/parboiled2/support/TailSwitch.scala rename to akka-parsing/src/main/scala-2/akka/parboiled2/support/TailSwitch.scala index e5855d96351..cd0743a359b 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/TailSwitch.scala +++ b/akka-parsing/src/main/scala-2/akka/parboiled2/support/TailSwitch.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -17,17 +17,17 @@ package akka.parboiled2.support import scala.annotation.implicitNotFound -import akka.shapeless._ -import akka.shapeless.ops.hlist.ReversePrepend +import akka.parboiled2.support.hlist._ +import akka.parboiled2.support.hlist.ops.hlist.ReversePrepend // format: OFF /** - * type-level implementation of this logic: - * Out = - * R if T has a tail of type L - * (L dropRight T) ::: R if L has a tail of type T - */ + * type-level implementation of this logic: + * Out = + * R if T has a tail of type L + * (L dropRight T) ::: R if L has a tail of type T + */ @implicitNotFound("Illegal rule composition") sealed trait TailSwitch[L <: HList, T <: HList, R <: HList] { type Out <: HList @@ -42,7 +42,7 @@ object TailSwitch { // else if (LI <: T) RI.reverse ::: R // else if (LI <: HNil) rec(L, HNil, T, TI.tail, R, RI) // else if (TI <: HNil) rec(L, LI.tail, T, HNil, R, LI.head :: RI) - // rec(L, LI.tail, T, TI.tail, R, LI.head :: RI) + // else rec(L, LI.tail, T, TI.tail, R, LI.head :: RI) // rec(L, L, T, T, R, HNil) sealed trait Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out <: HList] @@ -52,13 +52,13 @@ object TailSwitch { Aux[L, LI, T, TI, R, RI, R] = `n/a` } - private[parboiled2] abstract class Aux1 extends Aux2 { + abstract private[parboiled2] class Aux1 extends Aux2 { // if LI <: T then Out = RI.reverse ::: R implicit def terminate2[T <: HList, TI <: HList, L <: HList, LI <: T, R <: HList, RI <: HList, Out <: HList] (implicit rp: ReversePrepend.Aux[RI, R, Out]): Aux[L, LI, T, TI, R, RI, Out] = `n/a` } - private[parboiled2] abstract class Aux2 { + abstract private[parboiled2] class Aux2 { implicit def iter1[L <: HList, T <: HList, TH, TT <: HList, R <: HList, RI <: HList, Out <: HList] (implicit next: Aux[L, HNil, T, TT, R, RI, Out]): Aux[L, HNil, T, TH :: TT, R, RI, Out] = `n/a` @@ -68,4 +68,4 @@ object TailSwitch { implicit def iter3[L <: HList, LH, LT <: HList, T <: HList, TH, TT <: HList, R <: HList, RI <: HList, Out <: HList] (implicit next: Aux[L, LT, T, TT, R, LH :: RI, Out]): Aux[L, LH :: LT, T, TH :: TT, R, RI, Out] = `n/a` } -} \ No newline at end of file +} diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala new file mode 100644 index 00000000000..77a33bc85ea --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala @@ -0,0 +1,76 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2 + +import akka.parboiled2.support.hlist.HList + +import scala.collection.immutable + +trait DynamicRuleDispatchMacro { self: DynamicRuleDispatch.type => + + /** Implements efficient runtime dispatch to a predefined set of parser rules. + * Given a number of rule names this macro-supported method creates a `DynamicRuleDispatch` instance along with + * a sequence of the given rule names. + * Note that there is no reflection involved and compilation will fail, if one of the given rule names + * does not constitute a method of parser type `P` or has a type different from `RuleN[L]`. + */ + inline def apply[P <: Parser, L <: HList]( + inline ruleNames: String* + ): (DynamicRuleDispatch[P, L], immutable.Seq[String]) = + ${ DynamicRuleDispatch.__create[P, L]('ruleNames) } + + import scala.quoted._ + def __create[P <: Parser: Type, L <: HList: Type]( + ruleNames: Expr[Seq[String]] + )(using Quotes): Expr[(DynamicRuleDispatch[P, L], immutable.Seq[String])] = { + val names: Seq[String] = ruleNames match { + case Varargs(Exprs(args)) => args.sorted + } + + def dispatcher(handler: Expr[DynamicRuleHandler[P, L]], ruleName: Expr[String]): Expr[Any] = { + import quotes.reflect._ + def ruleExpr(name: String): Expr[RuleN[L]] = Select.unique('{ $handler.parser }.asTerm, name).asExprOf[RuleN[L]] + def rec(start: Int, end: Int): Expr[Any] = + if (start <= end) { + val mid = (start + end) >>> 1 + val name = names(mid) + + '{ + val c = ${ Expr(name) } compare $ruleName + if (c < 0) ${ rec(mid + 1, end) } + else if (c > 0) ${ rec(start, mid - 1) } + else { + val p = $handler.parser + p.__run[L](${ ruleExpr(name) })($handler) + } + } + } else '{ $handler.ruleNotFound($ruleName) } + + rec(0, names.length - 1) + } + + '{ + val dispatch: DynamicRuleDispatch[P, L] = + new DynamicRuleDispatch[P, L] { + def apply(handler: DynamicRuleHandler[P, L], ruleName: String): handler.Result = + ${ dispatcher('handler, 'ruleName).asInstanceOf[Expr[handler.Result]] } + } + + (dispatch, $ruleNames) + } + } +} diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala new file mode 100644 index 00000000000..5654a6bfc11 --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala @@ -0,0 +1,1127 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2 + +import akka.parboiled2.support.hlist.HList + +import scala.annotation.tailrec + +private[parboiled2] trait ParserMacroMethods { parser: Parser => + + /** Converts a compile-time only rule definition into the corresponding rule method implementation. + */ + inline def rule[I <: HList, O <: HList](inline r: Rule[I, O]): Rule[I, O] = ${ ParserMacros.ruleImpl('parser, 'r) } + + /** Converts a compile-time only rule definition into the corresponding rule method implementation + * with an explicitly given name. + */ + inline def namedRule[I <: HList, O <: HList](name: String)(inline r: Rule[I, O]): Rule[I, O] = ${ + ParserMacros.nameRuleImpl('parser, 'name, 'r) + } + +} + +private[parboiled2] trait RuleRunnable { + + /** THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! + */ + extension [L <: HList](inline rule: RuleN[L]) { + inline def run()(using scheme: Parser.DeliveryScheme[L]): scheme.Result = + ${ ParserMacros.runImpl[L, scheme.Result]()('rule, 'scheme) } + } +} + +import scala.quoted._ +class OpTreeContext(parser: Expr[Parser])(using Quotes) { + import quotes.reflect.* + + sealed trait OpTree { + def render(wrapped: Boolean): Expr[Boolean] + } + + sealed abstract class NonTerminalOpTree extends OpTree { + def bubbleUp(e: Expr[akka.parboiled2.Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] + + // renders a Boolean Tree + def render(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + val start = $parser.cursor + try ${ renderInner('start, wrapped) } catch { + case e: akka.parboiled2.Parser#TracingBubbleException => ${ bubbleUp('e, 'start) } + } + } + else renderInner(Expr(-1) /* dummy, won't be used */, wrapped) + + // renders a Boolean Tree + protected def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] + } + + sealed abstract class DefaultNonTerminalOpTree extends NonTerminalOpTree { + def bubbleUp(e: Expr[akka.parboiled2.Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] = '{ + $e.bubbleUp($ruleTraceNonTerminalKey, $start) + } + def ruleTraceNonTerminalKey: Expr[RuleTrace.NonTerminalKey] + } + + sealed abstract class TerminalOpTree extends OpTree { + def bubbleUp: Expr[Nothing] = '{ $parser.__bubbleUp($ruleTraceTerminal) } + def ruleTraceTerminal: Expr[RuleTrace.Terminal] + + final def render(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + try ${ renderInner(wrapped) } catch { case akka.parboiled2.Parser.StartTracingException => $bubbleUp } + } + else renderInner(wrapped) + + protected def renderInner(wrapped: Boolean): Expr[Boolean] + } + sealed abstract private class PotentiallyNamedTerminalOpTree(arg: Term) extends TerminalOpTree { + override def bubbleUp: Expr[Nothing] = + callName(arg) match { + case Some(name) => + '{ $parser.__bubbleUp(RuleTrace.NonTerminal(RuleTrace.Named(${ Expr(name) }), 0) :: Nil, $ruleTraceTerminal) } + case None => super.bubbleUp + } + } + + def Sequence(lhs: OpTree, rhs: OpTree): Sequence = + lhs -> rhs match { + case (Sequence(lops), Sequence(rops)) => Sequence(lops ++ rops) + case (Sequence(lops), _) => Sequence(lops :+ rhs) + case (_, Sequence(ops)) => Sequence(lhs +: ops) + case _ => Sequence(Seq(lhs, rhs)) + } + + case class Sequence(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { + require(ops.size >= 2) + override def ruleTraceNonTerminalKey = '{ RuleTrace.Sequence } + override def renderInner(start: quoted.Expr[Int], wrapped: Boolean): Expr[Boolean] = + ops + .map(_.render(wrapped)) + .reduceLeft((l, r) => '{ val ll = $l; if (ll) $r else false }) + } + + case class Cut(lhs: OpTree, rhs: OpTree) extends DefaultNonTerminalOpTree { + override def ruleTraceNonTerminalKey = '{ RuleTrace.Cut } + override def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = '{ + var matched = ${ lhs.render(wrapped) } + if (matched) { + matched = ${ rhs.render(wrapped) } + if (!matched) throw akka.parboiled2.Parser.CutError + true + } else false + } // work-around for https://issues.scala-lang.org/browse/SI-8657 + } + + def FirstOf(lhs: OpTree, rhs: OpTree): FirstOf = + lhs -> rhs match { + case (FirstOf(lops), FirstOf(rops)) => FirstOf(lops ++ rops) + case (FirstOf(lops), _) => FirstOf(lops :+ rhs) + case (_, FirstOf(ops)) => FirstOf(lhs +: ops) + case _ => FirstOf(Seq(lhs, rhs)) + } + case class FirstOf(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.FirstOf } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + '{ + val mark = $parser.__saveState + ${ + ops + .map(_.render(wrapped)) + .reduceLeft((l0, r) => + '{ + val l = $l0 + if (!l) { + $parser.__restoreState(mark) + $r + } else + true // work-around for https://issues.scala-lang.org/browse/SI-8657", FIXME: still valid for dotty? + } + ) + } + } + } + + sealed abstract class WithSeparator extends DefaultNonTerminalOpTree { + def withSeparator(sep: Separator): OpTree + } + + case class ZeroOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { + def withSeparator(sep: Separator) = copy(separator = sep) + def ruleTraceNonTerminalKey = '{ RuleTrace.ZeroOrMore } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + '{ + @ _root_.scala.annotation.tailrec + def rec(mark: akka.parboiled2.Parser.Mark): akka.parboiled2.Parser.Mark = { + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.popToBuilder } + ${ + if (separator eq null) '{ rec($parser.__saveState) } + else + '{ + val m = $parser.__saveState + if (${ separator(wrapped) }) rec(m) else m + } + } + } else mark + } + + $parser.__restoreState(rec($parser.__saveState)) + ${ coll.pushBuilderResult } + true + } + } + } + case class OneOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { + def withSeparator(sep: Separator) = copy(separator = sep) + def ruleTraceNonTerminalKey = '{ RuleTrace.OneOrMore } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + '{ + @ _root_.scala.annotation.tailrec + def rec(mark: akka.parboiled2.Parser.Mark): akka.parboiled2.Parser.Mark = { + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.popToBuilder } + ${ + if (separator eq null) '{ rec($parser.__saveState) } + else + '{ + val m = $parser.__saveState + if (${ separator(wrapped) }) rec(m) else m + } + } + } else mark + } + + val firstMark = $parser.__saveState + val mark = rec(firstMark) + mark != firstMark && { // FIXME: almost the same as ZeroOrMore and should be combined + $parser.__restoreState(mark) + ${ coll.pushBuilderResult } + true + } + } + } + } + + case class Optional(op: OpTree, collector: Collector) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Optional } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + '{ + val mark = $parser.__saveState + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.pushSomePop } + } else { + $parser.__restoreState(mark) + ${ coll.pushNone } + } + true + } + } + } + + trait MinMaxSupplier { + def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] + } + object MinMaxSupplier { + def constant(n: Expr[Int]): MinMaxSupplier = + new MinMaxSupplier { + override def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] = + '{ + val min = $n + val max = min + + ${ f('min, 'max) } + } + } + + def range(rangeExpr: Expr[Range]): MinMaxSupplier = + new MinMaxSupplier { + override def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] = + '{ + val r = $rangeExpr + val min = r.min + val max = r.max + + ${ f('min, 'max) } + } + } + + /* FIXME: implement optimzations for literal values as shown below + +base match { + case q"$a.this.int2NTimes($n)" => + n match { + case Literal(Constant(i: Int)) => + if (i <= 0) c.abort(base.pos, "`x` in `x.times` must be positive") + else if (i == 1) rule + else Times(rule, q"val min, max = $n", collector, separator) + case x @ (Ident(_) | Select(_, _)) => Times(rule, q"val min = $n; val max = min", collector, separator) + case _ => c.abort(n.pos, "Invalid int base expression for `.times(...)`: " + n) + } + case q"$a.this.range2NTimes($r)" => + r match { + case q"${_}.Predef.intWrapper($mn).to($mx)" => + mn match { + case Literal(Constant(min: Int)) => + if (min <= 0) c.abort(mn.pos, "`min` in `(min to max).times` must be positive") + case (Ident(_) | Select(_, _)) => + case _ => c.abort(r.pos, "Invalid int range expression for `min` in `.times(...)`: " + r) + } + mx match { + case Literal(Constant(max: Int)) => + if (max <= 0) c.abort(mx.pos, "`max` in `(min to max).times` must be positive") + case (Ident(_) | Select(_, _)) => + case _ => c.abort(r.pos, "Invalid int range expression for `max` in `.times(...)`: " + r) + } + (mn, mx) match { + case (Literal(Constant(min: Int)), Literal(Constant(max: Int))) => + if (max < min) c.abort(mx.pos, "`max` in `(min to max).times` must be >= `min`") + case _ => + } + Times(rule, q"val min = $mn; val max = $mx", collector, separator) + case x @ (Ident(_) | Select(_, _)) => + Times(rule, q"val r = $r; val min = r.start; val max = r.end", collector, separator) + case _ => c.abort(r.pos, "Invalid range base expression for `.times(...)`: " + r) + } + case _ => c.abort(base.pos, "Invalid base expression for `.times(...)`: " + base) +}*/ + } + + case class Times( + op: OpTree, + withMinMax: MinMaxSupplier, + collector: Collector, + separator: Separator + ) extends WithSeparator { + def withSeparator(sep: Separator) = copy(separator = sep) + def ruleTraceNonTerminalKey = withMinMax((min, max) => '{ akka.parboiled2.RuleTrace.Times($min, $max) }) + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + withMinMax { (minE, maxE) => + '{ + val min = $minE + val max = $maxE + require(min <= max, "`max` in `(min to max).times` must be >= `min`") + + @ _root_.scala.annotation.tailrec + def rec(count: Int, mark: akka.parboiled2.Parser.Mark): Boolean = { + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.popToBuilder } + if (count < max) ${ + if (separator eq null) '{ rec(count + 1, $parser.__saveState) } + else + '{ + val m = $parser.__saveState + if (${ separator(wrapped) }) rec(count + 1, m) + else (count >= min) && { $parser.__restoreState(m); true } + } + } + else true + + } else (count > min) && { $parser.__restoreState(mark); true } + } + + (max <= 0) || rec(1, $parser.__saveState) && { ${ coll.pushBuilderResult }; true } + } + } + } + } + + case class AndPredicate(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.AndPredicate } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + '{ + val mark = $parser.__saveState + val matched = ${ op.render(wrapped) } + $parser.__restoreState(mark) + matched + } + } + + case class NotPredicate(op: OpTree) extends OpTree { + + def render(wrapped: Boolean): Expr[Boolean] = { + def unwrappedExpr(setMatchEnd: Option[Expr[Int] => Expr[Unit]]): Expr[Boolean] = '{ + val mark = $parser.__saveState + val saved = $parser.__enterNotPredicate() + val matched = ${ op.render(wrapped) } + $parser.__exitNotPredicate(saved) + ${ + setMatchEnd match { + case Some(matchEndSetter) => matchEndSetter('{ $parser.cursor }) + case None => '{} + } + } + $parser.__restoreState(mark) + !matched + } + + if (wrapped) { + val base = op match { + case x: TerminalOpTree => '{ RuleTrace.NotPredicate.Terminal(${ x.ruleTraceTerminal }) } + case x: RuleCall => '{ RuleTrace.NotPredicate.RuleCall(${ x.calleeNameTree }) } + case x: StringMatch => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringTree }}\"") } + case x: IgnoreCaseString => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringTree }}\"") } + case x: Named => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringExpr }}\"") } + case _ => '{ RuleTrace.NotPredicate.Anonymous } + } + '{ + var matchEnd = 0 + try ${ unwrappedExpr(Some(v => '{ matchEnd = $v })) } || $parser.__registerMismatch() + catch { + case Parser.StartTracingException => + $parser.__bubbleUp { + RuleTrace.NotPredicate($base, matchEnd - $parser.cursor) + } + } + } + } else unwrappedExpr(None) + } + } + + private def expandLambda(body: Term, wrapped: Boolean): Expr[Boolean] = { + def popToVals(valdefs: List[ValDef]): List[Statement] = { + def convertOne(v: ValDef): ValDef = + v.tpt.tpe.asType match { + case '[t] => ValDef.copy(v)(v.name, v.tpt, Some('{ $parser.valueStack.pop().asInstanceOf[t] }.asTerm)) + } + + valdefs.map(convertOne).reverse + } + + body match { + case Lambda(args, body) => + def rewrite(tree: Term): Term = + tree.tpe.asType match { + case '[Rule[_, _]] => expand(tree, wrapped).asInstanceOf[Term] + case _ => + tree match { + case Block(statements, res) => block(statements, rewrite(res)) + case x => '{ $parser.__push(${ x.asExpr }) }.asTerm + } + } + // do a beta reduction, using the parameter definitions as stubs for variables + // that hold values popped from the stack + block(popToVals(args), rewrite(body)).asExprOf[Boolean] + } + } + + private case class Action(body: Term, ts: List[TypeTree]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Action } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = expandLambda(body, wrapped) + } + + case class RunAction(body: Expr[_]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Run } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + body.asTerm.tpe.asType match { + case '[Rule[_, _]] => expand(body, wrapped) + case '[t1 => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2) => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2, t3) => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2, t3, t4) => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2, t3, t4, t5) => r] => expandLambda(body.asTerm, wrapped) + case '[x] => '{ $body; true } + } + } + + case class SemanticPredicate(flagTree: Expr[Boolean]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.SemanticPredicate } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ $flagTree || $parser.__registerMismatch() } + else flagTree + } + + case class Capture(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Capture } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + '{ + val start1 = ${ if (wrapped) start else '{ $parser.cursor } } + val matched = ${ op.render(wrapped) } + if (matched) { + $parser.valueStack.push($parser.input.sliceString(start1, $parser.cursor)) + true + } else false + } + } + + private case class PushAction(valueExpr: Expr[_], argType: Type[_]) extends OpTree { + def render(wrapped: Boolean): Expr[Boolean] = { + val body = + argType match { + case '[Unit] => valueExpr + case '[HList] => '{ $parser.valueStack.pushAll($valueExpr.asInstanceOf[HList]) } + case _ => '{ $parser.valueStack.push($valueExpr) } + } + + '{ + $body + true + } + } + } + private case class DropAction(tpe: Type[_]) extends OpTree { + def render(wrapped: Boolean): Expr[Boolean] = { + import support.hlist._ + val body = + tpe match { + case '[Unit] => '{} + case '[HList] => + @tailrec def rec(t: Type[_], prefix: Expr[Unit]): Expr[Unit] = t match { + case '[HNil] => prefix + case '[h :: t] => + rec(Type.of[t], '{ $prefix; $parser.valueStack.pop() }) + + } + rec(tpe, '{}) + + case _ => '{ $parser.valueStack.pop() } + } + + '{ + $body + true + } + } + } + + private case class RuleCall(call: Either[OpTree, Expr[Rule[_, _]]], calleeNameTree: Expr[String]) + extends NonTerminalOpTree { + + def bubbleUp(e: Expr[Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] = + '{ $e.prepend(RuleTrace.RuleCall, $start).bubbleUp(RuleTrace.Named($calleeNameTree), $start) } + + override def render(wrapped: Boolean): Expr[Boolean] = call match { + case Left(_) => super.render(wrapped) + case Right(rule) => '{ $rule ne null } + } + protected def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = { + val Left(value) = call + value.render(wrapped) + } + } + + case class CharMatch(charTree: Expr[Char]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharMatch($charTree) } + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ + $parser.cursorChar == $charTree && $parser.__advance() + } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class StringMatch(stringTree: Expr[String]) extends OpTree { + final private val autoExpandMaxStringLength = 8 + + override def render(wrapped: Boolean): Expr[Boolean] = { + def unrollUnwrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) + '{ + if ($parser.cursorChar == ${ Expr(s.charAt(ix)) }) { + $parser.__advance() + ${ unrollUnwrapped(s, ix + 1) } + } else false + } + else '{ true } + + def unrollWrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) { + val ch = Expr(s.charAt(ix)) + '{ + if ($parser.cursorChar == $ch) { + $parser.__advance() + $parser.__updateMaxCursor() + ${ unrollWrapped(s, ix + 1) } + } else { + try $parser.__registerMismatch() + catch { + case akka.parboiled2.Parser.StartTracingException => + import akka.parboiled2.RuleTrace._ + $parser.__bubbleUp( + NonTerminal(akka.parboiled2.RuleTrace.StringMatch($stringTree), -${ Expr(ix) }) :: Nil, + akka.parboiled2.RuleTrace.CharMatch($ch) + ) + } + } + } + } else '{ true } + + stringTree.asTerm match { + case Literal(StringConstant(s: String)) if s.length <= autoExpandMaxStringLength => + if (s.isEmpty) '{ true } + else if (wrapped) unrollWrapped(s) + else unrollUnwrapped(s) + case _ => + if (wrapped) '{ $parser.__matchStringWrapped($stringTree) } + else '{ $parser.__matchString($stringTree) } + } + } + } + + case class MapMatch(mapTree: Expr[Map[String, Any]], ignoreCaseTree: Expr[Boolean]) extends OpTree { + + override def render(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ $parser.__matchMapWrapped($mapTree, $ignoreCaseTree) } + else '{ $parser.__matchMap($mapTree, $ignoreCaseTree) } + } + + case class IgnoreCaseChar(charTree: Expr[Char]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.IgnoreCaseChar($charTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ + _root_.java.lang.Character.toLowerCase($parser.cursorChar) == $charTree && $parser.__advance() + } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class IgnoreCaseString(stringTree: Expr[String]) extends OpTree { + final private val autoExpandMaxStringLength = 8 + + override def render(wrapped: Boolean): Expr[Boolean] = + def unrollUnwrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) + '{ + if (_root_.java.lang.Character.toLowerCase($parser.cursorChar) == ${ Expr(s.charAt(ix)) }) { + $parser.__advance() + ${ unrollUnwrapped(s, ix + 1) } + } else false + } + else '{ true } + + def unrollWrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) { + val ch = Expr(s.charAt(ix)) + '{ + if (_root_.java.lang.Character.toLowerCase($parser.cursorChar) == $ch) { + $parser.__advance() + $parser.__updateMaxCursor() + ${ unrollWrapped(s, ix + 1) } + } else { + try $parser.__registerMismatch() + catch { + case akka.parboiled2.Parser.StartTracingException => + import akka.parboiled2.RuleTrace._ + $parser.__bubbleUp( + NonTerminal(akka.parboiled2.RuleTrace.IgnoreCaseString($stringTree), -${ Expr(ix) }) :: Nil, + akka.parboiled2.RuleTrace.IgnoreCaseChar($ch) + ) + } + } + } + } else '{ true } + + stringTree.asTerm match { + case Literal(StringConstant(s: String)) if s.length <= autoExpandMaxStringLength => + if (s.isEmpty) '{ true } + else if (wrapped) unrollWrapped(s) + else unrollUnwrapped(s) + case _ => + if (wrapped) '{ $parser.__matchIgnoreCaseStringWrapped($stringTree) } + else '{ $parser.__matchIgnoreCaseString($stringTree) } + } + } + + private case class CharPredicateMatch(predicateTree: Expr[CharPredicate]) + extends PotentiallyNamedTerminalOpTree(predicateTree.asTerm) { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharPredicateMatch($predicateTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $predicateTree($parser.cursorChar) && $parser.__advance() } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class AnyOf(stringTree: Expr[String]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.AnyOf($stringTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $parser.__matchAnyOf($stringTree) } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class NoneOf(stringTree: Expr[String]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.NoneOf($stringTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $parser.__matchNoneOf($stringTree) } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case object ANY extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.ANY } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $parser.cursorChar != EOI && $parser.__advance() } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class Unknown(syntax: String, tree: String, outerSyntax: String) extends TerminalOpTree { + override def ruleTraceTerminal: Expr[RuleTrace.Terminal] = + '{ RuleTrace.Fail(s"unknown rule: $$infoExpr") } + + override protected def renderInner(wrapped: Boolean): Expr[Boolean] = + '{ + throw new RuntimeException( + s"unknown rule: [${${ Expr(syntax) }}] '${${ Expr(tree) }}' in [${${ Expr(outerSyntax) }}]" + ) + } + } + + def CharRange(lowerTree: Expr[String], upperTree: Expr[String]): CharacterRange = + (lowerTree.value, upperTree.value) match { + case (Some(lower), Some(upper)) => + if (lower.length != 1) reportError("lower bound must be a single char string", lowerTree) + if (upper.length != 1) reportError("upper bound must be a single char string", upperTree) + val lowerBoundChar = lower.charAt(0) + val upperBoundChar = upper.charAt(0) + if (lowerBoundChar > upperBoundChar) reportError("lower bound must not be > upper bound", lowerTree) + CharacterRange(Expr(lowerBoundChar), Expr(upperBoundChar)) + case _ => reportError("Character ranges must be specified with string literals", lowerTree) + } + + case class CharacterRange(lowerBound: Expr[Char], upperBound: Expr[Char]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharRange($lowerBound, $upperBound) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ + val char = $parser.cursorChar + $lowerBound <= char && char <= $upperBound && $parser.__advance() + } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class Fail(stringExpr: Expr[String]) extends OpTree { + def render(wrapped: Boolean): Expr[Boolean] = '{ throw new akka.parboiled2.Parser.Fail($stringExpr) } + } + case class Named(op: OpTree, stringExpr: Expr[String]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Named($stringExpr) } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = op.render(wrapped) + } + case class Atomic(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Atomic } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + val saved = $parser.__enterAtomic($start) + val matched = ${ op.render(wrapped) } + $parser.__exitAtomic(saved) + matched + } + else op.render(wrapped) + } + + case class Quiet(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Quiet } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + val saved = $parser.__enterQuiet() + val matched = ${ op.render(wrapped) } + $parser.__exitQuiet(saved) + matched + } + else op.render(wrapped) + } + + def topLevel(opTree: OpTree, name: Expr[String]): OpTree = RuleCall(Left(opTree), name) + + def deconstruct(outerRule: Expr[Rule[_, _]]): OpTree = deconstructPF(outerRule).get + def deconstructPF(outerRule: Expr[Rule[_, _]]): Option[OpTree] = { + import quotes.reflect.* + + def collector(lifter: Term): Collector = + lifter match { + case TypeApply(Ident("forRule0" | "forReduction"), _) => rule0Collector + case TypeApply(Ident("forRule1"), _) => rule1Collector + case x => reportError(s"Unexpected lifter ${lifter.show(using Printer.TreeStructure)}", lifter.asExpr) + } + + // a list of names for operations that are not yet implemented but that should not be interpreted as rule calls + // FIXME: can be removed when everything is implemented + val ruleNameBlacklist = + Set( + "str", + "!", + "?", + "&", + "optional", + "run", + "zeroOrMore", + "times", + "oneOrMore", + "rule2ActionOperator", + "range2NTimes", + "rule2WithSeparatedBy" + ) + + lazy val rules0PF: PartialFunction[Expr[Rule[_, _]], OpTree] = { + case '{ ($p: Parser).ch($c) } => CharMatch(c) + case '{ ($p: Parser).str($s) } => StringMatch(s) + case '{ ($p: Parser).valueMap($m: Map[String, Any]) } => MapMatch(m, '{ false }) + case '{ ($p: Parser).valueMap($m: Map[String, Any], $ic) } => MapMatch(m, ic) + case '{ ($p: Parser).ignoreCase($c: Char) } => IgnoreCaseChar(c) + case '{ ($p: Parser).ignoreCase($s: String) } => IgnoreCaseString(s) + case '{ ($p: Parser).predicate($pr) } => CharPredicateMatch(pr) + case '{ ($p: Parser).anyOf($s) } => AnyOf(s) + case '{ ($p: Parser).noneOf($s) } => NoneOf(s) + case '{ ($p: Parser).ANY } => ANY + case '{ ($p: Parser).str2CharRangeSupport($l).-($r) } => CharRange(l, r) + case '{ ($p: Parser).test($flag) } => SemanticPredicate(flag) + case '{ ($p: Parser).push[t]($value) } => PushAction(value, Type.of[t]) + case '{ ($p: Parser).drop[t] } => DropAction(Type.of[t]) + case '{ type i <: HList; type o <: HList; ($p: Parser).capture[`i`, `o`]($arg)($l) } => Capture(rec(arg.asTerm)) + case '{ + type i1 <: HList; type o1 <: HList + type i2 <: HList; type o2 <: HList + ($lhs: Rule[`i1`, `o1`]).~[`i2`, `o2`]($rhs)($_, $_) + } => + Sequence(Seq(rec(lhs.asTerm), rec(rhs.asTerm))) + + case '{ + type i1 <: HList; type o1 <: HList + type i2 <: `i1`; type o2 >: `o1` <: HList + ($lhs: Rule[`i1`, `o1`]).|[`i2`, `o2`]($rhs) + } => + FirstOf(rec(lhs.asTerm), rec(rhs.asTerm)) + + case '{ + type i1 <: HList; type o1 <: HList + type i2 <: HList; type o2 <: HList + ($lhs: Rule[`i1`, `o1`]).~!~[`i2`, `o2`]($rhs)($_, $_) + } => + Cut(rec(lhs.asTerm), rec(rhs.asTerm)) + + case '{ type i <: HList; type o <: HList; ($p: Parser).zeroOrMore[`i`, `o`]($arg)($l) } => + ZeroOrMore(rec(arg.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).*($l: support.Lifter[Seq, `i`, `o`]) } => + ZeroOrMore(rec(base.asTerm), collector(l.asTerm)) + + case '{ + type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).*($sep: Rule0)($l: support.Lifter[Seq, `i`, `o`]) + } => + ZeroOrMore(rec(base.asTerm), collector(l.asTerm), Separator(rec(sep.asTerm))) + + case '{ type i <: HList; type o <: HList; ($p: Parser).oneOrMore[`i`, `o`]($arg)($l) } => + OneOrMore(rec(arg.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).+($l: support.Lifter[Seq, `i`, `o`]) } => + OneOrMore(rec(base.asTerm), collector(l.asTerm)) + + case '{ + type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).+($sep: Rule0)($l: support.Lifter[Seq, `i`, `o`]) + } => + OneOrMore(rec(base.asTerm), collector(l.asTerm), Separator(rec(sep.asTerm))) + + case '{ type i <: HList; type o <: HList; ($p: Parser).optional[`i`, `o`]($arg)($l) } => + Optional(rec(arg.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).?($l: support.Lifter[Option, `i`, `o`]) } => + Optional(rec(base.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($p: Parser).int2NTimes($n).times[`i`, `o`]($arg)($l) } => + Times( + rec(arg.asTerm), + MinMaxSupplier.constant(n), + collector(l.asTerm), + null + ) + case '{ type i <: HList; type o <: HList; ($p: Parser).range2NTimes($r).times[`i`, `o`]($arg)($l) } => + Times( + rec(arg.asTerm), + MinMaxSupplier.range(r), + collector(l.asTerm), + null + ) + + case '{ type i <: HList; type o <: HList; !($arg: Rule[`i`, `o`]) } => + NotPredicate(rec(arg.asTerm)) + + case '{ ($p: Parser).&($arg) } => + AndPredicate(rec(arg.asTerm)) + + case '{ + type i <: HList; type o <: HList; ($p: Parser).rule2WithSeparatedBy[`i`, `o`]($base).separatedBy($sep) + } => + rec(base.asTerm) match { + case ws: WithSeparator => ws.withSeparator(Separator(rec(sep.asTerm))) + case _ => reportError(s"Illegal `separatedBy` base: $base", base) + } + + case '{ ($p: Parser).run[t]($e)($l) } => RunAction(e) + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).named($str) } => Named(rec(base.asTerm), str) + case '{ type i <: HList; type o <: HList; ($p: Parser).atomic[`i`, `o`]($r) } => Atomic(rec(r.asTerm)) + case '{ type i <: HList; type o <: HList; ($p: Parser).quiet[`i`, `o`]($r) } => Quiet(rec(r.asTerm)) + case '{ ($p: Parser).fail($str) } => Fail(str) + case '{ type i <: HList; type o <: HList; ($p: Parser).failX[`i`, `o`]($str) } => Fail(str) + } + + lazy val rules1PF: PartialFunction[Term, OpTree] = { + // cannot easily be converted because we would have to list all ActionOps instances + case Apply( + Apply( + TypeApply( + Select( + Select(Apply(Apply(TypeApply(Select(_, "rule2ActionOperator"), _), List(base)), _), "~>"), + "apply" + ), + _ + ), + List(body) + ), + List(_, TypeApply(Ident("apply"), ts)) + ) => + Sequence(rec(base), Action(body, ts)) + + case call @ (Apply(_, _) | Select(_, _) | Ident(_) | TypeApply(_, _)) + if !callName(call).exists(ruleNameBlacklist) => + RuleCall( + Right(call.asExprOf[Rule[_, _]]), + Expr(callName(call) getOrElse reportError("Illegal rule call: " + call, call.asExpr)) + ) + //case _ => Unknown(rule.show, rule.show(using Printer.TreeStructure), outerRule.toString) + } + lazy val allRules = rules0PF.orElse(rules1PF.compose[Expr[Rule[_, _]]] { case x => x.asTerm.underlyingArgument }) + def rec(rule: Term): OpTree = allRules.applyOrElse( + rule.asExprOf[Rule[_, _]], + rule => Unknown(rule.show, "" /*rule.show(using Printer.TreeStructure)*/, outerRule.toString) + ) + + allRules.lift(outerRule) + } + + private def reportError(error: String, expr: Expr[Any]): Nothing = { + quotes.reflect.report.error(error, expr) + throw new scala.quoted.runtime.StopMacroExpansion + } + + /////////////////////////////////// helpers //////////////////////////////////// + + trait Collector { + def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] + } + trait CollectorInstance { + def popToBuilder: Expr[Unit] + def pushBuilderResult: Expr[Unit] + def pushSomePop: Expr[Unit] + def pushNone: Expr[Unit] + } + + // no-op collector + object rule0Collector extends Collector with CollectorInstance { + override def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] = f(this) + private val unit: Expr[Unit] = '{} + def popToBuilder: Expr[Unit] = unit + def pushBuilderResult: Expr[Unit] = unit + def pushSomePop: Expr[Unit] = unit + def pushNone: Expr[Unit] = unit + } + + object rule1Collector extends Collector { + override def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] = '{ + val builder = new scala.collection.immutable.VectorBuilder[Any] + ${ + f(new CollectorInstance { + def popToBuilder: Expr[Unit] = '{ builder += $parser.valueStack.pop() } + def pushBuilderResult: Expr[Unit] = '{ $parser.valueStack.push(builder.result()) } + def pushSomePop: Expr[Unit] = '{ $parser.valueStack.push(Some($parser.valueStack.pop())) } + def pushNone: Expr[Unit] = '{ $parser.valueStack.push(None) } + }) + } + } + } + + type Separator = Boolean => Expr[Boolean] + private def Separator(op: OpTree): Separator = wrapped => op.render(wrapped) + + @tailrec + private def callName(tree: Term): Option[String] = + tree match { + case Ident(name) => Some(name) + case Select(_, name) => Some(name) + case Apply(fun, _) => callName(fun) + case TypeApply(fun, _) => callName(fun) + case _ => None + } + + // tries to match and expand the leaves of the given Tree + private def expand(expr: Expr[_], wrapped: Boolean): Expr[Boolean] = + expand(expr.asTerm, wrapped).asExprOf[Boolean] + private def expand(tree: Tree, wrapped: Boolean): Tree = + tree match { + case Block(statements, res) => block(statements, expand(res, wrapped).asInstanceOf[Term]) + case If(cond, thenExp, elseExp) => + If(cond, expand(thenExp, wrapped).asInstanceOf[Term], expand(elseExp, wrapped).asInstanceOf[Term]) + case Match(selector, cases) => Match(selector, cases.map(expand(_, wrapped).asInstanceOf[CaseDef])) + case CaseDef(pat, guard, body) => CaseDef(pat, guard, expand(body, wrapped).asInstanceOf[Term]) + case x => + deconstructPF(x.asExprOf[Rule[_, _]]) // can we pass the body as a rule? + .map(_.render(wrapped)) // then render it + .getOrElse('{ ${ x.asExprOf[Rule[_, _]] } ne null }) // otherwise, assume the expression is a rule itself + .asTerm + } + + private def block(a: Term, b: Term): Term = + a match { + case Block(a1, a2) => + b match { + case Block(b1, b2) => Block(a1 ::: a2 :: b1, b2) + case _ => Block(a1 ::: a2 :: Nil, b) + } + case _ => + b match { + case Block(b1, b2) => Block(a :: b1, b2) + case _ => Block(a :: Nil, b) + } + } + + private def block(stmts: List[Statement], expr: Term): Term = + expr match { + case Block(a, b) => block(stmts ::: a ::: Nil, b) + case _ => Block(stmts, expr) + } +} + +object ParserMacros { + import scala.quoted._ + import scala.compiletime._ + + // TODO: the `R` type parameter is a workaround for https://github.com/lampepfl/dotty/issues/13376 + // Discussion at https://github.com/sirthias/parboiled2/pull/274#issuecomment-904926294 + def runImpl[L <: HList: Type, R: Type]()(ruleExpr: Expr[RuleN[L]], schemeExpr: Expr[Parser.DeliveryScheme[L]])(using + Quotes + ): Expr[R] = { + import quotes.reflect.* + + /* + the `rule.run()` macro supports two scenarios (`rule` has type `RuleN[L]`): + + 1. someParserExpression.rule[targs](args).run()(deliveryScheme) + is re-written to + { val p = someParserExpression + p.__run[L](p.rule[targs](args))(deliveryScheme) } + + 2. Within a Parser subclass: + rule(...).run()(deliveryScheme) + is re-written to + this.__run[L](rule(...))(deliveryScheme) + Note that `rule` is also a macro, we work with the macro expansion of the `rule` call. + */ + + case class RuleFromParser(parser: Term, rule: Symbol, targs: List[TypeTree], argss: List[List[Term]]) { + def ruleCall[P](localParser: Expr[P]): Expr[RuleN[L]] = { + val r = Select(localParser.asTerm, rule) + argss.foldLeft(if (targs.isEmpty) r else TypeApply(r, targs))((t, args) => Apply(t, args)).asExprOf[RuleN[L]] + } + } + + object RuleFromParser { + def dissect(t: Term, targs: List[TypeTree], argss: List[List[Term]]): (Term, List[TypeTree], List[List[Term]]) = + t.underlyingArgument match { + case Apply(f, args) => dissect(f, targs, args :: argss) + case TypeApply(f, targs) => dissect(f, targs, argss) + case t => (t, targs, argss) + } + + def unapply(t: Term): Option[RuleFromParser] = dissect(t, Nil, Nil) match { + case (rule @ Select(parser, _), targs, argss) if parser.tpe <:< TypeRepr.of[Parser] => + Some(RuleFromParser(parser, rule.symbol, targs, argss)) + case _ => None + } + } + + def isRuleMacro(sym: Symbol) = + sym.owner == TypeRepr.of[ParserMacroMethods].typeSymbol && + (sym.name == "rule" || sym.name == "namedRule") + + ruleExpr.asTerm match { + case RuleFromParser(rule) => + rule.parser.tpe.asType match { + case '[pT] => + // TODO: the parser type `pT` is not bounded by `<: Parser`, not sure how to do that. + // This is why `asInstanceOf[Parser]` is needed below + val parserExpr = rule.parser.asExprOf[pT] + '{ + val p: pT = $parserExpr + p.asInstanceOf[Parser].__run[L](${ rule.ruleCall('p) })($schemeExpr).asInstanceOf[R] + } + } + case Inlined(_, _, Inlined(Some(ruleMacro), List(ValDef(_, _, Some(parserThis))), rule)) + if rule.tpe <:< TypeRepr.of[RuleX] && isRuleMacro(ruleMacro.symbol) => + // The `Inlined` tree for the `rule` macro has a binding for the parser instance. + // TODO: we re-use the rhs of that binding (parserThis), I didn't manage to create the right This() tree. + '{ ${ parserThis.asExprOf[Parser] }.__run[L]($ruleExpr)($schemeExpr).asInstanceOf[R] } + case r => + report.error(s"""Cannot rewrite `myRule.run()` call for rule: ${ruleExpr.show} + |`myRule` needs to be either of the form `someParser.someRule[targs](args)` + |or it needs to be a `rule(...)` definition within a Parser subclass.""".stripMargin) + throw new MatchError(r) + } + } + + def ruleImpl[I <: HList: Type, O <: HList: Type](parser: Expr[Parser], r: Expr[Rule[I, O]])(using + Quotes + ): Expr[Rule[I, O]] = { + import quotes.reflect.* + nameRuleImpl(parser, Expr(Symbol.spliceOwner.owner.name), r) + } + + def nameRuleImpl[I <: HList: Type, O <: HList: Type](parser: Expr[Parser], name: Expr[String], r: Expr[Rule[I, O]])( + using Quotes + ): Expr[Rule[I, O]] = { + import quotes.reflect.* + + val ctx = new OpTreeContext(parser) + val opTree = ctx.topLevel(ctx.deconstruct(r), name) + + '{ + def wrapped: Boolean = ${ opTree.render(wrapped = true) } + val matched = + if ($parser.__inErrorAnalysis) wrapped + else ${ opTree.render(wrapped = false) } + if (matched) akka.parboiled2.Rule.asInstanceOf[Rule[I, O]] else null + } + } +} diff --git a/akka-parsing/src/main/scala/akka/shapeless/package.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala similarity index 59% rename from akka-parsing/src/main/scala/akka/shapeless/package.scala rename to akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala index fe15b1b47ac..2440a2f0b69 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/package.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2013-14 Miles Sabin + * Copyright 2009-2019 Mathias Doenitz * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,16 +14,21 @@ * limitations under the License. */ -package akka.shapeless +package akka.parboiled2.support -/** Dependent unary function type. */ -trait DepFn1[T] { - type Out - def apply(t: T): Out +import akka.parboiled2.support.hlist._ + +trait HListable[T] { + type Out <: HList } -/** Dependent binary function type. */ -trait DepFn2[T, U] { - type Out - def apply(t: T, u: U): Out +object HListable { + type HL0[T] <: HList = T match { + case Unit => HNil + case HNil => HNil + case ::[a, b] => ::[a, b] + case _ => T :: HNil + } + + implicit def calc[T]: HListable[T] { type Out = HL0[T] } = `n/a` } diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala new file mode 100644 index 00000000000..84597d62a26 --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala @@ -0,0 +1,79 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2.support + +import hlist._ + +import scala.annotation.implicitNotFound + +/** + * type-level implementation of this logic: + * Out = + * R if T has a tail of type L + * (L dropRight T) ::: R if L has a tail of type T + */ +@implicitNotFound("Illegal rule composition") +sealed trait TailSwitch[L <: HList, T <: HList, R <: HList] { + type Out <: HList +} +object TailSwitch { + type Reverse0[Acc <: HList, L <: HList] <: HList = L match { + case HNil => Acc + case ::[h, t] => Reverse0[h :: Acc, t] + } + + type Reverse1[L <: HList] <: HList = L match { + case HNil => HNil + case ::[h, t] => Reverse0[h :: HNil, t] + } + + type Prepend0[A <: HList, B <: HList] <: HList = A match { + case HNil => B + case ::[h, t] => ::[h, Prepend0[t, B]] + } + + // type-level implementation of this algorithm: + // @tailrec def rec(L, LI, T, TI, R, RI) = + // if (TI <: L) R + // else if (LI <: T) RI.reverse ::: R + // else if (LI <: HNil) rec(L, HNil, T, TI.tail, R, RI) + // else if (TI <: HNil) rec(L, LI.tail, T, HNil, R, LI.head :: RI) + // else rec(L, LI.tail, T, TI.tail, R, LI.head :: RI) + // rec(L, L, T, T, R, HNil) + type TailSwitch0[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList] <: HList = TI match { + case L => R + case _ => + LI match { + case T => Prepend0[Reverse1[RI], R] + case HNil => + TI match { + case ::[_, t] => TailSwitch0[L, HNil, T, t, R, RI] + } + case ::[h, t] => + TI match { + case HNil => TailSwitch0[L, t, T, HNil, R, h :: RI] + case ::[_, tt] => TailSwitch0[L, t, T, tt, R, h :: RI] + } + } + } + + type Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out <: HList] = + TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } + + implicit def tailSwitch[L <: HList, T <: HList, R <: HList] + : TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } = `n/a` +} diff --git a/akka-parsing/src/main/scala/akka/parboiled2/CharPredicate.scala b/akka-parsing/src/main/scala/akka/parboiled2/CharPredicate.scala index 294fcfae3be..56a02f6f717 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/CharPredicate.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/CharPredicate.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,15 +16,10 @@ package akka.parboiled2 -import akka.annotation.InternalApi - import scala.annotation.tailrec import scala.collection.immutable.NumericRange -@InternalApi -private[akka] sealed abstract class CharPredicate { - def apply(char: Char): Boolean - +sealed abstract class CharPredicate extends (Char => Boolean) { import CharPredicate._ /** @@ -51,11 +46,12 @@ private[akka] sealed abstract class CharPredicate { def intersect(that: CharPredicate): CharPredicate - def negated: CharPredicate = this match { - case Empty => All - case All => Empty - case x => from(c => !x(c)) - } + def negated: CharPredicate = + this match { + case Empty => All + case All => Empty + case x => from(c => !x(c)) + } def matchesAny(string: String): Boolean = { @tailrec def rec(ix: Int): Boolean = @@ -93,16 +89,17 @@ private[akka] sealed abstract class CharPredicate { case ix => Some(string charAt ix) } - protected def or(that: CharPredicate): CharPredicate = - if (this == Empty) that else from(c => this(c) || that(c)) - protected def and(that: CharPredicate): CharPredicate = + protected def or(that: Char => Boolean): CharPredicate = + from(if (this == Empty) that else c => this(c) || that(c)) + + protected def and(that: Char => Boolean): CharPredicate = if (this == Empty) Empty else from(c => this(c) && that(c)) - protected def andNot(that: CharPredicate): CharPredicate = - if (this == Empty) from(c => !that(c)) else from(c => this(c) && !that(c)) + + protected def andNot(that: Char => Boolean): CharPredicate = + if (this == Empty) Empty else from(c => this(c) && !that(c)) } -@InternalApi -private[akka] object CharPredicate { +object CharPredicate { val Empty: CharPredicate = MaskBased(0L, 0L) val All: CharPredicate = from(_ => true) val LowerAlpha = CharPredicate('a' to 'z') @@ -118,17 +115,22 @@ private[akka] object CharPredicate { val Visible = CharPredicate('\u0021' to '\u007e') val Printable = Visible ++ ' ' - def from(predicate: Char => Boolean): CharPredicate = General(predicate) + def from(predicate: Char => Boolean): CharPredicate = + predicate match { + case x: CharPredicate => x + case x => General(x) + } - def apply(magnets: ApplyMagnet*): CharPredicate = magnets.foldLeft(Empty) { (a, m) => a ++ m.predicate } + def apply(magnets: ApplyMagnet*): CharPredicate = magnets.foldLeft(Empty)((a, m) => a ++ m.predicate) class ApplyMagnet(val predicate: CharPredicate) + object ApplyMagnet { implicit def fromPredicate(predicate: Char => Boolean): ApplyMagnet = new ApplyMagnet(from(predicate)) - implicit def fromPredicate(predicate: CharPredicate): ApplyMagnet = new ApplyMagnet(predicate) implicit def fromChar(c: Char): ApplyMagnet = fromChars(c :: Nil) implicit def fromCharArray(array: Array[Char]): ApplyMagnet = fromChars(array.toIndexedSeq) implicit def fromString(chars: String): ApplyMagnet = fromChars(chars) + implicit def fromChars(chars: Seq[Char]): ApplyMagnet = chars match { case _ if chars.size < 128 & !chars.exists(unmaskable) => @@ -146,48 +148,53 @@ private[akka] object CharPredicate { // efficient handling of 7bit-ASCII chars case class MaskBased private[CharPredicate] (lowMask: Long, highMask: Long) extends CharPredicate { + def apply(c: Char): Boolean = { val mask = if (c < 64) lowMask else highMask ((1L << c) & ((c - 128) >> 31) & mask) != 0L // branchless for `(c < 128) && (mask & (1L << c) != 0)` } - def ++(that: CharPredicate): CharPredicate = that match { - case Empty => this - case _ if this == Empty => that - case MaskBased(low, high) => MaskBased(lowMask | low, highMask | high) - case _ => this or that - } + def ++(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case _ if this == Empty => that + case MaskBased(low, high) => MaskBased(lowMask | low, highMask | high) + case _ => this or that + } - def ++(chars: Seq[Char]): CharPredicate = chars.foldLeft(this: CharPredicate) { - case (_: MaskBased, c) if unmaskable(c) => new ArrayBased(chars.toArray) ++ new ArrayBased(toArray) - case (MaskBased(low, high), c) if c < 64 => MaskBased(low | 1L << c, high) - case (MaskBased(low, high), c) => MaskBased(low, high | 1L << c) - case (x, _) => x // once the fold acc is not a MaskBased we are done - } + def ++(chars: Seq[Char]): CharPredicate = + chars.foldLeft(this: CharPredicate) { + case (_: MaskBased, c) if unmaskable(c) => new ArrayBased(chars.toArray) ++ new ArrayBased(toArray) + case (MaskBased(low, high), c) if c < 64 => MaskBased(low | 1L << c, high) + case (MaskBased(low, high), c) => MaskBased(low, high | 1L << c) + case (x, _) => x // once the fold acc is not a MaskBased we are done + } - def --(that: CharPredicate): CharPredicate = that match { - case Empty => this - case _ if this == Empty => this - case MaskBased(low, high) => MaskBased(lowMask & ~low, highMask & ~high) - case _ => this andNot that - } + def --(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case _ if this == Empty => this + case MaskBased(low, high) => MaskBased(lowMask & ~low, highMask & ~high) + case _ => this andNot that + } def --(chars: Seq[Char]): CharPredicate = - if (this != Empty) { + if (this != Empty) chars.foldLeft(this: CharPredicate) { case (_: MaskBased, c) if unmaskable(c) => this andNot new ArrayBased(chars.toArray) case (MaskBased(low, high), c) if c < 64 => MaskBased(low & ~(1L << c), high) case (MaskBased(low, high), c) => MaskBased(low, high & ~(1L << c)) case (x, _) => x // once the fold acc is not a MaskBased we are done } - } else this + else this - def intersect(that: CharPredicate) = that match { - case Empty => Empty - case _ if this == Empty => Empty - case MaskBased(low, high) => MaskBased(lowMask & low, highMask & high) - case _ => this and that - } + def intersect(that: CharPredicate) = + that match { + case Empty => Empty + case _ if this == Empty => Empty + case MaskBased(low, high) => MaskBased(lowMask & low, highMask & high) + case _ => this and that + } def size: Int = java.lang.Long.bitCount(lowMask) + java.lang.Long.bitCount(highMask) @@ -199,14 +206,18 @@ private[akka] object CharPredicate { def getChars(array: Array[Char], startIx: Int): Unit = { @tailrec def rec(mask: Long, offset: Int, bit: Int, ix: Int): Int = - if (bit < 64 && ix < array.length) { + if (bit < 64 && ix < array.length) if ((mask & (1L << bit)) > 0) { array(ix) = (offset + bit).toChar rec(mask, offset, bit + 1, ix + 1) } else rec(mask, offset, bit + 1, ix) - } else ix - rec(highMask, 64, java.lang.Long.numberOfTrailingZeros(highMask), - rec(lowMask, 0, java.lang.Long.numberOfTrailingZeros(lowMask), startIx)) + else ix + rec( + highMask, + 64, + java.lang.Long.numberOfTrailingZeros(highMask), + rec(lowMask, 0, java.lang.Long.numberOfTrailingZeros(lowMask), startIx) + ) } override def toString(): String = "CharPredicate.MaskBased(" + new String(toArray) + ')' @@ -215,27 +226,31 @@ private[akka] object CharPredicate { class RangeBased private[CharPredicate] (private val range: NumericRange[Char]) extends CharPredicate { def apply(c: Char): Boolean = range contains c - def ++(that: CharPredicate): CharPredicate = that match { - case Empty => this - case _ => this or that - } + def ++(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case _ => this or that + } def ++(other: Seq[Char]): CharPredicate = if (other.nonEmpty) this ++ CharPredicate(other) else this - def --(that: CharPredicate): CharPredicate = that match { - case Empty => this - case _ => this andNot that - } + def --(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case _ => this andNot that + } def --(other: Seq[Char]): CharPredicate = if (other.nonEmpty) this -- CharPredicate(other) else this - def intersect(that: CharPredicate): CharPredicate = that match { - case Empty => Empty - case _ => this and that - } + def intersect(that: CharPredicate): CharPredicate = + that match { + case Empty => Empty + case _ => this and that + } - override def toString(): String = s"CharPredicate.RangeBased(start = ${range.start}, end = ${range.end}, " + - s"step = ${range.step.toInt}, inclusive = ${range.isInclusive})" + override def toString(): String = + s"CharPredicate.RangeBased(start = ${range.start}, end = ${range.end}, " + + s"step = ${range.step.toInt}, inclusive = ${range.isInclusive})" } class ArrayBased private[CharPredicate] (private val chars: Array[Char]) extends CharPredicate { @@ -245,21 +260,23 @@ private[akka] object CharPredicate { // TODO: switch to faster binary search algorithm with an adaptive pivot, e.g. http://ochafik.com/blog/?p=106 def apply(c: Char): Boolean = binarySearch(chars, c) >= 0 - def ++(that: CharPredicate): CharPredicate = that match { - case Empty => this - case x: ArrayBased => this ++ x.chars.toIndexedSeq - case _ => this or that - } + def ++(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case x: ArrayBased => this ++ x.chars.toIndexedSeq + case _ => this or that + } def ++(other: Seq[Char]): CharPredicate = if (other.nonEmpty) new ArrayBased((this -- other).chars ++ other.toArray[Char]) else this - def --(that: CharPredicate): CharPredicate = that match { - case Empty => this - case x: ArrayBased => this -- x.chars.toIndexedSeq - case _ => this andNot that - } + def --(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case x: ArrayBased => this -- x.chars.toIndexedSeq + case _ => this andNot that + } def --(other: Seq[Char]): ArrayBased = if (other.nonEmpty) { @@ -267,23 +284,25 @@ private[akka] object CharPredicate { new ArrayBased(chars.filter(binarySearch(otherChars, _) < 0)) } else this - def intersect(that: CharPredicate): CharPredicate = that match { - case Empty => Empty - case x: ArrayBased => new ArrayBased(chars.intersect(x.chars)) - case _ => this and that - } + def intersect(that: CharPredicate): CharPredicate = + that match { + case Empty => Empty + case x: ArrayBased => new ArrayBased(chars.intersect(x.chars)) + case _ => this and that + } override def toString(): String = "CharPredicate.ArrayBased(" + new String(chars) + ')' } case class General private[CharPredicate] (predicate: Char => Boolean) extends CharPredicate { - def apply(c: Char): Boolean = predicate(c) + def apply(c: Char) = predicate(c) - def ++(that: CharPredicate): CharPredicate = that match { - case Empty => this - case General(thatPredicate) => from(c => predicate(c) || thatPredicate(c)) - case _ => from(c => predicate(c) || that(c)) - } + def ++(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case General(thatPredicate) => from(c => predicate(c) || thatPredicate(c)) + case _ => from(c => predicate(c) || that(c)) + } def ++(chars: Seq[Char]): CharPredicate = if (chars.nonEmpty) { @@ -291,11 +310,12 @@ private[akka] object CharPredicate { from(c => predicate(c) || abp(c)) } else this - def --(that: CharPredicate): CharPredicate = that match { - case Empty => this - case General(thatPredicate) => from(c => predicate(c) && !thatPredicate(c)) - case _ => from(c => predicate(c) && !that(c)) - } + def --(that: CharPredicate): CharPredicate = + that match { + case Empty => this + case General(thatPredicate) => from(c => predicate(c) && !thatPredicate(c)) + case _ => from(c => predicate(c) && !that(c)) + } def --(chars: Seq[Char]): CharPredicate = if (chars.nonEmpty) { @@ -303,11 +323,12 @@ private[akka] object CharPredicate { from(c => predicate(c) && !abp(c)) } else this - def intersect(that: CharPredicate) = that match { - case Empty => Empty - case General(thatPredicate) => from(c => predicate(c) && that(c)) - case _ => this and that - } + def intersect(that: CharPredicate) = + that match { + case Empty => Empty + case General(thatPredicate) => from(c => predicate(c) && that(c)) + case _ => this and that + } override def toString(): String = "CharPredicate.General@" + System.identityHashCode(this) } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/CharUtils.scala b/akka-parsing/src/main/scala/akka/parboiled2/CharUtils.scala index 2beca578e8e..b3e6a444210 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/CharUtils.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/CharUtils.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -20,6 +20,7 @@ import java.lang.{ StringBuilder => JStringBuilder } import scala.annotation.tailrec object CharUtils { + /** * Returns the int value of a given hex digit char. * Note: this implementation is very fast (since it's branchless) and therefore @@ -37,13 +38,13 @@ object CharUtils { * Returns the lower-case hex digit corresponding to the last 4 bits of the given Long. * (fast branchless implementation) */ - def lowerHexDigit(long: Long): Char = lowerHexDigit_internal((long & 0x0FL).toInt) + def lowerHexDigit(long: Long): Char = lowerHexDigit_internal((long & 0x0fL).toInt) /** * Returns the lower-case hex digit corresponding to the last 4 bits of the given Int. * (fast branchless implementation) */ - def lowerHexDigit(int: Int): Char = lowerHexDigit_internal(int & 0x0F) + def lowerHexDigit(int: Int): Char = lowerHexDigit_internal(int & 0x0f) private def lowerHexDigit_internal(i: Int) = (48 + i + (39 & ((9 - i) >> 31))).toChar @@ -51,13 +52,13 @@ object CharUtils { * Returns the upper-case hex digit corresponding to the last 4 bits of the given Long. * (fast branchless implementation) */ - def upperHexDigit(long: Long): Char = upperHexDigit_internal((long & 0x0FL).toInt) + def upperHexDigit(long: Long): Char = upperHexDigit_internal((long & 0x0fL).toInt) /** * Returns the upper-case hex digit corresponding to the last 4 bits of the given Int. * (fast branchless implementation) */ - def upperHexDigit(int: Int): Char = upperHexDigit_internal(int & 0x0F) + def upperHexDigit(int: Int): Char = upperHexDigit_internal(int & 0x0f) private def upperHexDigit_internal(i: Int) = (48 + i + (7 & ((9 - i) >> 31))).toChar @@ -76,7 +77,7 @@ object CharUtils { sb.append(upperHexDigit(long >>> shift)) if (shift > 0) putChar(shift - 4) else sb } - putChar((63 - java.lang.Long.numberOfLeadingZeros(long)) & 0xFC) + putChar((63 - java.lang.Long.numberOfLeadingZeros(long)) & 0xfc) } else sb.append('0') /** @@ -94,7 +95,7 @@ object CharUtils { sb.append(lowerHexDigit(long >>> shift)) if (shift > 0) putChar(shift - 4) else sb } - putChar((63 - java.lang.Long.numberOfLeadingZeros(long)) & 0xFC) + putChar((63 - java.lang.Long.numberOfLeadingZeros(long)) & 0xfc) } else sb.append('0') /** @@ -170,22 +171,23 @@ object CharUtils { * Efficiently lower-cases the given character. * Note: only works for 7-bit ASCII letters. */ - def toLowerCase(c: Char): Char = if (c >= 'A' && c <= 'Z') (c + 0x20 /* - 'A' + 'a' */ ).toChar else c + def toLowerCase(c: Char): Char = if (CharPredicate.UpperAlpha(c)) (c + 0x20).toChar else c /** * Efficiently upper-cases the given character. * Note: only works for 7-bit ASCII letters. */ - def toUpperCase(c: Char): Char = if (c >= 'a' && c <= 'z') (c - 0x20 /* - 'a' + 'A' */ ).toChar else c + def toUpperCase(c: Char): Char = if (CharPredicate.LowerAlpha(c)) (c + 0x20).toChar else c - def escape(c: Char): String = c match { - case '\t' => "\\t" - case '\r' => "\\r" - case '\n' => "\\n" - case EOI => "EOI" - case x if Character.isISOControl(x) => "\\u%04x" format c.toInt - case x => x.toString - } + def escape(c: Char): String = + c match { + case '\t' => "\\t" + case '\r' => "\\r" + case '\n' => "\\n" + case EOI => "EOI" + case x if Character.isISOControl(x) => "\\u%04x" format c.toInt + case x => x.toString + } val escapedChars = CharPredicate("\t\r\n", EOI, Character.isISOControl _) diff --git a/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala b/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala index 86921b4193b..5cbdd29caa2 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,9 +16,7 @@ package akka.parboiled2 -import scala.collection.immutable -import scala.reflect.macros.whitebox -import akka.shapeless.HList +import akka.parboiled2.support.hlist.HList /** * An application needs to implement this interface to receive the result @@ -46,45 +44,4 @@ trait RuleRunner[P <: Parser, L <: HList] { def apply(handler: DynamicRuleHandler[P, L]): handler.Result } -object DynamicRuleDispatch { - - /** - * Implements efficient runtime dispatch to a predefined set of parser rules. - * Given a number of rule names this macro-supported method creates a `DynamicRuleDispatch` instance along with - * a sequence of the given rule names. - * Note that there is no reflection involved and compilation will fail, if one of the given rule names - * does not constitute a method of parser type `P` or has a type different from `RuleN[L]`. - */ - def apply[P <: Parser, L <: HList](ruleNames: String*): (DynamicRuleDispatch[P, L], immutable.Seq[String]) = macro __create[P, L] - - ///////////////////// INTERNAL //////////////////////// - - def __create[P <: Parser, L <: HList](c: whitebox.Context)(ruleNames: c.Expr[String]*)(implicit P: c.WeakTypeTag[P], L: c.WeakTypeTag[L]): c.Expr[(DynamicRuleDispatch[P, L], immutable.Seq[String])] = { - import c.universe._ - val names = ruleNames.map { - _.tree match { - case Literal(Constant(s: String)) => s - case x => c.abort(x.pos, s"Invalid `String` argument `x`, only `String` literals are supported!") - } - } - - def ruleEntry(name: String): Tree = - q"""($name, new RuleRunner[$P, $L] { - def apply(handler: DynamicRuleHandler[$P, $L]): handler.Result = { - val p = handler.parser - p.__run[$L](p.${TermName(name).encodedName.toTermName})(handler) - } - })""" - val ruleEntries: Seq[Tree] = names.map(ruleEntry(_)) - - c.Expr[(DynamicRuleDispatch[P, L], immutable.Seq[String])] { - q"""val map: Map[String, RuleRunner[$P, $L]] = Map(..$ruleEntries) - val drd = - new akka.parboiled2.DynamicRuleDispatch[$P, $L] { - def lookup(ruleName: String): Option[RuleRunner[$P, $L]] = - map.get(ruleName) - } - (drd, scala.collection.immutable.Seq(..$ruleNames))""" - } - } -} +object DynamicRuleDispatch extends DynamicRuleDispatchMacro diff --git a/akka-parsing/src/main/scala/akka/parboiled2/ErrorFormatter.scala b/akka-parsing/src/main/scala/akka/parboiled2/ErrorFormatter.scala index ec7fcdf63d1..11691a26993 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/ErrorFormatter.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/ErrorFormatter.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,8 +16,8 @@ package akka.parboiled2 -import java.lang.{ StringBuilder => JStringBuilder } import scala.annotation.tailrec +import java.lang.{ StringBuilder => JStringBuilder } /** * Abstraction for error formatting logic. @@ -41,7 +41,8 @@ class ErrorFormatter( showTraces: Boolean = false, showFrameStartOffset: Boolean = true, expandTabs: Int = -1, - traceCutOff: Int = 120) { + traceCutOff: Int = 120 +) { /** * Formats the given [[ParseError]] into a String using the settings configured for this formatter instance. @@ -76,7 +77,10 @@ class ErrorFormatter( if (ix < input.length) { val chars = mismatchLength(error) if (chars == 1) sb.append("Invalid input '").append(CharUtils.escape(input charAt ix)).append('\'') - else sb.append("Invalid input \"").append(CharUtils.escape(input.sliceString(ix, ix + chars))).append('"') + else + sb.append("Invalid input \"") + .append(CharUtils.escape(input.sliceString(ix, math.min(ix + chars, input.length)))) + .append('"') } else sb.append("Unexpected end of input") } @@ -133,7 +137,7 @@ class ErrorFormatter( * Formats what is expected at the error location as a [[List]] of Strings. */ def formatExpectedAsList(error: ParseError): List[String] = { - val distinctStrings: Set[String] = error.effectiveTraces.iterator.map(formatAsExpected).toSet + val distinctStrings = error.effectiveTraces.map(formatAsExpected).distinct distinctStrings.toList } @@ -187,8 +191,14 @@ class ErrorFormatter( */ def formatTraces(error: ParseError): String = { import error._ - traces.map(formatTrace(_, position.index)).mkString(s"${traces.size} rule" + (if (traces.size != 1) "s" else "") + - " mismatched at error location:\n ", "\n ", "\n") + traces + .map(formatTrace(_, position.index)) + .mkString( + s"${traces.size} rule${(if (traces.size != 1) "s" else "")}" + + " mismatched at error location:\n ", + "\n ", + "\n" + ) } /** @@ -200,8 +210,11 @@ class ErrorFormatter( val doSep: String => JStringBuilder = sb.append val dontSep: String => JStringBuilder = _ => sb def render(names: List[String], sep: String = "") = if (names.nonEmpty) names.reverse.mkString("", ":", sep) else "" - @tailrec def rec(remainingPrefix: List[RuleTrace.NonTerminal], names: List[String], - sep: String => JStringBuilder): JStringBuilder = + @tailrec def rec( + remainingPrefix: List[RuleTrace.NonTerminal], + names: List[String], + sep: String => JStringBuilder + ): JStringBuilder = remainingPrefix match { case NonTerminal(Named(name), _) :: tail => rec(tail, name :: names, sep) @@ -228,7 +241,8 @@ class ErrorFormatter( */ def formatNonTerminal( nonTerminal: RuleTrace.NonTerminal, - showFrameStartOffset: Boolean = showFrameStartOffset): String = { + showFrameStartOffset: Boolean = showFrameStartOffset + ): String = { import RuleTrace._ import CharUtils.escape val keyString = nonTerminal.key match { diff --git a/akka-parsing/src/main/scala/akka/parboiled2/ParseError.scala b/akka-parsing/src/main/scala/akka/parboiled2/ParseError.scala index b30c07bde2c..f9ef4cff930 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/ParseError.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/ParseError.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -19,10 +19,8 @@ package akka.parboiled2 import scala.annotation.tailrec import scala.collection.immutable -case class ParseError( - position: Position, - principalPosition: Position, - traces: immutable.Seq[RuleTrace]) extends RuntimeException { +case class ParseError(position: Position, principalPosition: Position, traces: immutable.Seq[RuleTrace]) + extends RuntimeException { require(principalPosition.index >= position.index, "principalPosition must be > position") def format(parser: Parser): String = format(parser.input) def format(parser: Parser, formatter: ErrorFormatter): String = format(parser.input, formatter) @@ -49,6 +47,7 @@ case class ParseError( case class Position(index: Int, line: Int, column: Int) object Position { + def apply(index: Int, input: ParserInput): Position = { @tailrec def rec(ix: Int, line: Int, col: Int): Position = if (ix >= index) Position(index, line, col) diff --git a/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala b/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala index 30b0fac78be..a5aaad32e88 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -18,14 +18,14 @@ package akka.parboiled2 import scala.annotation.tailrec import scala.collection.immutable.VectorBuilder +import scala.collection.mutable import scala.util.{ Failure, Success, Try } import scala.util.control.{ NoStackTrace, NonFatal } -import akka.shapeless._ +import akka.parboiled2.support.hlist._ import akka.parboiled2.support._ -abstract class Parser( - initialValueStackSize: Int = 16, - maxValueStackSize: Int = 1024) extends RuleDSL { +abstract class Parser(initialValueStackSize: Int = 16, maxValueStackSize: Int = 1024) + extends RuleDSL with ParserMacroMethods { import Parser._ require(maxValueStackSize <= 65536, "`maxValueStackSize` > 2^16 is not supported") // due to current snapshot design @@ -35,17 +35,6 @@ abstract class Parser( */ def input: ParserInput - /** - * Converts a compile-time only rule definition into the corresponding rule method implementation. - */ - def rule[I <: HList, O <: HList](r: Rule[I, O]): Rule[I, O] = macro ParserMacros.ruleImpl[I, O] - - /** - * Converts a compile-time only rule definition into the corresponding rule method implementation - * with an explicitly given name. - */ - def namedRule[I <: HList, O <: HList](name: String)(r: Rule[I, O]): Rule[I, O] = macro ParserMacros.namedRuleImpl[I, O] - /** * The index of the next (yet unmatched) input character. * Might be equal to `input.length`! @@ -114,18 +103,15 @@ abstract class Parser( private var _cursor: Int = _ // the value stack instance we operate on - private var _valueStack: ValueStack = new ValueStack(initialValueStackSize, maxValueStackSize) + private var _valueStack: ValueStack = _ // the current ErrorAnalysisPhase or null (in the initial run) private var phase: ErrorAnalysisPhase = _ - private var _maxLength = -1 - def copyStateFrom(other: Parser, offset: Int): Unit = { _cursorChar = other._cursorChar _cursor = other._cursor - offset _valueStack = other._valueStack - _maxLength = other._maxLength phase = other.phase if (phase ne null) phase.applyOffset(offset) } @@ -141,7 +127,6 @@ abstract class Parser( def __run[L <: HList](rule: => RuleN[L])(implicit scheme: Parser.DeliveryScheme[L]): scheme.Result = { def runRule(): Boolean = { _cursor = -1 - _maxLength = input.length __advance() valueStack.clear() try rule ne null @@ -150,7 +135,10 @@ abstract class Parser( } } - def phase0_initialRun() = runRule() + def phase0_initialRun() = { + _valueStack = new ValueStack(initialValueStackSize, maxValueStackSize) + runRule() + } def phase1_establishPrincipalErrorIndex(): Int = { val phase1 = new EstablishingPrincipalErrorIndex() @@ -179,11 +167,13 @@ abstract class Parser( @tailrec def phase4_collectRuleTraces(reportedErrorIndex: Int, principalErrorIndex: Int, reportQuiet: Boolean)( phase3: CollectingRuleTraces = new CollectingRuleTraces(reportedErrorIndex, reportQuiet), - traces: VectorBuilder[RuleTrace] = new VectorBuilder): ParseError = { + traces: VectorBuilder[RuleTrace] = new VectorBuilder + ): ParseError = { def done = { val principalErrorPos = Position(principalErrorIndex, input) - val reportedErrorPos = if (reportedErrorIndex != principalErrorIndex) Position(reportedErrorIndex, input) else principalErrorPos + val reportedErrorPos = + if (reportedErrorIndex != principalErrorIndex) Position(reportedErrorIndex, input) else principalErrorPos ParseError(reportedErrorPos, principalErrorPos, traces.result()) } if (phase3.traceNr < errorTraceCollectionLimit) { @@ -196,8 +186,11 @@ abstract class Parser( case e: TracingBubbleException => e.trace } if (trace eq null) done - else phase4_collectRuleTraces(reportedErrorIndex, principalErrorIndex, - reportQuiet)(new CollectingRuleTraces(reportedErrorIndex, reportQuiet, phase3.traceNr + 1), traces += trace) + else + phase4_collectRuleTraces(reportedErrorIndex, principalErrorIndex, reportQuiet)( + new CollectingRuleTraces(reportedErrorIndex, reportQuiet, phase3.traceNr + 1), + traces += trace + ) } else done } @@ -217,19 +210,19 @@ abstract class Parser( scheme.parseError(ParseError(pos, pos, RuleTrace(Nil, RuleTrace.Fail(e.expected)) :: Nil)) case NonFatal(e) => scheme.failure(e) - } finally { - phase = null - } + } finally phase = null } /** * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! */ def __advance(): Boolean = { - val c = _cursor - if (c < _maxLength) { - _cursor = c + 1 - _cursorChar = if ((c + 1) == _maxLength) EOI else input charAt (c + 1) + var c = _cursor + val max = input.length + if (c < max) { + c += 1 + _cursor = c + _cursorChar = if (c == max) EOI else input charAt c } true } @@ -255,8 +248,8 @@ abstract class Parser( */ def __restoreState(mark: Mark): Unit = { _cursor = (mark.value >>> 32).toInt - _cursorChar = ((mark.value >>> 16) & 0x000000000000FFFF).toChar - valueStack.size = (mark.value & 0x000000000000FFFF).toInt + _cursorChar = ((mark.value >>> 16) & 0x000000000000ffff).toChar + valueStack.size = (mark.value & 0x000000000000ffff).toInt } /** @@ -289,12 +282,11 @@ abstract class Parser( * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! */ def __exitAtomic(saved: Boolean): Unit = - if (saved) { + if (saved) phase match { case x: EstablishingReportedErrorIndex => x.currentAtomicStart = Int.MinValue case _ => throw new IllegalStateException } - } /** * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! @@ -318,13 +310,12 @@ abstract class Parser( * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! */ def __exitQuiet(saved: Int): Unit = - if (saved >= 0) { + if (saved >= 0) phase match { case x: DetermineReportQuiet => x.inQuiet = false case x: CollectingRuleTraces => x.minErrorIndex = saved case _ => throw new IllegalStateException } - } /** * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! @@ -333,9 +324,8 @@ abstract class Parser( phase match { case null | _: EstablishingPrincipalErrorIndex => // nothing to do case x: CollectingRuleTraces => - if (_cursor >= x.minErrorIndex) { + if (_cursor >= x.minErrorIndex) if (x.errorMismatches == x.traceNr) throw Parser.StartTracingException else x.errorMismatches += 1 - } case x: EstablishingReportedErrorIndex => if (x.currentAtomicStart > x.maxAtomicErrorStart) x.maxAtomicErrorStart = x.currentAtomicStart case x: DetermineReportQuiet => @@ -388,14 +378,13 @@ abstract class Parser( __advance() __updateMaxCursor() __matchStringWrapped(string, ix + 1) - } else { + } else try __registerMismatch() catch { case Parser.StartTracingException => import RuleTrace._ __bubbleUp(NonTerminal(StringMatch(string), -ix) :: Nil, CharMatch(string charAt ix)) } - } else true /** @@ -418,14 +407,13 @@ abstract class Parser( __advance() __updateMaxCursor() __matchIgnoreCaseStringWrapped(string, ix + 1) - } else { + } else try __registerMismatch() catch { case Parser.StartTracingException => import RuleTrace._ __bubbleUp(NonTerminal(IgnoreCaseString(string), -ix) :: Nil, IgnoreCaseChar(string charAt ix)) } - } else true /** @@ -448,12 +436,16 @@ abstract class Parser( /** * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! */ - def __matchMap(m: Map[String, Any]): Boolean = { - val keys = m.keysIterator - while (keys.hasNext) { + def __matchMap(m: Map[String, Any], ignoreCase: Boolean): Boolean = { + val prioritizedKeys = new mutable.PriorityQueue[String]()(Ordering.by(_.length)) + prioritizedKeys ++= m.keysIterator + while (prioritizedKeys.nonEmpty) { val mark = __saveState - val key = keys.next() - if (__matchString(key)) { + val key = prioritizedKeys.dequeue() + val matchResult = + if (ignoreCase) __matchIgnoreCaseString(key) + else __matchString(key) + if (matchResult) { __push(m(key)) return true } else __restoreState(mark) @@ -464,14 +456,18 @@ abstract class Parser( /** * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! */ - def __matchMapWrapped(m: Map[String, Any]): Boolean = { - val keys = m.keysIterator + def __matchMapWrapped(m: Map[String, Any], ignoreCase: Boolean): Boolean = { + val prioritizedKeys = new mutable.PriorityQueue[String]()(Ordering.by(_.length)) + prioritizedKeys ++= m.keysIterator val start = _cursor try { - while (keys.hasNext) { + while (prioritizedKeys.nonEmpty) { val mark = __saveState - val key = keys.next() - if (__matchStringWrapped(key)) { + val key = prioritizedKeys.dequeue() + val matchResult = + if (ignoreCase) __matchIgnoreCaseStringWrapped(key) + else __matchStringWrapped(key) + if (matchResult) { __push(m(key)) return true } else __restoreState(mark) @@ -493,6 +489,7 @@ abstract class Parser( class TracingBubbleException(private var _trace: RuleTrace) extends RuntimeException with NoStackTrace { def trace = _trace def bubbleUp(key: RuleTrace.NonTerminalKey, start: Int): Nothing = throw prepend(key, start) + def prepend(key: RuleTrace.NonTerminalKey, start: Int): this.type = { val offset = phase match { case x: CollectingRuleTraces => start - x.minErrorIndex @@ -523,7 +520,8 @@ object Parser { } object DeliveryScheme extends AlternativeDeliverySchemes { - implicit def Try[L <: HList, Out](implicit unpack: Unpack.Aux[L, Out]) = + + implicit def Try[L <: HList, Out](implicit unpack: Unpack.Aux[L, Out]): DeliveryScheme[L] { type Result = Try[Out] } = new DeliveryScheme[L] { type Result = Try[Out] def success(result: L) = Success(unpack(result)) @@ -531,15 +529,18 @@ object Parser { def failure(error: Throwable) = Failure(error) } } + sealed abstract class AlternativeDeliverySchemes { - implicit def Either[L <: HList, Out](implicit unpack: Unpack.Aux[L, Out]) = + + implicit def Either[L <: HList, Out](implicit unpack: Unpack.Aux[L, Out]): DeliveryScheme[L] { type Result = Either[ParseError, Out] } = new DeliveryScheme[L] { type Result = Either[ParseError, Out] def success(result: L) = Right(unpack(result)) def parseError(error: ParseError) = Left(error) def failure(error: Throwable) = throw error } - implicit def Throw[L <: HList, Out](implicit unpack: Unpack.Aux[L, Out]) = + + implicit def Throw[L <: HList, Out](implicit unpack: Unpack.Aux[L, Out]): DeliveryScheme[L] { type Result = Out } = new DeliveryScheme[L] { type Result = Out def success(result: L) = unpack(result) @@ -578,7 +579,7 @@ object Parser { // 1: EstablishingPrincipalErrorIndex (1 run) // 2: EstablishingReportedErrorIndex (1 run) // 3: CollectingRuleTraces (n runs) - private sealed trait ErrorAnalysisPhase { + sealed private trait ErrorAnalysisPhase { def applyOffset(offset: Int): Unit } @@ -593,8 +594,10 @@ object Parser { private class EstablishingReportedErrorIndex( private var _principalErrorIndex: Int, var currentAtomicStart: Int = Int.MinValue, - var maxAtomicErrorStart: Int = Int.MinValue) extends ErrorAnalysisPhase { + var maxAtomicErrorStart: Int = Int.MinValue + ) extends ErrorAnalysisPhase { def reportedErrorIndex = if (maxAtomicErrorStart >= 0) maxAtomicErrorStart else _principalErrorIndex + def applyOffset(offset: Int) = { _principalErrorIndex -= offset if (currentAtomicStart != Int.MinValue) currentAtomicStart -= offset @@ -623,57 +626,3 @@ object Parser { def applyOffset(offset: Int) = minErrorIndex -= offset } } - -object ParserMacros { - import scala.reflect.macros.whitebox - - /** - * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! - */ - type RunnableRuleContext[L <: HList] = whitebox.Context { type PrefixType = Rule.Runnable[L] } - - def runImpl[L <: HList: c.WeakTypeTag](c: RunnableRuleContext[L])()(scheme: c.Expr[Parser.DeliveryScheme[L]]): c.Expr[scheme.value.Result] = { - import c.universe._ - val runCall = c.prefix.tree match { - case q"parboiled2.this.Rule.Runnable[$l]($ruleExpr)" => ruleExpr match { - case q"$p.$r" if p.tpe <:< typeOf[Parser] => q"val p = $p; p.__run[$l](p.$r)($scheme)" - case q"$p.$r($args)" if p.tpe <:< typeOf[Parser] => q"val p = $p; p.__run[$l](p.$r($args))($scheme)" - case q"$p.$r[$t]" if p.tpe <:< typeOf[Parser] => q"val p = $p; p.__run[$l](p.$r[$t])($scheme)" - case q"$p.$r[$t]" if p.tpe <:< typeOf[RuleX] => q"__run[$l]($ruleExpr)($scheme)" - case x => c.abort(x.pos, "Illegal `.run()` call base: " + x) - } - case x => c.abort(x.pos, "Illegal `Runnable.apply` call: " + x) - } - c.Expr[scheme.value.Result](runCall) - } - - /** - * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! - */ - type ParserContext = whitebox.Context { type PrefixType = Parser } - - def ruleImpl[I <: HList: ctx.WeakTypeTag, O <: HList: ctx.WeakTypeTag](ctx: ParserContext)(r: ctx.Expr[Rule[I, O]]): ctx.Expr[Rule[I, O]] = { - import ctx.universe._ - val ruleName = - if (ctx.internal.enclosingOwner.isMethod) - ctx.internal.enclosingOwner.name.decodedName.toString - else - ctx.abort(r.tree.pos, "`rule` can only be used from within a method") - - namedRuleImpl(ctx)(ctx.Expr[String](Literal(Constant(ruleName))))(r) - } - - def namedRuleImpl[I <: HList: ctx.WeakTypeTag, O <: HList: ctx.WeakTypeTag](ctx: ParserContext)(name: ctx.Expr[String])(r: ctx.Expr[Rule[I, O]]): ctx.Expr[Rule[I, O]] = { - val opTreeCtx = new OpTreeContext[ctx.type] { val c: ctx.type = ctx } - val opTree = opTreeCtx.RuleCall(Left(opTreeCtx.OpTree(r.tree)), name.tree) - import ctx.universe._ - val ruleTree = q""" - def wrapped: Boolean = ${opTree.render(wrapped = true)} - val matched = - if (__inErrorAnalysis) wrapped - else ${opTree.render(wrapped = false)} - if (matched) akka.parboiled2.Rule else null""" // we encode the "matched" boolean as 'ruleResult ne null' - - reify { ctx.Expr[RuleX](ruleTree).splice.asInstanceOf[Rule[I, O]] } - } -} diff --git a/akka-parsing/src/main/scala/akka/parboiled2/ParserInput.scala b/akka-parsing/src/main/scala/akka/parboiled2/ParserInput.scala index 00b379a9111..78811190ee3 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/ParserInput.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/ParserInput.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -20,6 +20,7 @@ import scala.annotation.tailrec import java.nio.ByteBuffer trait ParserInput { + /** * Returns the character at the given (zero-based) index. * Note: this method is hot and should be small and efficient. @@ -54,12 +55,17 @@ object ParserInput { val Empty = apply(Array.empty[Byte]) implicit def apply(bytes: Array[Byte]): ByteArrayBasedParserInput = new ByteArrayBasedParserInput(bytes) - implicit def apply(bytes: Array[Byte], endIndex: Int): ByteArrayBasedParserInput = new ByteArrayBasedParserInput(bytes, endIndex) + + implicit def apply(bytes: Array[Byte], endIndex: Int): ByteArrayBasedParserInput = + new ByteArrayBasedParserInput(bytes, endIndex) implicit def apply(string: String): StringBasedParserInput = new StringBasedParserInput(string) implicit def apply(chars: Array[Char]): CharArrayBasedParserInput = new CharArrayBasedParserInput(chars) - implicit def apply(chars: Array[Char], endIndex: Int): CharArrayBasedParserInput = new CharArrayBasedParserInput(chars, endIndex) + + implicit def apply(chars: Array[Char], endIndex: Int): CharArrayBasedParserInput = + new CharArrayBasedParserInput(chars, endIndex) abstract class DefaultParserInput extends ParserInput { + def getLine(line: Int): String = { @tailrec def rec(ix: Int, lineStartIx: Int, lineNr: Int): String = if (ix < length) @@ -67,7 +73,8 @@ object ParserInput { if (lineNr < line) rec(ix + 1, ix + 1, lineNr + 1) else sliceString(lineStartIx, ix) else rec(ix + 1, lineStartIx, lineNr) - else if (lineNr == line) sliceString(lineStartIx, ix) else "" + else if (lineNr == line) sliceString(lineStartIx, ix) + else "" rec(ix = 0, lineStartIx = 0, lineNr = 1) } } @@ -86,8 +93,9 @@ object ParserInput { */ class ByteArrayBasedParserInput(bytes: Array[Byte], endIndex: Int = 0) extends DefaultParserInput { val length = if (endIndex <= 0 || endIndex > bytes.length) bytes.length else endIndex - def charAt(ix: Int) = (bytes(ix) & 0xFF).toChar - def sliceString(start: Int, end: Int) = new String(bytes, start, end - start, `ISO-8859-1`) + def charAt(ix: Int) = (bytes(ix) & 0xff).toChar + def sliceString(start: Int, end: Int) = new String(bytes, start, math.max(end - start, 0), `ISO-8859-1`) + def sliceCharArray(start: Int, end: Int) = `ISO-8859-1`.decode(ByteBuffer.wrap(java.util.Arrays.copyOfRange(bytes, start, end))).array() } @@ -95,7 +103,8 @@ object ParserInput { class StringBasedParserInput(string: String) extends DefaultParserInput { def charAt(ix: Int) = string.charAt(ix) def length = string.length - def sliceString(start: Int, end: Int) = string.substring(start, end) + def sliceString(start: Int, end: Int) = string.substring(start, math.min(end, string.length)) + def sliceCharArray(start: Int, end: Int) = { val chars = new Array[Char](end - start) string.getChars(start, end, chars, 0) @@ -106,7 +115,7 @@ object ParserInput { class CharArrayBasedParserInput(chars: Array[Char], endIndex: Int = 0) extends DefaultParserInput { val length = if (endIndex <= 0 || endIndex > chars.length) chars.length else endIndex def charAt(ix: Int) = chars(ix) - def sliceString(start: Int, end: Int) = new String(chars, start, end - start) + def sliceString(start: Int, end: Int) = new String(chars, start, math.max(end - start, 0)) def sliceCharArray(start: Int, end: Int) = java.util.Arrays.copyOfRange(chars, start, end) } } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/Rule.scala b/akka-parsing/src/main/scala/akka/parboiled2/Rule.scala index 6acf8d41dc8..98941090dca 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/Rule.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/Rule.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -17,10 +17,10 @@ package akka.parboiled2 import scala.annotation.unchecked.uncheckedVariance -import scala.reflect.internal.annotations.compileTimeOnly +import scala.annotation.compileTimeOnly import scala.collection.immutable import akka.parboiled2.support._ -import akka.shapeless.HList +import akka.parboiled2.support.hlist.HList sealed trait RuleX @@ -48,7 +48,8 @@ sealed class Rule[-I <: HList, +O <: HList] extends RuleX { @compileTimeOnly("Calls to `~` must be inside `rule` macro") def ~[I2 <: HList, O2 <: HList](that: Rule[I2, O2])(implicit i: TailSwitch[I2, O @uncheckedVariance, I @uncheckedVariance], - o: TailSwitch[O @uncheckedVariance, I2, O2]): Rule[i.Out, o.Out] = `n/a` + o: TailSwitch[O @uncheckedVariance, I2, O2] + ): Rule[i.Out, o.Out] = `n/a` /** * Same as `~` but with "cut" semantics, meaning that the parser will never backtrack across this boundary. @@ -57,7 +58,8 @@ sealed class Rule[-I <: HList, +O <: HList] extends RuleX { @compileTimeOnly("Calls to `~!~` must be inside `rule` macro") def ~!~[I2 <: HList, O2 <: HList](that: Rule[I2, O2])(implicit i: TailSwitch[I2, O @uncheckedVariance, I @uncheckedVariance], - o: TailSwitch[O @uncheckedVariance, I2, O2]): Rule[i.Out, o.Out] = `n/a` + o: TailSwitch[O @uncheckedVariance, I2, O2] + ): Rule[i.Out, o.Out] = `n/a` /** * Combines this rule with the given other one in a way that the resulting rule matches if this rule matches @@ -115,19 +117,9 @@ sealed class Rule[-I <: HList, +O <: HList] extends RuleX { /** * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! */ -object Rule extends Rule0 { - /** - * THIS IS NOT PUBLIC API and might become hidden in future. Use only if you know what you are doing! - */ - implicit class Runnable[L <: HList](rule: RuleN[L]) { - def run()(implicit scheme: Parser.DeliveryScheme[L]): scheme.Result = macro ParserMacros.runImpl[L] - } -} +object Rule extends Rule0 with RuleRunnable -abstract class RuleDSL - extends RuleDSLBasics - with RuleDSLCombinators - with RuleDSLActions +abstract class RuleDSL extends RuleDSLBasics with RuleDSLCombinators with RuleDSLActions // phantom type for WithSeparatedBy pimp trait Repeated diff --git a/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLActions.scala b/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLActions.scala index 85f49bfcac0..3fda43aef72 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLActions.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLActions.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,10 +16,10 @@ package akka.parboiled2 -import scala.reflect.internal.annotations.compileTimeOnly -import akka.shapeless.ops.hlist.Prepend +import scala.annotation.compileTimeOnly +import akka.parboiled2.support.hlist.ops.hlist.Prepend import akka.parboiled2.support._ -import akka.shapeless._ +import akka.parboiled2.support.hlist._ trait RuleDSLActions { @@ -82,6 +82,7 @@ trait RuleDSLActions { @compileTimeOnly("Calls to `rule2ActionOperator` must be inside `rule` macro") implicit def rule2ActionOperator[I <: HList, O <: HList](r: Rule[I, O])(implicit ops: ActionOps[I, O]): ActionOperator[I, O, ops.Out] = `n/a` + sealed trait ActionOperator[I <: HList, O <: HList, Ops] { def ~> : Ops } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLBasics.scala b/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLBasics.scala index fdbed4a60d0..206c83a9382 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLBasics.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLBasics.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,9 +16,9 @@ package akka.parboiled2 -import scala.reflect.internal.annotations.compileTimeOnly +import scala.annotation.compileTimeOnly import akka.parboiled2.support._ -import akka.shapeless.HList +import akka.parboiled2.support.hlist.HList trait RuleDSLBasics { @@ -47,6 +47,15 @@ trait RuleDSLBasics { @compileTimeOnly("Calls to `valueMap` must be inside `rule` macro") implicit def valueMap[T](m: Map[String, T])(implicit h: HListable[T]): RuleN[h.Out] = `n/a` + /** + * Matches any of the given maps keys and pushes the respective value upon + * a successful match. + * + * @param ignoreCase a flag that tells if map keys case should be ignored + */ + @compileTimeOnly("Calls to `valueMap` must be inside `rule` macro") + def valueMap[T](m: Map[String, T], ignoreCase: Boolean = false)(implicit h: HListable[T]): RuleN[h.Out] = `n/a` + /** * Matches any single one of the given characters. * @@ -92,7 +101,7 @@ trait RuleDSLBasics { /** * Matches the EOI (end-of-input) character. */ - final def EOI: Char = akka.parboiled2.EOI + def EOI: Char = akka.parboiled2.EOI /** * Matches no character (i.e. doesn't cause the parser to make any progress) but succeeds always (as a rule). @@ -122,6 +131,7 @@ trait RuleDSLBasics { @compileTimeOnly("Calls to `str2CharRangeSupport` must be inside `rule` macro") implicit def str2CharRangeSupport(s: String): CharRangeSupport = `n/a` + sealed trait CharRangeSupport { def -(other: String): Rule0 } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLCombinators.scala b/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLCombinators.scala index a0a183ad8c1..0d91eb84d50 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLCombinators.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/RuleDSLCombinators.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,10 +16,10 @@ package akka.parboiled2 -import scala.reflect.internal.annotations.compileTimeOnly +import scala.annotation.compileTimeOnly import scala.collection.immutable import akka.parboiled2.support._ -import akka.shapeless._ +import akka.parboiled2.support.hlist._ trait RuleDSLCombinators { @@ -31,7 +31,8 @@ trait RuleDSLCombinators { * Rule[I, O] if r == Rule[I, O <: I] // so called "reduction", which leaves the value stack unchanged on a type level */ @compileTimeOnly("Calls to `optional` must be inside `rule` macro") - def optional[I <: HList, O <: HList](r: Rule[I, O])(implicit l: Lifter[Option, I, O]): Rule[l.In, l.OptionalOut] = `n/a` + def optional[I <: HList, O <: HList](r: Rule[I, O])(implicit l: Lifter[Option, I, O]): Rule[l.In, l.OptionalOut] = + `n/a` /** * Runs its inner rule until it fails, always succeeds. @@ -88,9 +89,12 @@ trait RuleDSLCombinators { @compileTimeOnly("Calls to `int2NTimes` must be inside `rule` macro") implicit def int2NTimes(i: Int): NTimes = `n/a` + @compileTimeOnly("Calls to `range2NTimes` must be inside `rule` macro") implicit def range2NTimes(range: Range): NTimes = `n/a` + sealed trait NTimes { + /** * Repeats the given sub rule `r` the given number of times. * Both bounds of the range must be positive and the upper bound must be >= the lower bound. @@ -107,6 +111,7 @@ trait RuleDSLCombinators { @compileTimeOnly("Calls to `rule2WithSeparatedBy` constructor must be inside `rule` macro") implicit def rule2WithSeparatedBy[I <: HList, O <: HList](r: Rule[I, O] with Repeated): WithSeparatedBy[I, O] = `n/a` + trait WithSeparatedBy[I <: HList, O <: HList] { def separatedBy(separator: Rule0): Rule[I, O] = `n/a` } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/ValueStack.scala b/akka-parsing/src/main/scala/akka/parboiled2/ValueStack.scala index b2853d5f293..7a2aa3bc309 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/ValueStack.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/ValueStack.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -17,7 +17,7 @@ package akka.parboiled2 import scala.annotation.tailrec -import akka.shapeless._ +import akka.parboiled2.support.hlist._ /** * A mutable untyped stack of values. @@ -65,7 +65,7 @@ class ValueStack private[parboiled2] (initialSize: Int, maxSize: Int) extends It */ @tailrec final def pushAll(hlist: HList): Unit = hlist match { - case akka.shapeless.::(head, tail) => + case akka.parboiled2.support.hlist.::(head, tail) => push(head) pushAll(tail) case HNil => diff --git a/akka-parsing/src/main/scala/akka/parboiled2/package.scala b/akka-parsing/src/main/scala/akka/parboiled2/package.scala index 8837a4d722a..ed37040b67b 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/package.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/package.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,7 +16,7 @@ package akka -import akka.shapeless._ +import akka.parboiled2.support.hlist._ import java.nio.charset.Charset package object parboiled2 { diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOps.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOps.scala index e6359bf5e49..2f81f0a8df5 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOps.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOps.scala @@ -1,2171 +1,2145 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev - * - * 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 - * - * http://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. - */ +* Copyright (C) 2009-2014 Mathias Doenitz, Alexander Myltsev +* +* 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 +* +* http://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 akka.parboiled2.support -import akka.shapeless._ +import akka.parboiled2.support.hlist._ import akka.parboiled2.Rule -// format: OFF - // provides the supported `~>` "overloads" for rules of type `Rule[I, O]` as `Out` // as a phantom type, which is only used for rule DSL typing sealed trait ActionOps[I <: HList, O <: HList] { type Out } object ActionOps { - private type SJoin[I <: HList, O <: HList, R] = Join[I, HNil, O, R] implicit def ops0[II <: HList, OO <: HNil]: ActionOps[II, OO] { type Out = Ops0[II] } = `n/a` sealed trait Ops0[II <: HList] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] - def apply[E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR) - (implicit j: SJoin[E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] + def apply[E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR)(implicit + j: Join[E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z) => RR]): Rule[j.In, j.Out] } implicit def ops1[II <: HList, A]: ActionOps[II, A :: HNil] { type Out = Ops1[II, A] } = `n/a` sealed trait Ops1[II <: HList, A] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - + def apply[RR](f: () => RR)(implicit j: Join[II, A :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] - def apply[F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR) - (implicit j: SJoin[F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] + def apply[F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR)(implicit + j: Join[F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A) => RR]): Rule[j.In, j.Out] } - implicit def ops2[II <: HList, A, B]: ActionOps[II, A :: B :: HNil] { type Out = Ops2[II, A, B] } = `n/a` sealed trait Ops2[II <: HList, A, B] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] - def apply[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR) - (implicit j: SJoin[G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] + def apply[G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR)(implicit + j: Join[G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B) => RR]): Rule[j.In, j.Out] } - implicit def ops3[II <: HList, A, B, C]: ActionOps[II, A :: B :: C :: HNil] { type Out = Ops3[II, A, B, C] } = `n/a` sealed trait Ops3[II <: HList, A, B, C] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] - def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR) - (implicit j: SJoin[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] + def apply[H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR)(implicit + j: Join[H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C) => RR]): Rule[j.In, j.Out] } - implicit def ops4[II <: HList, A, B, C, D]: ActionOps[II, A :: B :: C :: D :: HNil] { type Out = Ops4[II, A, B, C, D] } = `n/a` sealed trait Ops4[II <: HList, A, B, C, D] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] - def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR) - (implicit j: SJoin[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] + def apply[I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR)(implicit + j: Join[I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D) => RR]): Rule[j.In, j.Out] } - implicit def ops5[II <: HList, A, B, C, D, E]: ActionOps[II, A :: B :: C :: D :: E :: HNil] { type Out = Ops5[II, A, B, C, D, E] } = `n/a` sealed trait Ops5[II <: HList, A, B, C, D, E] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] - def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR) - (implicit j: SJoin[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] + def apply[J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR)(implicit + j: Join[J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E) => RR]): Rule[j.In, j.Out] } - implicit def ops6[II <: HList, A, B, C, D, E, F]: ActionOps[II, A :: B :: C :: D :: E :: F :: HNil] { type Out = Ops6[II, A, B, C, D, E, F] } = `n/a` sealed trait Ops6[II <: HList, A, B, C, D, E, F] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] - def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR) - (implicit j: SJoin[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] + def apply[K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR)(implicit + j: Join[K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F) => RR]): Rule[j.In, j.Out] } - implicit def ops7[II <: HList, A, B, C, D, E, F, G]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: HNil] { type Out = Ops7[II, A, B, C, D, E, F, G] } = `n/a` sealed trait Ops7[II <: HList, A, B, C, D, E, F, G] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] - def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR) - (implicit j: SJoin[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] + def apply[L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR)(implicit + j: Join[L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G) => RR]): Rule[j.In, j.Out] } - implicit def ops8[II <: HList, A, B, C, D, E, F, G, H]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil] { type Out = Ops8[II, A, B, C, D, E, F, G, H] } = `n/a` sealed trait Ops8[II <: HList, A, B, C, D, E, F, G, H] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] - def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR) - (implicit j: SJoin[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] + def apply[M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR)(implicit + j: Join[M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H) => RR]): Rule[j.In, j.Out] } - implicit def ops9[II <: HList, A, B, C, D, E, F, G, H, I]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil] { type Out = Ops9[II, A, B, C, D, E, F, G, H, I] } = `n/a` sealed trait Ops9[II <: HList, A, B, C, D, E, F, G, H, I] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] - def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR) - (implicit j: SJoin[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] + def apply[N, O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR)(implicit + j: Join[N :: O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I) => RR]): Rule[j.In, j.Out] } - implicit def ops10[II <: HList, A, B, C, D, E, F, G, H, I, J]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil] { type Out = Ops10[II, A, B, C, D, E, F, G, H, I, J] } = `n/a` sealed trait Ops10[II <: HList, A, B, C, D, E, F, G, H, I, J] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] - def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR) - (implicit j: SJoin[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] + def apply[O, P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR)(implicit + j: Join[O :: P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J) => RR]): Rule[j.In, j.Out] } - implicit def ops11[II <: HList, A, B, C, D, E, F, G, H, I, J, K]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil] { type Out = Ops11[II, A, B, C, D, E, F, G, H, I, J, K] } = `n/a` sealed trait Ops11[II <: HList, A, B, C, D, E, F, G, H, I, J, K] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] - def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR) - (implicit j: SJoin[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] + def apply[P, Q, R, S, T, U, V, W, X, Y, Z, RR](f: (P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR)(implicit + j: Join[P :: Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K) => RR]): Rule[j.In, j.Out] } - implicit def ops12[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil] { type Out = Ops12[II, A, B, C, D, E, F, G, H, I, J, K, L] } = `n/a` sealed trait Ops12[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] - def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR) - (implicit j: SJoin[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] + def apply[Q, R, S, T, U, V, W, X, Y, Z, RR](f: (Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR)(implicit + j: Join[Q :: R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(Q, R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L) => RR]): Rule[j.In, j.Out] } - implicit def ops13[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil] { type Out = Ops13[II, A, B, C, D, E, F, G, H, I, J, K, L, M] } = `n/a` sealed trait Ops13[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] - def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR) - (implicit j: SJoin[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] + def apply[R, S, T, U, V, W, X, Y, Z, RR](f: (R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR)(implicit + j: Join[R :: S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(R, S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M) => RR]): Rule[j.In, j.Out] } - implicit def ops14[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil] { type Out = Ops14[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N] } = `n/a` sealed trait Ops14[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] - def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR) - (implicit j: SJoin[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] + def apply[S, T, U, V, W, X, Y, Z, RR](f: (S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR)(implicit + j: Join[S :: T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(S, T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N) => RR]): Rule[j.In, j.Out] } - implicit def ops15[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil] { type Out = Ops15[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O] } = `n/a` sealed trait Ops15[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] - def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR) - (implicit j: SJoin[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] + def apply[T, U, V, W, X, Y, Z, RR](f: (T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR)(implicit + j: Join[T :: U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(T, U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O) => RR]): Rule[j.In, j.Out] } - implicit def ops16[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil] { type Out = Ops16[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P] } = `n/a` sealed trait Ops16[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] - def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR) - (implicit j: SJoin[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] + def apply[U, V, W, X, Y, Z, RR](f: (U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR)(implicit + j: Join[U :: V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(U, V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P) => RR]): Rule[j.In, j.Out] } - implicit def ops17[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil] { type Out = Ops17[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q] } = `n/a` sealed trait Ops17[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], - c: FCapture[(Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], + c: FCapture[(Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] - def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR) - (implicit j: SJoin[V :: W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] + def apply[V, W, X, Y, Z, RR](f: (V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR)(implicit + j: Join[V :: W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(V, W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q) => RR]): Rule[j.In, j.Out] } - implicit def ops18[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil] { type Out = Ops18[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R] } = `n/a` sealed trait Ops18[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], - c: FCapture[(R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], + c: FCapture[(R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], - c: FCapture[(Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], + c: FCapture[(Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] - def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR) - (implicit j: SJoin[W :: X :: Y :: Z :: II, HNil, RR], - c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] + def apply[W, X, Y, Z, RR](f: (W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR)(implicit + j: Join[W :: X :: Y :: Z :: II, HNil, RR], + c: FCapture[(W, X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R) => RR]): Rule[j.In, j.Out] } - implicit def ops19[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil] { type Out = Ops19[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S] } = `n/a` sealed trait Ops19[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], - c: FCapture[(S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], + c: FCapture[(S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], - c: FCapture[(R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], + c: FCapture[(R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], - c: FCapture[(Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], + c: FCapture[(Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] - def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR) - (implicit j: SJoin[X :: Y :: Z :: II, HNil, RR], - c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] + def apply[X, Y, Z, RR](f: (X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR)(implicit + j: Join[X :: Y :: Z :: II, HNil, RR], + c: FCapture[(X, Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S) => RR]): Rule[j.In, j.Out] } - implicit def ops20[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil] { type Out = Ops20[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T] } = `n/a` sealed trait Ops20[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], - c: FCapture[(T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], + c: FCapture[(T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], - c: FCapture[(S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], + c: FCapture[(S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], - c: FCapture[(R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], + c: FCapture[(R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], - c: FCapture[(Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], + c: FCapture[(Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] - def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR) - (implicit j: SJoin[Y :: Z :: II, HNil, RR], - c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] + def apply[Y, Z, RR](f: (Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR)(implicit + j: Join[Y :: Z :: II, HNil, RR], + c: FCapture[(Y, Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T) => RR]): Rule[j.In, j.Out] } - implicit def ops21[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: HNil] { type Out = Ops21[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U] } = `n/a` sealed trait Ops21[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil, RR], - c: FCapture[(U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil, RR], + c: FCapture[(U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], - c: FCapture[(T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], + c: FCapture[(T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], - c: FCapture[(S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], + c: FCapture[(S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], - c: FCapture[(R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], + c: FCapture[(R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], - c: FCapture[(Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], + c: FCapture[(Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] - def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR) - (implicit j: SJoin[Z :: II, HNil, RR], - c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] + def apply[Z, RR](f: (Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR)(implicit + j: Join[Z :: II, HNil, RR], + c: FCapture[(Z, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U) => RR]): Rule[j.In, j.Out] } - implicit def ops22[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V]: ActionOps[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: HNil] { type Out = Ops22[II, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V] } = `n/a` sealed trait Ops22[II <: HList, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V] { - def apply[RR](f: () => RR)(implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - - def apply[RR](f: (V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: HNil, RR], - c: FCapture[(V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: () => RR)(implicit j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: V :: HNil, RR], c: FCapture[() => RR]): Rule[j.In, j.Out] - def apply[RR](f: (U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil, RR], - c: FCapture[(U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: U :: HNil, RR], + c: FCapture[(V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], - c: FCapture[(T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: T :: HNil, RR], + c: FCapture[(U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], - c: FCapture[(S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: S :: HNil, RR], + c: FCapture[(T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], - c: FCapture[(R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: R :: HNil, RR], + c: FCapture[(S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], - c: FCapture[(Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: Q :: HNil, RR], + c: FCapture[(R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], - c: FCapture[(P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: P :: HNil, RR], + c: FCapture[(Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], - c: FCapture[(O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: O :: HNil, RR], + c: FCapture[(P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], - c: FCapture[(N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: N :: HNil, RR], + c: FCapture[(O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], - c: FCapture[(M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: M :: HNil, RR], + c: FCapture[(N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], - c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: L :: HNil, RR], + c: FCapture[(M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], - c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: K :: HNil, RR], + c: FCapture[(L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], - c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: J :: HNil, RR], + c: FCapture[(K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], - c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: I :: HNil, RR], + c: FCapture[(J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], - c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: H :: HNil, RR], + c: FCapture[(I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: F :: HNil, RR], - c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: G :: HNil, RR], + c: FCapture[(H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: E :: HNil, RR], - c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: F :: HNil, RR], + c: FCapture[(G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: D :: HNil, RR], - c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: E :: HNil, RR], + c: FCapture[(F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: C :: HNil, RR], - c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: D :: HNil, RR], + c: FCapture[(E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: B :: HNil, RR], - c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: C :: HNil, RR], + c: FCapture[(D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR) - (implicit j: SJoin[II, A :: HNil, RR], - c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: B :: HNil, RR], + c: FCapture[(C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] - def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit j: SJoin[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit + j: Join[II, A :: HNil, RR], + c: FCapture[(B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] + def apply[RR](f: (A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR)(implicit j: Join[II, HNil, RR], c: FCapture[(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V) => RR]): Rule[j.In, j.Out] } - } \ No newline at end of file +} diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOpsSupport.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOpsSupport.scala index 4518c3b6763..3793def1181 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOpsSupport.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/ActionOpsSupport.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,9 +16,9 @@ package akka.parboiled2.support -import akka.shapeless._ +import akka.parboiled2.support.hlist._ import akka.parboiled2.Rule -import akka.shapeless.ops.hlist.ReversePrepend +import akka.parboiled2.support.hlist.ops.hlist.Prepend /* * The main ActionOps boilerplate is generated by a custom SBT sourceGenerator. @@ -29,51 +29,40 @@ import akka.shapeless.ops.hlist.ReversePrepend // unfortunately the Tree for the function argument to the `apply` overloads above does *not* allow us to inspect the // function type which is why we capture it separately with this helper type sealed trait FCapture[T] + object FCapture { implicit def apply[T]: FCapture[T] = `n/a` } // builds `In` and `Out` types according to this logic: // if (R == Unit) -// In = I, Out = L1 ::: L2 +// In = I, Out = L // else if (R <: HList) -// In = I, Out = L1 ::: L2 ::: R +// In = I, Out = L ::: R // else if (R <: Rule[I2, O2]) -// In = TailSwitch[I2, L1 ::: L2, I], Out = TailSwitch[L1 ::: L2, I2, O2] +// In = TailSwitch[I2, L, I], Out = TailSwitch[L, I2, O2] // else -// In = I, Out = L1 ::: L2 ::: R :: HNil -sealed trait Join[I <: HList, L1 <: HList, L2 <: HList, R] { +// In = I, Out = L ::: R :: HNil +sealed trait Join[I <: HList, L <: HList, R] { type In <: HList type Out <: HList } -object Join { - implicit def join[I <: HList, L1 <: HList, L2 <: HList, R, In0 <: HList, Out0 <: HList](implicit x: Aux[I, L1, L2, R, HNil, In0, Out0]): Join[I, L1, L2, R] { type In = In0; type Out = Out0 } = `n/a` - sealed trait Aux[I <: HList, L1 <: HList, L2 <: HList, R, Acc <: HList, In <: HList, Out <: HList] - object Aux extends Aux1 { - // if R == Unit convert to HNil - implicit def forUnit[I <: HList, L1 <: HList, L2 <: HList, Acc <: HList, Out <: HList](implicit x: Aux[I, L1, L2, HNil, Acc, I, Out]): Aux[I, L1, L2, Unit, Acc, I, Out] = `n/a` +object Join extends LowPrioJoin { - // if R <: HList and L1 non-empty move head of L1 to Acc - implicit def iter1[I <: HList, H, T <: HList, L2 <: HList, R <: HList, Acc <: HList, Out <: HList](implicit x: Aux[I, T, L2, R, H :: Acc, I, Out]): Aux[I, H :: T, L2, R, Acc, I, Out] = `n/a` + implicit def forUnit[I <: HList, L <: HList]: Aux[I, L, Unit, I, L] = `n/a` - // if R <: HList and L1 empty and L2 non-empty move head of L2 to Acc - implicit def iter2[I <: HList, H, T <: HList, R <: HList, Acc <: HList, Out <: HList](implicit x: Aux[I, HNil, T, R, H :: Acc, I, Out]): Aux[I, HNil, H :: T, R, Acc, I, Out] = `n/a` + implicit def forHList[I <: HList, L <: HList, R <: HList, O <: HList](implicit x: Prepend.Aux[L, R, O]): Aux[I, L, R, I, O] = `n/a` - // if R <: HList and L1 and L2 empty set Out = reversePrepend Acc before R - implicit def terminate[I <: HList, R <: HList, Acc <: HList, Out <: HList](implicit x: ReversePrepend.Aux[Acc, R, Out]): Aux[I, HNil, HNil, R, Acc, I, Out] = `n/a` + implicit def forRule[I <: HList, O <: HList, I2 <: HList, O2 <: HList, In <: HList, Out <: HList](implicit + i: TailSwitch.Aux[I2, I2, O, O, I, HNil, In], + o: TailSwitch.Aux[O, O, I2, I2, O2, HNil, Out] + ): Aux[I, O, Rule[I2, O2], In, Out] = `n/a` +} - // if R <: Rule and L1 non-empty move head of L1 to Acc - implicit def iterRule1[I <: HList, L2 <: HList, I2 <: HList, O2 <: HList, In0 <: HList, Acc <: HList, Out0 <: HList, H, T <: HList](implicit x: Aux[I, T, L2, Rule[I2, O2], H :: Acc, In0, Out0]): Aux[I, H :: T, L2, Rule[I2, O2], HNil, In0, Out0] = `n/a` +sealed abstract class LowPrioJoin { - // if R <: Rule and L1 empty and Acc non-empty move head of Acc to L2 - implicit def iterRule2[I <: HList, L2 <: HList, I2 <: HList, O2 <: HList, In0 <: HList, Out0 <: HList, H, T <: HList](implicit x: Aux[I, HNil, H :: L2, Rule[I2, O2], T, In0, Out0]): Aux[I, HNil, L2, Rule[I2, O2], H :: T, In0, Out0] = `n/a` + type Aux[I <: HList, L <: HList, R, In0 <: HList, Out0 <: HList] = Join[I, L, R] { type In = In0; type Out = Out0 } - // if R <: Rule and L1 and Acc empty set In and Out to tailswitches result - implicit def terminateRule[I <: HList, O <: HList, I2 <: HList, O2 <: HList, In <: HList, Out <: HList](implicit i: TailSwitch.Aux[I2, I2, O, O, I, HNil, In], o: TailSwitch.Aux[O, O, I2, I2, O2, HNil, Out]): Aux[I, HNil, O, Rule[I2, O2], HNil, In, Out] = `n/a` - } - abstract class Aux1 { - // convert R to R :: HNil - implicit def forAny[I <: HList, L1 <: HList, L2 <: HList, R, Acc <: HList, Out <: HList](implicit x: Aux[I, L1, L2, R :: HNil, Acc, I, Out]): Aux[I, L1, L2, R, Acc, I, Out] = `n/a` - } + implicit def forAny[I <: HList, L <: HList, R, In <: HList, Out <: HList](implicit x: Aux[I, L, R :: HNil, In, Out]): Aux[I, L, R, In, Out] = `n/a` } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/Lifter.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/Lifter.scala index 553ec68d7ee..6219521bf98 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/Lifter.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/Lifter.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -17,10 +17,11 @@ package akka.parboiled2.support import scala.annotation.implicitNotFound -import akka.shapeless._ +import akka.parboiled2.support.hlist._ -@implicitNotFound("The `optional`, `zeroOrMore`, `oneOrMore` and `times` modifiers " + - "can only be used on rules of type `Rule0`, `Rule1[T]` and `Rule[I, O <: I]`!") +@implicitNotFound( + "The `optional`, `zeroOrMore`, `oneOrMore` and `times` modifiers " + "can only be used on rules of type `Rule0`, `Rule1[T]` and `Rule[I, O <: I]`!" +) sealed trait Lifter[M[_], I <: HList, O <: HList] { type In <: HList type StrictOut <: HList @@ -28,6 +29,7 @@ sealed trait Lifter[M[_], I <: HList, O <: HList] { } object Lifter extends LowerPriorityLifter { + implicit def forRule0[M[_]]: Lifter[M, HNil, HNil] { type In = HNil type StrictOut = HNil @@ -42,6 +44,7 @@ object Lifter extends LowerPriorityLifter { } sealed abstract class LowerPriorityLifter { + implicit def forReduction[M[_], L <: HList, R <: L]: Lifter[M, L, R] { type In = L type StrictOut = R diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/RunResult.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/RunResult.scala index aca1c677ca4..ffb02510416 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/RunResult.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/RunResult.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,7 +16,7 @@ package akka.parboiled2.support -import akka.shapeless._ +import akka.parboiled2.support.hlist._ import akka.parboiled2._ // phantom type, only used for rule DSL typing @@ -28,20 +28,27 @@ object RunResult { implicit def fromAux[T, Out0 <: RuleX](implicit aux: Aux[T, Out0]): RunResult[T] { type Out = Out0 } = `n/a` sealed trait Aux[T, Out] + object Aux extends Aux1 { implicit def forRule[R <: RuleX]: Aux[R, R] = `n/a` //implicit def forFHList[I <: HList, R, In0 <: HList, Out0 <: HList](implicit x: JA[I, R, In0, Out0]): Aux[I => R, Rule[In0, Out0]] = `n/a` } + abstract class Aux1 extends Aux2 { + implicit def forF1[Z, R, In0 <: HList, Out0 <: HList](implicit x: JA[Z :: HNil, R, In0, Out0]): Aux[Z => R, Rule[In0, Out0]] = `n/a` + implicit def forF2[Y, Z, R, In0 <: HList, Out0 <: HList](implicit x: JA[Y :: Z :: HNil, R, In0, Out0]): Aux[(Y, Z) => R, Rule[In0, Out0]] = `n/a` + implicit def forF3[X, Y, Z, R, In0 <: HList, Out0 <: HList](implicit x: JA[X :: Y :: Z :: HNil, R, In0, Out0]): Aux[(X, Y, Z) => R, Rule[In0, Out0]] = `n/a` + implicit def forF4[W, X, Y, Z, R, In0 <: HList, Out0 <: HList](implicit x: JA[W :: X :: Y :: Z :: HNil, R, In0, Out0]): Aux[(W, X, Y, Z) => R, Rule[In0, Out0]] = `n/a` + implicit def forF5[V, W, X, Y, Z, R, In0 <: HList, Out0 <: HList](implicit x: JA[V :: W :: X :: Y :: Z :: HNil, R, In0, Out0]): Aux[(V, W, X, Y, Z) => R, Rule[In0, Out0]] = `n/a` } abstract class Aux2 { - protected type JA[I <: HList, R, In0 <: HList, Out0 <: HList] = Join.Aux[I, HNil, HNil, R, HNil, In0, Out0] + protected type JA[I <: HList, R, In0 <: HList, Out0 <: HList] = Join.Aux[I, HNil, R, In0, Out0] implicit def forAny[T]: Aux[T, Rule0] = `n/a` } } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/Unpack.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/Unpack.scala index db0695af165..30b792a18e9 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/Unpack.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/Unpack.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, @@ -16,7 +16,7 @@ package akka.parboiled2.support -import akka.shapeless._ +import akka.parboiled2.support.hlist._ /** * "Unpacks" an HList if it has only zero or one element(s). @@ -34,34 +34,38 @@ sealed trait Unpack[L <: HList] { object Unpack extends AlternativeUnpacks { - implicit def fromAux[L <: HList, Out0](implicit aux: Aux[L, Out0]) = new Unpack[L] { - type Out = Out0 - def apply(hlist: L) = aux(hlist) - } + implicit def fromAux[L <: HList, Out0](implicit aux: Aux[L, Out0]): Unpack[L] { type Out = Out0 } = + new Unpack[L] { + type Out = Out0 + def apply(hlist: L) = aux(hlist) + } sealed trait Aux[L <: HList, Out0] { def apply(hlist: L): Out0 } implicit def hnil[L <: HNil]: Aux[L, Unit] = HNilUnpack.asInstanceOf[Aux[L, Unit]] + implicit object HNilUnpack extends Aux[HNil, Unit] { def apply(hlist: HNil): Unit = () } implicit def single[T]: Aux[T :: HNil, T] = SingleUnpack.asInstanceOf[Aux[T :: HNil, T]] + private object SingleUnpack extends Aux[Any :: HList, Any] { def apply(hlist: Any :: HList): Any = hlist.head } } sealed abstract class AlternativeUnpacks { + /** * Import if you'd like to *always* deliver the valueStack as an `HList` * at the end of the parsing run, even if it has only zero or one element(s). */ implicit def dontUnpack[L <: HList]: Unpack.Aux[L, L] = DontUnpack.asInstanceOf[Unpack.Aux[L, L]] + private object DontUnpack extends Unpack.Aux[HList, HList] { def apply(hlist: HList): HList = hlist } } - diff --git a/akka-parsing/src/main/scala/akka/shapeless/hlists.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/hlist/hlists.scala similarity index 72% rename from akka-parsing/src/main/scala/akka/shapeless/hlists.scala rename to akka-parsing/src/main/scala/akka/parboiled2/support/hlist/hlists.scala index 3fe74d735c8..0b1da3e3f55 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/hlists.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/hlist/hlists.scala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-13 Miles Sabin + * Copyright 2009-2019 Mathias Doenitz * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,14 +14,14 @@ * limitations under the License. */ -package akka.shapeless +package akka.parboiled2.support.hlist /** * `HList` ADT base trait. * * @author Miles Sabin */ -sealed trait HList +sealed trait HList extends Product with Serializable /** * Non-empty `HList` element type. @@ -29,7 +29,11 @@ sealed trait HList * @author Miles Sabin */ final case class ::[+H, +T <: HList](head: H, tail: T) extends HList { - override def toString = head.toString + " :: " + tail.toString + + override def toString: String = head match { + case _: ::[_, _] => s"($head) :: $tail" + case _ => s"$head :: $tail" + } } /** @@ -38,7 +42,7 @@ final case class ::[+H, +T <: HList](head: H, tail: T) extends HList { * @author Miles Sabin */ sealed trait HNil extends HList { - def ::[H](h: H) = akka.shapeless.::(h, this) + def ::[H](h: H): H :: HNil = new ::(h, this) override def toString = "HNil" } @@ -50,9 +54,11 @@ sealed trait HNil extends HList { case object HNil extends HNil object HList { - import syntax.HListOps + import akka.parboiled2.support.hlist.syntax.HListOps + + def apply(): HNil.type = HNil - def apply() = HNil + def apply[T](t: T): T :: HNil = t :: HNil implicit def hlistOps[L <: HList](l: L): HListOps[L] = new HListOps(l) @@ -61,6 +67,6 @@ object HList { */ object ListCompat { val :: = scala.collection.immutable.:: - val #: = akka.shapeless.:: + val #: = akka.parboiled2.support.hlist.:: } } diff --git a/akka-parsing/src/main/scala/akka/shapeless/ops/hlists.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/hlist/ops/hlists.scala similarity index 73% rename from akka-parsing/src/main/scala/akka/shapeless/ops/hlists.scala rename to akka-parsing/src/main/scala/akka/parboiled2/support/hlist/ops/hlists.scala index 679da615b12..0362d507329 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/ops/hlists.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/hlist/ops/hlists.scala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-13 Miles Sabin + * Copyright 2009-2019 Mathias Doenitz * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,35 +14,21 @@ * limitations under the License. */ -package akka.shapeless +package akka.parboiled2.support.hlist package ops object hlist { - /** - * Type class witnessing that this `HList` is composite and providing access to head and tail. - * - * @author Miles Sabin - */ - trait IsHCons[L <: HList] { - type H - type T <: HList - def head(l: L): H - def tail(l: L): T + /** Dependent unary function type. */ + trait DepFn1[T] { + type Out + def apply(t: T): Out } - object IsHCons { - def apply[L <: HList](implicit isHCons: IsHCons[L]): Aux[L, isHCons.H, isHCons.T] = isHCons - - type Aux[L <: HList, H0, T0 <: HList] = IsHCons[L] { type H = H0; type T = T0 } - implicit def hlistIsHCons[H0, T0 <: HList]: Aux[H0 :: T0, H0, T0] = - new IsHCons[H0 :: T0] { - type H = H0 - type T = T0 - - def head(l: H0 :: T0): H = l.head - def tail(l: H0 :: T0): T = l.tail - } + /** Dependent binary function type. */ + trait DepFn2[T, U] { + type Out + def apply(t: T, u: U): Out } /** @@ -50,7 +36,7 @@ object hlist { * * @author Miles Sabin */ - trait Reverse[L <: HList] extends DepFn1[L] { type Out <: HList } + trait Reverse[L <: HList] extends DepFn1[L] with Serializable { type Out <: HList } object Reverse { def apply[L <: HList](implicit reverse: Reverse[L]): Aux[L, reverse.Out] = reverse @@ -63,11 +49,12 @@ object hlist { def apply(l: L): Out = reverse(HNil, l) } - trait Reverse0[Acc <: HList, L <: HList, Out <: HList] { + trait Reverse0[Acc <: HList, L <: HList, Out <: HList] extends Serializable { def apply(acc: Acc, l: L): Out } object Reverse0 { + implicit def hnilReverse[Out <: HList]: Reverse0[Out, HNil, Out] = new Reverse0[Out, HNil, Out] { def apply(acc: Out, l: HNil): Out = acc @@ -85,12 +72,24 @@ object hlist { * * @author Miles Sabin */ - trait Prepend[P <: HList, S <: HList] extends DepFn2[P, S] { type Out <: HList } + trait Prepend[P <: HList, S <: HList] extends DepFn2[P, S] with Serializable { + type Out <: HList + } - trait LowPriorityPrepend { + trait LowestPriorityPrepend { type Aux[P <: HList, S <: HList, Out0 <: HList] = Prepend[P, S] { type Out = Out0 } - implicit def hnilPrepend0[P <: HList, S <: HNil]: Aux[P, S, P] = + implicit def hlistPrepend[PH, PT <: HList, S <: HList, PtOut <: HList](implicit pt: Prepend.Aux[PT, S, PtOut]): Prepend.Aux[PH :: PT, S, PH :: PtOut] = + new Prepend[PH :: PT, S] { + type Out = PH :: PtOut + def apply(prefix: PH :: PT, suffix: S): Out = prefix.head :: pt(prefix.tail, suffix) + } + } + + trait LowPriorityPrepend extends LowestPriorityPrepend { + override type Aux[P <: HList, S <: HList, Out0 <: HList] = Prepend[P, S] { type Out = Out0 } + + implicit def hnilPrepend0[P <: HList, S >: HNil.type <: HNil]: Aux[P, S, P] = new Prepend[P, S] { type Out = P def apply(prefix: P, suffix: S): P = prefix @@ -100,17 +99,11 @@ object hlist { object Prepend extends LowPriorityPrepend { def apply[P <: HList, S <: HList](implicit prepend: Prepend[P, S]): Aux[P, S, prepend.Out] = prepend - implicit def hnilPrepend1[P <: HNil, S <: HList]: Aux[P, S, S] = + implicit def hnilPrepend1[P >: HNil.type <: HNil, S <: HList]: Aux[P, S, S] = new Prepend[P, S] { type Out = S def apply(prefix: P, suffix: S): S = suffix } - - implicit def hlistPrepend[PH, PT <: HList, S <: HList](implicit pt: Prepend[PT, S]): Aux[PH :: PT, S, PH :: pt.Out] = - new Prepend[PH :: PT, S] { - type Out = PH :: pt.Out - def apply(prefix: PH :: PT, suffix: S): Out = prefix.head :: pt(prefix.tail, suffix) - } } /** @@ -118,7 +111,7 @@ object hlist { * * @author Miles Sabin */ - trait ReversePrepend[P <: HList, S <: HList] extends DepFn2[P, S] { type Out <: HList } + trait ReversePrepend[P <: HList, S <: HList] extends DepFn2[P, S] with Serializable { type Out <: HList } trait LowPriorityReversePrepend { type Aux[P <: HList, S <: HList, Out0 <: HList] = ReversePrepend[P, S] { type Out = Out0 } diff --git a/akka-parsing/src/main/scala/akka/shapeless/syntax/hlists.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/hlist/syntax/hlists.scala similarity index 79% rename from akka-parsing/src/main/scala/akka/shapeless/syntax/hlists.scala rename to akka-parsing/src/main/scala/akka/parboiled2/support/hlist/syntax/hlists.scala index 66cc3034644..91900268d45 100644 --- a/akka-parsing/src/main/scala/akka/shapeless/syntax/hlists.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/hlist/syntax/hlists.scala @@ -1,5 +1,5 @@ /* - * Copyright (c) 2011-13 Miles Sabin + * Copyright 2009-2019 Mathias Doenitz * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -14,9 +14,11 @@ * limitations under the License. */ -package akka.shapeless +package akka.parboiled2.support.hlist package syntax +import akka.parboiled2.support.hlist.ops.hlist.Reverse + /** * Carrier for `HList` operations. * @@ -25,13 +27,12 @@ package syntax * * @author Miles Sabin */ -final class HListOps[L <: HList](l: L) { - import ops.hlist._ +final class HListOps[L <: HList](l: L) extends Serializable { /** * Prepend the argument element to this `HList`. */ - def ::[H](h: H): H :: L = akka.shapeless.::(h, l) + def ::[H](h: H): H :: L = akka.parboiled2.support.hlist.::(h, l) /** * Reverses this `HList`. diff --git a/akka-parsing/src/main/scala/akka/parboiled2/support/package.scala b/akka-parsing/src/main/scala/akka/parboiled2/support/package.scala index 7aeed42c925..6c38915c8ae 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/support/package.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/support/package.scala @@ -1,11 +1,11 @@ /* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * Copyright 2009-2019 Mathias Doenitz * * 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 * - * http://www.apache.org/licenses/LICENSE-2.0 + * http://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, diff --git a/akka-parsing/src/main/scala/akka/parboiled2/util/Base64.scala b/akka-parsing/src/main/scala/akka/parboiled2/util/Base64.scala new file mode 100644 index 00000000000..b35e0100ee1 --- /dev/null +++ b/akka-parsing/src/main/scala/akka/parboiled2/util/Base64.scala @@ -0,0 +1,342 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2.util + +object Base64 { + private var RFC2045: Base64 = _ + private var CUSTOM: Base64 = _ + + def custom(): Base64 = { + if (CUSTOM == null) + CUSTOM = new Base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+-_") + CUSTOM + } + + def rfc2045(): Base64 = { + if (RFC2045 == null) + RFC2045 = new Base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/=") + RFC2045 + } +} + +class Base64(alphabet: String) { + if (alphabet == null || alphabet.length() != 65) + throw new IllegalArgumentException() + + val CA = alphabet.substring(0, 64).toCharArray + val fillChar = alphabet.charAt(64) + val IA: Array[Int] = Array.fill(256)(-1) + + (0 until CA.length).foreach(i => IA(CA(i)) = i) + + IA(fillChar) = 0 + + def getAlphabet: Array[Char] = + CA + + def decode(s: String): Array[Byte] = decode(s.toCharArray) + + /** + * Decodes a BASE64 encoded char array. All illegal characters will be ignored and can handle both arrays with + * and without line separators. + * + * @param sArr The source array. null or length 0 will return an empty array. + * @return The decoded array of bytes. May be of length 0. Will be null if the legal characters + * (including '=') isn't divideable by 4. (I.e. definitely corrupted). + */ + def decode(sArr: Array[Char]): Array[Byte] = { + // Check special case + val sLen = + if (sArr != null) + sArr.length + else + 0 + + if (sLen == 0) + return Array.empty[Byte] + + // Count illegal characters (including '\r', '\n') to know what size the returned array will be, + // so we don't have to reallocate & copy it later. + // If input is "pure" (I.e. no line separators or illegal chars) base64 this loop can be commented out. + var sepCnt = 0 // Number of separator characters. (Actually illegal characters, but that's a bonus...) + (0 until sLen).foreach { i => + if (IA(sArr(i)) < 0) + sepCnt += 1 + } + + // Check so that legal chars (including '=') are evenly divideable by 4 as specified in RFC 2045. + if ((sLen - sepCnt) % 4 != 0) + return null + + var pad = 0 + var i = sLen - 1 + while (i > 0 && IA(sArr(i)) <= 0) { + if (sArr(i) == fillChar) + pad += 1 + i -= 1 + } + + val len = ((sLen - sepCnt) * 6 >> 3) - pad + + val dArr = Array.ofDim[Byte](len) // Preallocate byte[] of exact length + var s = 0 + var d = 0 + while (d < len) { + // Assemble three bytes into an int from four "valid" characters. + var i = 0 + var j = 0 + + // j only increased if a valid char was found. + while (j < 4) { + val c = IA(sArr(s)) + s += 1 + if (c >= 0) + i |= c << (18 - j * 6) + else + j -= 1 + + j += 1 + } + + // Add the bytes + dArr(d) = (i >> 16).toByte + d += 1 + if (d < len) { + dArr(d) = (i >> 8).toByte + d += 1 + if (d < len) { + dArr(d) = i.toByte + d += 1 + } + } + } + + dArr + } + + def decodeFast(s: String): Array[Byte] = decodeFast(s.toCharArray) + + /** + * Decodes a BASE64 encoded char array that is known to be resonably well formatted. The method is about twice as + * fast as {@link #decode(char[])}. The preconditions are:
+ * + The array must have a line length of 76 chars OR no line separators at all (one line).
+ * + Line separator must be "\r\n", as specified in RFC 2045 + * + The array must not contain illegal characters within the encoded string
+ * + The array CAN have illegal characters at the beginning and end, those will be dealt with appropriately.
+ * + * @param sArr The source array. Length 0 will return an empty array. null will throw an exception. + * @return The decoded array of bytes. May be of length 0. + */ + def decodeFast(sArr: Array[Char]): Array[Byte] = { + // Check special case + val sLen = sArr.length + if (sLen == 0) + return Array.empty[Byte] + + // Start and end index after trimming. + var sIx = 0 + var eIx = sLen - 1 + + // Trim illegal chars from start + while (sIx < eIx && IA(sArr(sIx)) < 0) + sIx += 1 + + // Trim illegal chars from end + while (eIx > 0 && IA(sArr(eIx)) < 0) + eIx -= 1 + + // get the padding count (=) (0, 1 or 2) + // Count '=' at end. + val pad = + if (sArr(eIx) == fillChar) + if (sArr(eIx - 1) == fillChar) + 2 + else + 1 + else + 0 + + // Content count including possible separators + val cCnt = eIx - sIx + 1 + + // Count '=' at end. + val sepCnt = + if (sLen > 76) + (if (sArr(76) == '\r') + cCnt / 78 + else + 0) << 1 + else + 0 + + val len = ((cCnt - sepCnt) * 6 >> 3) - pad // The number of decoded bytes + val dArr = Array.ofDim[Byte](len); // Preallocate byte() of exact length + + // Decode all but the last 0 - 2 bytes. + var d = 0 + var cc = 0 + val eLen = (len / 3) * 3 + + while (d < eLen) { + // Assemble three bytes into an int from four "valid" characters. + var i = IA(sArr(sIx)) << 18 + sIx += 1 + i = i | IA(sArr(sIx)) << 12 + sIx += 1 + i = i | IA(sArr(sIx)) << 6 + sIx += 1 + i = i | IA(sArr(sIx)) + sIx += 1 + + // Add the bytes + dArr(d) = (i >> 16).toByte + d += 1 + dArr(d) = (i >> 8).toByte + d += 1 + dArr(d) = i.toByte + d += 1 + + // If line separator, jump over it. + cc += 1 + if (sepCnt > 0 && cc == 19) { + sIx += 2 + cc = 0 + } + } + + if (d < len) { + // Decode last 1-3 bytes (incl '=') into 1-3 bytes + var i = 0 + var j = 0 + while (sIx <= eIx - pad) { + i |= IA(sArr(sIx)) << (18 - j * 6) + sIx += 1 + j += 1 + } + + var r = 16 + while (d < len) { + dArr(d) = (i >> r).toByte + d += 1 + r -= 8 + } + } + + dArr + } + + /** + * Encodes a raw byte array into a BASE64 String representation in accordance with RFC 2045. + * + * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. + * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
+ * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a + * little faster. + * @return A BASE64 encoded array. Never null. + */ + def encodeToString(sArr: Array[Byte], lineSep: Boolean): String = + // Reuse char[] since we can't create a String incrementally anyway and StringBuffer/Builder would be slower. + new String(encodeToChar(sArr, lineSep)) + + /** + * Encodes a raw byte array into a BASE64 char[] representation i accordance with RFC 2045. + * + * @param sArr The bytes to convert. If null or length 0 an empty array will be returned. + * @param lineSep Optional "\r\n" after 76 characters, unless end of file.
+ * No line separator will be in breach of RFC 2045 which specifies max 76 per line but will be a + * little faster. + * @return A BASE64 encoded array. Never null. + */ + def encodeToChar(sArr: Array[Byte], lineSep: Boolean): Array[Char] = { + // Check special case + val sLen = + if (sArr != null) + sArr.length + else + 0 + + if (sLen == 0) + return Array.empty[Char] + + val eLen = (sLen / 3) * 3 // Length of even 24-bits. + val cCnt = ((sLen - 1) / 3 + 1) << 2 // Returned character count + + // Length of returned array + val dLen = cCnt + (if (lineSep == true) + (cCnt - 1) / 76 << 1 + else + 0) + + val dArr = Array.ofDim[Char](dLen) + + // Encode even 24-bits + var s = 0 + var d = 0 + var cc = 0 + while (s < eLen) { + // Copy next three bytes into lower 24 bits of int, paying attension to sign. + var i = (sArr(s) & 0xff) << 16 + s += 1 + i = i | ((sArr(s) & 0xff) << 8) + s += 1 + i = i | (sArr(s) & 0xff) + s += 1 + + // Encode the int into four chars + dArr(d) = CA((i >>> 18) & 0x3f) + d += 1 + dArr(d) = CA((i >>> 12) & 0x3f) + d += 1 + dArr(d) = CA((i >>> 6) & 0x3f) + d += 1 + dArr(d) = CA(i & 0x3f) + d += 1 + + // Add optional line separator + cc += 1 + if (lineSep && cc == 19 && d < dLen - 2) { + dArr(d) = '\r' + d += 1 + dArr(d) = '\n' + d += 1 + cc = 0 + } + } + + // Pad and encode last bits if source isn't even 24 bits. + val left = sLen - eLen; // 0 - 2. + if (left > 0) { + // Prepare the int + val i = ((sArr(eLen) & 0xff) << 10) | (if (left == 2) + (sArr(sLen - 1) & 0xff) << 2 + else + 0) + + // Set last four chars + dArr(dLen - 4) = CA(i >> 12) + dArr(dLen - 3) = CA((i >>> 6) & 0x3f) + dArr(dLen - 2) = + if (left == 2) + CA(i & 0x3f) + else + fillChar + dArr(dLen - 1) = fillChar + } + + dArr + } +} From 048f8c5ba1b532e3bc9aa40d38f3018a82797612 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 9 Sep 2021 12:13:36 +0200 Subject: [PATCH 04/51] parsing: Scala 3 port of LogHelper macros --- .../scala-2/akka/macros/LogHelperMacro.scala | 44 +++++++++++++++++++ .../scala-3/akka/macros/LogHelperMacro.scala | 19 ++++++++ .../main/scala/akka/macros/LogHelper.scala | 42 ++---------------- 3 files changed, 66 insertions(+), 39 deletions(-) create mode 100644 akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala create mode 100644 akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala diff --git a/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala b/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala new file mode 100644 index 00000000000..acdf188ab5b --- /dev/null +++ b/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala @@ -0,0 +1,44 @@ +package akka.macros + +import akka.annotation.InternalApi + +import scala.reflect.macros.blackbox + +/** INTERNAL API */ +@InternalApi +private[akka] trait LogHelperMacro { + def debug(msg: String): Unit = macro LogHelperMacro.debugMacro + def info(msg: String): Unit = macro LogHelperMacro.infoMacro + def warning(msg: String): Unit = macro LogHelperMacro.warningMacro +} + +/** INTERNAL API */ +@InternalApi +private[akka] object LogHelperMacro { + type LoggerContext = blackbox.Context { type PrefixType = LogHelper } + + def debugMacro(ctx: LoggerContext)(msg: ctx.Expr[String]): ctx.Expr[Unit] = + ctx.universe.reify { + { + val logHelper = ctx.prefix.splice + if (logHelper.isDebugEnabled) + logHelper.log.debug(logHelper.prefixString + msg.splice) + } + } + def infoMacro(ctx: LoggerContext)(msg: ctx.Expr[String]): ctx.Expr[Unit] = + ctx.universe.reify { + { + val logHelper = ctx.prefix.splice + if (logHelper.isInfoEnabled) + logHelper.log.info(logHelper.prefixString + msg.splice) + } + } + def warningMacro(ctx: LoggerContext)(msg: ctx.Expr[String]): ctx.Expr[Unit] = + ctx.universe.reify { + { + val logHelper = ctx.prefix.splice + if (logHelper.isWarningEnabled) + logHelper.log.warning(logHelper.prefixString + msg.splice) + } + } +} diff --git a/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala b/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala new file mode 100644 index 00000000000..1b664673318 --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala @@ -0,0 +1,19 @@ +package akka.macros + +import akka.annotation.InternalApi + +import scala.quoted._ + +/** INTERNAL API */ +@InternalApi +private[akka] trait LogHelperMacro { self: LogHelper => + inline def debug(inline msg: String): Unit = ${LogHelperMacro.guard('{isDebugEnabled}, '{log.debug(prefixString + msg)})} + inline def info(inline msg: String): Unit = ${LogHelperMacro.guard('{isInfoEnabled}, '{log.info(prefixString + msg)})} + inline def warning(inline msg: String): Unit = ${LogHelperMacro.guard('{isWarningEnabled}, '{log.warning(prefixString + msg)})} +} + +/** INTERNAL API */ +@InternalApi +private[akka] object LogHelperMacro { + def guard(isEnabled: Expr[Boolean], log: Expr[Unit])(using Quotes): Expr[Unit] = '{ if ($isEnabled) $log } +} diff --git a/akka-parsing/src/main/scala/akka/macros/LogHelper.scala b/akka-parsing/src/main/scala/akka/macros/LogHelper.scala index c781fe61a04..b2999c93b26 100644 --- a/akka-parsing/src/main/scala/akka/macros/LogHelper.scala +++ b/akka-parsing/src/main/scala/akka/macros/LogHelper.scala @@ -5,9 +5,7 @@ package akka.macros import akka.annotation.InternalApi -import akka.event.LoggingAdapter - -import scala.reflect.macros.blackbox +//import akka.event.LoggingAdapter /** * INTERNAL API @@ -16,47 +14,13 @@ import scala.reflect.macros.blackbox * the message expression eagerly. */ @InternalApi -private[akka] trait LogHelper { - def log: LoggingAdapter +private[akka] trait LogHelper extends LogHelperMacro { + def log: akka.event.LoggingAdapter def isDebugEnabled: Boolean = log.isDebugEnabled def isInfoEnabled: Boolean = log.isInfoEnabled def isWarningEnabled: Boolean = log.isWarningEnabled /** Override to prefix every log message with a user-defined context string */ def prefixString: String = "" - - def debug(msg: String): Unit = macro LogHelper.debugMacro - def info(msg: String): Unit = macro LogHelper.infoMacro - def warning(msg: String): Unit = macro LogHelper.warningMacro } -/** INTERNAL API */ -@InternalApi -private[akka] object LogHelper { - type LoggerContext = blackbox.Context { type PrefixType = LogHelper } - - def debugMacro(ctx: LoggerContext)(msg: ctx.Expr[String]): ctx.Expr[Unit] = - ctx.universe.reify { - { - val logHelper = ctx.prefix.splice - if (logHelper.isDebugEnabled) - logHelper.log.debug(logHelper.prefixString + msg.splice) - } - } - def infoMacro(ctx: LoggerContext)(msg: ctx.Expr[String]): ctx.Expr[Unit] = - ctx.universe.reify { - { - val logHelper = ctx.prefix.splice - if (logHelper.isInfoEnabled) - logHelper.log.info(logHelper.prefixString + msg.splice) - } - } - def warningMacro(ctx: LoggerContext)(msg: ctx.Expr[String]): ctx.Expr[Unit] = - ctx.universe.reify { - { - val logHelper = ctx.prefix.splice - if (logHelper.isWarningEnabled) - logHelper.log.warning(logHelper.prefixString + msg.splice) - } - } -} From 1cf775772611f430bc96756d7eccd821399e83bc Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 9 Sep 2021 12:14:09 +0200 Subject: [PATCH 05/51] parsing: port Akka HTTP version of DynamicRuleDispatchMacro --- .../parboiled2/DynamicRuleDispatchMacro.scala | 42 ++++++++----------- .../akka/parboiled2/DynamicRuleDispatch.scala | 2 +- 2 files changed, 18 insertions(+), 26 deletions(-) diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala index 77a33bc85ea..89f686b76a9 100644 --- a/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/DynamicRuleDispatchMacro.scala @@ -37,40 +37,32 @@ trait DynamicRuleDispatchMacro { self: DynamicRuleDispatch.type => def __create[P <: Parser: Type, L <: HList: Type]( ruleNames: Expr[Seq[String]] )(using Quotes): Expr[(DynamicRuleDispatch[P, L], immutable.Seq[String])] = { + import quotes.reflect._ + val names: Seq[String] = ruleNames match { case Varargs(Exprs(args)) => args.sorted } - def dispatcher(handler: Expr[DynamicRuleHandler[P, L]], ruleName: Expr[String]): Expr[Any] = { - import quotes.reflect._ - def ruleExpr(name: String): Expr[RuleN[L]] = Select.unique('{ $handler.parser }.asTerm, name).asExprOf[RuleN[L]] - def rec(start: Int, end: Int): Expr[Any] = - if (start <= end) { - val mid = (start + end) >>> 1 - val name = names(mid) - - '{ - val c = ${ Expr(name) } compare $ruleName - if (c < 0) ${ rec(mid + 1, end) } - else if (c > 0) ${ rec(start, mid - 1) } - else { - val p = $handler.parser - p.__run[L](${ ruleExpr(name) })($handler) - } - } - } else '{ $handler.ruleNotFound($ruleName) } - - rec(0, names.length - 1) + def ruleEntry(name: String): Expr[(String, RuleRunner[P, L])] = '{ + val runner = new RuleRunner[P, L] { + def apply(handler: DynamicRuleHandler[P, L]): handler.Result = { + val p = handler.parser + p.__run[L](${Select.unique('{ handler.parser }.asTerm, name).asExprOf[RuleN[L]]})(handler) + } + } + (${Expr(name)}, runner) } + val ruleEntries: Expr[Seq[(String, RuleRunner[P, L])]] = Expr.ofSeq(names.map(ruleEntry(_))) '{ - val dispatch: DynamicRuleDispatch[P, L] = - new DynamicRuleDispatch[P, L] { - def apply(handler: DynamicRuleHandler[P, L], ruleName: String): handler.Result = - ${ dispatcher('handler, 'ruleName).asInstanceOf[Expr[handler.Result]] } + val map: Map[String, RuleRunner[P, L]] = Map($ruleEntries*) + val drd = + new akka.parboiled2.DynamicRuleDispatch[P, L] { + def lookup(ruleName: String): Option[RuleRunner[P, L]] = + map.get(ruleName) } - (dispatch, $ruleNames) + (drd, $ruleNames) } } } diff --git a/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala b/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala index 5cbdd29caa2..77fc3e76361 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/DynamicRuleDispatch.scala @@ -35,7 +35,7 @@ trait DynamicRuleHandler[P <: Parser, L <: HList] extends Parser.DeliveryScheme[ */ trait DynamicRuleDispatch[P <: Parser, L <: HList] { def apply(handler: DynamicRuleHandler[P, L], ruleName: String): handler.Result = - lookup(ruleName).map(_(handler)).getOrElse(handler.ruleNotFound(ruleName)) + lookup(ruleName).map(_(handler)).getOrElse(handler.ruleNotFound(ruleName)).asInstanceOf[handler.Result] // FIXME: something wrong with Scala 3 type inference def lookup(ruleName: String): Option[RuleRunner[P, L]] } From ad513a2ad55610584d3c3cdc4e05368da042ce6e Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 9 Sep 2021 12:14:29 +0200 Subject: [PATCH 06/51] parsing: port Akka HTTP changes of parboiled2 Parser changes --- akka-parsing/src/main/scala/akka/parboiled2/Parser.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala b/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala index a5aaad32e88..eee5cdfd0dd 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala @@ -108,10 +108,13 @@ abstract class Parser(initialValueStackSize: Int = 16, maxValueStackSize: Int = // the current ErrorAnalysisPhase or null (in the initial run) private var phase: ErrorAnalysisPhase = _ + private var _maxLength = -1 + def copyStateFrom(other: Parser, offset: Int): Unit = { _cursorChar = other._cursorChar _cursor = other._cursor - offset _valueStack = other._valueStack + _maxLength = other._maxLength phase = other.phase if (phase ne null) phase.applyOffset(offset) } @@ -127,6 +130,7 @@ abstract class Parser(initialValueStackSize: Int = 16, maxValueStackSize: Int = def __run[L <: HList](rule: => RuleN[L])(implicit scheme: Parser.DeliveryScheme[L]): scheme.Result = { def runRule(): Boolean = { _cursor = -1 + _maxLength = input.length __advance() valueStack.clear() try rule ne null From 9a589a3c3b66d86ef126b8cb948355759e86a5d7 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 15 Feb 2022 16:18:13 +0100 Subject: [PATCH 07/51] parsing: use latest parboiled2 version --- .../akka/parboiled2/ParserMacros.scala | 985 +--------------- .../akka/parboiled2/support/HListable.scala | 2 +- .../parboiled2/support/OpTreeContext.scala | 1009 +++++++++++++++++ 3 files changed, 1012 insertions(+), 984 deletions(-) create mode 100644 akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala index 5654a6bfc11..aeb06959f02 100644 --- a/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/ParserMacros.scala @@ -16,9 +16,7 @@ package akka.parboiled2 -import akka.parboiled2.support.hlist.HList - -import scala.annotation.tailrec +import support.hlist.HList private[parboiled2] trait ParserMacroMethods { parser: Parser => @@ -45,985 +43,6 @@ private[parboiled2] trait RuleRunnable { } } -import scala.quoted._ -class OpTreeContext(parser: Expr[Parser])(using Quotes) { - import quotes.reflect.* - - sealed trait OpTree { - def render(wrapped: Boolean): Expr[Boolean] - } - - sealed abstract class NonTerminalOpTree extends OpTree { - def bubbleUp(e: Expr[akka.parboiled2.Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] - - // renders a Boolean Tree - def render(wrapped: Boolean): Expr[Boolean] = - if (wrapped) '{ - val start = $parser.cursor - try ${ renderInner('start, wrapped) } catch { - case e: akka.parboiled2.Parser#TracingBubbleException => ${ bubbleUp('e, 'start) } - } - } - else renderInner(Expr(-1) /* dummy, won't be used */, wrapped) - - // renders a Boolean Tree - protected def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] - } - - sealed abstract class DefaultNonTerminalOpTree extends NonTerminalOpTree { - def bubbleUp(e: Expr[akka.parboiled2.Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] = '{ - $e.bubbleUp($ruleTraceNonTerminalKey, $start) - } - def ruleTraceNonTerminalKey: Expr[RuleTrace.NonTerminalKey] - } - - sealed abstract class TerminalOpTree extends OpTree { - def bubbleUp: Expr[Nothing] = '{ $parser.__bubbleUp($ruleTraceTerminal) } - def ruleTraceTerminal: Expr[RuleTrace.Terminal] - - final def render(wrapped: Boolean): Expr[Boolean] = - if (wrapped) '{ - try ${ renderInner(wrapped) } catch { case akka.parboiled2.Parser.StartTracingException => $bubbleUp } - } - else renderInner(wrapped) - - protected def renderInner(wrapped: Boolean): Expr[Boolean] - } - sealed abstract private class PotentiallyNamedTerminalOpTree(arg: Term) extends TerminalOpTree { - override def bubbleUp: Expr[Nothing] = - callName(arg) match { - case Some(name) => - '{ $parser.__bubbleUp(RuleTrace.NonTerminal(RuleTrace.Named(${ Expr(name) }), 0) :: Nil, $ruleTraceTerminal) } - case None => super.bubbleUp - } - } - - def Sequence(lhs: OpTree, rhs: OpTree): Sequence = - lhs -> rhs match { - case (Sequence(lops), Sequence(rops)) => Sequence(lops ++ rops) - case (Sequence(lops), _) => Sequence(lops :+ rhs) - case (_, Sequence(ops)) => Sequence(lhs +: ops) - case _ => Sequence(Seq(lhs, rhs)) - } - - case class Sequence(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { - require(ops.size >= 2) - override def ruleTraceNonTerminalKey = '{ RuleTrace.Sequence } - override def renderInner(start: quoted.Expr[Int], wrapped: Boolean): Expr[Boolean] = - ops - .map(_.render(wrapped)) - .reduceLeft((l, r) => '{ val ll = $l; if (ll) $r else false }) - } - - case class Cut(lhs: OpTree, rhs: OpTree) extends DefaultNonTerminalOpTree { - override def ruleTraceNonTerminalKey = '{ RuleTrace.Cut } - override def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = '{ - var matched = ${ lhs.render(wrapped) } - if (matched) { - matched = ${ rhs.render(wrapped) } - if (!matched) throw akka.parboiled2.Parser.CutError - true - } else false - } // work-around for https://issues.scala-lang.org/browse/SI-8657 - } - - def FirstOf(lhs: OpTree, rhs: OpTree): FirstOf = - lhs -> rhs match { - case (FirstOf(lops), FirstOf(rops)) => FirstOf(lops ++ rops) - case (FirstOf(lops), _) => FirstOf(lops :+ rhs) - case (_, FirstOf(ops)) => FirstOf(lhs +: ops) - case _ => FirstOf(Seq(lhs, rhs)) - } - case class FirstOf(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.FirstOf } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - '{ - val mark = $parser.__saveState - ${ - ops - .map(_.render(wrapped)) - .reduceLeft((l0, r) => - '{ - val l = $l0 - if (!l) { - $parser.__restoreState(mark) - $r - } else - true // work-around for https://issues.scala-lang.org/browse/SI-8657", FIXME: still valid for dotty? - } - ) - } - } - } - - sealed abstract class WithSeparator extends DefaultNonTerminalOpTree { - def withSeparator(sep: Separator): OpTree - } - - case class ZeroOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { - def withSeparator(sep: Separator) = copy(separator = sep) - def ruleTraceNonTerminalKey = '{ RuleTrace.ZeroOrMore } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - collector.withCollector { coll => - '{ - @ _root_.scala.annotation.tailrec - def rec(mark: akka.parboiled2.Parser.Mark): akka.parboiled2.Parser.Mark = { - val matched = ${ op.render(wrapped) } - if (matched) { - ${ coll.popToBuilder } - ${ - if (separator eq null) '{ rec($parser.__saveState) } - else - '{ - val m = $parser.__saveState - if (${ separator(wrapped) }) rec(m) else m - } - } - } else mark - } - - $parser.__restoreState(rec($parser.__saveState)) - ${ coll.pushBuilderResult } - true - } - } - } - case class OneOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { - def withSeparator(sep: Separator) = copy(separator = sep) - def ruleTraceNonTerminalKey = '{ RuleTrace.OneOrMore } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - collector.withCollector { coll => - '{ - @ _root_.scala.annotation.tailrec - def rec(mark: akka.parboiled2.Parser.Mark): akka.parboiled2.Parser.Mark = { - val matched = ${ op.render(wrapped) } - if (matched) { - ${ coll.popToBuilder } - ${ - if (separator eq null) '{ rec($parser.__saveState) } - else - '{ - val m = $parser.__saveState - if (${ separator(wrapped) }) rec(m) else m - } - } - } else mark - } - - val firstMark = $parser.__saveState - val mark = rec(firstMark) - mark != firstMark && { // FIXME: almost the same as ZeroOrMore and should be combined - $parser.__restoreState(mark) - ${ coll.pushBuilderResult } - true - } - } - } - } - - case class Optional(op: OpTree, collector: Collector) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Optional } - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - collector.withCollector { coll => - '{ - val mark = $parser.__saveState - val matched = ${ op.render(wrapped) } - if (matched) { - ${ coll.pushSomePop } - } else { - $parser.__restoreState(mark) - ${ coll.pushNone } - } - true - } - } - } - - trait MinMaxSupplier { - def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] - } - object MinMaxSupplier { - def constant(n: Expr[Int]): MinMaxSupplier = - new MinMaxSupplier { - override def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] = - '{ - val min = $n - val max = min - - ${ f('min, 'max) } - } - } - - def range(rangeExpr: Expr[Range]): MinMaxSupplier = - new MinMaxSupplier { - override def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] = - '{ - val r = $rangeExpr - val min = r.min - val max = r.max - - ${ f('min, 'max) } - } - } - - /* FIXME: implement optimzations for literal values as shown below - -base match { - case q"$a.this.int2NTimes($n)" => - n match { - case Literal(Constant(i: Int)) => - if (i <= 0) c.abort(base.pos, "`x` in `x.times` must be positive") - else if (i == 1) rule - else Times(rule, q"val min, max = $n", collector, separator) - case x @ (Ident(_) | Select(_, _)) => Times(rule, q"val min = $n; val max = min", collector, separator) - case _ => c.abort(n.pos, "Invalid int base expression for `.times(...)`: " + n) - } - case q"$a.this.range2NTimes($r)" => - r match { - case q"${_}.Predef.intWrapper($mn).to($mx)" => - mn match { - case Literal(Constant(min: Int)) => - if (min <= 0) c.abort(mn.pos, "`min` in `(min to max).times` must be positive") - case (Ident(_) | Select(_, _)) => - case _ => c.abort(r.pos, "Invalid int range expression for `min` in `.times(...)`: " + r) - } - mx match { - case Literal(Constant(max: Int)) => - if (max <= 0) c.abort(mx.pos, "`max` in `(min to max).times` must be positive") - case (Ident(_) | Select(_, _)) => - case _ => c.abort(r.pos, "Invalid int range expression for `max` in `.times(...)`: " + r) - } - (mn, mx) match { - case (Literal(Constant(min: Int)), Literal(Constant(max: Int))) => - if (max < min) c.abort(mx.pos, "`max` in `(min to max).times` must be >= `min`") - case _ => - } - Times(rule, q"val min = $mn; val max = $mx", collector, separator) - case x @ (Ident(_) | Select(_, _)) => - Times(rule, q"val r = $r; val min = r.start; val max = r.end", collector, separator) - case _ => c.abort(r.pos, "Invalid range base expression for `.times(...)`: " + r) - } - case _ => c.abort(base.pos, "Invalid base expression for `.times(...)`: " + base) -}*/ - } - - case class Times( - op: OpTree, - withMinMax: MinMaxSupplier, - collector: Collector, - separator: Separator - ) extends WithSeparator { - def withSeparator(sep: Separator) = copy(separator = sep) - def ruleTraceNonTerminalKey = withMinMax((min, max) => '{ akka.parboiled2.RuleTrace.Times($min, $max) }) - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - collector.withCollector { coll => - withMinMax { (minE, maxE) => - '{ - val min = $minE - val max = $maxE - require(min <= max, "`max` in `(min to max).times` must be >= `min`") - - @ _root_.scala.annotation.tailrec - def rec(count: Int, mark: akka.parboiled2.Parser.Mark): Boolean = { - val matched = ${ op.render(wrapped) } - if (matched) { - ${ coll.popToBuilder } - if (count < max) ${ - if (separator eq null) '{ rec(count + 1, $parser.__saveState) } - else - '{ - val m = $parser.__saveState - if (${ separator(wrapped) }) rec(count + 1, m) - else (count >= min) && { $parser.__restoreState(m); true } - } - } - else true - - } else (count > min) && { $parser.__restoreState(mark); true } - } - - (max <= 0) || rec(1, $parser.__saveState) && { ${ coll.pushBuilderResult }; true } - } - } - } - } - - case class AndPredicate(op: OpTree) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.AndPredicate } - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - '{ - val mark = $parser.__saveState - val matched = ${ op.render(wrapped) } - $parser.__restoreState(mark) - matched - } - } - - case class NotPredicate(op: OpTree) extends OpTree { - - def render(wrapped: Boolean): Expr[Boolean] = { - def unwrappedExpr(setMatchEnd: Option[Expr[Int] => Expr[Unit]]): Expr[Boolean] = '{ - val mark = $parser.__saveState - val saved = $parser.__enterNotPredicate() - val matched = ${ op.render(wrapped) } - $parser.__exitNotPredicate(saved) - ${ - setMatchEnd match { - case Some(matchEndSetter) => matchEndSetter('{ $parser.cursor }) - case None => '{} - } - } - $parser.__restoreState(mark) - !matched - } - - if (wrapped) { - val base = op match { - case x: TerminalOpTree => '{ RuleTrace.NotPredicate.Terminal(${ x.ruleTraceTerminal }) } - case x: RuleCall => '{ RuleTrace.NotPredicate.RuleCall(${ x.calleeNameTree }) } - case x: StringMatch => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringTree }}\"") } - case x: IgnoreCaseString => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringTree }}\"") } - case x: Named => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringExpr }}\"") } - case _ => '{ RuleTrace.NotPredicate.Anonymous } - } - '{ - var matchEnd = 0 - try ${ unwrappedExpr(Some(v => '{ matchEnd = $v })) } || $parser.__registerMismatch() - catch { - case Parser.StartTracingException => - $parser.__bubbleUp { - RuleTrace.NotPredicate($base, matchEnd - $parser.cursor) - } - } - } - } else unwrappedExpr(None) - } - } - - private def expandLambda(body: Term, wrapped: Boolean): Expr[Boolean] = { - def popToVals(valdefs: List[ValDef]): List[Statement] = { - def convertOne(v: ValDef): ValDef = - v.tpt.tpe.asType match { - case '[t] => ValDef.copy(v)(v.name, v.tpt, Some('{ $parser.valueStack.pop().asInstanceOf[t] }.asTerm)) - } - - valdefs.map(convertOne).reverse - } - - body match { - case Lambda(args, body) => - def rewrite(tree: Term): Term = - tree.tpe.asType match { - case '[Rule[_, _]] => expand(tree, wrapped).asInstanceOf[Term] - case _ => - tree match { - case Block(statements, res) => block(statements, rewrite(res)) - case x => '{ $parser.__push(${ x.asExpr }) }.asTerm - } - } - // do a beta reduction, using the parameter definitions as stubs for variables - // that hold values popped from the stack - block(popToVals(args), rewrite(body)).asExprOf[Boolean] - } - } - - private case class Action(body: Term, ts: List[TypeTree]) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Action } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = expandLambda(body, wrapped) - } - - case class RunAction(body: Expr[_]) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Run } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - body.asTerm.tpe.asType match { - case '[Rule[_, _]] => expand(body, wrapped) - case '[t1 => r] => expandLambda(body.asTerm, wrapped) - case '[(t1, t2) => r] => expandLambda(body.asTerm, wrapped) - case '[(t1, t2, t3) => r] => expandLambda(body.asTerm, wrapped) - case '[(t1, t2, t3, t4) => r] => expandLambda(body.asTerm, wrapped) - case '[(t1, t2, t3, t4, t5) => r] => expandLambda(body.asTerm, wrapped) - case '[x] => '{ $body; true } - } - } - - case class SemanticPredicate(flagTree: Expr[Boolean]) extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.SemanticPredicate } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = - if (wrapped) '{ $flagTree || $parser.__registerMismatch() } - else flagTree - } - - case class Capture(op: OpTree) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Capture } - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - '{ - val start1 = ${ if (wrapped) start else '{ $parser.cursor } } - val matched = ${ op.render(wrapped) } - if (matched) { - $parser.valueStack.push($parser.input.sliceString(start1, $parser.cursor)) - true - } else false - } - } - - private case class PushAction(valueExpr: Expr[_], argType: Type[_]) extends OpTree { - def render(wrapped: Boolean): Expr[Boolean] = { - val body = - argType match { - case '[Unit] => valueExpr - case '[HList] => '{ $parser.valueStack.pushAll($valueExpr.asInstanceOf[HList]) } - case _ => '{ $parser.valueStack.push($valueExpr) } - } - - '{ - $body - true - } - } - } - private case class DropAction(tpe: Type[_]) extends OpTree { - def render(wrapped: Boolean): Expr[Boolean] = { - import support.hlist._ - val body = - tpe match { - case '[Unit] => '{} - case '[HList] => - @tailrec def rec(t: Type[_], prefix: Expr[Unit]): Expr[Unit] = t match { - case '[HNil] => prefix - case '[h :: t] => - rec(Type.of[t], '{ $prefix; $parser.valueStack.pop() }) - - } - rec(tpe, '{}) - - case _ => '{ $parser.valueStack.pop() } - } - - '{ - $body - true - } - } - } - - private case class RuleCall(call: Either[OpTree, Expr[Rule[_, _]]], calleeNameTree: Expr[String]) - extends NonTerminalOpTree { - - def bubbleUp(e: Expr[Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] = - '{ $e.prepend(RuleTrace.RuleCall, $start).bubbleUp(RuleTrace.Named($calleeNameTree), $start) } - - override def render(wrapped: Boolean): Expr[Boolean] = call match { - case Left(_) => super.render(wrapped) - case Right(rule) => '{ $rule ne null } - } - protected def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = { - val Left(value) = call - value.render(wrapped) - } - } - - case class CharMatch(charTree: Expr[Char]) extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharMatch($charTree) } - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ - $parser.cursorChar == $charTree && $parser.__advance() - } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case class StringMatch(stringTree: Expr[String]) extends OpTree { - final private val autoExpandMaxStringLength = 8 - - override def render(wrapped: Boolean): Expr[Boolean] = { - def unrollUnwrapped(s: String, ix: Int = 0): Expr[Boolean] = - if (ix < s.length) - '{ - if ($parser.cursorChar == ${ Expr(s.charAt(ix)) }) { - $parser.__advance() - ${ unrollUnwrapped(s, ix + 1) } - } else false - } - else '{ true } - - def unrollWrapped(s: String, ix: Int = 0): Expr[Boolean] = - if (ix < s.length) { - val ch = Expr(s.charAt(ix)) - '{ - if ($parser.cursorChar == $ch) { - $parser.__advance() - $parser.__updateMaxCursor() - ${ unrollWrapped(s, ix + 1) } - } else { - try $parser.__registerMismatch() - catch { - case akka.parboiled2.Parser.StartTracingException => - import akka.parboiled2.RuleTrace._ - $parser.__bubbleUp( - NonTerminal(akka.parboiled2.RuleTrace.StringMatch($stringTree), -${ Expr(ix) }) :: Nil, - akka.parboiled2.RuleTrace.CharMatch($ch) - ) - } - } - } - } else '{ true } - - stringTree.asTerm match { - case Literal(StringConstant(s: String)) if s.length <= autoExpandMaxStringLength => - if (s.isEmpty) '{ true } - else if (wrapped) unrollWrapped(s) - else unrollUnwrapped(s) - case _ => - if (wrapped) '{ $parser.__matchStringWrapped($stringTree) } - else '{ $parser.__matchString($stringTree) } - } - } - } - - case class MapMatch(mapTree: Expr[Map[String, Any]], ignoreCaseTree: Expr[Boolean]) extends OpTree { - - override def render(wrapped: Boolean): Expr[Boolean] = - if (wrapped) '{ $parser.__matchMapWrapped($mapTree, $ignoreCaseTree) } - else '{ $parser.__matchMap($mapTree, $ignoreCaseTree) } - } - - case class IgnoreCaseChar(charTree: Expr[Char]) extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.IgnoreCaseChar($charTree) } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ - _root_.java.lang.Character.toLowerCase($parser.cursorChar) == $charTree && $parser.__advance() - } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case class IgnoreCaseString(stringTree: Expr[String]) extends OpTree { - final private val autoExpandMaxStringLength = 8 - - override def render(wrapped: Boolean): Expr[Boolean] = - def unrollUnwrapped(s: String, ix: Int = 0): Expr[Boolean] = - if (ix < s.length) - '{ - if (_root_.java.lang.Character.toLowerCase($parser.cursorChar) == ${ Expr(s.charAt(ix)) }) { - $parser.__advance() - ${ unrollUnwrapped(s, ix + 1) } - } else false - } - else '{ true } - - def unrollWrapped(s: String, ix: Int = 0): Expr[Boolean] = - if (ix < s.length) { - val ch = Expr(s.charAt(ix)) - '{ - if (_root_.java.lang.Character.toLowerCase($parser.cursorChar) == $ch) { - $parser.__advance() - $parser.__updateMaxCursor() - ${ unrollWrapped(s, ix + 1) } - } else { - try $parser.__registerMismatch() - catch { - case akka.parboiled2.Parser.StartTracingException => - import akka.parboiled2.RuleTrace._ - $parser.__bubbleUp( - NonTerminal(akka.parboiled2.RuleTrace.IgnoreCaseString($stringTree), -${ Expr(ix) }) :: Nil, - akka.parboiled2.RuleTrace.IgnoreCaseChar($ch) - ) - } - } - } - } else '{ true } - - stringTree.asTerm match { - case Literal(StringConstant(s: String)) if s.length <= autoExpandMaxStringLength => - if (s.isEmpty) '{ true } - else if (wrapped) unrollWrapped(s) - else unrollUnwrapped(s) - case _ => - if (wrapped) '{ $parser.__matchIgnoreCaseStringWrapped($stringTree) } - else '{ $parser.__matchIgnoreCaseString($stringTree) } - } - } - - private case class CharPredicateMatch(predicateTree: Expr[CharPredicate]) - extends PotentiallyNamedTerminalOpTree(predicateTree.asTerm) { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharPredicateMatch($predicateTree) } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ $predicateTree($parser.cursorChar) && $parser.__advance() } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case class AnyOf(stringTree: Expr[String]) extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.AnyOf($stringTree) } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ $parser.__matchAnyOf($stringTree) } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case class NoneOf(stringTree: Expr[String]) extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.NoneOf($stringTree) } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ $parser.__matchNoneOf($stringTree) } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case object ANY extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.ANY } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ $parser.cursorChar != EOI && $parser.__advance() } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case class Unknown(syntax: String, tree: String, outerSyntax: String) extends TerminalOpTree { - override def ruleTraceTerminal: Expr[RuleTrace.Terminal] = - '{ RuleTrace.Fail(s"unknown rule: $$infoExpr") } - - override protected def renderInner(wrapped: Boolean): Expr[Boolean] = - '{ - throw new RuntimeException( - s"unknown rule: [${${ Expr(syntax) }}] '${${ Expr(tree) }}' in [${${ Expr(outerSyntax) }}]" - ) - } - } - - def CharRange(lowerTree: Expr[String], upperTree: Expr[String]): CharacterRange = - (lowerTree.value, upperTree.value) match { - case (Some(lower), Some(upper)) => - if (lower.length != 1) reportError("lower bound must be a single char string", lowerTree) - if (upper.length != 1) reportError("upper bound must be a single char string", upperTree) - val lowerBoundChar = lower.charAt(0) - val upperBoundChar = upper.charAt(0) - if (lowerBoundChar > upperBoundChar) reportError("lower bound must not be > upper bound", lowerTree) - CharacterRange(Expr(lowerBoundChar), Expr(upperBoundChar)) - case _ => reportError("Character ranges must be specified with string literals", lowerTree) - } - - case class CharacterRange(lowerBound: Expr[Char], upperBound: Expr[Char]) extends TerminalOpTree { - def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharRange($lowerBound, $upperBound) } - - override def renderInner(wrapped: Boolean): Expr[Boolean] = { - val unwrappedTree = '{ - val char = $parser.cursorChar - $lowerBound <= char && char <= $upperBound && $parser.__advance() - } - if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } - else unwrappedTree - } - } - - case class Fail(stringExpr: Expr[String]) extends OpTree { - def render(wrapped: Boolean): Expr[Boolean] = '{ throw new akka.parboiled2.Parser.Fail($stringExpr) } - } - case class Named(op: OpTree, stringExpr: Expr[String]) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Named($stringExpr) } - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = op.render(wrapped) - } - case class Atomic(op: OpTree) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Atomic } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - if (wrapped) '{ - val saved = $parser.__enterAtomic($start) - val matched = ${ op.render(wrapped) } - $parser.__exitAtomic(saved) - matched - } - else op.render(wrapped) - } - - case class Quiet(op: OpTree) extends DefaultNonTerminalOpTree { - def ruleTraceNonTerminalKey = '{ RuleTrace.Quiet } - - def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = - if (wrapped) '{ - val saved = $parser.__enterQuiet() - val matched = ${ op.render(wrapped) } - $parser.__exitQuiet(saved) - matched - } - else op.render(wrapped) - } - - def topLevel(opTree: OpTree, name: Expr[String]): OpTree = RuleCall(Left(opTree), name) - - def deconstruct(outerRule: Expr[Rule[_, _]]): OpTree = deconstructPF(outerRule).get - def deconstructPF(outerRule: Expr[Rule[_, _]]): Option[OpTree] = { - import quotes.reflect.* - - def collector(lifter: Term): Collector = - lifter match { - case TypeApply(Ident("forRule0" | "forReduction"), _) => rule0Collector - case TypeApply(Ident("forRule1"), _) => rule1Collector - case x => reportError(s"Unexpected lifter ${lifter.show(using Printer.TreeStructure)}", lifter.asExpr) - } - - // a list of names for operations that are not yet implemented but that should not be interpreted as rule calls - // FIXME: can be removed when everything is implemented - val ruleNameBlacklist = - Set( - "str", - "!", - "?", - "&", - "optional", - "run", - "zeroOrMore", - "times", - "oneOrMore", - "rule2ActionOperator", - "range2NTimes", - "rule2WithSeparatedBy" - ) - - lazy val rules0PF: PartialFunction[Expr[Rule[_, _]], OpTree] = { - case '{ ($p: Parser).ch($c) } => CharMatch(c) - case '{ ($p: Parser).str($s) } => StringMatch(s) - case '{ ($p: Parser).valueMap($m: Map[String, Any]) } => MapMatch(m, '{ false }) - case '{ ($p: Parser).valueMap($m: Map[String, Any], $ic) } => MapMatch(m, ic) - case '{ ($p: Parser).ignoreCase($c: Char) } => IgnoreCaseChar(c) - case '{ ($p: Parser).ignoreCase($s: String) } => IgnoreCaseString(s) - case '{ ($p: Parser).predicate($pr) } => CharPredicateMatch(pr) - case '{ ($p: Parser).anyOf($s) } => AnyOf(s) - case '{ ($p: Parser).noneOf($s) } => NoneOf(s) - case '{ ($p: Parser).ANY } => ANY - case '{ ($p: Parser).str2CharRangeSupport($l).-($r) } => CharRange(l, r) - case '{ ($p: Parser).test($flag) } => SemanticPredicate(flag) - case '{ ($p: Parser).push[t]($value) } => PushAction(value, Type.of[t]) - case '{ ($p: Parser).drop[t] } => DropAction(Type.of[t]) - case '{ type i <: HList; type o <: HList; ($p: Parser).capture[`i`, `o`]($arg)($l) } => Capture(rec(arg.asTerm)) - case '{ - type i1 <: HList; type o1 <: HList - type i2 <: HList; type o2 <: HList - ($lhs: Rule[`i1`, `o1`]).~[`i2`, `o2`]($rhs)($_, $_) - } => - Sequence(Seq(rec(lhs.asTerm), rec(rhs.asTerm))) - - case '{ - type i1 <: HList; type o1 <: HList - type i2 <: `i1`; type o2 >: `o1` <: HList - ($lhs: Rule[`i1`, `o1`]).|[`i2`, `o2`]($rhs) - } => - FirstOf(rec(lhs.asTerm), rec(rhs.asTerm)) - - case '{ - type i1 <: HList; type o1 <: HList - type i2 <: HList; type o2 <: HList - ($lhs: Rule[`i1`, `o1`]).~!~[`i2`, `o2`]($rhs)($_, $_) - } => - Cut(rec(lhs.asTerm), rec(rhs.asTerm)) - - case '{ type i <: HList; type o <: HList; ($p: Parser).zeroOrMore[`i`, `o`]($arg)($l) } => - ZeroOrMore(rec(arg.asTerm), collector(l.asTerm)) - - case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).*($l: support.Lifter[Seq, `i`, `o`]) } => - ZeroOrMore(rec(base.asTerm), collector(l.asTerm)) - - case '{ - type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).*($sep: Rule0)($l: support.Lifter[Seq, `i`, `o`]) - } => - ZeroOrMore(rec(base.asTerm), collector(l.asTerm), Separator(rec(sep.asTerm))) - - case '{ type i <: HList; type o <: HList; ($p: Parser).oneOrMore[`i`, `o`]($arg)($l) } => - OneOrMore(rec(arg.asTerm), collector(l.asTerm)) - - case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).+($l: support.Lifter[Seq, `i`, `o`]) } => - OneOrMore(rec(base.asTerm), collector(l.asTerm)) - - case '{ - type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).+($sep: Rule0)($l: support.Lifter[Seq, `i`, `o`]) - } => - OneOrMore(rec(base.asTerm), collector(l.asTerm), Separator(rec(sep.asTerm))) - - case '{ type i <: HList; type o <: HList; ($p: Parser).optional[`i`, `o`]($arg)($l) } => - Optional(rec(arg.asTerm), collector(l.asTerm)) - - case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).?($l: support.Lifter[Option, `i`, `o`]) } => - Optional(rec(base.asTerm), collector(l.asTerm)) - - case '{ type i <: HList; type o <: HList; ($p: Parser).int2NTimes($n).times[`i`, `o`]($arg)($l) } => - Times( - rec(arg.asTerm), - MinMaxSupplier.constant(n), - collector(l.asTerm), - null - ) - case '{ type i <: HList; type o <: HList; ($p: Parser).range2NTimes($r).times[`i`, `o`]($arg)($l) } => - Times( - rec(arg.asTerm), - MinMaxSupplier.range(r), - collector(l.asTerm), - null - ) - - case '{ type i <: HList; type o <: HList; !($arg: Rule[`i`, `o`]) } => - NotPredicate(rec(arg.asTerm)) - - case '{ ($p: Parser).&($arg) } => - AndPredicate(rec(arg.asTerm)) - - case '{ - type i <: HList; type o <: HList; ($p: Parser).rule2WithSeparatedBy[`i`, `o`]($base).separatedBy($sep) - } => - rec(base.asTerm) match { - case ws: WithSeparator => ws.withSeparator(Separator(rec(sep.asTerm))) - case _ => reportError(s"Illegal `separatedBy` base: $base", base) - } - - case '{ ($p: Parser).run[t]($e)($l) } => RunAction(e) - case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).named($str) } => Named(rec(base.asTerm), str) - case '{ type i <: HList; type o <: HList; ($p: Parser).atomic[`i`, `o`]($r) } => Atomic(rec(r.asTerm)) - case '{ type i <: HList; type o <: HList; ($p: Parser).quiet[`i`, `o`]($r) } => Quiet(rec(r.asTerm)) - case '{ ($p: Parser).fail($str) } => Fail(str) - case '{ type i <: HList; type o <: HList; ($p: Parser).failX[`i`, `o`]($str) } => Fail(str) - } - - lazy val rules1PF: PartialFunction[Term, OpTree] = { - // cannot easily be converted because we would have to list all ActionOps instances - case Apply( - Apply( - TypeApply( - Select( - Select(Apply(Apply(TypeApply(Select(_, "rule2ActionOperator"), _), List(base)), _), "~>"), - "apply" - ), - _ - ), - List(body) - ), - List(_, TypeApply(Ident("apply"), ts)) - ) => - Sequence(rec(base), Action(body, ts)) - - case call @ (Apply(_, _) | Select(_, _) | Ident(_) | TypeApply(_, _)) - if !callName(call).exists(ruleNameBlacklist) => - RuleCall( - Right(call.asExprOf[Rule[_, _]]), - Expr(callName(call) getOrElse reportError("Illegal rule call: " + call, call.asExpr)) - ) - //case _ => Unknown(rule.show, rule.show(using Printer.TreeStructure), outerRule.toString) - } - lazy val allRules = rules0PF.orElse(rules1PF.compose[Expr[Rule[_, _]]] { case x => x.asTerm.underlyingArgument }) - def rec(rule: Term): OpTree = allRules.applyOrElse( - rule.asExprOf[Rule[_, _]], - rule => Unknown(rule.show, "" /*rule.show(using Printer.TreeStructure)*/, outerRule.toString) - ) - - allRules.lift(outerRule) - } - - private def reportError(error: String, expr: Expr[Any]): Nothing = { - quotes.reflect.report.error(error, expr) - throw new scala.quoted.runtime.StopMacroExpansion - } - - /////////////////////////////////// helpers //////////////////////////////////// - - trait Collector { - def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] - } - trait CollectorInstance { - def popToBuilder: Expr[Unit] - def pushBuilderResult: Expr[Unit] - def pushSomePop: Expr[Unit] - def pushNone: Expr[Unit] - } - - // no-op collector - object rule0Collector extends Collector with CollectorInstance { - override def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] = f(this) - private val unit: Expr[Unit] = '{} - def popToBuilder: Expr[Unit] = unit - def pushBuilderResult: Expr[Unit] = unit - def pushSomePop: Expr[Unit] = unit - def pushNone: Expr[Unit] = unit - } - - object rule1Collector extends Collector { - override def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] = '{ - val builder = new scala.collection.immutable.VectorBuilder[Any] - ${ - f(new CollectorInstance { - def popToBuilder: Expr[Unit] = '{ builder += $parser.valueStack.pop() } - def pushBuilderResult: Expr[Unit] = '{ $parser.valueStack.push(builder.result()) } - def pushSomePop: Expr[Unit] = '{ $parser.valueStack.push(Some($parser.valueStack.pop())) } - def pushNone: Expr[Unit] = '{ $parser.valueStack.push(None) } - }) - } - } - } - - type Separator = Boolean => Expr[Boolean] - private def Separator(op: OpTree): Separator = wrapped => op.render(wrapped) - - @tailrec - private def callName(tree: Term): Option[String] = - tree match { - case Ident(name) => Some(name) - case Select(_, name) => Some(name) - case Apply(fun, _) => callName(fun) - case TypeApply(fun, _) => callName(fun) - case _ => None - } - - // tries to match and expand the leaves of the given Tree - private def expand(expr: Expr[_], wrapped: Boolean): Expr[Boolean] = - expand(expr.asTerm, wrapped).asExprOf[Boolean] - private def expand(tree: Tree, wrapped: Boolean): Tree = - tree match { - case Block(statements, res) => block(statements, expand(res, wrapped).asInstanceOf[Term]) - case If(cond, thenExp, elseExp) => - If(cond, expand(thenExp, wrapped).asInstanceOf[Term], expand(elseExp, wrapped).asInstanceOf[Term]) - case Match(selector, cases) => Match(selector, cases.map(expand(_, wrapped).asInstanceOf[CaseDef])) - case CaseDef(pat, guard, body) => CaseDef(pat, guard, expand(body, wrapped).asInstanceOf[Term]) - case x => - deconstructPF(x.asExprOf[Rule[_, _]]) // can we pass the body as a rule? - .map(_.render(wrapped)) // then render it - .getOrElse('{ ${ x.asExprOf[Rule[_, _]] } ne null }) // otherwise, assume the expression is a rule itself - .asTerm - } - - private def block(a: Term, b: Term): Term = - a match { - case Block(a1, a2) => - b match { - case Block(b1, b2) => Block(a1 ::: a2 :: b1, b2) - case _ => Block(a1 ::: a2 :: Nil, b) - } - case _ => - b match { - case Block(b1, b2) => Block(a :: b1, b2) - case _ => Block(a :: Nil, b) - } - } - - private def block(stmts: List[Statement], expr: Term): Term = - expr match { - case Block(a, b) => block(stmts ::: a ::: Nil, b) - case _ => Block(stmts, expr) - } -} - object ParserMacros { import scala.quoted._ import scala.compiletime._ @@ -1113,7 +132,7 @@ object ParserMacros { ): Expr[Rule[I, O]] = { import quotes.reflect.* - val ctx = new OpTreeContext(parser) + val ctx = new support.OpTreeContext(parser) val opTree = ctx.topLevel(ctx.deconstruct(r), name) '{ diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala index 2440a2f0b69..49b28e6c368 100644 --- a/akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/HListable.scala @@ -16,7 +16,7 @@ package akka.parboiled2.support -import akka.parboiled2.support.hlist._ +import hlist._ trait HListable[T] { type Out <: HList diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala new file mode 100644 index 00000000000..e49bc498481 --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala @@ -0,0 +1,1009 @@ +/* + * Copyright 2009-2019 Mathias Doenitz + * + * 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 + * + * http://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 akka.parboiled2.support + +import akka.parboiled2._ +import akka.parboiled2.support.hlist.HList + +import scala.quoted._ +import scala.annotation.tailrec + +class OpTreeContext(parser: Expr[Parser])(using Quotes) { + import quotes.reflect.* + + sealed trait OpTree { + def render(wrapped: Boolean): Expr[Boolean] + } + + sealed abstract class NonTerminalOpTree extends OpTree { + def bubbleUp(e: Expr[akka.parboiled2.Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] + + // renders a Boolean Tree + def render(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + val start = $parser.cursor + try ${ renderInner('start, wrapped) } catch { + case e: akka.parboiled2.Parser#TracingBubbleException => ${ bubbleUp('e, 'start) } + } + } + else renderInner(Expr(-1) /* dummy, won't be used */, wrapped) + + // renders a Boolean Tree + protected def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] + } + + sealed abstract class DefaultNonTerminalOpTree extends NonTerminalOpTree { + def bubbleUp(e: Expr[akka.parboiled2.Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] = '{ + $e.bubbleUp($ruleTraceNonTerminalKey, $start) + } + def ruleTraceNonTerminalKey: Expr[RuleTrace.NonTerminalKey] + } + + sealed abstract class TerminalOpTree extends OpTree { + def bubbleUp: Expr[Nothing] = '{ $parser.__bubbleUp($ruleTraceTerminal) } + def ruleTraceTerminal: Expr[RuleTrace.Terminal] + + final def render(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + try ${ renderInner(wrapped) } catch { case akka.parboiled2.Parser.StartTracingException => $bubbleUp } + } + else renderInner(wrapped) + + protected def renderInner(wrapped: Boolean): Expr[Boolean] + } + sealed abstract private class PotentiallyNamedTerminalOpTree(arg: Term) extends TerminalOpTree { + override def bubbleUp: Expr[Nothing] = + callName(arg) match { + case Some(name) => + '{ $parser.__bubbleUp(RuleTrace.NonTerminal(RuleTrace.Named(${ Expr(name) }), 0) :: Nil, $ruleTraceTerminal) } + case None => super.bubbleUp + } + } + + def Sequence(lhs: OpTree, rhs: OpTree): Sequence = + lhs -> rhs match { + case (Sequence(lops), Sequence(rops)) => Sequence(lops ++ rops) + case (Sequence(lops), _) => Sequence(lops :+ rhs) + case (_, Sequence(ops)) => Sequence(lhs +: ops) + case _ => Sequence(Seq(lhs, rhs)) + } + + case class Sequence(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { + require(ops.size >= 2) + override def ruleTraceNonTerminalKey = '{ RuleTrace.Sequence } + override def renderInner(start: quoted.Expr[Int], wrapped: Boolean): Expr[Boolean] = + ops + .map(_.render(wrapped)) + .reduceLeft((l, r) => '{ val ll = $l; if (ll) $r else false }) + } + + case class Cut(lhs: OpTree, rhs: OpTree) extends DefaultNonTerminalOpTree { + override def ruleTraceNonTerminalKey = '{ RuleTrace.Cut } + override def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = '{ + var matched = ${ lhs.render(wrapped) } + if (matched) { + matched = ${ rhs.render(wrapped) } + if (!matched) throw akka.parboiled2.Parser.CutError + true + } else false + } // work-around for https://issues.scala-lang.org/browse/SI-8657 + } + + def FirstOf(lhs: OpTree, rhs: OpTree): FirstOf = + lhs -> rhs match { + case (FirstOf(lops), FirstOf(rops)) => FirstOf(lops ++ rops) + case (FirstOf(lops), _) => FirstOf(lops :+ rhs) + case (_, FirstOf(ops)) => FirstOf(lhs +: ops) + case _ => FirstOf(Seq(lhs, rhs)) + } + case class FirstOf(ops: Seq[OpTree]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.FirstOf } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + '{ + val mark = $parser.__saveState + ${ + ops + .map(_.render(wrapped)) + .reduceLeft((l0, r) => + '{ + val l = $l0 + if (!l) { + $parser.__restoreState(mark) + $r + } else + true // work-around for https://issues.scala-lang.org/browse/SI-8657", FIXME: still valid for dotty? + } + ) + } + } + } + + sealed abstract class WithSeparator extends DefaultNonTerminalOpTree { + def withSeparator(sep: Separator): OpTree + } + + case class ZeroOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { + def withSeparator(sep: Separator) = copy(separator = sep) + def ruleTraceNonTerminalKey = '{ RuleTrace.ZeroOrMore } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + '{ + @ _root_.scala.annotation.tailrec + def rec(mark: akka.parboiled2.Parser.Mark): akka.parboiled2.Parser.Mark = { + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.popToBuilder } + ${ + if (separator eq null) '{ rec($parser.__saveState) } + else + '{ + val m = $parser.__saveState + if (${ separator(wrapped) }) rec(m) else m + } + } + } else mark + } + + $parser.__restoreState(rec($parser.__saveState)) + ${ coll.pushBuilderResult } + true + } + } + } + case class OneOrMore(op: OpTree, collector: Collector, separator: Separator = null) extends WithSeparator { + def withSeparator(sep: Separator) = copy(separator = sep) + def ruleTraceNonTerminalKey = '{ RuleTrace.OneOrMore } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + '{ + @ _root_.scala.annotation.tailrec + def rec(mark: akka.parboiled2.Parser.Mark): akka.parboiled2.Parser.Mark = { + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.popToBuilder } + ${ + if (separator eq null) '{ rec($parser.__saveState) } + else + '{ + val m = $parser.__saveState + if (${ separator(wrapped) }) rec(m) else m + } + } + } else mark + } + + val firstMark = $parser.__saveState + val mark = rec(firstMark) + mark != firstMark && { // FIXME: almost the same as ZeroOrMore and should be combined + $parser.__restoreState(mark) + ${ coll.pushBuilderResult } + true + } + } + } + } + + case class Optional(op: OpTree, collector: Collector) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Optional } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + '{ + val mark = $parser.__saveState + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.pushSomePop } + } else { + $parser.__restoreState(mark) + ${ coll.pushNone } + } + true + } + } + } + + trait MinMaxSupplier { + def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] + } + object MinMaxSupplier { + def constant(n: Expr[Int]): MinMaxSupplier = + new MinMaxSupplier { + override def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] = + '{ + val min = $n + val max = min + + ${ f('min, 'max) } + } + } + + def range(rangeExpr: Expr[Range]): MinMaxSupplier = + new MinMaxSupplier { + override def apply[T: Type](f: (Expr[Int], Expr[Int]) => Expr[T]): Expr[T] = + '{ + val r = $rangeExpr + val min = r.min + val max = r.max + + ${ f('min, 'max) } + } + } + } + + def Int2NTimes( + n: Expr[Int], + op: OpTree, + withMinMax: MinMaxSupplier, + collector: Collector, + separator: Separator + ): OpTree = + n.asTerm match { + case Literal(IntConstant(i)) => + if (i <= 0) reportError("`x` in `x.times` must be positive", n) + else if (i == 1) op + else Times(op, withMinMax, collector, separator) + case _ => + Times(op, withMinMax, collector, separator) + } + + def Range2NTimes( + range: Expr[Range], + op: OpTree, + withMinMax: MinMaxSupplier, + collector: Collector, + separator: Separator + ): OpTree = { + range match { + case '{ scala.Predef.intWrapper($mn).to($mx) } => + mn.asTerm match { + case Literal(IntConstant(min)) if min <= 0 => + reportError("`min` in `(min to max).times` must be positive", mn) + case _ => () + } + mx.asTerm match { + case Literal(IntConstant(max)) if max <= 0 => + reportError("`max` in `(min to max).times` must be positive", mx) + case _ => () + } + (mn.asTerm, mx.asTerm) match { + case (Literal(IntConstant(min)), Literal(IntConstant(max))) if max < min => + reportError("`max` in `(min to max).times` must be >= `min`", mx) + case _ => () + } + Times(op, withMinMax, collector, separator) + case _ => + reportError("Invalid base expression for `.times(...)`: " + range.show, range) + } + } + + case class Times( + op: OpTree, + withMinMax: MinMaxSupplier, + collector: Collector, + separator: Separator + ) extends WithSeparator { + def withSeparator(sep: Separator) = copy(separator = sep) + def ruleTraceNonTerminalKey = withMinMax((min, max) => '{ akka.parboiled2.RuleTrace.Times($min, $max) }) + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + collector.withCollector { coll => + withMinMax { (minE, maxE) => + '{ + val min = $minE + val max = $maxE + require(min <= max, "`max` in `(min to max).times` must be >= `min`") + + @ _root_.scala.annotation.tailrec + def rec(count: Int, mark: akka.parboiled2.Parser.Mark): Boolean = { + val matched = ${ op.render(wrapped) } + if (matched) { + ${ coll.popToBuilder } + if (count < max) ${ + if (separator eq null) '{ rec(count + 1, $parser.__saveState) } + else + '{ + val m = $parser.__saveState + if (${ separator(wrapped) }) rec(count + 1, m) + else (count >= min) && { $parser.__restoreState(m); true } + } + } + else true + + } else (count > min) && { $parser.__restoreState(mark); true } + } + + (max <= 0) || rec(1, $parser.__saveState) && { ${ coll.pushBuilderResult }; true } + } + } + } + } + + case class AndPredicate(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.AndPredicate } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + '{ + val mark = $parser.__saveState + val matched = ${ op.render(wrapped) } + $parser.__restoreState(mark) + matched + } + } + + case class NotPredicate(op: OpTree) extends OpTree { + + def render(wrapped: Boolean): Expr[Boolean] = { + def unwrappedExpr(setMatchEnd: Option[Expr[Int] => Expr[Unit]]): Expr[Boolean] = '{ + val mark = $parser.__saveState + val saved = $parser.__enterNotPredicate() + val matched = ${ op.render(wrapped) } + $parser.__exitNotPredicate(saved) + ${ + setMatchEnd match { + case Some(matchEndSetter) => matchEndSetter('{ $parser.cursor }) + case None => '{} + } + } + $parser.__restoreState(mark) + !matched + } + + if (wrapped) { + val base = op match { + case x: TerminalOpTree => '{ RuleTrace.NotPredicate.Terminal(${ x.ruleTraceTerminal }) } + case x: RuleCall => '{ RuleTrace.NotPredicate.RuleCall(${ x.calleeNameTree }) } + case x: StringMatch => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringTree }}\"") } + case x: IgnoreCaseString => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringTree }}\"") } + case x: Named => '{ RuleTrace.NotPredicate.Named(s"\"${${ x.stringExpr }}\"") } + case _ => '{ RuleTrace.NotPredicate.Anonymous } + } + '{ + var matchEnd = 0 + try ${ unwrappedExpr(Some(v => '{ matchEnd = $v })) } || $parser.__registerMismatch() + catch { + case Parser.StartTracingException => + $parser.__bubbleUp { + RuleTrace.NotPredicate($base, matchEnd - $parser.cursor) + } + } + } + } else unwrappedExpr(None) + } + } + + private def expandLambda(body: Term, wrapped: Boolean): Expr[Boolean] = { + def popToVals(valdefs: List[ValDef]): List[Statement] = { + def convertOne(v: ValDef): ValDef = + v.tpt.tpe.asType match { + case '[t] => ValDef.copy(v)(v.name, v.tpt, Some('{ $parser.valueStack.pop().asInstanceOf[t] }.asTerm)) + } + + valdefs.map(convertOne).reverse + } + + body match { + case Lambda(args, body) => + def rewrite(tree: Term): Term = + tree.tpe.asType match { + case '[Rule[_, _]] => expand(tree, wrapped).asInstanceOf[Term] + case _ => + tree match { + case Block(statements, res) => block(statements, rewrite(res)) + case x => '{ $parser.__push(${ x.asExpr }) }.asTerm + } + } + // do a beta reduction, using the parameter definitions as stubs for variables + // that hold values popped from the stack + block(popToVals(args), rewrite(body)).asExprOf[Boolean] + } + } + + private case class Action(body: Term, ts: List[TypeTree]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Action } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = expandLambda(body, wrapped) + } + + case class RunAction(body: Expr[_]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Run } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + body.asTerm.tpe.asType match { + case '[Rule[_, _]] => expand(body, wrapped) + case '[t1 => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2) => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2, t3) => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2, t3, t4) => r] => expandLambda(body.asTerm, wrapped) + case '[(t1, t2, t3, t4, t5) => r] => expandLambda(body.asTerm, wrapped) + case '[x] => '{ $body; true } + } + } + + case class SemanticPredicate(flagTree: Expr[Boolean]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.SemanticPredicate } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ $flagTree || $parser.__registerMismatch() } + else flagTree + } + + case class Capture(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Capture } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + '{ + val start1 = ${ if (wrapped) start else '{ $parser.cursor } } + val matched = ${ op.render(wrapped) } + if (matched) { + $parser.valueStack.push($parser.input.sliceString(start1, $parser.cursor)) + true + } else false + } + } + + private case class PushAction(valueExpr: Expr[_], argType: Type[_]) extends OpTree { + def render(wrapped: Boolean): Expr[Boolean] = { + val body = + argType match { + case '[Unit] => valueExpr + case '[HList] => '{ $parser.valueStack.pushAll($valueExpr.asInstanceOf[HList]) } + case _ => '{ $parser.valueStack.push($valueExpr) } + } + + '{ + $body + true + } + } + } + private case class DropAction(tpe: Type[_]) extends OpTree { + def render(wrapped: Boolean): Expr[Boolean] = { + import support.hlist._ + val body = + tpe match { + case '[Unit] => '{} + case '[HList] => + @tailrec def rec(t: Type[_], prefix: Expr[Unit]): Expr[Unit] = t match { + case '[HNil] => prefix + case '[h :: t] => + rec(Type.of[t], '{ $prefix; $parser.valueStack.pop() }) + + } + rec(tpe, '{}) + + case _ => '{ $parser.valueStack.pop() } + } + + '{ + $body + true + } + } + } + + private case class RuleCall(call: Either[OpTree, Expr[Rule[_, _]]], calleeNameTree: Expr[String]) + extends NonTerminalOpTree { + + def bubbleUp(e: Expr[Parser#TracingBubbleException], start: Expr[Int]): Expr[Nothing] = + '{ $e.prepend(RuleTrace.RuleCall, $start).bubbleUp(RuleTrace.Named($calleeNameTree), $start) } + + override def render(wrapped: Boolean): Expr[Boolean] = call match { + case Left(_) => super.render(wrapped) + case Right(rule) => '{ $rule ne null } + } + protected def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = { + val Left(value) = call + value.render(wrapped) + } + } + + case class CharMatch(charTree: Expr[Char]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharMatch($charTree) } + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ + $parser.cursorChar == $charTree && $parser.__advance() + } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class StringMatch(stringTree: Expr[String]) extends OpTree { + final private val autoExpandMaxStringLength = 8 + + override def render(wrapped: Boolean): Expr[Boolean] = { + def unrollUnwrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) + '{ + if ($parser.cursorChar == ${ Expr(s.charAt(ix)) }) { + $parser.__advance() + ${ unrollUnwrapped(s, ix + 1) } + } else false + } + else '{ true } + + def unrollWrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) { + val ch = Expr(s.charAt(ix)) + '{ + if ($parser.cursorChar == $ch) { + $parser.__advance() + $parser.__updateMaxCursor() + ${ unrollWrapped(s, ix + 1) } + } else { + try $parser.__registerMismatch() + catch { + case akka.parboiled2.Parser.StartTracingException => + import akka.parboiled2.RuleTrace._ + $parser.__bubbleUp( + NonTerminal(akka.parboiled2.RuleTrace.StringMatch($stringTree), -${ Expr(ix) }) :: Nil, + akka.parboiled2.RuleTrace.CharMatch($ch) + ) + } + } + } + } else '{ true } + + stringTree.asTerm match { + case Literal(StringConstant(s: String)) if s.length <= autoExpandMaxStringLength => + if (s.isEmpty) '{ true } + else if (wrapped) unrollWrapped(s) + else unrollUnwrapped(s) + case _ => + if (wrapped) '{ $parser.__matchStringWrapped($stringTree) } + else '{ $parser.__matchString($stringTree) } + } + } + } + + case class MapMatch(mapTree: Expr[Map[String, Any]], ignoreCaseTree: Expr[Boolean]) extends OpTree { + + override def render(wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ $parser.__matchMapWrapped($mapTree, $ignoreCaseTree) } + else '{ $parser.__matchMap($mapTree, $ignoreCaseTree) } + } + + case class IgnoreCaseChar(charTree: Expr[Char]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.IgnoreCaseChar($charTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ + _root_.java.lang.Character.toLowerCase($parser.cursorChar) == $charTree && $parser.__advance() + } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class IgnoreCaseString(stringTree: Expr[String]) extends OpTree { + final private val autoExpandMaxStringLength = 8 + + override def render(wrapped: Boolean): Expr[Boolean] = + def unrollUnwrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) + '{ + if (_root_.java.lang.Character.toLowerCase($parser.cursorChar) == ${ Expr(s.charAt(ix)) }) { + $parser.__advance() + ${ unrollUnwrapped(s, ix + 1) } + } else false + } + else '{ true } + + def unrollWrapped(s: String, ix: Int = 0): Expr[Boolean] = + if (ix < s.length) { + val ch = Expr(s.charAt(ix)) + '{ + if (_root_.java.lang.Character.toLowerCase($parser.cursorChar) == $ch) { + $parser.__advance() + $parser.__updateMaxCursor() + ${ unrollWrapped(s, ix + 1) } + } else { + try $parser.__registerMismatch() + catch { + case akka.parboiled2.Parser.StartTracingException => + import akka.parboiled2.RuleTrace._ + $parser.__bubbleUp( + NonTerminal(akka.parboiled2.RuleTrace.IgnoreCaseString($stringTree), -${ Expr(ix) }) :: Nil, + akka.parboiled2.RuleTrace.IgnoreCaseChar($ch) + ) + } + } + } + } else '{ true } + + stringTree.asTerm match { + case Literal(StringConstant(s: String)) if s.length <= autoExpandMaxStringLength => + if (s.isEmpty) '{ true } + else if (wrapped) unrollWrapped(s) + else unrollUnwrapped(s) + case _ => + if (wrapped) '{ $parser.__matchIgnoreCaseStringWrapped($stringTree) } + else '{ $parser.__matchIgnoreCaseString($stringTree) } + } + } + + private case class CharPredicateMatch(predicateTree: Expr[CharPredicate]) + extends PotentiallyNamedTerminalOpTree(predicateTree.asTerm) { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharPredicateMatch($predicateTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $predicateTree($parser.cursorChar) && $parser.__advance() } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class AnyOf(stringTree: Expr[String]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.AnyOf($stringTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $parser.__matchAnyOf($stringTree) } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class NoneOf(stringTree: Expr[String]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.NoneOf($stringTree) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $parser.__matchNoneOf($stringTree) } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case object ANY extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.ANY } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ $parser.cursorChar != EOI && $parser.__advance() } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class Unknown(syntax: String, tree: String, outerSyntax: String) extends TerminalOpTree { + override def ruleTraceTerminal: Expr[RuleTrace.Terminal] = + '{ RuleTrace.Fail(s"unknown rule: $$infoExpr") } + + override protected def renderInner(wrapped: Boolean): Expr[Boolean] = + '{ + throw new RuntimeException( + s"unknown rule: [${${ Expr(syntax) }}] '${${ Expr(tree) }}' in [${${ Expr(outerSyntax) }}]" + ) + } + } + + def CharRange(lowerTree: Expr[String], upperTree: Expr[String]): CharacterRange = + (lowerTree.value, upperTree.value) match { + case (Some(lower), Some(upper)) => + if (lower.length != 1) reportError("lower bound must be a single char string", lowerTree) + if (upper.length != 1) reportError("upper bound must be a single char string", upperTree) + val lowerBoundChar = lower.charAt(0) + val upperBoundChar = upper.charAt(0) + if (lowerBoundChar > upperBoundChar) reportError("lower bound must not be > upper bound", lowerTree) + CharacterRange(Expr(lowerBoundChar), Expr(upperBoundChar)) + case _ => reportError("Character ranges must be specified with string literals", lowerTree) + } + + case class CharacterRange(lowerBound: Expr[Char], upperBound: Expr[Char]) extends TerminalOpTree { + def ruleTraceTerminal = '{ akka.parboiled2.RuleTrace.CharRange($lowerBound, $upperBound) } + + override def renderInner(wrapped: Boolean): Expr[Boolean] = { + val unwrappedTree = '{ + val char = $parser.cursorChar + $lowerBound <= char && char <= $upperBound && $parser.__advance() + } + if (wrapped) '{ $unwrappedTree && $parser.__updateMaxCursor() || $parser.__registerMismatch() } + else unwrappedTree + } + } + + case class Fail(stringExpr: Expr[String]) extends OpTree { + def render(wrapped: Boolean): Expr[Boolean] = '{ throw new akka.parboiled2.Parser.Fail($stringExpr) } + } + case class Named(op: OpTree, stringExpr: Expr[String]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Named($stringExpr) } + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = op.render(wrapped) + } + case class Atomic(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Atomic } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + val saved = $parser.__enterAtomic($start) + val matched = ${ op.render(wrapped) } + $parser.__exitAtomic(saved) + matched + } + else op.render(wrapped) + } + + case class Quiet(op: OpTree) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.Quiet } + + def renderInner(start: Expr[Int], wrapped: Boolean): Expr[Boolean] = + if (wrapped) '{ + val saved = $parser.__enterQuiet() + val matched = ${ op.render(wrapped) } + $parser.__exitQuiet(saved) + matched + } + else op.render(wrapped) + } + + def topLevel(opTree: OpTree, name: Expr[String]): OpTree = RuleCall(Left(opTree), name) + + def deconstruct(outerRule: Expr[Rule[_, _]]): OpTree = deconstructPF(outerRule).get + def deconstructPF(outerRule: Expr[Rule[_, _]]): Option[OpTree] = { + import quotes.reflect.* + + def collector(lifter: Term): Collector = + lifter match { + case TypeApply(Ident("forRule0" | "forReduction"), _) => rule0Collector + case TypeApply(Ident("forRule1"), _) => rule1Collector + case x => reportError(s"Unexpected lifter ${lifter.show(using Printer.TreeStructure)}", lifter.asExpr) + } + + // a list of names for operations that are not yet implemented but that should not be interpreted as rule calls + // FIXME: can be removed when everything is implemented + val ruleNameBlacklist = + Set( + "str", + "!", + "?", + "&", + "optional", + "run", + "zeroOrMore", + "times", + "oneOrMore", + "rule2ActionOperator", + "range2NTimes", + "rule2WithSeparatedBy" + ) + + lazy val rules0PF: PartialFunction[Expr[Rule[_, _]], OpTree] = { + case '{ ($p: Parser).ch($c) } => CharMatch(c) + case '{ ($p: Parser).str($s) } => StringMatch(s) + case '{ ($p: Parser).valueMap($m: Map[String, Any]) } => MapMatch(m, '{ false }) + case '{ ($p: Parser).valueMap($m: Map[String, Any], $ic) } => MapMatch(m, ic) + case '{ ($p: Parser).ignoreCase($c: Char) } => IgnoreCaseChar(c) + case '{ ($p: Parser).ignoreCase($s: String) } => IgnoreCaseString(s) + case '{ ($p: Parser).predicate($pr) } => CharPredicateMatch(pr) + case '{ ($p: Parser).anyOf($s) } => AnyOf(s) + case '{ ($p: Parser).noneOf($s) } => NoneOf(s) + case '{ ($p: Parser).ANY } => ANY + case '{ ($p: Parser).str2CharRangeSupport($l).-($r) } => CharRange(l, r) + case '{ ($p: Parser).test($flag) } => SemanticPredicate(flag) + case '{ ($p: Parser).push[t]($value) } => PushAction(value, Type.of[t]) + case '{ ($p: Parser).drop[t] } => DropAction(Type.of[t]) + case '{ type i <: HList; type o <: HList; ($p: Parser).capture[`i`, `o`]($arg)($l) } => Capture(rec(arg.asTerm)) + case '{ + type i1 <: HList; type o1 <: HList + type i2 <: HList; type o2 <: HList + ($lhs: Rule[`i1`, `o1`]).~[`i2`, `o2`]($rhs)($_, $_) + } => + Sequence(Seq(rec(lhs.asTerm), rec(rhs.asTerm))) + + case '{ + type i1 <: HList; type o1 <: HList + type i2 <: `i1`; type o2 >: `o1` <: HList + ($lhs: Rule[`i1`, `o1`]).|[`i2`, `o2`]($rhs) + } => + FirstOf(rec(lhs.asTerm), rec(rhs.asTerm)) + + case '{ + type i1 <: HList; type o1 <: HList + type i2 <: HList; type o2 <: HList + ($lhs: Rule[`i1`, `o1`]).~!~[`i2`, `o2`]($rhs)($_, $_) + } => + Cut(rec(lhs.asTerm), rec(rhs.asTerm)) + + case '{ type i <: HList; type o <: HList; ($p: Parser).zeroOrMore[`i`, `o`]($arg)($l) } => + ZeroOrMore(rec(arg.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).*($l: support.Lifter[Seq, `i`, `o`]) } => + ZeroOrMore(rec(base.asTerm), collector(l.asTerm)) + + case '{ + type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).*($sep: Rule0)($l: support.Lifter[Seq, `i`, `o`]) + } => + ZeroOrMore(rec(base.asTerm), collector(l.asTerm), Separator(rec(sep.asTerm))) + + case '{ type i <: HList; type o <: HList; ($p: Parser).oneOrMore[`i`, `o`]($arg)($l) } => + OneOrMore(rec(arg.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).+($l: support.Lifter[Seq, `i`, `o`]) } => + OneOrMore(rec(base.asTerm), collector(l.asTerm)) + + case '{ + type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).+($sep: Rule0)($l: support.Lifter[Seq, `i`, `o`]) + } => + OneOrMore(rec(base.asTerm), collector(l.asTerm), Separator(rec(sep.asTerm))) + + case '{ type i <: HList; type o <: HList; ($p: Parser).optional[`i`, `o`]($arg)($l) } => + Optional(rec(arg.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).?($l: support.Lifter[Option, `i`, `o`]) } => + Optional(rec(base.asTerm), collector(l.asTerm)) + + case '{ type i <: HList; type o <: HList; ($p: Parser).int2NTimes($n).times[`i`, `o`]($arg)($l) } => + Int2NTimes( + n, + rec(arg.asTerm), + MinMaxSupplier.constant(n), + collector(l.asTerm), + null + ) + case '{ type i <: HList; type o <: HList; ($p: Parser).range2NTimes($r).times[`i`, `o`]($arg)($l) } => + Range2NTimes( + r, + rec(arg.asTerm), + MinMaxSupplier.range(r), + collector(l.asTerm), + null + ) + + case '{ type i <: HList; type o <: HList; !($arg: Rule[`i`, `o`]) } => + NotPredicate(rec(arg.asTerm)) + + case '{ ($p: Parser).&($arg) } => + AndPredicate(rec(arg.asTerm)) + + case '{ + type i <: HList; type o <: HList; ($p: Parser).rule2WithSeparatedBy[`i`, `o`]($base).separatedBy($sep) + } => + rec(base.asTerm) match { + case ws: WithSeparator => ws.withSeparator(Separator(rec(sep.asTerm))) + case _ => reportError(s"Illegal `separatedBy` base: $base", base) + } + + case '{ ($p: Parser).run[t]($e)($l) } => RunAction(e) + case '{ type i <: HList; type o <: HList; ($base: Rule[`i`, `o`]).named($str) } => Named(rec(base.asTerm), str) + case '{ type i <: HList; type o <: HList; ($p: Parser).atomic[`i`, `o`]($r) } => Atomic(rec(r.asTerm)) + case '{ type i <: HList; type o <: HList; ($p: Parser).quiet[`i`, `o`]($r) } => Quiet(rec(r.asTerm)) + case '{ ($p: Parser).fail($str) } => Fail(str) + case '{ type i <: HList; type o <: HList; ($p: Parser).failX[`i`, `o`]($str) } => Fail(str) + } + + lazy val rules1PF: PartialFunction[Term, OpTree] = { + // cannot easily be converted because we would have to list all ActionOps instances + case Apply( + Apply( + TypeApply( + Select( + Select(Apply(Apply(TypeApply(Select(_, "rule2ActionOperator"), _), List(base)), _), "~>"), + "apply" + ), + _ + ), + List(body) + ), + List(_, TypeApply(Ident("apply"), ts)) + ) => + Sequence(rec(base), Action(body, ts)) + + case call @ (Apply(_, _) | Select(_, _) | Ident(_) | TypeApply(_, _)) + if !callName(call).exists(ruleNameBlacklist) => + RuleCall( + Right(call.asExprOf[Rule[_, _]]), + Expr(callName(call) getOrElse reportError("Illegal rule call: " + call, call.asExpr)) + ) + //case _ => Unknown(rule.show, rule.show(using Printer.TreeStructure), outerRule.toString) + } + lazy val allRules = rules0PF.orElse(rules1PF.compose[Expr[Rule[_, _]]] { case x => x.asTerm.underlyingArgument }) + def rec(rule: Term): OpTree = allRules.applyOrElse( + rule.asExprOf[Rule[_, _]], + rule => Unknown(rule.show, "" /*rule.show(using Printer.TreeStructure)*/, outerRule.toString) + ) + + allRules.lift(outerRule) + } + + private def reportError(error: String, expr: Expr[Any]): Nothing = { + quotes.reflect.report.error(error, expr) + throw new scala.quoted.runtime.StopMacroExpansion + } + + /////////////////////////////////// helpers //////////////////////////////////// + + trait Collector { + def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] + } + trait CollectorInstance { + def popToBuilder: Expr[Unit] + def pushBuilderResult: Expr[Unit] + def pushSomePop: Expr[Unit] + def pushNone: Expr[Unit] + } + + // no-op collector + object rule0Collector extends Collector with CollectorInstance { + override def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] = f(this) + private val unit: Expr[Unit] = '{} + def popToBuilder: Expr[Unit] = unit + def pushBuilderResult: Expr[Unit] = unit + def pushSomePop: Expr[Unit] = unit + def pushNone: Expr[Unit] = unit + } + + object rule1Collector extends Collector { + override def withCollector(f: CollectorInstance => Expr[Boolean]): Expr[Boolean] = '{ + val builder = new scala.collection.immutable.VectorBuilder[Any] + ${ + f(new CollectorInstance { + def popToBuilder: Expr[Unit] = '{ builder += $parser.valueStack.pop() } + def pushBuilderResult: Expr[Unit] = '{ $parser.valueStack.push(builder.result()) } + def pushSomePop: Expr[Unit] = '{ $parser.valueStack.push(Some($parser.valueStack.pop())) } + def pushNone: Expr[Unit] = '{ $parser.valueStack.push(None) } + }) + } + } + } + + type Separator = Boolean => Expr[Boolean] + private def Separator(op: OpTree): Separator = wrapped => op.render(wrapped) + + @tailrec + private def callName(tree: Term): Option[String] = + tree match { + case Ident(name) => Some(name) + case Select(_, name) => Some(name) + case Apply(fun, _) => callName(fun) + case TypeApply(fun, _) => callName(fun) + case _ => None + } + + // tries to match and expand the leaves of the given Tree + private def expand(expr: Expr[_], wrapped: Boolean): Expr[Boolean] = + expand(expr.asTerm, wrapped).asExprOf[Boolean] + private def expand(tree: Tree, wrapped: Boolean): Tree = + tree match { + case Block(statements, res) => block(statements, expand(res, wrapped).asInstanceOf[Term]) + case If(cond, thenExp, elseExp) => + If(cond, expand(thenExp, wrapped).asInstanceOf[Term], expand(elseExp, wrapped).asInstanceOf[Term]) + case Match(selector, cases) => Match(selector, cases.map(expand(_, wrapped).asInstanceOf[CaseDef])) + case CaseDef(pat, guard, body) => CaseDef(pat, guard, expand(body, wrapped).asInstanceOf[Term]) + case x => + deconstructPF(x.asExprOf[Rule[_, _]]) // can we pass the body as a rule? + .map(_.render(wrapped)) // then render it + .getOrElse('{ ${ x.asExprOf[Rule[_, _]] } ne null }) // otherwise, assume the expression is a rule itself + .asTerm + } + + private def block(a: Term, b: Term): Term = + a match { + case Block(a1, a2) => + b match { + case Block(b1, b2) => Block(a1 ::: a2 :: b1, b2) + case _ => Block(a1 ::: a2 :: Nil, b) + } + case _ => + b match { + case Block(b1, b2) => Block(a :: b1, b2) + case _ => Block(a :: Nil, b) + } + } + + private def block(stmts: List[Statement], expr: Term): Term = + expr match { + case Block(a, b) => block(stmts ::: a ::: Nil, b) + case _ => Block(stmts, expr) + } +} From fee4a47755c75c34a494d052a51077bf069efd62 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 9 Sep 2021 12:11:23 +0200 Subject: [PATCH 08/51] parsing: Scala 3 pre213 / since213 annotations (without function) --- .../akka/http/ccompat/pre213macro.scala | 0 .../akka/http/ccompat/since213macro.scala | 0 .../main/scala-3/akka/http/ccompat/pre213macro.scala | 10 ++++++++++ .../main/scala-3/akka/http/ccompat/since213macro.scala | 9 +++++++++ 4 files changed, 19 insertions(+) rename akka-parsing/src/main/{scala => scala-2}/akka/http/ccompat/pre213macro.scala (100%) rename akka-parsing/src/main/{scala => scala-2}/akka/http/ccompat/since213macro.scala (100%) create mode 100644 akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala create mode 100644 akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala diff --git a/akka-parsing/src/main/scala/akka/http/ccompat/pre213macro.scala b/akka-parsing/src/main/scala-2/akka/http/ccompat/pre213macro.scala similarity index 100% rename from akka-parsing/src/main/scala/akka/http/ccompat/pre213macro.scala rename to akka-parsing/src/main/scala-2/akka/http/ccompat/pre213macro.scala diff --git a/akka-parsing/src/main/scala/akka/http/ccompat/since213macro.scala b/akka-parsing/src/main/scala-2/akka/http/ccompat/since213macro.scala similarity index 100% rename from akka-parsing/src/main/scala/akka/http/ccompat/since213macro.scala rename to akka-parsing/src/main/scala-2/akka/http/ccompat/since213macro.scala diff --git a/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala b/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala new file mode 100644 index 00000000000..91d936c0153 --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala @@ -0,0 +1,10 @@ +/* + * Copyright (C) 2019-2021 Lightbend Inc. + */ + +package akka.http.ccompat + +import scala.annotation.StaticAnnotation + +// FIXME: need to implement or we will resurrect some ugly things (or remove 2.12 support) +class pre213 extends StaticAnnotation diff --git a/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala b/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala new file mode 100644 index 00000000000..5dc84ee1599 --- /dev/null +++ b/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala @@ -0,0 +1,9 @@ +/* + * Copyright (C) 2019-2021 Lightbend Inc. + */ + +package akka.http.ccompat + +import scala.annotation.StaticAnnotation + +class since213 extends StaticAnnotation From 10b7d4a894aba27f2b7cc252ee18d09eceb909da Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 15 Feb 2022 16:57:58 +0100 Subject: [PATCH 09/51] core: fore now disable Scala 2.12 code that cannot be elided in Scala 3 easily pre213 macro is broken and cannot be repaired. Maybe we'll need a simple compiler plugin for Scala 3 to redo that functionality. --- .../http/scaladsl/model/HttpMessage.scala | 8 ++-- .../model/headers/CacheDirective.scala | 8 ++-- .../model/headers/LanguageRange.scala | 4 +- .../scaladsl/model/headers/LinkValue.scala | 4 +- .../http/scaladsl/model/headers/headers.scala | 44 +++++++++---------- .../directives/FormFieldDirectives.scala | 8 ++-- .../directives/RespondWithDirectives.scala | 8 ++-- 7 files changed, 42 insertions(+), 42 deletions(-) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala index 55fd7acec7d..a56c1757a52 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala @@ -72,8 +72,8 @@ sealed trait HttpMessage extends jm.HttpMessage { def discardEntityBytes(system: ClassicActorSystemProvider): HttpMessage.DiscardedEntity = entity.discardBytes()(SystemMaterializer(system).materializer) /** Returns a copy of this message with the list of headers set to the given ones. */ - @pre213 - def withHeaders(headers: HttpHeader*): Self = withHeaders(headers.toList) + /*@pre213 + def withHeaders(headers: HttpHeader*): Self = withHeaders(headers.toList)*/ /** Returns a copy of this message with the list of headers set to the given ones. */ def withHeaders(headers: immutable.Seq[HttpHeader]): Self @@ -87,8 +87,8 @@ sealed trait HttpMessage extends jm.HttpMessage { * Returns a new message that contains all of the given default headers which didn't already * exist (by case-insensitive header name) in this message. */ - @pre213 - def withDefaultHeaders(defaultHeaders: HttpHeader*): Self = withDefaultHeaders(defaultHeaders.toList) + /*@pre213 + def withDefaultHeaders(defaultHeaders: HttpHeader*): Self = withDefaultHeaders(defaultHeaders.toList)*/ /** * Returns a new message that contains all of the given default headers which didn't already diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala index 732cb1c62e2..a4976b6355e 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala @@ -83,9 +83,9 @@ object CacheDirectives { * http://tools.ietf.org/html/rfc7234#section-5.2.1.4 */ case object `no-cache` extends SingletonValueRenderable with RequestDirective with ResponseDirective { - @pre213 + /*@pre213 def apply(fieldNames: String*): `no-cache` = - new `no-cache`(immutable.Seq(fieldNames: _*)) + new `no-cache`(immutable.Seq(fieldNames: _*))*/ @since213 def apply(firstFieldName: String, otherFieldNames: String*): `no-cache` = new `no-cache`(firstFieldName +: otherFieldNames.toList) @@ -138,8 +138,8 @@ object CacheDirectives { */ final case class `private`(fieldNames: immutable.Seq[String]) extends FieldNamesDirective with ResponseDirective object `private` { - @pre213 - def apply(fieldNames: String*): `private` = new `private`(immutable.Seq(fieldNames: _*)) + /*@pre213 + def apply(fieldNames: String*): `private` = new `private`(immutable.Seq(fieldNames: _*))*/ @since213 def apply(): `private` = new `private`(immutable.Seq.empty) @since213 diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala index 45f6dcacfd9..8bd0cdcc3cd 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala @@ -72,9 +72,9 @@ object Language { val tags = compoundTag.split('-') new Language(tags.head, immutable.Seq(tags.tail: _*)) } else new Language(compoundTag, immutable.Seq.empty) - @pre213 + /*@pre213 def apply(primaryTag: String, subTags: String*): Language = - new Language(primaryTag, immutable.Seq(subTags: _*)) + new Language(primaryTag, immutable.Seq(subTags: _*))*/ @since213 def apply(primaryTag: String, firstSubTag: String, otherSubTags: String*): Language = new Language(primaryTag, firstSubTag +: otherSubTags) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala index 75258dc0d18..411982a4bc6 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala @@ -25,8 +25,8 @@ final case class LinkValue(uri: Uri, params: immutable.Seq[LinkParam]) extends j } object LinkValue { - @pre213 - def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*)) + /*@pre213 + def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*))*/ @since213 def apply(uri: Uri, firstParam: LinkParam, otherParams: LinkParam*): LinkValue = apply(uri, firstParam +: otherParams) } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala index 7fa944fdd7a..376d08085f5 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala @@ -136,9 +136,9 @@ import akka.http.impl.util.JavaMapping.Implicits._ // https://tools.ietf.org/html/rfc7231#section-5.3.2 object Accept extends ModeledCompanion[Accept] { - @pre213 + /*@pre213 def apply(mediaRanges: MediaRange*): Accept = - apply(immutable.Seq(mediaRanges: _*)) + apply(immutable.Seq(mediaRanges: _*))*/ @since213 def apply(firstMediaRange: MediaRange, otherMediaRanges: MediaRange*): Accept = apply(firstMediaRange +: otherMediaRanges) @@ -172,9 +172,9 @@ final case class `Accept-Charset`(charsetRanges: immutable.Seq[HttpCharsetRange] // https://tools.ietf.org/html/rfc7231#section-5.3.4 object `Accept-Encoding` extends ModeledCompanion[`Accept-Encoding`] { - @pre213 + /*@pre213 def apply(encodings: HttpEncodingRange*): `Accept-Encoding` = - apply(immutable.Seq(encodings: _*)) + apply(immutable.Seq(encodings: _*))*/ @since213 def apply(): `Accept-Encoding` = apply(immutable.Seq.empty) @@ -211,9 +211,9 @@ final case class `Accept-Language`(languages: immutable.Seq[LanguageRange]) exte // https://tools.ietf.org/html/rfc7233#section-2.3 object `Accept-Ranges` extends ModeledCompanion[`Accept-Ranges`] { - @pre213 + /*@pre213 def apply(rangeUnits: RangeUnit*): `Accept-Ranges` = - apply(immutable.Seq(rangeUnits: _*)) + apply(immutable.Seq(rangeUnits: _*))*/ @since213 def apply(): `Accept-Ranges` = apply(immutable.Seq.empty) @@ -242,9 +242,9 @@ final case class `Access-Control-Allow-Credentials`(allow: Boolean) // https://www.w3.org/TR/cors/#access-control-allow-headers-response-header object `Access-Control-Allow-Headers` extends ModeledCompanion[`Access-Control-Allow-Headers`] { - @pre213 + /*@pre213 def apply(headers: String*): `Access-Control-Allow-Headers` = - apply(immutable.Seq(headers: _*)) + apply(immutable.Seq(headers: _*))*/ @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Allow-Headers` = apply(firstHeader +: otherHeaders) @@ -262,9 +262,9 @@ final case class `Access-Control-Allow-Headers`(headers: immutable.Seq[String]) // https://www.w3.org/TR/cors/#access-control-allow-methods-response-header object `Access-Control-Allow-Methods` extends ModeledCompanion[`Access-Control-Allow-Methods`] { - @pre213 + /*@pre213 def apply(methods: HttpMethod*): `Access-Control-Allow-Methods` = - apply(immutable.Seq(methods: _*)) + apply(immutable.Seq(methods: _*))*/ @since213 def apply(firstMethod: HttpMethod, otherMethods: HttpMethod*): `Access-Control-Allow-Methods` = apply(firstMethod +: otherMethods) @@ -303,9 +303,9 @@ final case class `Access-Control-Allow-Origin` private (range: HttpOriginRange) // https://www.w3.org/TR/cors/#access-control-expose-headers-response-header object `Access-Control-Expose-Headers` extends ModeledCompanion[`Access-Control-Expose-Headers`] { - @pre213 + /*@pre213 def apply(headers: String*): `Access-Control-Expose-Headers` = - apply(immutable.Seq(headers: _*)) + apply(immutable.Seq(headers: _*))*/ @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Expose-Headers` = apply(firstHeader +: otherHeaders) @@ -331,9 +331,9 @@ final case class `Access-Control-Max-Age`(deltaSeconds: Long) extends jm.headers // https://www.w3.org/TR/cors/#access-control-request-headers-request-header object `Access-Control-Request-Headers` extends ModeledCompanion[`Access-Control-Request-Headers`] { - @pre213 + /*@pre213 def apply(headers: String*): `Access-Control-Request-Headers` = - apply(immutable.Seq(headers: _*)) + apply(immutable.Seq(headers: _*))*/ @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Request-Headers` = apply(firstHeader +: otherHeaders) @@ -366,9 +366,9 @@ final case class Age(deltaSeconds: Long) extends jm.headers.Age with ResponseHea // https://tools.ietf.org/html/rfc7231#section-7.4.1 object Allow extends ModeledCompanion[Allow] { - @pre213 + /*@pre213 def apply(methods: HttpMethod*): Allow = - apply(immutable.Seq(methods: _*)) + apply(immutable.Seq(methods: _*))*/ @since213 def apply(): `Allow` = apply(immutable.Seq.empty) @@ -546,8 +546,8 @@ final case class `Content-Type` private[http] (contentType: ContentType) extends object Cookie extends ModeledCompanion[Cookie] { def apply(first: HttpCookiePair, more: HttpCookiePair*): Cookie = apply(immutable.Seq(first +: more: _*)) def apply(name: String, value: String): Cookie = apply(HttpCookiePair(name, value)) - @pre213 - def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList) + /*@pre213 + def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList)*/ @since213 def apply(first: (String, String), more: (String, String)*): Cookie = apply((first +: more).map(HttpCookiePair(_))) implicit val cookiePairsRenderer = Renderer.seqRenderer[HttpCookiePair](separator = "; ") // cache @@ -695,8 +695,8 @@ final case class `Last-Modified`(date: DateTime) extends jm.headers.LastModified // https://tools.ietf.org/html/rfc5988#section-5 object Link extends ModeledCompanion[Link] { def apply(uri: Uri, first: LinkParam, more: LinkParam*): Link = apply(immutable.Seq(LinkValue(uri, first +: more.toList))) - @pre213 - def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*)) + /*@pre213 + def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*))*/ @since213 def apply(firstValue: LinkValue, otherValues: LinkValue*): Link = apply(firstValue +: otherValues) @@ -723,8 +723,8 @@ final case class Location(uri: Uri) extends jm.headers.Location with ResponseHea // https://tools.ietf.org/html/rfc6454#section-7 object Origin extends ModeledCompanion[Origin] { - @pre213 - def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*)) + /*@pre213 + def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*))*/ @since213 def apply(firstOrigin: HttpOrigin, otherOrigins: HttpOrigin*): Origin = apply(firstOrigin +: otherOrigins) } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala index 5c665f8310a..aa0ecf313a0 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala @@ -54,9 +54,9 @@ trait FormFieldDirectives extends FormFieldDirectivesInstances with ToNameRecept * * @group form */ - @pre213 + /*@pre213 @deprecated("Use new `formField` overloads with FieldSpec parameters. Kept for binary compatibility", "10.2.0") - private[http] def formField(pdm: FieldMagnet): pdm.Out = formFields(pdm) + private[http] def formField(pdm: FieldMagnet): pdm.Out = formFields(pdm)*/ /** * Extracts an HTTP form field from the request. @@ -74,10 +74,10 @@ trait FormFieldDirectives extends FormFieldDirectivesInstances with ToNameRecept * * @group form */ - @pre213 + /*@pre213 @deprecated("Use new `formField` overloads with FieldSpec parameters. Kept for binary compatibility", "10.2.0") private[http] def formFields(pdm: FieldMagnet): pdm.Out = - pdm.convert(toStrictEntity(StrictForm.toStrictTimeout).wrap { pdm() }) + pdm.convert(toStrictEntity(StrictForm.toStrictTimeout).wrap { pdm() })*/ /** * Extracts a number of HTTP form field from the request. diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala index a249d7b7b23..5de9e2b2f03 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala @@ -37,9 +37,9 @@ trait RespondWithDirectives { * * @group response */ - @pre213 + /*@pre213 def respondWithHeaders(responseHeaders: HttpHeader*): Directive0 = - respondWithHeaders(responseHeaders.toList) + respondWithHeaders(responseHeaders.toList)*/ /** * Unconditionally adds the given response headers to all HTTP responses of its inner Route. @@ -59,9 +59,9 @@ trait RespondWithDirectives { * * @group response */ - @pre213 + /*@pre213 def respondWithDefaultHeaders(responseHeaders: HttpHeader*): Directive0 = - respondWithDefaultHeaders(responseHeaders.toList) + respondWithDefaultHeaders(responseHeaders.toList)*/ /** * Adds the given response headers to all HTTP responses of its inner Route, From 0135521723cc6d2599b909e771f56c6a947719cc Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 13:56:56 +0100 Subject: [PATCH 10/51] core: make some types explicit as required by Scala 3 compiler --- .../client/OutgoingConnectionBlueprint.scala | 2 +- .../impl/engine/client/pool/SlotState.scala | 2 +- .../akka/http/impl/engine/http2/Http2.scala | 4 +- .../impl/engine/http2/Http2Blueprint.scala | 2 +- .../http/impl/engine/http2/Http2Demux.scala | 8 +-- .../impl/engine/http2/Http2Protocol.scala | 2 +- .../engine/http2/Http2StreamHandling.scala | 12 ++-- .../http2/OutgoingConnectionBuilderImpl.scala | 8 +-- .../engine/parsing/HttpHeaderParser.scala | 2 +- .../engine/rendering/BodyPartRenderer.scala | 2 +- .../impl/engine/rendering/RenderSupport.scala | 7 ++- .../akka/http/impl/util/JavaMapping.scala | 2 +- .../scala/akka/http/impl/util/Rendering.scala | 6 +- .../scaladsl/model/headers/EntityTag.scala | 2 +- .../http/scaladsl/model/headers/headers.scala | 57 ++++++++++--------- 15 files changed, 62 insertions(+), 56 deletions(-) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala index cfb9ca48df0..495c09056f6 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/OutgoingConnectionBlueprint.scala @@ -97,7 +97,7 @@ private[http] object OutgoingConnectionBlueprint { val terminationFanout = b.add(Broadcast[HttpResponse](2)) val logger = b.add(Flow[ByteString].mapError { case t => log.debug(s"Outgoing request stream error {}", t); t }.named("errorLogger")) - val wrapTls = b.add(Flow[ByteString].map(SendBytes)) + val wrapTls = b.add(Flow[ByteString].map(SendBytes(_))) val collectSessionBytes = b.add(Flow[SslTlsInbound].collect { case s: SessionBytes => s }) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/client/pool/SlotState.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/client/pool/SlotState.scala index 2587e511ad7..8e1ec8116d7 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/client/pool/SlotState.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/client/pool/SlotState.scala @@ -332,7 +332,7 @@ private[pool] object SlotState { WaitingForEndOfResponseEntity(ongoingRequest, ongoingResponse, waitingForEndOfRequestEntity = false) } } - final case object WaitingForEndOfRequestEntity extends ConnectedState { + case object WaitingForEndOfRequestEntity extends ConnectedState { final override def isIdle = false override def onRequestEntityCompleted(ctx: SlotContext): SlotState = diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala index b6457de2d2e..7595c82ea77 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala @@ -78,10 +78,10 @@ private[http] final class Http2Ext(implicit val system: ActorSystem) val masterTerminator = new MasterServerTerminator(log) - Tcp().bind(interface, effectivePort, settings.backlog, settings.socketOptions, halfClose = false, Duration.Inf) // we knowingly disable idle-timeout on TCP level, as we handle it explicitly in Akka HTTP itself + Tcp(system).bind(interface, effectivePort, settings.backlog, settings.socketOptions, halfClose = false, Duration.Inf) // we knowingly disable idle-timeout on TCP level, as we handle it explicitly in Akka HTTP itself .via(if (telemetry == NoOpTelemetry) Flow[Tcp.IncomingConnection] else telemetry.serverBinding) .mapAsyncUnordered(settings.maxConnections) { - incoming: Tcp.IncomingConnection => + (incoming: Tcp.IncomingConnection) => try { httpPlusSwitching(http1, http2).addAttributes(prepareServerAttributes(settings, incoming)) .watchTermination() { diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Blueprint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Blueprint.scala index a42363890aa..e4139e98a0c 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Blueprint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Blueprint.scala @@ -256,7 +256,7 @@ private[http] object Http2Blueprint { } private[http] val unwrapTls: BidiFlow[ByteString, SslTlsOutbound, SslTlsInbound, ByteString, NotUsed] = - BidiFlow.fromFlows(Flow[ByteString].map(SendBytes), Flow[SslTlsInbound].collect { + BidiFlow.fromFlows(Flow[ByteString].map(SendBytes(_)), Flow[SslTlsInbound].collect { case SessionBytes(_, bytes) => bytes }) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Demux.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Demux.scala index fc817866585..13372d00402 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Demux.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Demux.scala @@ -24,7 +24,7 @@ import akka.stream.Inlet import akka.stream.Outlet import akka.stream.impl.io.ByteStringParser.ParsingException import akka.stream.scaladsl.Source -import akka.stream.stage.{ GraphStageLogic, GraphStageWithMaterializedValue, InHandler, StageLogging, TimerGraphStageLogic } +import akka.stream.stage.{ GraphStageLogic, GraphStageWithMaterializedValue, InHandler, OutHandler, StageLogging, TimerGraphStageLogic } import akka.util.{ ByteString, OptionVal } import scala.collection.immutable @@ -108,12 +108,12 @@ private[http2] object ConfigurablePing { def sendingPing(): Unit = () def pingAckOverdue(): Boolean = false } - final class EnabledPingState(tickInterval: FiniteDuration, pingEveryNTickWithoutData: Long) extends PingState { + final class EnabledPingState(_tickInterval: FiniteDuration, pingEveryNTickWithoutData: Long) extends PingState { private var ticksWithoutData = 0L private var ticksSincePing = 0L private var pingInFlight = false - def tickInterval(): Option[FiniteDuration] = Some(tickInterval) + def tickInterval(): Option[FiniteDuration] = Some(_tickInterval) def onDataFrameSeen(): Unit = { ticksWithoutData = 0L @@ -261,7 +261,7 @@ private[http2] abstract class Http2Demux(http2Settings: Http2CommonSettings, ini push(frameOut, event) } - val multiplexer = createMultiplexer(StreamPrioritizer.First) + val multiplexer: Http2Multiplexer with OutHandler = createMultiplexer(StreamPrioritizer.First) setHandler(frameOut, multiplexer) val pingState = ConfigurablePing.PingState(http2Settings) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Protocol.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Protocol.scala index 62c6228f37b..28a77c06662 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Protocol.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2Protocol.scala @@ -339,7 +339,7 @@ private[http] object Http2Protocol { */ case object HTTP_1_1_REQUIRED extends ErrorCode(0xd) - case class Unknown private (override val id: Int) extends ErrorCode(id) + case class Unknown private[ErrorCode] (override val id: Int) extends ErrorCode(id) val All = Array( // must start with id = 0 and don't have holes between ids diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala index 357c3a5ac39..83b1f03ce0a 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala @@ -212,7 +212,7 @@ private[http2] trait Http2StreamHandling { self: GraphStageLogic with LogHelper * * Open -> HalfClosedRemoteSendingData: on receiving response DATA with endStream = true before request has been fully sent out (uncommon) * * HalfClosedRemoteSendingData -> Closed: on sending out request DATA with endStream = true */ - sealed abstract class StreamState { _: Product => + sealed abstract class StreamState { self: Product => def handle(event: StreamFrameEvent): StreamState def stateName: String = productPrefix @@ -327,7 +327,7 @@ private[http2] trait Http2StreamHandling { self: GraphStageLogic with LogHelper override def incrementWindow(delta: Int): StreamState = copy(extraInitialWindow = extraInitialWindow + delta) } - trait Sending extends StreamState { _: Product => + trait Sending extends StreamState { self: Product => protected def outStream: OutStream override def pullNextFrame(maxSize: Int): (StreamState, PullFrameResult) = { @@ -342,7 +342,7 @@ private[http2] trait Http2StreamHandling { self: GraphStageLogic with LogHelper } val nextState = - if (outStream.isDone) handleOutgoingEnded() + if (outStream.isDone) this.handleOutgoingEnded() else this (nextState, res) @@ -385,10 +385,10 @@ private[http2] trait Http2StreamHandling { self: GraphStageLogic with LogHelper // We're not planning on sending any data on this stream anymore, so we don't care about window updates. this case _ => - expectIncomingStream(event, Closed, HalfClosedLocal, correlationAttributes) + expectIncomingStream(event, Closed, HalfClosedLocal(_), correlationAttributes) } } - sealed abstract class ReceivingData extends StreamState { _: Product => + sealed abstract class ReceivingData extends StreamState { self: Product => def handle(event: StreamFrameEvent): StreamState = event match { case d: DataFrame => outstandingConnectionLevelWindow -= d.sizeInWindow @@ -425,7 +425,7 @@ private[http2] trait Http2StreamHandling { self: GraphStageLogic with LogHelper protected def incrementWindow(delta: Int): StreamState protected def onRstStreamFrame(rstStreamFrame: RstStreamFrame): Unit } - sealed abstract class ReceivingDataWithBuffer(afterEndStreamReceived: StreamState) extends ReceivingData { _: Product => + sealed abstract class ReceivingDataWithBuffer(afterEndStreamReceived: StreamState) extends ReceivingData { self: Product => protected def buffer: IncomingStreamBuffer override protected def onDataFrame(dataFrame: DataFrame): StreamState = { diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala index 4f797e7c31e..8763a472a01 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/OutgoingConnectionBuilderImpl.scala @@ -64,18 +64,18 @@ private[akka] object OutgoingConnectionBuilderImpl { override def http(): Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = { // http/1.1 plaintext - Http(system).outgoingConnectionUsingContext(host, port.getOrElse(80), ConnectionContext.noEncryption(), clientConnectionSettings, log) + Http(system.classicSystem).outgoingConnectionUsingContext(host, port.getOrElse(80), ConnectionContext.noEncryption(), clientConnectionSettings, log) } override def https(): Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = { // http/1.1 tls - Http(system).outgoingConnectionHttps(host, port.getOrElse(443), connectionContext.getOrElse(Http(system).defaultClientHttpsContext), None, clientConnectionSettings, log) + Http(system.classicSystem).outgoingConnectionHttps(host, port.getOrElse(443), connectionContext.getOrElse(Http(system.classicSystem).defaultClientHttpsContext), None, clientConnectionSettings, log) } override def http2(): Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = { // http/2 tls val port = this.port.getOrElse(443) - Http2(system).outgoingConnection(host, port, connectionContext.getOrElse(Http(system).defaultClientHttpsContext), clientConnectionSettings, log) + Http2(system.classicSystem).outgoingConnection(host, port, connectionContext.getOrElse(Http(system.classicSystem).defaultClientHttpsContext), clientConnectionSettings, log) } override def managedPersistentHttp2(): Flow[HttpRequest, HttpResponse, NotUsed] = @@ -85,7 +85,7 @@ private[akka] object OutgoingConnectionBuilderImpl { override def http2WithPriorKnowledge(): Flow[HttpRequest, HttpResponse, Future[OutgoingConnection]] = { // http/2 prior knowledge plaintext - Http2(system).outgoingConnectionPriorKnowledge(host, port.getOrElse(80), clientConnectionSettings, log) + Http2(system.classicSystem).outgoingConnectionPriorKnowledge(host, port.getOrElse(80), clientConnectionSettings, log) } override def managedPersistentHttp2WithPriorKnowledge(): Flow[HttpRequest, HttpResponse, NotUsed] = diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpHeaderParser.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpHeaderParser.scala index d186517ab56..4184c6c63a8 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpHeaderParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/parsing/HttpHeaderParser.scala @@ -419,7 +419,7 @@ private[engine] final class HttpHeaderParser private ( charBuffer.flip() val result = if (coderResult.isUnderflow & charBuffer.hasRemaining) { - val c = charBuffer.get() + val c = charBuffer.get().toInt if (charBuffer.hasRemaining) (charBuffer.get() << 16) | c else c } else -1 byteBuffer.clear() diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/BodyPartRenderer.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/BodyPartRenderer.scala index 77b374661e2..fc24045a7a4 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/BodyPartRenderer.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/BodyPartRenderer.scala @@ -139,7 +139,7 @@ private[http] object BodyPartRenderer { def randomBoundary(length: Int = 18, random: java.util.Random = ThreadLocalRandom.current()): String = { val array = new Array[Byte](length) random.nextBytes(array) - Base64.custom.encodeToString(array, false) + Base64.custom().encodeToString(array, false) } /** diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala index 872c29b57c1..d52330388bb 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala @@ -19,6 +19,8 @@ import akka.stream.stage.GraphStage import akka.stream._ import akka.stream.scaladsl.{ Flow, Sink, Source } +import scala.collection.immutable + /** * INTERNAL API */ @@ -41,12 +43,13 @@ private[http] object RenderSupport { private val TextHtmlContentType = preRenderContentType(`text/html(UTF-8)`) private val TextCsvContentType = preRenderContentType(`text/csv(UTF-8)`) - implicit val trailerRenderer = Renderer.genericSeqRenderer[Renderable, HttpHeader](Rendering.CrLf, Rendering.Empty) + implicit val trailerRenderer: Renderer[immutable.Iterable[HttpHeader]] = + Renderer.genericSeqRenderer[Renderable, HttpHeader](Rendering.CrLf, Rendering.Empty) val defaultLastChunkBytes: ByteString = renderChunk(HttpEntity.LastChunk) def CancelSecond[T, Mat](first: Source[T, Mat], second: Source[T, Any]): Source[T, Mat] = { - Source.fromGraph(GraphDSL.create(first) { implicit b => frst => + Source.fromGraph(GraphDSL.create(first) { implicit b => (frst: SourceShape[T]) => import GraphDSL.Implicits._ second ~> Sink.cancelled SourceShape(frst.out) diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala b/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala index b086234e608..3a726b19db2 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/JavaMapping.scala @@ -213,7 +213,7 @@ private[http] object JavaMapping { implicit object InetSocketAddress extends Identity[java.net.InetSocketAddress] implicit object ByteString extends Identity[akka.util.ByteString] - implicit val AttributeKey = new Inherited[jm.AttributeKey[_], sm.AttributeKey[_]] + implicit val AttributeKey: Inherited[jm.AttributeKey[_], sm.AttributeKey[_]] = new Inherited[jm.AttributeKey[_], sm.AttributeKey[_]] implicit def attributeKey[T]: Inherited[jm.AttributeKey[T], sm.AttributeKey[T]] = AttributeKey.asInstanceOf[Inherited[jm.AttributeKey[T], sm.AttributeKey[T]]] implicit object ContentType extends Inherited[jm.ContentType, sm.ContentType] diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala b/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala index 57fbbdab3fb..2dead05bb57 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala @@ -116,8 +116,10 @@ private[http] object Renderer { if (value.isEmpty) sRenderer.render(r, defaultValue) else tRenderer.render(r, value.get) } - def defaultSeqRenderer[T: Renderer] = genericSeqRenderer[Renderable, T](Rendering.`, `, Rendering.Empty) - def seqRenderer[T: Renderer](separator: String = ", ", empty: String = "") = genericSeqRenderer[String, T](separator, empty) + def defaultSeqRenderer[T: Renderer]: Renderer[immutable.Iterable[T]] = + genericSeqRenderer[Renderable, T](Rendering.`, `, Rendering.Empty) + def seqRenderer[T: Renderer](separator: String = ", ", empty: String = ""): Renderer[immutable.Iterable[T]] = + genericSeqRenderer[String, T](separator, empty) def genericSeqRenderer[S, T](separator: S, empty: S)(implicit sRenderer: Renderer[S], tRenderer: Renderer[T]): Renderer[immutable.Iterable[T]] = new Renderer[immutable.Iterable[T]] { def render[R <: Rendering](r: R, value: immutable.Iterable[T]): r.type = { diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/EntityTag.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/EntityTag.scala index 002e37c5fb1..64710a56ee5 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/EntityTag.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/EntityTag.scala @@ -27,7 +27,7 @@ sealed abstract class EntityTagRange extends jm.headers.EntityTagRange with Valu object EntityTagRange { def apply(tags: EntityTag*) = Default(immutable.Seq(tags: _*)) - implicit val tagsRenderer = Renderer.defaultSeqRenderer[EntityTag] // cache + implicit val tagsRenderer: Renderer[immutable.Iterable[EntityTag]] = Renderer.defaultSeqRenderer[EntityTag] // cache case object `*` extends EntityTagRange { def render[R <: Rendering](r: R): r.type = r ~~ '*' diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala index 376d08085f5..9ec683be92f 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala @@ -142,7 +142,7 @@ object Accept extends ModeledCompanion[Accept] { @since213 def apply(firstMediaRange: MediaRange, otherMediaRanges: MediaRange*): Accept = apply(firstMediaRange +: otherMediaRanges) - implicit val mediaRangesRenderer = Renderer.defaultSeqRenderer[MediaRange] // cache + implicit val mediaRangesRenderer: Renderer[immutable.Iterable[MediaRange]] = Renderer.defaultSeqRenderer[MediaRange] // cache } final case class Accept(mediaRanges: immutable.Seq[MediaRange]) extends jm.headers.Accept with RequestHeader { import Accept.mediaRangesRenderer @@ -157,7 +157,7 @@ final case class Accept(mediaRanges: immutable.Seq[MediaRange]) extends jm.heade // https://tools.ietf.org/html/rfc7231#section-5.3.3 object `Accept-Charset` extends ModeledCompanion[`Accept-Charset`] { def apply(first: HttpCharsetRange, more: HttpCharsetRange*): `Accept-Charset` = apply(immutable.Seq(first +: more: _*)) - implicit val charsetRangesRenderer = Renderer.defaultSeqRenderer[HttpCharsetRange] // cache + implicit val charsetRangesRenderer: Renderer[immutable.Iterable[HttpCharsetRange]] = Renderer.defaultSeqRenderer[HttpCharsetRange] // cache } final case class `Accept-Charset`(charsetRanges: immutable.Seq[HttpCharsetRange]) extends jm.headers.AcceptCharset with RequestHeader { @@ -181,7 +181,7 @@ object `Accept-Encoding` extends ModeledCompanion[`Accept-Encoding`] { @since213 def apply(firstEncoding: HttpEncodingRange, otherEncodings: HttpEncodingRange*): `Accept-Encoding` = apply(firstEncoding +: otherEncodings) - implicit val encodingsRenderer = Renderer.defaultSeqRenderer[HttpEncodingRange] // cache + implicit val encodingsRenderer: Renderer[immutable.Iterable[HttpEncodingRange]] = Renderer.defaultSeqRenderer[HttpEncodingRange] // cache } final case class `Accept-Encoding`(encodings: immutable.Seq[HttpEncodingRange]) extends jm.headers.AcceptEncoding with RequestHeader { @@ -196,7 +196,7 @@ final case class `Accept-Encoding`(encodings: immutable.Seq[HttpEncodingRange]) // https://tools.ietf.org/html/rfc7231#section-5.3.5 object `Accept-Language` extends ModeledCompanion[`Accept-Language`] { def apply(first: LanguageRange, more: LanguageRange*): `Accept-Language` = apply(immutable.Seq(first +: more: _*)) - implicit val languagesRenderer = Renderer.defaultSeqRenderer[LanguageRange] // cache + implicit val languagesRenderer: Renderer[immutable.Iterable[LanguageRange]] = Renderer.defaultSeqRenderer[LanguageRange] // cache } final case class `Accept-Language`(languages: immutable.Seq[LanguageRange]) extends jm.headers.AcceptLanguage with RequestHeader { @@ -220,7 +220,7 @@ object `Accept-Ranges` extends ModeledCompanion[`Accept-Ranges`] { @since213 def apply(firstRangeUnit: RangeUnit, otherRangeUnits: RangeUnit*): `Accept-Ranges` = apply(firstRangeUnit +: otherRangeUnits) - implicit val rangeUnitsRenderer = Renderer.defaultSeqRenderer[RangeUnit] // cache + implicit val rangeUnitsRenderer: Renderer[immutable.Iterable[RangeUnit]] = Renderer.defaultSeqRenderer[RangeUnit] // cache } final case class `Accept-Ranges`(rangeUnits: immutable.Seq[RangeUnit]) extends jm.headers.AcceptRanges with ResponseHeader { @@ -248,7 +248,7 @@ object `Access-Control-Allow-Headers` extends ModeledCompanion[`Access-Control-A @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Allow-Headers` = apply(firstHeader +: otherHeaders) - implicit val headersRenderer = Renderer.defaultSeqRenderer[String] // cache + implicit val headersRenderer: Renderer[immutable.Iterable[String]] = Renderer.defaultSeqRenderer[String] // cache } final case class `Access-Control-Allow-Headers`(headers: immutable.Seq[String]) extends jm.headers.AccessControlAllowHeaders with ResponseHeader { @@ -268,7 +268,7 @@ object `Access-Control-Allow-Methods` extends ModeledCompanion[`Access-Control-A @since213 def apply(firstMethod: HttpMethod, otherMethods: HttpMethod*): `Access-Control-Allow-Methods` = apply(firstMethod +: otherMethods) - implicit val methodsRenderer = Renderer.defaultSeqRenderer[HttpMethod] // cache + implicit val methodsRenderer: Renderer[immutable.Iterable[HttpMethod]] = Renderer.defaultSeqRenderer[HttpMethod] // cache } final case class `Access-Control-Allow-Methods`(methods: immutable.Seq[HttpMethod]) extends jm.headers.AccessControlAllowMethods with ResponseHeader { @@ -309,7 +309,7 @@ object `Access-Control-Expose-Headers` extends ModeledCompanion[`Access-Control- @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Expose-Headers` = apply(firstHeader +: otherHeaders) - implicit val headersRenderer = Renderer.defaultSeqRenderer[String] // cache + implicit val headersRenderer: Renderer[immutable.Iterable[String]] = Renderer.defaultSeqRenderer[String] // cache } final case class `Access-Control-Expose-Headers`(headers: immutable.Seq[String]) extends jm.headers.AccessControlExposeHeaders with ResponseHeader { @@ -337,7 +337,7 @@ object `Access-Control-Request-Headers` extends ModeledCompanion[`Access-Control @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Request-Headers` = apply(firstHeader +: otherHeaders) - implicit val headersRenderer = Renderer.defaultSeqRenderer[String] // cache + implicit val headersRenderer: Renderer[immutable.Iterable[String]] = Renderer.defaultSeqRenderer[String] // cache } final case class `Access-Control-Request-Headers`(headers: immutable.Seq[String]) extends jm.headers.AccessControlRequestHeaders with RequestHeader { @@ -375,7 +375,7 @@ object Allow extends ModeledCompanion[Allow] { @since213 def apply(firstMethod: HttpMethod, otherMethods: HttpMethod*): Allow = apply(firstMethod +: otherMethods) - implicit val methodsRenderer = Renderer.defaultSeqRenderer[HttpMethod] // cache + implicit val methodsRenderer: Renderer[immutable.Iterable[HttpMethod]] = Renderer.defaultSeqRenderer[HttpMethod] // cache } final case class Allow(methods: immutable.Seq[HttpMethod]) extends jm.headers.Allow with ResponseHeader { import Allow.methodsRenderer @@ -397,7 +397,7 @@ final case class Authorization(credentials: HttpCredentials) extends jm.headers. // https://tools.ietf.org/html/rfc7234#section-5.2 object `Cache-Control` extends ModeledCompanion[`Cache-Control`] { def apply(first: CacheDirective, more: CacheDirective*): `Cache-Control` = apply(immutable.Seq(first +: more: _*)) - implicit val directivesRenderer = Renderer.defaultSeqRenderer[CacheDirective] // cache + implicit val directivesRenderer: Renderer[immutable.Iterable[CacheDirective]] = Renderer.defaultSeqRenderer[CacheDirective] // cache } final case class `Cache-Control`(directives: immutable.Seq[CacheDirective]) extends jm.headers.CacheControl with RequestResponseHeader { @@ -413,7 +413,7 @@ final case class `Cache-Control`(directives: immutable.Seq[CacheDirective]) exte // https://tools.ietf.org/html/rfc7230#section-6.1 object Connection extends ModeledCompanion[Connection] { def apply(first: String, more: String*): Connection = apply(immutable.Seq(first +: more: _*)) - implicit val tokensRenderer = Renderer.defaultSeqRenderer[String] // cache + implicit val tokensRenderer: Renderer[immutable.Iterable[String]] = Renderer.defaultSeqRenderer[String] // cache } final case class Connection(tokens: immutable.Seq[String]) extends jm.headers.Connection with RequestResponseHeader { @@ -507,7 +507,7 @@ final case class `Content-Disposition`(dispositionType: ContentDispositionType, // https://tools.ietf.org/html/rfc7231#section-3.1.2.2 object `Content-Encoding` extends ModeledCompanion[`Content-Encoding`] { def apply(first: HttpEncoding, more: HttpEncoding*): `Content-Encoding` = apply(immutable.Seq(first +: more: _*)) - implicit val encodingsRenderer = Renderer.defaultSeqRenderer[HttpEncoding] // cache + implicit val encodingsRenderer: Renderer[immutable.Iterable[HttpEncoding]] = Renderer.defaultSeqRenderer[HttpEncoding] // cache } final case class `Content-Encoding`(encodings: immutable.Seq[HttpEncoding]) extends jm.headers.ContentEncoding with RequestResponseHeader { @@ -550,7 +550,7 @@ object Cookie extends ModeledCompanion[Cookie] { def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList)*/ @since213 def apply(first: (String, String), more: (String, String)*): Cookie = apply((first +: more).map(HttpCookiePair(_))) - implicit val cookiePairsRenderer = Renderer.seqRenderer[HttpCookiePair](separator = "; ") // cache + implicit val cookiePairsRenderer: Renderer[immutable.Iterable[HttpCookiePair]] = Renderer.seqRenderer[HttpCookiePair](separator = "; ") // cache } final case class Cookie(cookies: immutable.Seq[HttpCookiePair]) extends jm.headers.Cookie with RequestHeader with SensitiveHttpHeader { @@ -700,7 +700,7 @@ object Link extends ModeledCompanion[Link] { @since213 def apply(firstValue: LinkValue, otherValues: LinkValue*): Link = apply(firstValue +: otherValues) - implicit val valuesRenderer = Renderer.defaultSeqRenderer[LinkValue] // cache + implicit val valuesRenderer: Renderer[immutable.Iterable[LinkValue]] = Renderer.defaultSeqRenderer[LinkValue] // cache } final case class Link(values: immutable.Seq[LinkValue]) extends jm.headers.Link with RequestResponseHeader { import Link.valuesRenderer @@ -741,7 +741,7 @@ final case class Origin(origins: immutable.Seq[HttpOrigin]) extends jm.headers.O // https://tools.ietf.org/html/rfc7235#section-4.3 object `Proxy-Authenticate` extends ModeledCompanion[`Proxy-Authenticate`] { def apply(first: HttpChallenge, more: HttpChallenge*): `Proxy-Authenticate` = apply(immutable.Seq(first +: more: _*)) - implicit val challengesRenderer = Renderer.defaultSeqRenderer[HttpChallenge] // cache + implicit val challengesRenderer: Renderer[immutable.Iterable[HttpChallenge]] = Renderer.defaultSeqRenderer[HttpChallenge] // cache } final case class `Proxy-Authenticate`(challenges: immutable.Seq[HttpChallenge]) extends jm.headers.ProxyAuthenticate with ResponseHeader { @@ -766,7 +766,7 @@ final case class `Proxy-Authorization`(credentials: HttpCredentials) extends jm. object Range extends ModeledCompanion[Range] { def apply(first: ByteRange, more: ByteRange*): Range = apply(immutable.Seq(first +: more: _*)) def apply(ranges: immutable.Seq[ByteRange]): Range = Range(RangeUnits.Bytes, ranges) - implicit val rangesRenderer = Renderer.defaultSeqRenderer[ByteRange] // cache + implicit val rangesRenderer: Renderer[immutable.Iterable[ByteRange]] = Renderer.defaultSeqRenderer[ByteRange] // cache } final case class Range(rangeUnit: RangeUnit, ranges: immutable.Seq[ByteRange]) extends jm.headers.Range with RequestHeader { @@ -876,7 +876,7 @@ private[http] final case class `Sec-WebSocket-Accept`(key: String) extends Respo // https://tools.ietf.org/html/rfc6455#section-4.3 @InternalApi private[http] object `Sec-WebSocket-Extensions` extends ModeledCompanion[`Sec-WebSocket-Extensions`] { - implicit val extensionsRenderer = Renderer.defaultSeqRenderer[WebSocketExtension] + implicit val extensionsRenderer: Renderer[immutable.Iterable[WebSocketExtension]] = Renderer.defaultSeqRenderer[WebSocketExtension] } /** * INTERNAL API @@ -923,7 +923,7 @@ private[http] final case class `Sec-WebSocket-Key`(key: String) extends RequestH */ @InternalApi private[http] object `Sec-WebSocket-Protocol` extends ModeledCompanion[`Sec-WebSocket-Protocol`] { - implicit val protocolsRenderer = Renderer.defaultSeqRenderer[String] + implicit val protocolsRenderer: Renderer[immutable.Iterable[String]] = Renderer.defaultSeqRenderer[String] } /** * INTERNAL API @@ -946,7 +946,7 @@ private[http] final case class `Sec-WebSocket-Protocol`(protocols: immutable.Seq */ @InternalApi private[http] object `Sec-WebSocket-Version` extends ModeledCompanion[`Sec-WebSocket-Version`] { - implicit val versionsRenderer = Renderer.defaultSeqRenderer[Int] + implicit val versionsRenderer: Renderer[immutable.Iterable[Int]] = Renderer.defaultSeqRenderer[Int] } /** * INTERNAL API @@ -966,7 +966,7 @@ private[http] final case class `Sec-WebSocket-Version`(versions: immutable.Seq[I object Server extends ModeledCompanion[Server] { def apply(products: String): Server = apply(ProductVersion.parseMultiple(products)) def apply(first: ProductVersion, more: ProductVersion*): Server = apply(immutable.Seq(first +: more: _*)) - implicit val productsRenderer = Renderer.seqRenderer[ProductVersion](separator = " ") // cache + implicit val productsRenderer: Renderer[immutable.Iterable[ProductVersion]] = Renderer.seqRenderer[ProductVersion](separator = " ") // cache } final case class Server(products: immutable.Seq[ProductVersion]) extends jm.headers.Server with ResponseHeader { require(products.nonEmpty, "products must not be empty") @@ -1053,7 +1053,7 @@ final case class `Tls-Session-Info`(session: SSLSession) extends jm.headers.TlsS // https://tools.ietf.org/html/rfc7230#section-3.3.1 object `Transfer-Encoding` extends ModeledCompanion[`Transfer-Encoding`] { def apply(first: TransferEncoding, more: TransferEncoding*): `Transfer-Encoding` = apply(immutable.Seq(first +: more: _*)) - implicit val encodingsRenderer = Renderer.defaultSeqRenderer[TransferEncoding] // cache + implicit val encodingsRenderer: Renderer[immutable.Iterable[TransferEncoding]] = Renderer.defaultSeqRenderer[TransferEncoding] // cache } final case class `Transfer-Encoding`(encodings: immutable.Seq[TransferEncoding]) extends jm.headers.TransferEncoding with RequestResponseHeader { @@ -1078,7 +1078,7 @@ final case class `Transfer-Encoding`(encodings: immutable.Seq[TransferEncoding]) // https://tools.ietf.org/html/rfc7230#section-6.7 object Upgrade extends ModeledCompanion[Upgrade] { - implicit val protocolsRenderer = Renderer.defaultSeqRenderer[UpgradeProtocol] + implicit val protocolsRenderer: Renderer[immutable.Iterable[UpgradeProtocol]] = Renderer.defaultSeqRenderer[UpgradeProtocol] } final case class Upgrade(protocols: immutable.Seq[UpgradeProtocol]) extends RequestResponseHeader { import Upgrade.protocolsRenderer @@ -1093,7 +1093,7 @@ final case class Upgrade(protocols: immutable.Seq[UpgradeProtocol]) extends Requ object `User-Agent` extends ModeledCompanion[`User-Agent`] { def apply(products: String): `User-Agent` = apply(ProductVersion.parseMultiple(products)) def apply(first: ProductVersion, more: ProductVersion*): `User-Agent` = apply(immutable.Seq(first +: more: _*)) - implicit val productsRenderer = Renderer.seqRenderer[ProductVersion](separator = " ") // cache + implicit val productsRenderer: Renderer[immutable.Iterable[ProductVersion]] = Renderer.seqRenderer[ProductVersion](separator = " ") // cache } final case class `User-Agent`(products: immutable.Seq[ProductVersion]) extends jm.headers.UserAgent with RequestHeader { require(products.nonEmpty, "products must not be empty") @@ -1108,7 +1108,7 @@ final case class `User-Agent`(products: immutable.Seq[ProductVersion]) extends j // https://tools.ietf.org/html/rfc7235#section-4.1 object `WWW-Authenticate` extends ModeledCompanion[`WWW-Authenticate`] { def apply(first: HttpChallenge, more: HttpChallenge*): `WWW-Authenticate` = apply(immutable.Seq(first +: more: _*)) - implicit val challengesRenderer = Renderer.defaultSeqRenderer[HttpChallenge] // cache + implicit val challengesRenderer: Renderer[immutable.Iterable[HttpChallenge]] = Renderer.defaultSeqRenderer[HttpChallenge] // cache } final case class `WWW-Authenticate`(challenges: immutable.Seq[HttpChallenge]) extends jm.headers.WWWAuthenticate with ResponseHeader { @@ -1124,7 +1124,7 @@ final case class `WWW-Authenticate`(challenges: immutable.Seq[HttpChallenge]) ex // https://en.wikipedia.org/wiki/X-Forwarded-For object `X-Forwarded-For` extends ModeledCompanion[`X-Forwarded-For`] { def apply(first: RemoteAddress, more: RemoteAddress*): `X-Forwarded-For` = apply(immutable.Seq(first +: more: _*)) - implicit val addressesRenderer = { + implicit val addressesRenderer: Renderer[immutable.Iterable[RemoteAddress]] = { implicit val singleAddressRenderer = RemoteAddress.renderWithoutPort Renderer.defaultSeqRenderer[RemoteAddress] // cache } @@ -1141,7 +1141,8 @@ final case class `X-Forwarded-For`(addresses: immutable.Seq[RemoteAddress]) exte } object `X-Forwarded-Host` extends ModeledCompanion[`X-Forwarded-Host`] { - implicit val hostRenderer = UriRendering.HostRenderer // cache + // keep overly accurate return type for bin compat + implicit val hostRenderer: UriRendering.HostRenderer.type = UriRendering.HostRenderer // cache } /** @@ -1175,7 +1176,7 @@ final case class `X-Forwarded-Proto`(protocol: String) extends jm.headers.XForwa } object `X-Real-Ip` extends ModeledCompanion[`X-Real-Ip`] { - implicit val addressRenderer = RemoteAddress.renderWithoutPort // cache + implicit val addressRenderer: Renderer[RemoteAddress] = RemoteAddress.renderWithoutPort // cache } final case class `X-Real-Ip`(address: RemoteAddress) extends jm.headers.XRealIp with RequestHeader with SensitiveHttpHeader { From 979ac0c1d5cc7dc8dc7db96c9e7839a62a4c264b Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 13:51:41 +0100 Subject: [PATCH 11/51] core: typing fixes to improve Scala 3 compatibility --- .../engine/server/HttpServerBluePrint.scala | 2 +- .../engine/ws/WebSocketClientBlueprint.scala | 2 +- .../akka/http/impl/util/One2OneBidiFlow.scala | 4 +-- .../impl/util/StageLoggingWithOverride.scala | 5 ++- .../main/scala/akka/http/javadsl/Http.scala | 2 +- .../akka/http/javadsl/ServerBuilder.scala | 2 +- .../akka/http/scaladsl/ClientTransport.scala | 2 +- .../main/scala/akka/http/scaladsl/Http.scala | 6 ++-- .../akka/http/scaladsl/ServerBuilder.scala | 2 +- .../akka/http/scaladsl/model/ErrorInfo.scala | 2 +- .../akka/http/scaladsl/model/HttpEntity.scala | 4 +-- .../http/scaladsl/model/HttpMessage.scala | 6 ++-- .../akka/http/scaladsl/model/MediaType.scala | 36 +++++++++---------- .../scaladsl/model/headers/HttpCookie.scala | 21 +++++------ .../model/headers/HttpCredentials.scala | 4 +-- .../settings/ClientConnectionSettings.scala | 4 +-- .../settings/ConnectionPoolSettings.scala | 10 +++--- 17 files changed, 53 insertions(+), 61 deletions(-) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala index 500ba8387bf..1ff1e39885d 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/server/HttpServerBluePrint.scala @@ -71,7 +71,7 @@ private[http] object HttpServerBluePrint { logTLSBidiBySetting("server-plain-text", settings.logUnencryptedNetworkBytes) val tlsSupport: BidiFlow[ByteString, SslTlsOutbound, SslTlsInbound, SessionBytes, NotUsed] = - BidiFlow.fromFlows(Flow[ByteString].map(SendBytes), Flow[SslTlsInbound].collect { case x: SessionBytes => x }) + BidiFlow.fromFlows(Flow[ByteString].map(SendBytes(_)), Flow[SslTlsInbound].collect { case x: SessionBytes => x }) def websocketSupport(settings: ServerSettings, log: LoggingAdapter): BidiFlow[ResponseRenderingOutput, ByteString, SessionBytes, SessionBytes, NotUsed] = BidiFlow.fromGraph(new ProtocolSwitchStage(settings, log)) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala index 647f9e9d379..e73fd85a86b 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/ws/WebSocketClientBlueprint.scala @@ -166,5 +166,5 @@ private[http] object WebSocketClientBlueprint { def simpleTls: BidiFlow[SslTlsInbound, ByteString, ByteString, SendBytes, NotUsed] = BidiFlow.fromFlowsMat( Flow[SslTlsInbound].collect { case SessionBytes(_, bytes) => bytes }, - Flow[ByteString].map(SendBytes))(Keep.none) + Flow[ByteString].map(SendBytes(_)))(Keep.none) } diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/One2OneBidiFlow.scala b/akka-http-core/src/main/scala/akka/http/impl/util/One2OneBidiFlow.scala index b07828a88fb..19822f12552 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/One2OneBidiFlow.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/One2OneBidiFlow.scala @@ -37,8 +37,8 @@ private[http] object One2OneBidiFlow { */ def apply[I, O]( maxPending: Int, - outputTruncationException: Int => Throwable = OutputTruncationException, - unexpectedOutputException: Any => Throwable = UnexpectedOutputException): BidiFlow[I, I, O, O, NotUsed] = + outputTruncationException: Int => Throwable = OutputTruncationException(_), + unexpectedOutputException: Any => Throwable = UnexpectedOutputException(_)): BidiFlow[I, I, O, O, NotUsed] = BidiFlow.fromGraph(new One2OneBidi[I, O](maxPending, outputTruncationException, unexpectedOutputException)) /* diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala b/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala index 2ed60fe6a1c..7b99a8ecb71 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala @@ -9,9 +9,8 @@ package akka.http.impl.util import akka.annotation.InternalApi import akka.stream.stage.GraphStageLogic -import akka.event.LoggingAdapter +import akka.event.{ LogSource, LoggingAdapter, NoLogging } import akka.stream.ActorMaterializer -import akka.event.NoLogging // TODO Try to reconcile with what Akka provides in StageLogging. // We thought this could be removed when https://github.com/akka/akka/issues/18793 had been implemented @@ -35,7 +34,7 @@ private[akka] trait StageLoggingWithOverride { self: GraphStageLogic => logOverride match { case DefaultNoLogging => materializer match { - case a: ActorMaterializer => akka.event.Logging(a.system, logSource) + case a: ActorMaterializer => akka.event.Logging(a.system, logSource)(LogSource.fromClass) case _ => NoLogging } case x => x diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala b/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala index 6bcae7ade7a..d492e72aa34 100644 --- a/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala @@ -811,7 +811,7 @@ class Http(system: ExtendedActorSystem) extends akka.actor.Extension { delegate.createDefaultClientHttpsContext() private def adaptTupleFlow[T, Mat](scalaFlow: stream.scaladsl.Flow[(scaladsl.model.HttpRequest, T), (Try[scaladsl.model.HttpResponse], T), Mat]): Flow[Pair[HttpRequest, T], Pair[Try[HttpResponse], T], Mat] = { - implicit def id[X] = JavaMapping.identity[X] + implicit def id[X]: JavaMapping[X, X] = JavaMapping.identity[X] JavaMapping.toJava(scalaFlow)(JavaMapping.flowMapping[Pair[HttpRequest, T], (scaladsl.model.HttpRequest, T), Pair[Try[HttpResponse], T], (Try[scaladsl.model.HttpResponse], T), Mat, Mat]) } diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/ServerBuilder.scala b/akka-http-core/src/main/scala/akka/http/javadsl/ServerBuilder.scala index f9bf16cc892..a3b90fc5618 100644 --- a/akka-http-core/src/main/scala/akka/http/javadsl/ServerBuilder.scala +++ b/akka-http-core/src/main/scala/akka/http/javadsl/ServerBuilder.scala @@ -152,7 +152,7 @@ object ServerBuilder { materializer: Materializer ) extends ServerBuilder { private implicit def executionContext: ExecutionContext = system.classicSystem.dispatcher - private def http: scaladsl.HttpExt = scaladsl.Http(system) + private def http: scaladsl.HttpExt = scaladsl.Http(system.classicSystem) def onInterface(newInterface: String): ServerBuilder = copy(interface = newInterface) def onPort(newPort: Int): ServerBuilder = copy(port = newPort) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/ClientTransport.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/ClientTransport.scala index 821d5406cc9..88e09ea0c9c 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/ClientTransport.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/ClientTransport.scala @@ -47,7 +47,7 @@ object ClientTransport { } private def connectToAddress(address: InetSocketAddress, settings: ClientConnectionSettings)(implicit system: ActorSystem): Flow[ByteString, ByteString, Future[OutgoingConnection]] = { - Tcp().outgoingConnection(address, settings.localAddress, + Tcp(system.classicSystem).outgoingConnection(address, settings.localAddress, settings.socketOptions, halfClose = true, settings.connectingTimeout, settings.idleTimeout) .mapMaterializedValue(_.map(tcpConn => OutgoingConnection(tcpConn.localAddress, tcpConn.remoteAddress))(system.dispatcher)) } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala index 66bbfbd9a17..ee66d39f126 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala @@ -10,7 +10,7 @@ import javax.net.ssl._ import akka.actor._ import akka.annotation.{ DoNotInherit, InternalApi, InternalStableApi } import akka.dispatch.ExecutionContexts -import akka.event.{ Logging, LoggingAdapter } +import akka.event.{ LogSource, Logging, LoggingAdapter } import akka.http.impl.engine.HttpConnectionIdleTimeoutBidi import akka.http.impl.engine.client._ import akka.http.impl.engine.http2.Http2 @@ -133,7 +133,7 @@ class HttpExt @InternalStableApi /* constructor signature is hardcoded in Teleme ) private def tcpBind(interface: String, port: Int, settings: ServerSettings): Source[Tcp.IncomingConnection, Future[Tcp.ServerBinding]] = - Tcp() + Tcp(system) .bind( interface, port, @@ -1160,7 +1160,7 @@ trait DefaultSSLContextCreation { def createClientHttpsContext(sslConfig: AkkaSSLConfig): HttpsConnectionContext = { val config = sslConfig.config - val log = Logging(system, getClass) + val log = Logging(system, getClass)(LogSource.fromClass) val mkLogger = new AkkaLoggerFactory(system) // initial ssl context! diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/ServerBuilder.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/ServerBuilder.scala index 77bbc728bec..821dc46f937 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/ServerBuilder.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/ServerBuilder.scala @@ -131,7 +131,7 @@ private[http] object ServerBuilder { system: ClassicActorSystemProvider, materializer: Materializer ) extends ServerBuilder { - private val http: scaladsl.HttpExt = scaladsl.Http(system) + private val http: scaladsl.HttpExt = scaladsl.Http(system.classicSystem) def onInterface(newInterface: String): ServerBuilder = copy(interface = newInterface) def onPort(newPort: Int): ServerBuilder = copy(port = newPort) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/ErrorInfo.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/ErrorInfo.scala index e925034d8e9..6b6826e4730 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/ErrorInfo.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/ErrorInfo.scala @@ -17,7 +17,7 @@ final class ErrorInfo( val summary: String = "", val detail: String = "", val errorHeaderName: String = "" -) extends scala.Product with scala.Serializable with scala.Equals with java.io.Serializable { +) extends scala.Product with scala.Equals with java.io.Serializable { def withSummary(newSummary: String) = copy(summary = newSummary) def withSummaryPrepended(prefix: String) = withSummary(if (summary.isEmpty) prefix else prefix + ": " + summary) def withErrorHeaderName(headerName: String) = new ErrorInfo(summary, detail, headerName.toLowerCase) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpEntity.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpEntity.scala index acb066675de..ee0015193c3 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpEntity.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpEntity.scala @@ -634,12 +634,12 @@ object HttpEntity { override val shape = FlowShape.of(in, out) override protected val initialAttributes: Attributes = Limitable.limitableDefaults - override def createLogic(attributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { + override def createLogic(_attributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with InHandler with OutHandler { private var maxBytes = -1L private var bytesLeft = Long.MaxValue override def preStart(): Unit = { - attributes.getFirst[SizeLimit] match { + _attributes.getFirst[SizeLimit] match { case Some(limit: SizeLimit) if limit.isDisabled => // "no limit" case Some(SizeLimit(bytes, cl @ Some(contentLength))) => diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala index a56c1757a52..85aafc83ca9 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala @@ -216,10 +216,8 @@ sealed trait HttpMessage extends jm.HttpMessage { /** Java API */ def addHeaders(headers: JIterable[jm.HttpHeader]): Self = withHeaders(this.headers ++ headers.asScala.asInstanceOf[Iterable[HttpHeader]]) /** Java API */ - def withHeaders(headers: JIterable[jm.HttpHeader]): Self = { - import JavaMapping.Implicits._ - withHeaders(headers.asScala.toVector.map(_.asScala)) - } + def withHeaders(headers: JIterable[jm.HttpHeader]): Self = + withHeaders(headers.asScala.toVector.map(x => JavaMapping.toScala(x)) /** Java API */ def getAttribute[T](attributeKey: jm.AttributeKey[T]): Optional[T] = Util.convertOption(attribute(attributeKey)) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala index c2bdf2f97fb..1c03d9551d5 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala @@ -131,12 +131,12 @@ object MediaType { val _params = params new Binary(renderValue(mainType, subType, params), mainType, subType, comp, fileExtensions) { override def params = _params - override def isApplication = mainType == "application" - override def isAudio = mainType == "audio" - override def isImage = mainType == "image" - override def isMessage = mainType == "message" - override def isText = mainType == "text" - override def isVideo = mainType == "video" + override def isApplication = this.mainType == "application" + override def isAudio = this.mainType == "audio" + override def isImage = this.mainType == "image" + override def isMessage = this.mainType == "message" + override def isText = this.mainType == "text" + override def isVideo = this.mainType == "video" } } @@ -148,12 +148,12 @@ object MediaType { val _params = params new WithFixedCharset(renderValue(mainType, subType, params), mainType, subType, charset, fileExtensions) { override def params = _params - override def isApplication = mainType == "application" - override def isAudio = mainType == "audio" - override def isImage = mainType == "image" - override def isMessage = mainType == "message" - override def isText = mainType == "text" - override def isVideo = mainType == "video" + override def isApplication = this.mainType == "application" + override def isAudio = this.mainType == "audio" + override def isImage = this.mainType == "image" + override def isMessage = this.mainType == "message" + override def isText = this.mainType == "text" + override def isVideo = this.mainType == "video" } } @@ -165,12 +165,12 @@ object MediaType { val _params = params new NonMultipartWithOpenCharset(renderValue(mainType, subType, params), mainType, subType, fileExtensions) { override def params = _params - override def isApplication = mainType == "application" - override def isAudio = mainType == "audio" - override def isImage = mainType == "image" - override def isMessage = mainType == "message" - override def isText = mainType == "text" - override def isVideo = mainType == "video" + override def isApplication = this.mainType == "application" + override def isAudio = this.mainType == "audio" + override def isImage = this.mainType == "image" + override def isMessage = this.mainType == "message" + override def isText = this.mainType == "text" + override def isVideo = this.mainType == "video" } } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCookie.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCookie.scala index 2969f9665d6..51fbbf712b6 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCookie.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCookie.scala @@ -57,14 +57,14 @@ object HttpCookiePair { * http://tools.ietf.org/html/rfc6265 */ final class HttpCookie private[http] ( - name: String, - value: String, + val name: String, + val value: String, val expires: Option[DateTime], val maxAge: Option[Long], val domain: Option[String], val path: Option[String], - secure: Boolean, - httpOnly: Boolean, + val secure: Boolean, + val httpOnly: Boolean, val extension: Option[String], val sameSite: Option[SameSite]) extends jm.headers.HttpCookie with ToStringRenderable with Product with Serializable with Equals { @@ -162,11 +162,6 @@ final class HttpCookie private[http] ( r } - override def name(): String = this.name - override def value(): String = this.value - override def secure(): Boolean = this.secure - override def httpOnly(): Boolean = this.httpOnly - /** Java API */ def getSameSite: Optional[jm.headers.SameSite] = sameSite.map(_.asJava).asJava /** Java API */ @@ -223,14 +218,14 @@ object HttpCookie { @deprecated("Pattern matching on HttpCookie is deprecated because of the big number of fields and potential future compatibility hazards. Please use other means to check the fields.", since = "10.2.0") def unapply(cookie: HttpCookie) = Option(( - cookie.name(), - cookie.value(), + cookie.name, + cookie.value, cookie.expires, cookie.maxAge, cookie.domain, cookie.path, - cookie.secure(), - cookie.httpOnly(), + cookie.secure, + cookie.httpOnly, cookie.extension )) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCredentials.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCredentials.scala index ca1d1fc9dec..0d5bc9795d0 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCredentials.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/HttpCredentials.scala @@ -23,7 +23,7 @@ final case class BasicHttpCredentials(username: String, password: String) extend val cookie = { val userPass = username + ':' + password val bytes = userPass.getBytes(`UTF-8`.nioCharset) - Base64.rfc2045.encodeToChar(bytes, false) + Base64.rfc2045().encodeToChar(bytes, false) } def render[R <: Rendering](r: R): r.type = r ~~ "Basic " ~~ cookie @@ -34,7 +34,7 @@ final case class BasicHttpCredentials(username: String, password: String) extend object BasicHttpCredentials { def apply(credentials: String): BasicHttpCredentials = { - val bytes = Base64.rfc2045.decodeFast(credentials) + val bytes = Base64.rfc2045().decodeFast(credentials) val userPass = new String(bytes, `UTF-8`.nioCharset) userPass.indexOf(':') match { case -1 => apply(userPass, "") diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala index d9313d0a178..97cadd7b3ac 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ClientConnectionSettings.scala @@ -52,7 +52,7 @@ abstract class ClientConnectionSettings private[akka] () extends akka.http.javad // overloads for idiomatic Scala use def withWebsocketSettings(newValue: WebSocketSettings): ClientConnectionSettings = self.copy(websocketSettings = newValue) - def withWebsocketRandomFactory(newValue: () => Random): ClientConnectionSettings = withWebsocketSettings(websocketSettings.withRandomFactoryFactory(new Supplier[Random] { + def withWebsocketRandomFactory(newValue: () => Random): ClientConnectionSettings = withWebsocketSettings(self.websocketSettings.withRandomFactoryFactory(new Supplier[Random] { override def get(): Random = newValue() })) def withUserAgentHeader(newValue: Option[`User-Agent`]): ClientConnectionSettings = self.copy(userAgentHeader = newValue) @@ -66,7 +66,7 @@ abstract class ClientConnectionSettings private[akka] () extends akka.http.javad def withTransport(newTransport: ClientTransport): ClientConnectionSettings = self.copy(transport = newTransport) // Scala-only lenses - def mapHttp2Settings(f: Http2ClientSettings => Http2ClientSettings): ClientConnectionSettings = withHttp2Settings(f(http2Settings)) + def mapHttp2Settings(f: Http2ClientSettings => Http2ClientSettings): ClientConnectionSettings = withHttp2Settings(f(self.http2Settings)) /** * Returns a new instance with the given local address set if the given override is `Some(address)`, otherwise diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala index 6abb12a8ab6..60314290369 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala @@ -38,13 +38,13 @@ abstract class ConnectionPoolSettings extends js.ConnectionPoolSettings { self: * the first matching set of overrides is selected. */ private[akka] def forHost(host: String): ConnectionPoolSettings = - hostOverrides.collectFirst { case (regex, overrides) if regex.pattern.matcher(host).matches() => overrides }.getOrElse(this) + self.hostOverrides.collectFirst { case (regex, overrides) if regex.pattern.matcher(host).matches() => overrides }.getOrElse(this) /** * The underlying transport used to connect to hosts. By default [[ClientTransport.TCP]] is used. */ @deprecated("Deprecated in favor of connectionSettings.transport", "10.1.0") - def transport: ClientTransport = connectionSettings.transport + def transport: ClientTransport = self.connectionSettings.transport /** The time after which the pool will drop an entity automatically if it wasn't read or discarded */ @ApiMayChange @@ -53,10 +53,10 @@ abstract class ConnectionPoolSettings extends js.ConnectionPoolSettings { self: // --- @ApiMayChange - def withHostOverrides(hostOverrides: immutable.Seq[(String, ConnectionPoolSettings)]): ConnectionPoolSettings = self.copy(hostOverrides = hostOverrides.map { case (h, s) => ConnectionPoolSettingsImpl.hostRegex(h) -> s }) + def withHostOverrides(hostOverrides: immutable.Seq[(String, ConnectionPoolSettings)]): ConnectionPoolSettings = self.copy(hostOverrides = self.hostOverrides.map { case (h, s) => ConnectionPoolSettingsImpl.hostRegex(h) -> s }) @ApiMayChange - def appendHostOverride(hostPattern: String, settings: ConnectionPoolSettings): ConnectionPoolSettings = self.copy(hostOverrides = hostOverrides :+ (ConnectionPoolSettingsImpl.hostRegex(hostPattern) -> settings)) + def appendHostOverride(hostPattern: String, settings: ConnectionPoolSettings): ConnectionPoolSettings = self.copy(hostOverrides = self.hostOverrides :+ (ConnectionPoolSettingsImpl.hostRegex(hostPattern) -> settings)) override def withMaxConnections(n: Int): ConnectionPoolSettings = self.copyDeep(_.withMaxConnections(n), maxConnections = n) override def withMinConnections(n: Int): ConnectionPoolSettings = self.copyDeep(_.withMinConnections(n), minConnections = n) @@ -78,7 +78,7 @@ abstract class ConnectionPoolSettings extends js.ConnectionPoolSettings { self: * `withUpdatedConnectionSettings(_.withTransport(newTransport))`. */ def withTransport(newValue: ClientTransport): ConnectionPoolSettings = - withUpdatedConnectionSettings(_.withTransport(newValue)) + self.withUpdatedConnectionSettings(_.withTransport(newValue)) def withUpdatedConnectionSettings(f: ClientConnectionSettings => ClientConnectionSettings): ConnectionPoolSettings } From ebd17d4dce37ffd7d08f7f5ea1159db406600356 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Wed, 16 Feb 2022 12:17:12 +0100 Subject: [PATCH 12/51] core: fix remaining compilation errors (not related to parsing) --- .../impl/engine/http2/BufferedOutletSupport.scala | 2 +- .../http/impl/engine/http2/Http2StreamHandling.scala | 2 +- .../http/impl/engine/rendering/RenderSupport.scala | 11 +++++++---- .../main/scala/akka/http/impl/util/Rendering.scala | 2 +- .../http/impl/util/StageLoggingWithOverride.scala | 2 +- .../main/scala/akka/http/impl/util/StreamUtils.scala | 2 +- .../http/javadsl/settings/Http2ServerSettings.scala | 2 +- .../scala/akka/http/scaladsl/model/HttpMessage.scala | 2 +- .../scala/akka/http/scaladsl/model/MediaType.scala | 2 +- .../scaladsl/settings/ConnectionPoolSettings.scala | 3 ++- 10 files changed, 17 insertions(+), 13 deletions(-) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/BufferedOutletSupport.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/BufferedOutletSupport.scala index 1b64123fb6d..d64fbbf21cb 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/BufferedOutletSupport.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/BufferedOutletSupport.scala @@ -98,7 +98,7 @@ private[http2] class BufferedOutletExtended[T](outlet: GenericOutlet[T]) extends * INTERNAL API */ @InternalApi -private[http2] trait GenericOutletSupport { logic: GraphStageLogic => +private[http2] trait GenericOutletSupport extends GraphStageLogic { logic => def fromSubSourceOutlet[T](subSourceOutlet: SubSourceOutlet[T]): GenericOutlet[T] = new GenericOutlet[T] { def setHandler(handler: OutHandler): Unit = subSourceOutlet.setHandler(handler) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala index 83b1f03ce0a..41e3640e313 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2StreamHandling.scala @@ -29,7 +29,7 @@ import scala.util.control.NoStackTrace * Mixed into the Http2ServerDemux graph logic. */ @InternalApi -private[http2] trait Http2StreamHandling { self: GraphStageLogic with LogHelper => +private[http2] trait Http2StreamHandling extends GraphStageLogic with LogHelper { self => // required API from demux def isServer: Boolean def multiplexer: Http2Multiplexer diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala index d52330388bb..64666be6b00 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala @@ -49,10 +49,13 @@ private[http] object RenderSupport { val defaultLastChunkBytes: ByteString = renderChunk(HttpEntity.LastChunk) def CancelSecond[T, Mat](first: Source[T, Mat], second: Source[T, Any]): Source[T, Mat] = { - Source.fromGraph(GraphDSL.create(first) { implicit b => (frst: SourceShape[T]) => - import GraphDSL.Implicits._ - second ~> Sink.cancelled - SourceShape(frst.out) + Source.fromGraph(GraphDSL.create[SourceShape[T], Mat](first) { implicit b => + { + case frst: SourceShape[T] => + import GraphDSL.Implicits._ + second ~> Sink.cancelled + SourceShape(frst.out) + } }) } diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala b/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala index 2dead05bb57..afd600345a4 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/Rendering.scala @@ -218,7 +218,7 @@ private[http] trait Rendering { /** * Renders the given string in double quotes. */ - def ~~#!(s: String): this.type = ~~('"').putEscaped(s) ~~ '"' + def ~~#!(s: String): this.type = this.~~('"').putEscaped(s, Rendering.`\"`, '\\').~~('"') def putEscaped(s: String, escape: CharPredicate = Rendering.`\"`, escChar: Char = '\\'): this.type = { @tailrec def rec(ix: Int = 0): this.type = diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala b/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala index 7b99a8ecb71..83f8aa93266 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/StageLoggingWithOverride.scala @@ -19,7 +19,7 @@ import akka.stream.ActorMaterializer * INTERNAL API */ @InternalApi -private[akka] trait StageLoggingWithOverride { self: GraphStageLogic => +private[akka] trait StageLoggingWithOverride extends GraphStageLogic { def logOverride: LoggingAdapter = DefaultNoLogging private var _log: LoggingAdapter = null diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala b/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala index 29c1792c118..597a3988af6 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala @@ -260,7 +260,7 @@ private[http] object StreamUtils { def statefulAttrsMap[T, U](functionConstructor: Attributes => T => U): Flow[T, U, NotUsed] = Flow[T].via(ExposeAttributes[T, U](functionConstructor)) - trait ScheduleSupport { self: GraphStageLogic => + trait ScheduleSupport extends GraphStageLogic { self => /** * Schedule a block to be run once after the given duration in the context of this graph stage. */ diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/settings/Http2ServerSettings.scala b/akka-http-core/src/main/scala/akka/http/javadsl/settings/Http2ServerSettings.scala index 4845481d482..92fc9eaffad 100644 --- a/akka-http-core/src/main/scala/akka/http/javadsl/settings/Http2ServerSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/javadsl/settings/Http2ServerSettings.scala @@ -12,7 +12,7 @@ import com.typesafe.config.Config import scala.concurrent.duration._ @DoNotInherit -trait Http2ServerSettings { self: scaladsl.settings.Http2ServerSettings => +trait Http2ServerSettings { self: scaladsl.settings.Http2ServerSettings with akka.http.scaladsl.settings.Http2ServerSettings.Http2ServerSettingsImpl => def getRequestEntityChunkSize: Int = requestEntityChunkSize def withRequestEntityChunkSize(newRequestEntityChunkSize: Int): Http2ServerSettings diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala index 85aafc83ca9..9ddf40e8a1f 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala @@ -217,7 +217,7 @@ sealed trait HttpMessage extends jm.HttpMessage { def addHeaders(headers: JIterable[jm.HttpHeader]): Self = withHeaders(this.headers ++ headers.asScala.asInstanceOf[Iterable[HttpHeader]]) /** Java API */ def withHeaders(headers: JIterable[jm.HttpHeader]): Self = - withHeaders(headers.asScala.toVector.map(x => JavaMapping.toScala(x)) + withHeaders(headers.asScala.toVector.map(x => JavaMapping.toScala(x))) /** Java API */ def getAttribute[T](attributeKey: jm.AttributeKey[T]): Optional[T] = Util.convertOption(attribute(attributeKey)) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala index 1c03d9551d5..78fda309a73 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/MediaType.scala @@ -320,7 +320,7 @@ object MediaTypes extends ObjectRegistry[(String, String), MediaType] { mediaType } - private def register[T <: MediaType](mediaType: T): T = { + private def register(mediaType: MediaType): mediaType.type = { registerFileExtensions(mediaType) register(mediaType.mainType.toRootLowerCase -> mediaType.subType.toRootLowerCase, mediaType) } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala index 60314290369..f91b724b865 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ConnectionPoolSettings.scala @@ -53,7 +53,8 @@ abstract class ConnectionPoolSettings extends js.ConnectionPoolSettings { self: // --- @ApiMayChange - def withHostOverrides(hostOverrides: immutable.Seq[(String, ConnectionPoolSettings)]): ConnectionPoolSettings = self.copy(hostOverrides = self.hostOverrides.map { case (h, s) => ConnectionPoolSettingsImpl.hostRegex(h) -> s }) + def withHostOverrides(hostOverrides: immutable.Seq[(String, ConnectionPoolSettings)]): ConnectionPoolSettings = + self.copy(hostOverrides = hostOverrides.map { case (h, s) => ConnectionPoolSettingsImpl.hostRegex(h) -> s }) @ApiMayChange def appendHostOverride(hostPattern: String, settings: ConnectionPoolSettings): ConnectionPoolSettings = self.copy(hostOverrides = self.hostOverrides :+ (ConnectionPoolSettingsImpl.hostRegex(hostPattern) -> settings)) From 5394bff9e5da42eac3a993a4a936d40a67ef1399 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 13:56:18 +0100 Subject: [PATCH 13/51] core: ignore internal signature changes (required for Scala 3 compat) --- .../10.2.9.backwards.excludes/http2-signature-changes.excludes | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 akka-http-core/src/main/mima-filters/10.2.9.backwards.excludes/http2-signature-changes.excludes diff --git a/akka-http-core/src/main/mima-filters/10.2.9.backwards.excludes/http2-signature-changes.excludes b/akka-http-core/src/main/mima-filters/10.2.9.backwards.excludes/http2-signature-changes.excludes new file mode 100644 index 00000000000..8be68aae407 --- /dev/null +++ b/akka-http-core/src/main/mima-filters/10.2.9.backwards.excludes/http2-signature-changes.excludes @@ -0,0 +1,2 @@ +# Changes to internal signatures +ProblemFilters.exclude[Problem]("akka.http.impl.engine.http2.*") \ No newline at end of file From 96c640b5161c2e5b6e72873c7785cbc2d98885c8 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 14:02:30 +0100 Subject: [PATCH 14/51] parsing: port latest changing from parboiled2 Up to c18fa929ebccf583f9d8d27a0c2588516ed75872 --- .../parboiled2/support/OpTreeContext.scala | 32 +++++++++++++++++++ .../akka/parboiled2/support/TailSwitch.scala | 4 +-- .../main/scala/akka/parboiled2/Parser.scala | 2 ++ 3 files changed, 36 insertions(+), 2 deletions(-) diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala index e49bc498481..a562fd10b20 100644 --- a/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/OpTreeContext.scala @@ -22,6 +22,9 @@ import akka.parboiled2.support.hlist.HList import scala.quoted._ import scala.annotation.tailrec +import scala.quoted._ +import scala.annotation.tailrec + class OpTreeContext(parser: Expr[Parser])(using Quotes) { import quotes.reflect.* @@ -455,6 +458,34 @@ class OpTreeContext(parser: Expr[Parser])(using Quotes) { } } + private case class RunSubParser(fTree: Expr[_]) extends DefaultNonTerminalOpTree { + def ruleTraceNonTerminalKey = '{ RuleTrace.RunSubParser } + def renderInner(start: quoted.Expr[Int], wrapped: Boolean): Expr[Boolean] = { + def rewrite(arg: ValDef, tree: Term): Expr[Boolean] = { + tree match { + case Block(statements, res) => block(statements, rewrite(arg, res).asTerm).asExprOf[Boolean] + case Select(Apply(parserCons, List(consArg @ Ident(_))), rule) if consArg.symbol == arg.symbol => + val term = Apply(parserCons, List('{ $parser.__subParserInput }.asTerm)) + term.tpe.asType match { + case '[p] => + '{ + val __subParser = ${ term.asExprOf[Parser with p] } + val offset = $parser.cursor + __subParser.copyStateFrom($parser, offset) + try ${ Select.unique('{ __subParser }.asTerm, rule).asExpr } != null + finally $parser.copyStateFrom(__subParser, -offset) + } + } + case x => reportError("Illegal runSubParser expr: " + x.show, fTree) + } + } + fTree.asTerm match { + case Lambda(List(vd @ ValDef(_, _, _)), body) => rewrite(vd, body) + case x => reportError("Illegal runSubParser expr: " + x.show, fTree) + } + } + } + private case class PushAction(valueExpr: Expr[_], argType: Type[_]) extends OpTree { def render(wrapped: Boolean): Expr[Boolean] = { val body = @@ -794,6 +825,7 @@ class OpTreeContext(parser: Expr[Parser])(using Quotes) { case '{ ($p: Parser).push[t]($value) } => PushAction(value, Type.of[t]) case '{ ($p: Parser).drop[t] } => DropAction(Type.of[t]) case '{ type i <: HList; type o <: HList; ($p: Parser).capture[`i`, `o`]($arg)($l) } => Capture(rec(arg.asTerm)) + case '{ type i <: HList; type o <: HList; ($p: Parser).runSubParser[`i`, `o`]($f) } => RunSubParser(f) case '{ type i1 <: HList; type o1 <: HList type i2 <: HList; type o2 <: HList diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala index 84597d62a26..7a6485f165a 100644 --- a/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala @@ -71,8 +71,8 @@ object TailSwitch { } } - type Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out <: HList] = - TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } + type Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out0] = + TailSwitch[L, T, R] { type Out = Out0 } implicit def tailSwitch[L <: HList, T <: HList, R <: HList] : TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } = `n/a` diff --git a/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala b/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala index eee5cdfd0dd..77492db62ac 100644 --- a/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala +++ b/akka-parsing/src/main/scala/akka/parboiled2/Parser.scala @@ -512,6 +512,8 @@ abstract class Parser(initialValueStackSize: Int = 16, maxValueStackSize: Int = def length: Int = input.length - offset def charAt(ix: Int): Char = input.charAt(offset + ix) } + + def __subParserInput = new __SubParserInput() } object Parser { From 6c045deda2fa1b4606bccc6bfaff47d29cdb3ff1 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 14:49:58 +0100 Subject: [PATCH 15/51] build: for now only enable Scala 3 for parsing and core --- build.sbt | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/build.sbt b/build.sbt index f6b45bf44e7..ea571f565a1 100644 --- a/build.sbt +++ b/build.sbt @@ -184,6 +184,7 @@ lazy val http = project("akka-http") .settings(scalaMacroSupport) .enablePlugins(BootstrapGenjavadoc, BoilerplatePlugin) .enablePlugins(ReproducibleBuildsPlugin) + .enablePlugins(NoScala3) // FIXME def gustavDir(kind: String) = Def.task { val ver = @@ -233,6 +234,7 @@ lazy val http2Support = project("akka-http2-support") .enablePlugins(BootstrapGenjavadoc) .enablePlugins(ReproducibleBuildsPlugin) .disablePlugins(MimaPlugin) // experimental module still + .enablePlugins(NoScala3) // FIXME lazy val httpTestkit = project("akka-http-testkit") .settings(commonSettings) @@ -250,6 +252,7 @@ lazy val httpTestkit = project("akka-http-testkit") .enablePlugins(BootstrapGenjavadoc, MultiNodeScalaTest, ScaladocNoVerificationOfDiagrams) .enablePlugins(ReproducibleBuildsPlugin) .disablePlugins(MimaPlugin) // testkit, no bin compat guaranteed + .enablePlugins(NoScala3) // FIXME lazy val httpTests = project("akka-http-tests") .settings(commonSettings) @@ -280,6 +283,7 @@ lazy val httpTests = project("akka-http-tests") targetFile } ) + .enablePlugins(NoScala3) // FIXME lazy val httpJmhBench = project("akka-http-bench-jmh") .settings(commonSettings) @@ -288,6 +292,7 @@ lazy val httpJmhBench = project("akka-http-bench-jmh") .enablePlugins(JmhPlugin) .enablePlugins(NoPublish) // don't release benchs .disablePlugins(MimaPlugin) + .enablePlugins(NoScala3) // FIXME lazy val httpMarshallersScala = project("akka-http-marshallers-scala") .settings(commonSettings) @@ -300,12 +305,14 @@ lazy val httpXml = .settings(AutomaticModuleName.settings("akka.http.marshallers.scalaxml")) .addAkkaModuleDependency("akka-stream", "provided") .settings(Dependencies.httpXml) + .enablePlugins(NoScala3) // FIXME lazy val httpSprayJson = httpMarshallersScalaSubproject("spray-json") .settings(AutomaticModuleName.settings("akka.http.marshallers.sprayjson")) .addAkkaModuleDependency("akka-stream", "provided") .settings(Dependencies.httpSprayJson) + .enablePlugins(NoScala3) // FIXME lazy val httpMarshallersJava = project("akka-http-marshallers-java") .settings(commonSettings) @@ -321,6 +328,7 @@ lazy val httpJackson = .dependsOn(httpTestkit % "test") .settings(Dependencies.httpJackson) .enablePlugins(ScaladocNoVerificationOfDiagrams) + .enablePlugins(NoScala3) // FIXME lazy val httpCaching = project("akka-http-caching") .settings(commonSettings) @@ -330,6 +338,7 @@ lazy val httpCaching = project("akka-http-caching") .settings(Dependencies.httpCaching) .dependsOn(http, httpCore, httpTestkit % "test") .enablePlugins(BootstrapGenjavadoc) + .enablePlugins(NoScala3) // FIXME def project(name: String) = Project(id = name, base = file(name)) @@ -410,6 +419,7 @@ lazy val httpScalafixTests = lazy val docs = project("docs") .enablePlugins(AkkaParadoxPlugin, NoPublish, PublishRsyncPlugin) + .enablePlugins(NoScala3) // FIXME .disablePlugins(MimaPlugin) .addAkkaModuleDependency("akka-stream", "provided", AkkaDependency.docs) .addAkkaModuleDependency("akka-actor-typed", "provided", AkkaDependency.docs) From cc9b468d164769a5f578b84ce31448adb99545e8 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Wed, 16 Feb 2022 11:34:09 +0100 Subject: [PATCH 16/51] core: move parsing code for now to Scala 2 only --- .../akka/http/impl/model/parser/AcceptCharsetHeader.scala | 0 .../akka/http/impl/model/parser/AcceptEncodingHeader.scala | 0 .../akka/http/impl/model/parser/AcceptHeader.scala | 0 .../akka/http/impl/model/parser/AcceptLanguageHeader.scala | 0 .../akka/http/impl/model/parser/Base64Parsing.scala | 0 .../akka/http/impl/model/parser/CacheControlHeader.scala | 0 .../akka/http/impl/model/parser/CommonActions.scala | 0 .../akka/http/impl/model/parser/CommonRules.scala | 0 .../akka/http/impl/model/parser/ContentDispositionHeader.scala | 0 .../akka/http/impl/model/parser/ContentTypeHeader.scala | 0 .../akka/http/impl/model/parser/HeaderParser.scala | 0 .../akka/http/impl/model/parser/IpAddressParsing.scala | 0 .../akka/http/impl/model/parser/LinkHeader.scala | 0 .../akka/http/impl/model/parser/SimpleHeaders.scala | 0 .../akka/http/impl/model/parser/StringBuilding.scala | 0 .../akka/http/impl/model/parser/UriParser.scala | 0 .../akka/http/impl/model/parser/WebSocketHeaders.scala | 0 17 files changed, 0 insertions(+), 0 deletions(-) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/AcceptCharsetHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/AcceptEncodingHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/AcceptHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/AcceptLanguageHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/Base64Parsing.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/CacheControlHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/CommonActions.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/CommonRules.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/ContentDispositionHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/ContentTypeHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/HeaderParser.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/IpAddressParsing.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/LinkHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/SimpleHeaders.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/StringBuilding.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/UriParser.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/impl/model/parser/WebSocketHeaders.scala (100%) diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptCharsetHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptCharsetHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptCharsetHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptCharsetHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptEncodingHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptEncodingHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptEncodingHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptEncodingHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptLanguageHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptLanguageHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptLanguageHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptLanguageHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/Base64Parsing.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/Base64Parsing.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CacheControlHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CacheControlHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonActions.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonActions.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonActions.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonActions.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonRules.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonRules.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentDispositionHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentDispositionHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentDispositionHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentDispositionHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentTypeHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentTypeHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentTypeHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentTypeHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/HeaderParser.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/HeaderParser.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/IpAddressParsing.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/IpAddressParsing.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/IpAddressParsing.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/IpAddressParsing.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/LinkHeader.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/LinkHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/LinkHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/LinkHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/SimpleHeaders.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/SimpleHeaders.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/SimpleHeaders.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/SimpleHeaders.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/StringBuilding.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/StringBuilding.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/StringBuilding.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/StringBuilding.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/UriParser.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/UriParser.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/UriParser.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/UriParser.scala diff --git a/akka-http-core/src/main/scala/akka/http/impl/model/parser/WebSocketHeaders.scala b/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/WebSocketHeaders.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/impl/model/parser/WebSocketHeaders.scala rename to akka-http-core/src/main/scala-2/akka/http/impl/model/parser/WebSocketHeaders.scala From 44d1c28bda1421d36053ea7d6bfcfd2fdba5720f Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 14:59:32 +0100 Subject: [PATCH 17/51] core: provide broken stub entries for header parsing for Scala 3 But at least make it compile for Scala 3 --- .../akka/http/scaladsl/model/HttpHeader.scala | 0 .../model/headers/ProductVersion.scala | 0 .../akka/http/scaladsl/model/HttpHeader.scala | 125 ++++++++++++++++++ .../model/headers/ProductVersion.scala | 39 ++++++ 4 files changed, 164 insertions(+) rename akka-http-core/src/main/{scala => scala-2}/akka/http/scaladsl/model/HttpHeader.scala (100%) rename akka-http-core/src/main/{scala => scala-2}/akka/http/scaladsl/model/headers/ProductVersion.scala (100%) create mode 100644 akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala create mode 100644 akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpHeader.scala b/akka-http-core/src/main/scala-2/akka/http/scaladsl/model/HttpHeader.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpHeader.scala rename to akka-http-core/src/main/scala-2/akka/http/scaladsl/model/HttpHeader.scala diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/ProductVersion.scala b/akka-http-core/src/main/scala-2/akka/http/scaladsl/model/headers/ProductVersion.scala similarity index 100% rename from akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/ProductVersion.scala rename to akka-http-core/src/main/scala-2/akka/http/scaladsl/model/headers/ProductVersion.scala diff --git a/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala b/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala new file mode 100644 index 00000000000..458019c510a --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala @@ -0,0 +1,125 @@ +/* + * Copyright (C) 2009-2021 Lightbend Inc. + */ + +package akka.http.scaladsl.model + +import akka.annotation.InternalApi + +import scala.util.{ Failure, Success } +import akka.parboiled2.ParseError +import akka.http.impl.util.ToStringRenderable +import akka.http.impl.model.parser.{ CharacterClasses, HeaderParser } +import akka.http.javadsl.{ model => jm } +import akka.http.scaladsl.model.headers._ +import akka.util.OptionVal + +import scala.collection.immutable + +/** + * Marker trait for headers which contain portentially secret / sensitive information. + * + * Mixing this trait will make `toString` to return the name of the header thus avoiding any + * detail leak. + */ +trait SensitiveHttpHeader { + this: HttpHeader => + + // This header is tagged as potentially containing personal sensitive information + final override def toString: String = name +} + +/** + * The model of an HTTP header. In its most basic form headers are simple name-value pairs. Header names + * are compared in a case-insensitive way. + */ +abstract class HttpHeader extends jm.HttpHeader with ToStringRenderable { + def name: String + def value: String + def lowercaseName: String + def is(nameInLowerCase: String): Boolean = lowercaseName == nameInLowerCase + def isNot(nameInLowerCase: String): Boolean = lowercaseName != nameInLowerCase + + def unsafeToString: String = super.toString +} + +object HttpHeader { + /** + * Extract name and value from a header. + * CAUTION: The name must be matched in *all-lowercase*!. + */ + def unapply(header: HttpHeader): Option[(String, String)] = Some((header.lowercaseName, header.value)) + + /** + * Attempts to parse the given header name and value string into a header model instance. + * + * This process has several possible outcomes: + * + * 1. The header name corresponds to a properly modelled header and + * a) the value is valid for this header type. + * In this case the method returns a `ParsingResult.Ok` with the respective header instance and no errors. + * b) the value consists of a number elements, some of which valid and some invalid, and the header type supports + * partial value parsing. In this case the method returns a `ParsingResult.Ok` with the respective header + * instance holding the valid value elements and an [[ErrorInfo]] for each invalid value. + * c) the value has invalid elements and the header type doesn't support partial value parsing. + * In this case the method returns a `ParsingResult.Ok` with a [[akka.http.scaladsl.model.headers.RawHeader]] instance and + * a single [[ErrorInfo]] for the value parsing problem. + * + * 2. The header name does not correspond to a properly modelled header but the header name and the value are both + * syntactically legal according to the basic header requirements from the HTTP specification. + * (http://tools.ietf.org/html/rfc7230#section-3.2) + * In this case the method returns a `ParsingResult.Ok` with a [[akka.http.scaladsl.model.headers.RawHeader]] instance and no errors. + * + * 3. The header name or value are illegal according to the basic requirements for HTTP headers + * (http://tools.ietf.org/html/rfc7230#section-3.2). In this case the method returns a `ParsingResult.Error`. + */ + def parse(name: String, value: String, settings: HeaderParser.Settings = HeaderParser.DefaultSettings): ParsingResult = + if (name.forall(c => CharacterClasses.tchar(c))) { + import akka.parboiled2.Parser.DeliveryScheme.Try + /*val parser = new HeaderParser(value, settings) + parser.`header-field-value`.run() match { + case Success(preProcessedValue) => + HeaderParser.parseFull(name.toLowerCase, preProcessedValue, settings) match { + case HeaderParser.Success(header) => ParsingResult.Ok(header, Nil) + case HeaderParser.Failure(info) => + val errors = info.withSummaryPrepended(s"Illegal HTTP header '$name'") :: Nil + ParsingResult.Ok(RawHeader(name, preProcessedValue), errors) + case HeaderParser.RuleNotFound => ParsingResult.Ok(RawHeader(name, preProcessedValue), Nil) + } + case Failure(error) => + val info = (error match { + case e: ParseError => parser.parseError(e) + case e => parser.failure(e) + }).info + ParsingResult.Error(info.withSummaryPrepended(s"Illegal HTTP header value")) + }*/ ??? + } else ParsingResult.Error(ErrorInfo(s"Illegal HTTP header name", name)) + + /** INTERNAL API */ + @InternalApi + private[akka] def fastFind[T >: Null <: jm.HttpHeader](clazz: Class[T], headers: immutable.Seq[HttpHeader]): OptionVal[T] = { + val it = headers.iterator + while (it.hasNext) it.next() match { + case h if clazz.isInstance(h) => return OptionVal.Some[T](h.asInstanceOf[T]) + case _ => // continue ... + } + OptionVal.None + } + + sealed trait ParsingResult { + def errors: List[ErrorInfo] + } + + object ParsingResult { + /** + * The parsing run produced a result. If there were parsing errors (which did not prevent the run from + * completing) they are reported in the given error list. + */ + final case class Ok(header: HttpHeader, errors: List[ErrorInfo]) extends ParsingResult + + /** + * The parsing run failed due to a fatal parsing error. + */ + final case class Error(error: ErrorInfo) extends ParsingResult { def errors = error :: Nil } + } +} diff --git a/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala b/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala new file mode 100644 index 00000000000..6720dfa7d66 --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala @@ -0,0 +1,39 @@ +/* + * Copyright (C) 2009-2021 Lightbend Inc. + */ + +package akka.http.scaladsl.model.headers + +import scala.collection.immutable +import scala.util.{ Failure, Success } +import akka.parboiled2.ParseError +import akka.http.javadsl.{ model => jm } +import akka.http.impl.model.parser.HeaderParser +import akka.http.impl.util._ + +final case class ProductVersion(product: String = "", version: String = "", comment: String = "") extends jm.headers.ProductVersion with ValueRenderable { + def render[R <: Rendering](r: R): r.type = { + r ~~ product + if (!version.isEmpty) r ~~ '/' ~~ version + if (!comment.isEmpty) { + if (!product.isEmpty || !version.isEmpty) r ~~ ' ' + r ~~ '(' ~~ comment ~~ ')' + } + r + } +} + +object ProductVersion { + implicit val productsRenderer: Renderer[immutable.Seq[ProductVersion]] = Renderer.seqRenderer[ProductVersion](separator = " ") + + /** parses a string of multiple ProductVersions */ + def parseMultiple(string: String): immutable.Seq[ProductVersion] = ??? /*{ + val parser = new HeaderParser(string) + def fail(msg: String) = throw new IllegalArgumentException(s"'$string' is not a legal sequence of ProductVersions: $msg") + parser.products.run() match { + case Success(x) => immutable.Seq(x: _*) + case Failure(e: ParseError) => fail(parser.formatError(e)) + case Failure(e) => fail(e.getMessage) + } + }*/ +} From 56bb381e83481937d80766d7d66969b6d50dfe65 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 14:57:45 +0100 Subject: [PATCH 18/51] core: make a subset of parsers compile (Scala 3) --- .../impl/model/parser/Base64Parsing.scala | 90 ++++ .../http/impl/model/parser/CommonRules.scala | 475 ++++++++++++++++++ .../http/impl/model/parser/HeaderParser.scala | 230 +++++++++ .../impl/model/parser/StringBuilding.scala | 68 +++ .../http/impl/model/parser/UriParser.scala | 254 ++++++++++ 5 files changed, 1117 insertions(+) create mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala create mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala create mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala create mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala create mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala new file mode 100644 index 00000000000..ae1f9ecaf9c --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala @@ -0,0 +1,90 @@ +/* + * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * + * 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 + * + * http://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 akka.http.impl.model.parser + +import akka.annotation.InternalApi +import akka.parboiled2.util.Base64 +import akka.parboiled2._ + +/** + * INTERNAL API + * + * Rules for parsing Base-64 encoded strings. + */ +@InternalApi +private[parser] trait Base64Parsing { this: Parser => + import Base64Parsing._ + + /** + * Parses an RFC4045-encoded string and decodes it onto the value stack. + */ + def rfc2045String: Rule1[Array[Byte]] = base64StringOrBlock(rfc2045Alphabet, rfc2045StringDecoder) + + /** + * Parses an RFC4045-encoded string potentially containing newlines and decodes it onto the value stack. + */ + def rfc2045Block: Rule1[Array[Byte]] = base64StringOrBlock(rfc2045Alphabet, rfc2045BlockDecoder) + + /** + * Parses a akka.parboiled2.util.Base64.custom()-encoded string and decodes it onto the value stack. + */ + def base64CustomString: Rule1[Array[Byte]] = base64StringOrBlock(customAlphabet, customStringDecoder) + + /** + * Parses a akka.parboiled2.util.Base64.custom()-encoded string potentially containing newlines + * and decodes it onto the value stack. + */ + def base64CustomBlock: Rule1[Array[Byte]] = base64StringOrBlock(customAlphabet, customBlockDecoder) + + /** + * Parses a BASE64-encoded string with the given alphabet and decodes it onto the value + * stack using the given codec. + */ + def base64StringOrBlock(alphabet: CharPredicate, decoder: Decoder): Rule1[Array[Byte]] = { + val start = cursor + rule { + oneOrMore(alphabet) ~ run { + decoder(input.sliceCharArray(start, cursor)) match { + case null => MISMATCH + case bytes => push(bytes) + } + } + } + } +} + +/** INTERNAL API */ +@InternalApi +private[http] object Base64Parsing { + type Decoder = Array[Char] => Array[Byte] + + val rfc2045Alphabet = CharPredicate(Base64.rfc2045().getAlphabet).asMaskBased + val customAlphabet = CharPredicate(Base64.custom().getAlphabet).asMaskBased + + val rfc2045StringDecoder: Decoder = decodeString(Base64.rfc2045()) + val customStringDecoder: Decoder = decodeString(Base64.custom()) + + val rfc2045BlockDecoder: Decoder = decodeBlock(Base64.rfc2045()) + val customBlockDecoder: Decoder = decodeBlock(Base64.custom()) + + private val base64url = new Base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=") + /** as described in RFC4648 5. - https://tools.ietf.org/html/rfc4648#section-5 */ + val base64UrlStringDecoder: Decoder = decodeString(base64url) + + def decodeString(codec: Base64)(chars: Array[Char]): Array[Byte] = codec.decodeFast(chars) + def decodeBlock(codec: Base64)(chars: Array[Char]): Array[Byte] = codec.decode(chars) +} diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala new file mode 100644 index 00000000000..64fd5f728c2 --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala @@ -0,0 +1,475 @@ +/* + * Copyright (C) 2009-2021 Lightbend Inc. + */ + +package akka.http.impl.model.parser + +import scala.collection.immutable +import scala.collection.immutable.TreeMap + +import akka.http.scaladsl.model._ +import akka.http.scaladsl.model.headers._ +import akka.parboiled2._ +import akka.parboiled2.support.hlist._ + +private[parser] trait CommonRules { this: Parser with StringBuilding => + import CharacterClasses._ + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7230#section-1.2 referencing + // http://tools.ietf.org/html/rfc5234#appendix-B.1 + // ****************************************************************************************** + def CRLF = rule { CR ~ LF } + + def OCTET = rule { ANY } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7230#section-3.2.3 + // ****************************************************************************************** + + def OWS = rule { zeroOrMore(optional(CRLF) ~ oneOrMore(WSP)) } // extended with `obs-fold` + + def RWS = rule { oneOrMore(optional(CRLF) ~ oneOrMore(WSP)) } // extended with `obs-fold` + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7230#section-3.2.6 + // ****************************************************************************************** + def word = rule { token | `quoted-string` } + + def token: Rule1[String] = rule { capture(token0) ~ OWS } + + def `quoted-string`: Rule1[String] = rule { + DQUOTE ~ clearSB() ~ zeroOrMore(qdtext ~ appendSB() | `quoted-pair`) ~ push(sb.toString) ~ DQUOTE ~ OWS + } + + def qdtext = rule { `qdtext-base` | `obs-text` } + + def `obs-text` = rule { "\u0080" - "\uFFFE" } + + def `quoted-pair` = rule { '\\' ~ (`quotable-base` | `obs-text`) ~ appendSB() } + + // builds a string via the StringBuilding StringBuilder + def comment(maxNesting: Int = 10): Rule0 = rule { + ws('(') ~ clearSB() ~ zeroOrMore(ctext | `quoted-cpair` | `nested-comment`(maxNesting)) ~ ws(')') + } + + def `nested-comment`(maxNesting: Int) = + if (maxNesting == 0) throw new ParsingException(ErrorInfo("Illegal header value", "Header comment nested too deeply")) + else { + var saved: String = null + rule { &('(') ~ run { saved = sb.toString } ~ (comment(maxNesting - 1) ~ prependSB(saved + " (") ~ appendSB(')') | setSB(saved) ~ test(false)) } + } + + def ctext = rule { (`ctext-base` | `obs-text`) ~ appendSB() } + + def `quoted-cpair` = `quoted-pair` + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7234#section-5.3 + // ****************************************************************************************** + + def `expires-date`: Rule1[DateTime] = ??? /*rule { + (`HTTP-date` | zeroOrMore(ANY) ~ push(DateTime.MinValue)) ~ OWS + }*/ + /* + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7231#section-7.1.1.1 + // but more lenient where we have already seen differing implementations in the field + // ****************************************************************************************** + + def `HTTP-date`: Rule1[DateTime] = rule { + (`IMF-fixdate` | `asctime-date` | '0' ~ push(DateTime.MinValue)) ~ OWS + } + + def `IMF-fixdate` = rule { // mixture of the spec-ed `IMF-fixdate` and `rfc850-date` + (`day-name-l` | `day-name`) ~ ", " ~ (date1 | date2) ~ ' ' ~ `time-of-day` ~ ' ' ~ ("GMT" | "UTC") ~> { + (wkday, day, month, year, hour, min, sec) => createDateTime(year, month, day, hour, min, sec, wkday) + } + } + + def `day-name` = rule( + "Sun" ~ push(0) | "Mon" ~ push(1) | "Tue" ~ push(2) | "Wed" ~ push(3) | "Thu" ~ push(4) | "Fri" ~ push(5) | "Sat" ~ push(6)) + + def date1 = rule { day ~ `date-sep` ~ month ~ `date-sep` ~ year } + + def day = rule { digit2 | digit } + + def month = rule( + "Jan" ~ push(1) | "Feb" ~ push(2) | "Mar" ~ push(3) | "Apr" ~ push(4) | "May" ~ push(5) | "Jun" ~ push(6) | "Jul" ~ push(7) | + "Aug" ~ push(8) | "Sep" ~ push(9) | "Oct" ~ push(10) | "Nov" ~ push(11) | "Dec" ~ push(12)) + + def year = rule { digit4 | digit2 ~> (y => if (y <= 69) y + 2000 else y + 1900) } + + def `time-of-day` = rule { hour ~ ':' ~ minute ~ ':' ~ second } + def hour = rule { digit2 } + def minute = rule { digit2 } + def second = rule { digit2 } + + // def `obs-date` = rule { `rfc850-date` | `asctime-date` } + + // def `rfc850-date` = rule { `day-name-l` ~ ", " ~ date2 ~ ' ' ~ `time-of-day` ~ " GMT" } + + // per #17714, parse two digit year to https://tools.ietf.org/html/rfc6265#section-5.1.1 + def date2 = rule { day ~ '-' ~ month ~ '-' ~ (digit2 ~> (y => if (y <= 69) y + 2000 else y + 1900)) } + + def `day-name-l` = rule( + "Sunday" ~ push(0) | "Monday" ~ push(1) | "Tuesday" ~ push(2) | "Wednesday" ~ push(3) | "Thursday" ~ push(4) | + "Friday" ~ push(5) | "Saturday" ~ push(6)) + + def `asctime-date` = rule { + `day-name` ~ ' ' ~ date3 ~ ' ' ~ `time-of-day` ~ ' ' ~ year ~> { + (wkday, month, day, hour, min, sec, year) => createDateTime(year, month, day, hour, min, sec, wkday) + } + } + + def date3 = rule { month ~ ' ' ~ (digit2 | ' ' ~ digit) } +*/ + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7231#section-5.3.1 + // ****************************************************************************************** + + def weight = rule { ws(';') ~ ws('q') ~ ws('=') ~ qvalue } // a bit more lenient than the spec + + def qvalue = rule { // a bit more lenient than the spec + capture('0' ~ optional('.' ~ zeroOrMore(DIGIT)) + | '.' ~ oneOrMore(DIGIT) + | '1' ~ optional('.' ~ zeroOrMore('0'))) ~> (_.toFloat) ~ OWS + } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7231#section-3.1.1.1 + // ****************************************************************************************** + + def `media-type`: RuleN[String :: String :: Seq[(String, String)] :: HNil] = rule { + `type` ~ '/' ~ subtype ~ zeroOrMore(ws(';') ~ parameter) + } + + def `type` = rule { token } + + def subtype = rule { token } + + def parameter = rule { attribute ~ ws('=') ~ value ~> ((_, _)) } + + def attribute = rule { token } + + def value = rule { word } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc4647#section-2.1 + // ****************************************************************************************** + def language = rule { + `primary-tag` ~ zeroOrMore('-' ~ `sub-tag`) ~> (Language(_, _)) + } + + def `primary-tag` = rule { capture(oneOrMore(ALPHA)) ~ OWS } + + def `sub-tag` = rule { capture(oneOrMore(ALPHANUM)) ~ OWS } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc4647#section-2.1 + // ****************************************************************************************** + + def `auth-scheme` = rule { token } + + def `auth-param` = rule { token ~ ws('=') ~ word } + + def `token68` = rule { capture(oneOrMore(`token68-start`) ~ zeroOrMore('=')) ~ OWS } + + def challenge = rule { + `challenge-or-credentials` ~> { (scheme, tokenAndParams) => + tokenAndParams match { + case ("", Nil) => HttpChallenge(scheme, None) + case (token, Nil) => HttpChallenge(scheme, None, Map("" -> token)) + case (_, params) => { + val (realms, otherParams) = params.partition(_._1 equalsIgnoreCase "realm") + HttpChallenge(scheme, realms.headOption.map(_._2), TreeMap(otherParams: _*)) + } + } + } + } + + def `challenge-or-credentials`: Rule2[String, (String, Seq[(String, String)])] = rule { + `auth-scheme` ~ ( + oneOrMore(`auth-param` ~> (_ -> _)).separatedBy(listSep) ~> (x => ("", x)) + | `token68` ~> (x => (x, Nil)) + | push(("", Nil))) + } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7234#section-1.2.1 + // ****************************************************************************************** + + def `delta-seconds` = rule { longNumberCappedAtIntMaxValue } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7232#section-2.3 + // ****************************************************************************************** + + def `entity-tag` = rule { + ("W/" ~ push(true) | push(false)) ~ `opaque-tag` ~> ((weak, tag) => EntityTag(tag, weak)) + } + + def `opaque-tag` = rule { '"' ~ capture(zeroOrMore(`etagc-base` | `obs-text`)) ~ '"' } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7235#section-2.1 + // ****************************************************************************************** + def credentials = rule { + `basic-credential-def` | `oauth2-bearer-token` | `generic-credentials` + } + + def `basic-credential-def` = rule { + ignoreCase("basic") ~ OWS ~ `basic-cookie` ~> (BasicHttpCredentials(_)) + } + + def `basic-cookie` = rule { `token68` } + + // http://tools.ietf.org/html/rfc6750#section-2.1 + def `oauth2-bearer-token` = rule { + ignoreCase("bearer") ~ OWS ~ `token68` ~> (OAuth2BearerToken(_)) + } + + def `generic-credentials` = rule { + `challenge-or-credentials` ~> ((scheme, tokenAndParams) => { + val (token, params) = tokenAndParams + GenericHttpCredentials(scheme, token, TreeMap(params: _*)) + }) + } + + /** + * Either `Some(cookiePair)` if the cookie pair is parsable using the giving cookie parsing mode + * or None, otherwise. + */ + def `optional-cookie-pair`: Rule1[Option[HttpCookiePair]] = rule { + (`cookie-pair` ~ &(`cookie-separator`) ~> (Some(_: HttpCookiePair))) | + // fallback that parses and discards everything until the next semicolon + (zeroOrMore(!`cookie-separator` ~ ANY) ~ &(`cookie-separator`) ~ push(None)) + } + + def `cookie-pair`: Rule1[HttpCookiePair] = rule { + `cookie-name` ~ ws('=') ~ `cookie-value` ~> (createCookiePair _) + } + + def `cookie-name` = rule { token } + + // abstract methods need to be implemented depending on actual cookie parsing mode + def `cookie-value`: Rule1[String] + def createCookiePair(name: String, value: String): HttpCookiePair + + // ****************************************************************************************** + // https://tools.ietf.org/html/rfc6265#section-4.1.1 + // ****************************************************************************************** + def `cookie-value-rfc-6265` = rule { + ('"' ~ capture(zeroOrMore(`cookie-octet-rfc-6265`)) ~ '"' | capture(zeroOrMore(`cookie-octet-rfc-6265`))) ~ OWS + } + + def `cookie-value-raw` = rule { + capture(zeroOrMore(`cookie-octet-raw`)) ~ OWS + } + + def `cookie-av` = rule { + `expires-av` | `max-age-av` | `domain-av` | `path-av` | `same-site-av` | `secure-av` | `httponly-av` | `extension-av` + } + + def `expires-av` = rule { + ignoreCase("expires=") ~ OWS ~ `expires-date` ~> { (c: HttpCookie, dt: DateTime) => c.withExpires(dt) } + } + + def `max-age-av` = rule { + ignoreCase("max-age=") ~ OWS ~ longNumberCappedAtIntMaxValue ~> { (c: HttpCookie, seconds: Long) => c.withMaxAge(seconds) } + } + + def `domain-av` = rule { + ignoreCase("domain=") ~ OWS ~ `domain-value` ~> { (c: HttpCookie, domainName: String) => c.withDomain(domainName) } + } + + // https://tools.ietf.org/html/rfc1034#section-3.5 relaxed by https://tools.ietf.org/html/rfc1123#section-2 + // to also allow digits at the start of a label + def `domain-value` = rule { + optional('.') ~ capture(oneOrMore(oneOrMore(oneOrMore(ALPHANUM)).separatedBy('-')).separatedBy('.')) ~ OWS + } + + def `path-av` = rule { + ignoreCase("path=") ~ OWS ~ `path-value` ~> { (c: HttpCookie, pathValue: String) => c.withPath(pathValue) } + } + + // http://www.rfc-editor.org/errata_search.php?rfc=6265 + def `path-value` = rule { + capture(zeroOrMore(`av-octet`)) ~ OWS + } + + def `same-site-av` = rule { + ignoreCase("samesite=") ~ OWS ~ `same-site-value` ~> { (c: HttpCookie, sameSiteValue: String) => c.withSameSite(sameSite = SameSite(sameSiteValue)) } + } + + def `same-site-value` = rule { + capture(ignoreCase("lax") | ignoreCase("strict") | ignoreCase("none")) ~ OWS + } + + def `secure-av` = rule { + ignoreCase("secure") ~ OWS ~> { (cookie: HttpCookie) => cookie.withSecure(true) } + } + + def `httponly-av` = rule { + ignoreCase("httponly") ~ OWS ~> { (cookie: HttpCookie) => cookie.withHttpOnly(true) } + } + + // http://www.rfc-editor.org/errata_search.php?rfc=6265 + def `extension-av` = rule { + !(ignoreCase("expires=") + | ignoreCase("max-age=") + | ignoreCase("domain=") + | ignoreCase("path=") + | ignoreCase("samesite=") + | ignoreCase("secure") + | ignoreCase("httponly")) ~ + capture(zeroOrMore(`av-octet`)) ~ OWS ~> { (c: HttpCookie, s: String) => c.withExtension(s) } + } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc6454#section-7.1 + // ****************************************************************************************** + def `origin-list-or-null` = rule { + "null" ~ OWS ~ push(immutable.Seq.empty[HttpOrigin]) | `origin-list` + } + + def `origin-list` = rule { + oneOrMore(capture(oneOrMore(VCHAR)) ~> (HttpOrigin(_))).separatedBy(SP) ~ OWS // offload to URL parser + } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7233#appendix-D + // ****************************************************************************************** + + def `byte-content-range` = rule { `bytes-unit` ~ (`byte-range-resp` | `unsatisfied-range`) } + + def `byte-range` = rule { + `first-byte-pos` ~ ws('-') ~ `last-byte-pos` + } + + def `byte-range-resp` = rule { + `byte-range` ~ ws('/') ~ (`complete-length` ~> (Some(_)) | ws('*') ~ push(None)) ~> (ContentRange(_, _, _)) + } + + def `byte-range-set` = rule { + zeroOrMore(ws(',')) ~ oneOrMore(`byte-range-spec` | `suffix-byte-range-spec`).separatedBy(listSep) + } + + def `byte-range-spec` = rule { + `first-byte-pos` ~ ws('-') ~ (`last-byte-pos` ~> (ByteRange(_: Long, _)) | run(ByteRange.fromOffset(_))) + } + + def `byte-ranges-specifier` = rule { `bytes-unit` ~ ws('=') ~ `byte-range-set` } + + def `bytes-unit` = rule { "bytes" ~ OWS ~ push(RangeUnits.Bytes) } + + def `complete-length` = rule { longNumberCapped } + + def `first-byte-pos` = rule { longNumberCapped } + + def `last-byte-pos` = rule { longNumberCapped } + + def `other-content-range` = rule { `other-range-unit` ~ `other-range-resp` } + + def `other-range-resp` = rule { capture(zeroOrMore(ANY)) ~> (ContentRange.Other(_)) } + + def `other-range-set` = rule { oneOrMore(VCHAR) ~ OWS } + + def `other-range-unit` = rule { token ~> (RangeUnits.Other(_)) } + + def `other-ranges-specifier` = rule { `other-range-unit` ~ ws('=') ~ `other-range-set` } + + def `range-unit` = rule { `bytes-unit` | `other-range-unit` } + + def `suffix-byte-range-spec` = rule { '-' ~ `suffix-length` ~> (ByteRange.suffix(_)) } + + def `suffix-length` = rule { longNumberCapped } + + def `unsatisfied-range` = rule { '*' ~ '/' ~ `complete-length` ~> (ContentRange.Unsatisfiable(_)) } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7231#section-5.5.3 + // ****************************************************************************************** + + def product = rule { token ~ (ws('/') ~ `product-version` | push("")) } + + def `product-version` = rule { token } + + def `product-or-comment`: Rule1[ProductVersion] = rule( + product ~ comment() ~> (ProductVersion(_, _, sb.toString)) + | product ~> (ProductVersion(_, _)) + | comment() ~ push(ProductVersion("", "", sb.toString))) + + def products: Rule1[Seq[ProductVersion]] = rule { + `product-or-comment` ~ zeroOrMore(`product-or-comment`) ~> (_ +: _) + } + + // ****************************************************************************************** + // http://tools.ietf.org/html/rfc7230#section-4 + // ****************************************************************************************** + + def `transfer-coding`: Rule1[TransferEncoding] = rule( + ignoreCase("chunked") ~ OWS ~ push(TransferEncodings.chunked) + | ignoreCase("gzip") ~ OWS ~ push(TransferEncodings.gzip) + | ignoreCase("deflate") ~ OWS ~ push(TransferEncodings.deflate) + | ignoreCase("compress") ~ OWS ~ push(TransferEncodings.compress) + | ignoreCase("trailers") ~ OWS ~ push(TransferEncodings.trailers) + | `transfer-extension`) + + def `transfer-extension`: Rule1[TransferEncodings.Extension] = rule { + token ~ zeroOrMore(ws(';') ~ `transfer-parameter`) ~> (p => TreeMap(p: _*)) ~> (TransferEncodings.Extension(_, _)) + } + + def `transfer-parameter` = rule { token ~ ws('=') ~ word ~> (_ -> _) } + + // ****************************************************************************************** + // helpers + // ****************************************************************************************** + def token0: Rule0 = rule { oneOrMore(tchar) } + + def listSep: Rule0 = rule { ',' ~ OWS } + + def digit: Rule1[Int] = rule { DIGIT ~ push(digitInt(lastChar)) } + + def digit2: Rule1[Int] = rule { DIGIT ~ DIGIT ~ push(digitInt(charAt(-2)) * 10 + digitInt(lastChar)) } + + def digit4: Rule1[Int] = rule { + DIGIT ~ DIGIT ~ DIGIT ~ DIGIT ~ push(digitInt(charAt(-4)) * 1000 + digitInt(charAt(-3)) * 100 + digitInt(charAt(-2)) * 10 + digitInt(lastChar)) + } + + def ws(c: Char): Rule0 = rule { c ~ OWS } + def ws(s: String): Rule0 = rule { s ~ OWS } + + // parses a potentially long series of digits and extracts its Long value capping at Int.MaxValue in case of overflows + def longNumberCappedAtIntMaxValue: Rule1[Long] = rule { + capture((1 to 11).times(DIGIT)) ~> (s => math.min(s.toLong, Int.MaxValue)) ~ zeroOrMore(DIGIT) ~ OWS + } + + // parses a potentially long series of digits and extracts its Long value capping at 999,999,999,999,999,999 in case of overflows + def longNumberCapped: Rule1[Long] = rule( + (capture((1 to 18).times(DIGIT)) ~ !DIGIT ~> (_.toLong) + | oneOrMore(DIGIT) ~ push(999999999999999999L)) ~ OWS) + + private def digitInt(c: Char): Int = c - '0' + + private def createDateTime(year: Int, month: Int, day: Int, hour: Int, min: Int, sec: Int, wkday: Int): DateTime = { + val dt = DateTime(year, month, day, hour, min, sec) + if (dt.weekday != wkday) + throw ParsingException(s"Illegal weekday in date $dt: is '${DateTime.weekday(wkday)}' but " + + s"should be '${DateTime.weekday(dt.weekday)}'") + dt + } + + def httpMethodDef: Rule1[HttpMethod] = rule { + token ~> { s => + HttpMethods.getForKey(s) match { + case Some(m) => m + case None => HttpMethod.custom(s) + } + } + } + + def newUriParser(input: ParserInput): UriParser + def uriReference: Rule1[Uri] = rule { runSubParser(newUriParser(_).`URI-reference-pushed`) } +} + diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala new file mode 100644 index 00000000000..af38548c4cb --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala @@ -0,0 +1,230 @@ +/* + * Copyright (C) 2009-2021 Lightbend Inc. + */ + +package akka.http.impl.model.parser + +import akka.annotation.InternalApi +import akka.http.scaladsl.settings.ParserSettings +import akka.http.scaladsl.settings.ParserSettings.CookieParsingMode +import akka.http.scaladsl.settings.ParserSettings.{ IllegalResponseHeaderValueProcessingMode, IllegalResponseHeaderNameProcessingMode } +import akka.http.scaladsl.model.headers.HttpCookiePair +import akka.util.ConstantFun + +import scala.util.control.NonFatal +import akka.http.impl.util.SingletonException +import akka.parboiled2._ +import akka.parboiled2.support.hlist._ +import akka.http.scaladsl.model._ + +/** + * INTERNAL API. + */ +//@InternalApi +//private[http] class HeaderParser( +// val input: ParserInput, +// settings: HeaderParser.Settings = HeaderParser.DefaultSettings) +// extends Parser with DynamicRuleHandler[HeaderParser, HttpHeader :: HNil] +// with CommonRules +// with AcceptCharsetHeader +// with AcceptEncodingHeader +// with AcceptHeader +// with AcceptLanguageHeader +// with CacheControlHeader +// with ContentDispositionHeader +// with ContentTypeHeader +// with CommonActions +// with IpAddressParsing +// with LinkHeader +// with SimpleHeaders +// with StringBuilding +// with WebSocketHeaders { +// import CharacterClasses._ +// +// override def customMediaTypes = settings.customMediaTypes +// protected def maxCommentParsingDepth: Int = settings.maxCommentParsingDepth +// +// // http://www.rfc-editor.org/errata_search.php?rfc=7230 errata id 4189 +// def `header-field-value`: Rule1[String] = rule { +// FWS ~ clearSB() ~ `field-value` ~ FWS ~ EOI ~ push(sb.toString) +// } +// def `field-value` = { +// var fwsStart = cursor +// rule { +// zeroOrMore(`field-value-chunk`).separatedBy { // zeroOrMore because we need to also accept empty values +// run { fwsStart = cursor } ~ FWS ~ &(`field-value-char`) ~ run { if (cursor > fwsStart) sb.append(' ') } +// } +// } +// } +// def `field-value-chunk` = rule { oneOrMore(`field-value-char` ~ appendSB()) } +// def `field-value-char` = rule { VCHAR | `obs-text` } +// def FWS = rule { zeroOrMore(WSP) ~ zeroOrMore(`obs-fold`) } +// def `obs-fold` = rule { CRLF ~ oneOrMore(WSP) } +// +// ///////////////// DynamicRuleHandler ////////////// +// +// override type Result = HeaderParser.Result +// def parser: HeaderParser = this +// def success(result: HttpHeader :: HNil): Result = HeaderParser.Success(result.head) +// def parseError(error: ParseError): HeaderParser.Failure = { +// val formatter = new ErrorFormatter(showLine = false) +// HeaderParser.Failure(ErrorInfo(formatter.format(error, input), formatter.formatErrorLine(error, input))) +// } +// def failure(error: Throwable): HeaderParser.Failure = +// HeaderParser.Failure { +// error match { +// case IllegalUriException(info) => info +// case NonFatal(e) => ErrorInfo.fromCompoundString(e.getMessage) +// } +// } +// def ruleNotFound(ruleName: String): Result = HeaderParser.RuleNotFound +// +// def newUriParser(input: ParserInput): UriParser = new UriParser(input, uriParsingMode = settings.uriParsingMode) +// +// def `cookie-value`: Rule1[String] = +// settings.cookieParsingMode match { +// case CookieParsingMode.RFC6265 => rule { `cookie-value-rfc-6265` } +// case CookieParsingMode.Raw => rule { `cookie-value-raw` } +// } +// +// def createCookiePair(name: String, value: String): HttpCookiePair = settings.cookieParsingMode match { +// case CookieParsingMode.RFC6265 => HttpCookiePair(name, value) +// case CookieParsingMode.Raw => HttpCookiePair.raw(name, value) +// } +//} + +/** + * INTERNAL API. + */ +@InternalApi +private[http] object HeaderParser { + sealed trait Result + case class Success(header: HttpHeader) extends Result + case class Failure(info: ErrorInfo) extends Result + case object RuleNotFound extends Result + + object EmptyCookieException extends SingletonException("Cookie header contained no parsable cookie values.") + + def lookupParser(headerName: String, settings: Settings = DefaultSettings): Option[String => HeaderParser.Result] = + ??? + // dispatch.lookup(headerName).map { runner => (value: String) => + // import akka.parboiled2.EOI + // val v = value + EOI // this makes sure the parser isn't broken even if there's no trailing garbage in this value + // val parser = new HeaderParser(v, settings) + // runner(parser) match { + // case r @ Success(_) if parser.cursor == v.length => r + // case r @ Success(_) => + // Failure(ErrorInfo( + // "Header parsing error", + // s"Rule for $headerName accepted trailing garbage. Is the parser missing a trailing EOI?")) + // case Failure(e) => Failure(e.copy(summary = e.summary.filterNot(_ == EOI), detail = e.detail.filterNot(_ == EOI))) + // case RuleNotFound => RuleNotFound + // } + // } + + def parseFull(headerName: String, value: String, settings: Settings = DefaultSettings): HeaderParser.Result = + lookupParser(headerName, settings).map(_(value)).getOrElse(HeaderParser.RuleNotFound) + + def ruleNames: Seq[String] = ??? + // val (dispatch, ruleNames) = DynamicRuleDispatch[HeaderParser, HttpHeader :: HNil]( + // "accept", + // "accept-charset", + // "accept-encoding", + // "accept-language", + // "accept-ranges", + // "access-control-allow-credentials", + // "access-control-allow-headers", + // "access-control-allow-methods", + // "access-control-allow-origin", + // "access-control-expose-headers", + // "access-control-max-age", + // "access-control-request-headers", + // "access-control-request-method", + // "accept", + // "age", + // "allow", + // "authorization", + // "cache-control", + // "connection", + // "content-disposition", + // "content-encoding", + // "content-length", + // "content-location", + // "content-range", + // "content-type", + // "cookie", + // "date", + // "etag", + // "expect", + // "expires", + // "host", + // "if-match", + // "if-modified-since", + // "if-none-match", + // "if-range", + // "if-unmodified-since", + // "last-modified", + // "link", + // "location", + // "origin", + // "proxy-authenticate", + // "proxy-authorization", + // "range", + // "referer", + // "retry-after", + // "server", + // "sec-websocket-accept", + // "sec-websocket-extensions", + // "sec-websocket-key", + // "sec-websocket-protocol", + // "sec-websocket-version", + // "set-cookie", + // "strict-transport-security", + // "te", + // "transfer-encoding", + // "upgrade", + // "user-agent", + // "www-authenticate", + // "x-forwarded-for", + // "x-forwarded-host", + // "x-forwarded-proto", + // "x-real-ip") + + abstract class Settings { + def uriParsingMode: Uri.ParsingMode + def cookieParsingMode: ParserSettings.CookieParsingMode + def customMediaTypes: MediaTypes.FindCustom + def maxCommentParsingDepth: Int + def illegalResponseHeaderNameProcessingMode: IllegalResponseHeaderNameProcessingMode + def illegalResponseHeaderValueProcessingMode: IllegalResponseHeaderValueProcessingMode + } + def Settings( + uriParsingMode: Uri.ParsingMode = Uri.ParsingMode.Relaxed, + cookieParsingMode: ParserSettings.CookieParsingMode = ParserSettings.CookieParsingMode.RFC6265, + customMediaTypes: MediaTypes.FindCustom = ConstantFun.scalaAnyTwoToNone, + maxCommentParsingDepth: Int = 5, + modeValue: IllegalResponseHeaderValueProcessingMode = ParserSettings.IllegalResponseHeaderValueProcessingMode.Error, + modeName: IllegalResponseHeaderNameProcessingMode = ParserSettings.IllegalResponseHeaderNameProcessingMode.Error): Settings = { + + val _uriParsingMode = uriParsingMode + val _cookieParsingMode = cookieParsingMode + val _customMediaTypes = customMediaTypes + val _maxCommentParsingDepth = maxCommentParsingDepth + val _illegalResponseHeaderValueProcessingMode = modeValue + val _illegalResponseHeaderNameProcessingMode = modeName + + new Settings { + def uriParsingMode: Uri.ParsingMode = _uriParsingMode + def cookieParsingMode: CookieParsingMode = _cookieParsingMode + def customMediaTypes: MediaTypes.FindCustom = _customMediaTypes + def maxCommentParsingDepth: Int = _maxCommentParsingDepth + + def illegalResponseHeaderValueProcessingMode: IllegalResponseHeaderValueProcessingMode = + _illegalResponseHeaderValueProcessingMode + + def illegalResponseHeaderNameProcessingMode: IllegalResponseHeaderNameProcessingMode = + _illegalResponseHeaderNameProcessingMode + } + } + val DefaultSettings: Settings = Settings() +} diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala new file mode 100644 index 00000000000..3e95c2a99af --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala @@ -0,0 +1,68 @@ +/* + * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev + * + * 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 + * + * http://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 akka.http.impl.model.parser + +import akka.parboiled2._ + +/** + * For certain high-performance use-cases it is better to construct Strings + * that the parser is to produce/extract from the input in a char-by-char fashion. + * + * Mixing this trait into your parser gives you a simple facility to support this. + */ +private[parser] trait StringBuilding { this: Parser => + protected val sb = new java.lang.StringBuilder + + def clearSB(): Rule0 = rule { run(sb.setLength(0)) } + + def appendSB(): Rule0 = rule { run(sb.append(lastChar)) } + + def appendSB(offset: Int): Rule0 = rule { run(sb.append(charAt(offset))) } + + def appendSB(c: Char): Rule0 = rule { run(sb.append(c)) } + + def appendSB(s: String): Rule0 = rule { run(sb.append(s)) } + + def prependSB(): Rule0 = rule { run(doPrepend(lastChar)) } + + def prependSB(offset: Int): Rule0 = rule { run(doPrepend(charAt(offset))) } + + def prependSB(c: Char): Rule0 = rule { run(doPrepend(c)) } + + def prependSB(s: String): Rule0 = rule { run(doPrepend(s)) } + + def setSB(s: String): Rule0 = rule { run(doSet(s)) } + + private def doPrepend(c: Char): Unit = { + val saved = sb.toString + sb.setLength(0) + sb.append(c) + sb.append(saved) + } + + private def doPrepend(s: String): Unit = { + val saved = sb.toString + sb.setLength(0) + sb.append(s) + sb.append(saved) + } + + private def doSet(s: String): Unit = { + sb.setLength(0) + sb.append(s) + } +} diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala new file mode 100644 index 00000000000..5d237afc903 --- /dev/null +++ b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala @@ -0,0 +1,254 @@ +/* + * Copyright (C) 2009-2021 Lightbend Inc. + */ + +package akka.http.impl.model.parser + +import java.nio.charset.Charset + +import akka.parboiled2._ +import akka.http.impl.util.{ StringRendering, enhanceString_ } +import akka.http.scaladsl.model.{ Uri, UriRendering } +import akka.http.scaladsl.model.headers.HttpOrigin +import Parser.DeliveryScheme.Either +import Uri._ +import akka.annotation.InternalApi + +/** + * INTERNAL API + * + * http://tools.ietf.org/html/rfc3986 + */ +@InternalApi +private[http] final class UriParser( + private[this] var _input: ParserInput, + val uriParsingCharset: Charset, + val uriParsingMode: Uri.ParsingMode, + val maxValueStackSize: Int) extends Parser(maxValueStackSize = maxValueStackSize) /*with IpAddressParsing with StringBuilding*/ { + import CharacterClasses._ + + override def input: ParserInput = _input + + def this( + input: ParserInput, + uriParsingCharset: Charset = UTF8, + uriParsingMode: Uri.ParsingMode = Uri.ParsingMode.Relaxed) = + this(input, uriParsingCharset, uriParsingMode, 1024) + + def parseAbsoluteUri(): Uri = ??? + + def parseUriReference(): Uri = ??? + + def parseAndResolveUriReference(base: Uri): Uri = ??? + + def parseOrigin(): HttpOrigin = ??? + + def parseHost(): Host = ??? + + /** + * @return a 'raw' (percent-encoded) query string that does not contain invalid characters. + */ + def parseRawQueryString(): String = ??? + + /** + * @param rawQueryString 'raw' (percent-encoded) query string that in Relaxed mode may contain characters not allowed + * by https://tools.ietf.org/html/rfc3986#section-3.4 but is guaranteed not to have invalid percent-encoded characters + * @return a 'raw' (percent-encoded) query string that does not contain invalid characters. + */ + def parseSafeRawQueryString(rawQueryString: String): String = uriParsingMode match { + case Uri.ParsingMode.Strict => + // Cannot contain invalid characters in strict mode + rawQueryString + case Uri.ParsingMode.Relaxed => + // Percent-encode invalid characters + UriRendering.encode(new StringRendering, rawQueryString, uriParsingCharset, `query-fragment-char` ++ '%', false).get + } + + def parseQuery(): Query = ??? + + def parseAuthority(): Authority = ??? + /*rule(authority ~ EOI).run() match { + case Right(_) => Authority(_host, _port, _userinfo) + case Left(error) => fail(error, "authority") + }*/ + + // def fail(error: ParseError, target: String): Nothing = { + // val formatter = new ErrorFormatter(showLine = false) + // Uri.fail(s"Illegal $target: " + formatter.format(error, input), formatter.formatErrorLine(error, input)) + // } + // + // private[this] val `path-segment-char` = uriParsingMode match { + // case Uri.ParsingMode.Strict => `pchar-base` + // case _ => `relaxed-path-segment-char` + // } + // private[this] val `query-char` = uriParsingMode match { + // case Uri.ParsingMode.Strict => `query-fragment-char` + // case _ => `relaxed-query-char` + // } + // private[this] val `query-key-char` = uriParsingMode match { + // case Uri.ParsingMode.Strict => `strict-query-key-char` + // case Uri.ParsingMode.Relaxed => `relaxed-query-key-char` + // } + // private[this] val `query-value-char` = uriParsingMode match { + // case Uri.ParsingMode.Strict => `strict-query-value-char` + // case Uri.ParsingMode.Relaxed => `relaxed-query-value-char` + // } + // private[this] val `fragment-char` = uriParsingMode match { + // case Uri.ParsingMode.Strict => `query-fragment-char` + // case _ => `relaxed-fragment-char` + // } + // + // // New vars need to be reset in `reset` below + // private[this] var _scheme = "" + // private[this] var _userinfo = "" + // private[this] var _host: Host = Host.Empty + // private[this] var _port: Int = 0 + // private[this] var _path: Path = Path.Empty + // /** + // * Percent-encoded. When in in 'relaxed' mode, characters not permitted by https://tools.ietf.org/html/rfc3986#section-3.4 + // * are already automatically percent-encoded here + // */ + // private[this] var _rawQueryString: Option[String] = None + // private[this] var _fragment: Option[String] = None + // + // /** Allows to reuse this parser. */ + // def reset(newInput: ParserInput): Unit = { + // _input = newInput + // _scheme = "" + // _userinfo = "" + // _host = Host.Empty + // _port = 0 + // _path = Path.Empty + // _rawQueryString = None + // _fragment = None + // _firstPercentIx = -1 + // } + // + // private[this] def setScheme(scheme: String): Unit = _scheme = scheme + // private[this] def setUserInfo(userinfo: String): Unit = _userinfo = userinfo + // private[this] def setHost(host: Host): Unit = _host = host + // private[this] def setPort(port: Int): Unit = _port = port + // private[this] def setPath(path: Path): Unit = _path = path + // private[this] def setRawQueryString(rawQueryString: String): Unit = _rawQueryString = Some(parseSafeRawQueryString(rawQueryString)) + // private[this] def setFragment(fragment: String): Unit = _fragment = Some(fragment) + // + // // http://tools.ietf.org/html/rfc3986#appendix-A + // + // def URI = rule { scheme ~ ':' ~ `hier-part` ~ optional('?' ~ rawQueryString) ~ optional('#' ~ fragment) } + // + // def origin = rule { scheme ~ ':' ~ '/' ~ '/' ~ hostAndPort } + // + // def `hier-part` = rule( + // '/' ~ '/' ~ authority ~ `path-abempty` + // | `path-absolute` + // | `path-rootless` + // | `path-empty`) + // + // def `URI-reference` = rule { URI | `relative-ref` } + // + def `URI-reference-pushed`: Rule1[Uri] = ??? // rule { `URI-reference` ~ push(createUriReference()) } + // + // def `absolute-URI` = rule { scheme ~ ':' ~ `hier-part` ~ optional('?' ~ rawQueryString) } + // + // def `relative-ref` = rule { `relative-part` ~ optional('?' ~ rawQueryString) ~ optional('#' ~ fragment) } + // + // def `relative-part` = rule( + // '/' ~ '/' ~ authority ~ `path-abempty` + // | `path-absolute` + // | `path-noscheme` + // | `path-empty`) + // + // def scheme = rule( + // 'h' ~ 't' ~ 't' ~ 'p' ~ (&(':') ~ run(setScheme("http")) | 's' ~ &(':') ~ run(setScheme("https"))) + // | clearSB() ~ ALPHA ~ appendLowered() ~ zeroOrMore(`scheme-char` ~ appendLowered()) ~ &(':') ~ run(setScheme(sb.toString))) + // + // def `scheme-pushed` = rule { oneOrMore(`scheme-char` ~ appendLowered()) ~ run(setScheme(sb.toString)) ~ push(_scheme) } + // + // def authority = rule { optional(userinfo) ~ hostAndPort } + // + // def userinfo = rule { + // clearSBForDecoding() ~ zeroOrMore(`userinfo-char` ~ appendSB() | `pct-encoded`) ~ '@' ~ run(setUserInfo(getDecodedString())) + // } + // + // def hostAndPort = rule { host ~ optional(':' ~ port) } + // + // def `hostAndPort-pushed` = rule { hostAndPort ~ push(_host) ~ push(_port) } + // + // def host = rule { `IP-literal` | ipv4Host | `reg-name` } + // + // /** A relaxed host rule to use in `parseHost` that also recognizes IPv6 address without the brackets. */ + // def relaxedHost = rule { `IP-literal` | ipv6Host | ipv4Host | `reg-name` } + // + // def port = rule { + // DIGIT ~ run(setPort(lastChar - '0')) ~ optional( + // DIGIT ~ run(setPort(10 * _port + lastChar - '0')) ~ optional( + // DIGIT ~ run(setPort(10 * _port + lastChar - '0')) ~ optional( + // DIGIT ~ run(setPort(10 * _port + lastChar - '0')) ~ optional( + // DIGIT ~ run(setPort(10 * _port + lastChar - '0')))))) + // } + // + // def `IP-literal` = rule { '[' ~ ipv6Host ~ ']' } // IPvFuture not currently recognized + // + // def ipv4Host = rule { capture(`ip-v4-address`) ~ &(colonSlashEOI) ~> ((b, a) => _host = IPv4Host(b, a)) } + // def ipv6Host = rule { capture(`ip-v6-address`) ~> ((b, a) => setHost(IPv6Host(b, a))) } + // + // def `reg-name` = rule( + // clearSBForDecoding() ~ oneOrMore(`lower-reg-name-char` ~ appendSB() | UPPER_ALPHA ~ appendLowered() | `pct-encoded`) ~ + // run(setHost(NamedHost(getDecodedStringAndLowerIfEncoded(UTF8)))) + // | run(setHost(Host.Empty))) + // + // def `path-abempty` = rule { clearSB() ~ slashSegments ~ savePath() } + // def `path-absolute` = rule { clearSB() ~ '/' ~ appendSB('/') ~ optional(`segment-nz` ~ slashSegments) ~ savePath() } + // def `path-noscheme` = rule { clearSB() ~ `segment-nz-nc` ~ slashSegments ~ savePath() } + // def `path-rootless` = rule { clearSB() ~ `segment-nz` ~ slashSegments ~ savePath() } + // def `path-empty` = rule { MATCH } + // + // def slashSegments = rule { zeroOrMore('/' ~ appendSB('/') ~ segment) } + // + // def segment = rule { zeroOrMore(pchar) } + // def `segment-nz` = rule { oneOrMore(pchar) } + // def `segment-nz-nc` = rule { oneOrMore(!':' ~ pchar) } + // + // def pchar = rule { `path-segment-char` ~ appendSB() | `pct-encoded` } + // + // def rawQueryString = rule { + // clearSB() ~ oneOrMore(`query-char` ~ appendSB() | `pct-encoded`) ~ run(setRawQueryString(sb.toString)) | run(setRawQueryString("")) + // } + + // https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 + def query: Rule1[Query] = ??? + + def fragment = ??? + + def `pct-encoded` = ??? + + //////////////////////////// ADDITIONAL HTTP-SPECIFIC RULES ////////////////////////// + + // http://tools.ietf.org/html/rfc7230#section-2.7 + def `absolute-path` = ??? + + // http://tools.ietf.org/html/rfc7230#section-5.3 + def `request-target` = ??? + + def parseHttpRequestTarget(): Uri = ??? + + /////////////////////////// ADDITIONAL HTTP/2-SPECIFIC RULES ///////////////////////// + + // https://tools.ietf.org/html/rfc7540#section-8.1.2.3 + // https://tools.ietf.org/html/rfc3986#section-3.2 - without deprecated userinfo + def `http2-authority-pseudo-header` = ??? + + def parseHttp2AuthorityPseudoHeader(): Uri.Authority = ??? + + // https://tools.ietf.org/html/rfc7540#section-8.1.2.3 + def `http2-path-pseudo-header` = ??? + + /** + * @return path and percent-encoded query string. When in in 'relaxed' mode, characters not permitted by https://tools.ietf.org/html/rfc3986#section-3.4 + * are already automatically percent-encoded here + */ + def parseHttp2PathPseudoHeader(): (Uri.Path, Option[String]) = ??? + + /** Allows to reuse this parser. */ + def reset(newInput: ParserInput): Unit = ??? +} From 64d49c3709fcda4ff7e4b5e94378014d069da80f Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 15:04:44 +0100 Subject: [PATCH 19/51] core: move all tests to scala-2 dir for now (for incremental reenabling) --- .../src/test/{scala => scala-2}/akka/http/ConfigSpec.scala | 0 .../src/test/{scala => scala-2}/akka/http/HashCodeCollider.scala | 0 .../akka/http/impl/engine/client/ClientCancellationSpec.scala | 0 .../akka/http/impl/engine/client/ConnectionPoolSpec.scala | 0 .../http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala | 0 .../akka/http/impl/engine/client/HostConnectionPoolSpec.scala | 0 .../akka/http/impl/engine/client/HttpConfigurationSpec.scala | 0 .../akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala | 0 .../http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala | 0 .../akka/http/impl/engine/client/PrepareResponseSpec.scala | 0 .../akka/http/impl/engine/client/ResponseParsingMergeSpec.scala | 0 .../http/impl/engine/client/TlsEndpointVerificationSpec.scala | 0 .../akka/http/impl/engine/client/pool/SlotStateSpec.scala | 0 .../akka/http/impl/engine/parsing/BoyerMooreSpec.scala | 0 .../http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala | 0 .../akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala | 0 .../akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala | 0 .../akka/http/impl/engine/parsing/RequestParserSpec.scala | 0 .../akka/http/impl/engine/parsing/ResponseParserSpec.scala | 0 .../akka/http/impl/engine/rendering/RequestRendererSpec.scala | 0 .../akka/http/impl/engine/rendering/ResponseRendererSpec.scala | 0 .../akka/http/impl/engine/server/HttpServerBug21008Spec.scala | 0 .../akka/http/impl/engine/server/HttpServerSpec.scala | 0 .../akka/http/impl/engine/server/HttpServerTestSetupBase.scala | 0 .../impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala | 0 .../akka/http/impl/engine/server/PrepareRequestsSpec.scala | 0 .../{scala => scala-2}/akka/http/impl/engine/ws/BitBuilder.scala | 0 .../akka/http/impl/engine/ws/ByteStringSinkProbe.scala | 0 .../akka/http/impl/engine/ws/EchoTestClientApp.scala | 0 .../{scala => scala-2}/akka/http/impl/engine/ws/FramingSpec.scala | 0 .../{scala => scala-2}/akka/http/impl/engine/ws/MessageSpec.scala | 0 .../akka/http/impl/engine/ws/Utf8CodingSpecs.scala | 0 .../akka/http/impl/engine/ws/WSClientAutobahnTest.scala | 0 .../akka/http/impl/engine/ws/WSServerAutobahnTest.scala | 0 .../akka/http/impl/engine/ws/WSTestSetupBase.scala | 0 .../{scala => scala-2}/akka/http/impl/engine/ws/WSTestUtils.scala | 0 .../akka/http/impl/engine/ws/WebSocketClientSpec.scala | 0 .../akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala | 0 .../akka/http/impl/engine/ws/WebSocketServerSpec.scala | 0 .../akka/http/impl/model/parser/HttpHeaderSpec.scala | 0 .../akka/http/impl/util/AkkaSpecWithMaterializer.scala | 0 .../test/{scala => scala-2}/akka/http/impl/util/BenchUtils.scala | 0 .../akka/http/impl/util/ByteStringParserInputSpec.scala | 0 .../{scala => scala-2}/akka/http/impl/util/CollectionStage.scala | 0 .../akka/http/impl/util/ExampleHttpContexts.scala | 0 .../akka/http/impl/util/One2OneBidiFlowSpec.scala | 0 .../{scala => scala-2}/akka/http/impl/util/RenderingSpec.scala | 0 .../{scala => scala-2}/akka/http/impl/util/StreamUtilsSpec.scala | 0 .../{scala => scala-2}/akka/http/impl/util/WithLogCapturing.scala | 0 .../{scala => scala-2}/akka/http/javadsl/ConnectHttpSpec.scala | 0 .../akka/http/javadsl/ConnectionContextSpec.scala | 0 .../akka/http/javadsl/HttpExtensionApiSpec.scala | 0 .../akka/http/javadsl/JavaInitializationSpec.scala | 0 .../{scala => scala-2}/akka/http/javadsl/model/JavaApiSpec.scala | 0 .../akka/http/javadsl/model/JavaApiTestCaseSpecs.scala | 0 .../akka/http/javadsl/model/MultipartsSpec.scala | 0 .../akka/http/javadsl/model/headers/HttpCookieSpec.scala | 0 .../{scala => scala-2}/akka/http/scaladsl/ClientServerSpec.scala | 0 .../test/{scala => scala-2}/akka/http/scaladsl/ClientSpec.scala | 0 .../http/scaladsl/ClientTransportWithCustomResolverSpec.scala | 0 .../akka/http/scaladsl/GracefulTerminationSpec.scala | 0 .../test/{scala => scala-2}/akka/http/scaladsl/TestClient.scala | 0 .../test/{scala => scala-2}/akka/http/scaladsl/TestServer.scala | 0 .../akka/http/scaladsl/TightRequestTimeoutSpec.scala | 0 .../akka/http/scaladsl/model/DateTimeSpec.scala | 0 .../akka/http/scaladsl/model/EntityDiscardingSpec.scala | 0 .../akka/http/scaladsl/model/HttpEntitySpec.scala | 0 .../akka/http/scaladsl/model/HttpMessageSpec.scala | 0 .../akka/http/scaladsl/model/HttpMethodsSpec.scala | 0 .../akka/http/scaladsl/model/MultipartSpec.scala | 0 .../akka/http/scaladsl/model/SerializabilitySpec.scala | 0 .../akka/http/scaladsl/model/TurkishISpec.scala | 0 .../{scala => scala-2}/akka/http/scaladsl/model/UriSpec.scala | 0 .../akka/http/scaladsl/model/headers/HeaderSpec.scala | 0 .../akka/http/scaladsl/model/sse/ServerSentEventSpec.scala | 0 .../http/scaladsl/settings/ClientConnectionSettingsSpec.scala | 0 .../akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala | 0 .../akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala | 0 .../akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala | 0 .../akka/http/scaladsl/settings/ServerSettingsSpec.scala | 0 .../akka/http/scaladsl/settings/SettingsEqualitySpec.scala | 0 .../akka/http/scaladsl/util/FastFutureSpec.scala | 0 .../src/test/{scala => scala-2}/akka/stream/testkit/Utils.scala | 0 .../src/test/{scala => scala-2}/akka/testkit/AkkaSpec.scala | 0 .../src/test/{scala => scala-2}/akka/testkit/Coroner.scala | 0 .../io/akka/integrationtest/http/HttpModelIntegrationSpec.scala | 0 86 files changed, 0 insertions(+), 0 deletions(-) rename akka-http-core/src/test/{scala => scala-2}/akka/http/ConfigSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/HashCodeCollider.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/ClientCancellationSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/ConnectionPoolSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/HostConnectionPoolSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/HttpConfigurationSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/PrepareResponseSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/client/pool/SlotStateSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/parsing/BoyerMooreSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/parsing/RequestParserSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/parsing/ResponseParserSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/rendering/RequestRendererSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/rendering/ResponseRendererSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/server/HttpServerBug21008Spec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/server/HttpServerSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/server/HttpServerTestSetupBase.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/server/PrepareRequestsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/BitBuilder.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/ByteStringSinkProbe.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/EchoTestClientApp.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/FramingSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/MessageSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/Utf8CodingSpecs.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WSClientAutobahnTest.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WSServerAutobahnTest.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WSTestSetupBase.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WSTestUtils.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WebSocketClientSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/engine/ws/WebSocketServerSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/model/parser/HttpHeaderSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/AkkaSpecWithMaterializer.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/BenchUtils.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/ByteStringParserInputSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/CollectionStage.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/ExampleHttpContexts.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/One2OneBidiFlowSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/RenderingSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/StreamUtilsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/impl/util/WithLogCapturing.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/ConnectHttpSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/ConnectionContextSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/HttpExtensionApiSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/JavaInitializationSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/model/JavaApiSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/model/MultipartsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/javadsl/model/headers/HttpCookieSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/ClientServerSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/ClientSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/GracefulTerminationSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/TestClient.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/TestServer.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/TightRequestTimeoutSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/DateTimeSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/EntityDiscardingSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/HttpEntitySpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/HttpMessageSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/HttpMethodsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/MultipartSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/SerializabilitySpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/TurkishISpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/UriSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/headers/HeaderSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/settings/ServerSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/settings/SettingsEqualitySpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/http/scaladsl/util/FastFutureSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/stream/testkit/Utils.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/testkit/AkkaSpec.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/akka/testkit/Coroner.scala (100%) rename akka-http-core/src/test/{scala => scala-2}/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala (100%) diff --git a/akka-http-core/src/test/scala/akka/http/ConfigSpec.scala b/akka-http-core/src/test/scala-2/akka/http/ConfigSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/ConfigSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/ConfigSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/HashCodeCollider.scala b/akka-http-core/src/test/scala-2/akka/http/HashCodeCollider.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/HashCodeCollider.scala rename to akka-http-core/src/test/scala-2/akka/http/HashCodeCollider.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ClientCancellationSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ClientCancellationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/ClientCancellationSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ClientCancellationSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ConnectionPoolSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ConnectionPoolSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HostConnectionPoolSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HostConnectionPoolSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpConfigurationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpConfigurationSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/PrepareResponseSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/PrepareResponseSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/PrepareResponseSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/PrepareResponseSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/pool/SlotStateSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/pool/SlotStateSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/pool/SlotStateSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/client/pool/SlotStateSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/BoyerMooreSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/BoyerMooreSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/parsing/BoyerMooreSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/BoyerMooreSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/RequestParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/RequestParserSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ResponseParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ResponseParserSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/RequestRendererSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/RequestRendererSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/rendering/RequestRendererSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/RequestRendererSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/ResponseRendererSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/ResponseRendererSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerBug21008Spec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerBug21008Spec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerBug21008Spec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerBug21008Spec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerTestSetupBase.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerTestSetupBase.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/server/PrepareRequestsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/PrepareRequestsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/server/PrepareRequestsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/server/PrepareRequestsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/BitBuilder.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/BitBuilder.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/BitBuilder.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/BitBuilder.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/ByteStringSinkProbe.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/ByteStringSinkProbe.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/ByteStringSinkProbe.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/ByteStringSinkProbe.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/EchoTestClientApp.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/EchoTestClientApp.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/EchoTestClientApp.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/EchoTestClientApp.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/FramingSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/FramingSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/FramingSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/FramingSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/MessageSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/MessageSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/MessageSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/MessageSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/Utf8CodingSpecs.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/Utf8CodingSpecs.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/Utf8CodingSpecs.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/Utf8CodingSpecs.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSClientAutobahnTest.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSClientAutobahnTest.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSClientAutobahnTest.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSClientAutobahnTest.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSServerAutobahnTest.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSServerAutobahnTest.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSServerAutobahnTest.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSServerAutobahnTest.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestSetupBase.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestSetupBase.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestSetupBase.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestSetupBase.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestUtils.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestUtils.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestUtils.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestUtils.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketClientSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketClientSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketServerSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketServerSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketServerSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketServerSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/model/parser/HttpHeaderSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/model/parser/HttpHeaderSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/AkkaSpecWithMaterializer.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/AkkaSpecWithMaterializer.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/AkkaSpecWithMaterializer.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/AkkaSpecWithMaterializer.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/BenchUtils.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/BenchUtils.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/BenchUtils.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/BenchUtils.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/ByteStringParserInputSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/ByteStringParserInputSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/ByteStringParserInputSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/ByteStringParserInputSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/CollectionStage.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/CollectionStage.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/CollectionStage.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/CollectionStage.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/ExampleHttpContexts.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/ExampleHttpContexts.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/ExampleHttpContexts.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/ExampleHttpContexts.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/One2OneBidiFlowSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/One2OneBidiFlowSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/One2OneBidiFlowSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/One2OneBidiFlowSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/RenderingSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/RenderingSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/RenderingSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/RenderingSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/StreamUtilsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/StreamUtilsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/StreamUtilsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/StreamUtilsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/impl/util/WithLogCapturing.scala b/akka-http-core/src/test/scala-2/akka/http/impl/util/WithLogCapturing.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/util/WithLogCapturing.scala rename to akka-http-core/src/test/scala-2/akka/http/impl/util/WithLogCapturing.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/ConnectHttpSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectHttpSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/ConnectHttpSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectHttpSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/ConnectionContextSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectionContextSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/ConnectionContextSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectionContextSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/HttpExtensionApiSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/HttpExtensionApiSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/HttpExtensionApiSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/HttpExtensionApiSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/JavaInitializationSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/JavaInitializationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/JavaInitializationSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/JavaInitializationSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/model/MultipartsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/model/MultipartsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/model/MultipartsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/model/MultipartsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/javadsl/model/headers/HttpCookieSpec.scala b/akka-http-core/src/test/scala-2/akka/http/javadsl/model/headers/HttpCookieSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/javadsl/model/headers/HttpCookieSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/javadsl/model/headers/HttpCookieSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientServerSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientServerSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/ClientSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/GracefulTerminationSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/GracefulTerminationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/GracefulTerminationSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/GracefulTerminationSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/TestClient.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/TestClient.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/TestClient.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/TestClient.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/TestServer.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/TestServer.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/TestServer.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/TestServer.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/TightRequestTimeoutSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/TightRequestTimeoutSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/TightRequestTimeoutSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/TightRequestTimeoutSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/DateTimeSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/DateTimeSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/EntityDiscardingSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/EntityDiscardingSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/EntityDiscardingSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/EntityDiscardingSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpEntitySpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpEntitySpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMessageSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMessageSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMessageSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMessageSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMethodsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMethodsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMethodsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMethodsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/MultipartSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/MultipartSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/MultipartSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/MultipartSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/SerializabilitySpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/SerializabilitySpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/SerializabilitySpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/SerializabilitySpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/TurkishISpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/TurkishISpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/TurkishISpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/TurkishISpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/UriSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/UriSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/UriSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/UriSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/headers/HeaderSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/headers/HeaderSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/headers/HeaderSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/headers/HeaderSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/settings/ServerSettingsSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ServerSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/settings/ServerSettingsSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ServerSettingsSpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/settings/SettingsEqualitySpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/SettingsEqualitySpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/settings/SettingsEqualitySpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/SettingsEqualitySpec.scala diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/util/FastFutureSpec.scala b/akka-http-core/src/test/scala-2/akka/http/scaladsl/util/FastFutureSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/scaladsl/util/FastFutureSpec.scala rename to akka-http-core/src/test/scala-2/akka/http/scaladsl/util/FastFutureSpec.scala diff --git a/akka-http-core/src/test/scala/akka/stream/testkit/Utils.scala b/akka-http-core/src/test/scala-2/akka/stream/testkit/Utils.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/stream/testkit/Utils.scala rename to akka-http-core/src/test/scala-2/akka/stream/testkit/Utils.scala diff --git a/akka-http-core/src/test/scala/akka/testkit/AkkaSpec.scala b/akka-http-core/src/test/scala-2/akka/testkit/AkkaSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/testkit/AkkaSpec.scala rename to akka-http-core/src/test/scala-2/akka/testkit/AkkaSpec.scala diff --git a/akka-http-core/src/test/scala/akka/testkit/Coroner.scala b/akka-http-core/src/test/scala-2/akka/testkit/Coroner.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/testkit/Coroner.scala rename to akka-http-core/src/test/scala-2/akka/testkit/Coroner.scala diff --git a/akka-http-core/src/test/scala/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala b/akka-http-core/src/test/scala-2/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala rename to akka-http-core/src/test/scala-2/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala From 67adeabf5c72f1df13036579e958d46554f7a66d Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 15:14:01 +0100 Subject: [PATCH 20/51] build: for now change default Akka version to 2.6.18 --- project/AkkaDependency.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/AkkaDependency.scala b/project/AkkaDependency.scala index 481c449b64e..0f7467ab10b 100644 --- a/project/AkkaDependency.scala +++ b/project/AkkaDependency.scala @@ -42,7 +42,7 @@ object AkkaDependency { } // Default version updated only when needed, https://doc.akka.io//docs/akka/current/project/downstream-upgrade-strategy.html - val minimumExpectedAkkaVersion = "2.5.32" + val minimumExpectedAkkaVersion = "2.6.18" val default = akkaDependency(defaultVersion = minimumExpectedAkkaVersion) val minimumExpectedAkka26Version = "2.6.8" val docs = akkaDependency(defaultVersion = minimumExpectedAkka26Version) From 71b2621bb1ed9b458f0bcd11f0b2333ca9bcf1fe Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 21 Mar 2022 15:44:56 +0100 Subject: [PATCH 21/51] parsing: add missing copyright header --- .../src/main/scala-3/akka/macros/LogHelperMacro.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala b/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala index 1b664673318..dfed8febb33 100644 --- a/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala +++ b/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala @@ -1,3 +1,7 @@ +/* + * Copyright (C) 2021 Lightbend Inc. + */ + package akka.macros import akka.annotation.InternalApi From 019c24f8b3f4d1bfd0e936f980c2fe045022917d Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Thu, 24 Mar 2022 15:16:00 +0100 Subject: [PATCH 22/51] Add missing header (#4085) --- .../src/main/scala-2/akka/macros/LogHelperMacro.scala | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala b/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala index acdf188ab5b..0a06bb096d8 100644 --- a/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala +++ b/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala @@ -1,3 +1,7 @@ +/* + * Copyright (C) 2021 Lightbend Inc. + */ + package akka.macros import akka.annotation.InternalApi From 27685a25b7d467a72dd9cc74d0a16c4090eba94b Mon Sep 17 00:00:00 2001 From: Jan Chyb <48855024+jchyb@users.noreply.github.com> Date: Mon, 4 Apr 2022 10:31:24 +0200 Subject: [PATCH 23/51] http: compile akka-http module with Scala 3 (#4091) --- .../http/javadsl/marshalling/Marshaller.scala | 2 +- .../http/javadsl/server/RejectionHandler.scala | 2 +- .../akka/http/javadsl/server/Rejections.scala | 12 ++++++------ .../server/directives/AttributeDirectives.scala | 2 +- .../directives/CacheConditionDirectives.scala | 2 +- .../FramedEntityStreamingDirectives.scala | 5 +++-- .../server/directives/PathDirectives.scala | 2 +- .../server/directives/RouteDirectives.scala | 11 ++++++----- .../server/directives/SecurityDirectives.scala | 4 ++-- .../server/directives/WebSocketDirectives.scala | 4 ++-- .../server/directives/PathDirectives.scala | 4 ++-- .../scaladsl/settings/RoutingSettings.scala | 16 ++++++++-------- build.sbt | 17 ++++++++--------- 13 files changed, 42 insertions(+), 41 deletions(-) diff --git a/akka-http/src/main/scala/akka/http/javadsl/marshalling/Marshaller.scala b/akka-http/src/main/scala/akka/http/javadsl/marshalling/Marshaller.scala index 35024abbf9b..016cd250ef4 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/marshalling/Marshaller.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/marshalling/Marshaller.scala @@ -66,7 +66,7 @@ object Marshaller { // TODO make sure these are actually usable in a sane way def wrapEntity[A, C](f: function.BiFunction[ExecutionContext, C, A], m: Marshaller[A, RequestEntity], mediaType: MediaType): Marshaller[C, RequestEntity] = { val scalaMarshaller = m.asScalaCastOutput - fromScala(scalaMarshaller.wrapWithEC(mediaType.asScala) { ctx => c: C => f(ctx, c) }(ContentTypeOverrider.forEntity)) + fromScala(scalaMarshaller.wrapWithEC(mediaType.asScala) { ctx => (c: C) => f(ctx, c) }(ContentTypeOverrider.forEntity)) } def wrapEntity[A, C, E <: RequestEntity](f: function.Function[C, A], m: Marshaller[A, E], mediaType: MediaType): Marshaller[C, RequestEntity] = { diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/RejectionHandler.scala b/akka-http/src/main/scala/akka/http/javadsl/server/RejectionHandler.scala index ae7e3e2afd0..ae9fabd1796 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/RejectionHandler.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/RejectionHandler.scala @@ -55,7 +55,7 @@ class RejectionHandlerBuilder(asScala: server.RejectionHandler.Builder) { * The list passed to the given function is guaranteed to be non-empty. */ def handleAll[T <: Rejection](t: Class[T], handler: function.Function[java.util.List[T], Route]): RejectionHandlerBuilder = { - asScala.handleAll { rejections: collection.immutable.Seq[T] => handler.apply(rejections.asJava).delegate }(ClassTag(t)) + asScala.handleAll { (rejections: collection.immutable.Seq[T]) => handler.apply(rejections.asJava).delegate }(ClassTag(t)) this } diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/Rejections.scala b/akka-http/src/main/scala/akka/http/javadsl/server/Rejections.scala index 7da8e1334ca..015c3e0e982 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/Rejections.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/Rejections.scala @@ -389,13 +389,13 @@ object Rejections { supported: java.lang.Iterable[MediaType], contentType: Optional[ContentType]): UnsupportedRequestContentTypeRejection = s.UnsupportedRequestContentTypeRejection( - supported = supported.asScala.map(m => scaladsl.model.ContentTypeRange(m.asScala)).toSet, - contentType = contentType.asScala.map(_.asScala)) + supported = supported.asScala.map((m: MediaType) => scaladsl.model.ContentTypeRange(m.asScala)).toSet, + contentType = contentType.asScala.map((c: ContentType) => c.asScala)) // for backwards compatibility def unsupportedRequestContentType(supported: java.lang.Iterable[MediaType]): UnsupportedRequestContentTypeRejection = s.UnsupportedRequestContentTypeRejection( - supported = supported.asScala.map(m => scaladsl.model.ContentTypeRange(m.asScala)).toSet, + supported = supported.asScala.map((m: MediaType) => scaladsl.model.ContentTypeRange(m.asScala)).toSet, contentType = None) def unsupportedRequestEncoding(supported: HttpEncoding): UnsupportedRequestEncodingRejection = @@ -414,15 +414,15 @@ object Rejections { def unacceptedResponseContentType( supportedContentTypes: java.lang.Iterable[ContentType], supportedMediaTypes: java.lang.Iterable[MediaType]): UnacceptedResponseContentTypeRejection = { - val s1: Set[Alternative] = supportedContentTypes.asScala.map(_.asScala).map(ct => ContentNegotiator.Alternative(ct)).toSet - val s2: Set[Alternative] = supportedMediaTypes.asScala.map(_.asScala).map(mt => ContentNegotiator.Alternative(mt)).toSet + val s1: Set[Alternative] = supportedContentTypes.asScala.map((c: ContentType) => c.asScala).map(ct => ContentNegotiator.Alternative(ct)).toSet + val s2: Set[Alternative] = supportedMediaTypes.asScala.map((m: MediaType) => m.asScala).map(mt => ContentNegotiator.Alternative(mt)).toSet s.UnacceptedResponseContentTypeRejection(s1 ++ s2) } def unacceptedResponseEncoding(supported: HttpEncoding) = s.UnacceptedResponseEncodingRejection(supported.asScala) def unacceptedResponseEncoding(supported: java.lang.Iterable[HttpEncoding]) = - s.UnacceptedResponseEncodingRejection(supported.asScala.map(_.asScala).toSet) + s.UnacceptedResponseEncodingRejection(supported.asScala.map((h: HttpEncoding) => h.asScala).toSet) def authenticationCredentialsMissing(challenge: HttpChallenge): AuthenticationFailedRejection = s.AuthenticationFailedRejection(s.AuthenticationFailedRejection.CredentialsMissing, challenge.asScala) diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/AttributeDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/AttributeDirectives.scala index a6445008a82..e6fb7c07fcc 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/AttributeDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/AttributeDirectives.scala @@ -20,7 +20,7 @@ abstract class AttributeDirectives extends HeaderDirectives { * If no attribute is found the request is rejected with a [[akka.http.javadsl.server.MissingAttributeRejection]]. */ def attribute[T](key: AttributeKey[T], inner: jf.Function[T, Route]) = RouteAdapter { - D.attribute(toScala(key)) { value: T => + D.attribute(toScala(key)) { (value: T) => inner.apply(value).delegate } } diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/CacheConditionDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/CacheConditionDirectives.scala index 0da19b102ec..1fd874099ec 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/CacheConditionDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/CacheConditionDirectives.scala @@ -74,7 +74,7 @@ abstract class CacheConditionDirectives extends BasicDirectives { * must be on a deeper level in your route structure in order to function correctly. */ def conditional(eTag: Optional[EntityTag], lastModified: Optional[DateTime], inner: Supplier[Route]): Route = RouteAdapter { - D.conditional(eTag.asScala.map(_.asScala), lastModified.asScala.map(_.asScala)) { inner.get.delegate } + D.conditional(eTag.asScala.map((e: EntityTag) => e.asScala), lastModified.asScala.map((d: DateTime) => d.asScala)) { inner.get.delegate } } } diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/FramedEntityStreamingDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/FramedEntityStreamingDirectives.scala index e9a64f6fa52..1e6795eb6a2 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/FramedEntityStreamingDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/FramedEntityStreamingDirectives.scala @@ -10,6 +10,7 @@ import akka.http.javadsl.marshalling.Marshaller import akka.http.javadsl.model.{ HttpEntity, _ } import akka.http.javadsl.server.Route import akka.http.javadsl.unmarshalling.Unmarshaller +import akka.http.scaladsl.marshalling.ToResponseMarshaller import akka.http.scaladsl.marshalling.ToResponseMarshallable import akka.http.scaladsl.server.{ Directives => D } import akka.stream.javadsl.Source @@ -25,7 +26,7 @@ abstract class FramedEntityStreamingDirectives extends TimeoutDirectives { def entityAsSourceOf[T](um: Unmarshaller[ByteString, T], support: EntityStreamingSupport, inner: java.util.function.Function[Source[T, NotUsed], Route]): Route = RouteAdapter { val umm = D.asSourceOf(um.asScala, support.asScala) - D.entity(umm) { s: akka.stream.scaladsl.Source[T, NotUsed] => + D.entity(umm) { (s: akka.stream.scaladsl.Source[T, NotUsed]) => inner(s.asJava).delegate } } @@ -46,7 +47,7 @@ abstract class FramedEntityStreamingDirectives extends TimeoutDirectives { import akka.http.scaladsl.marshalling.PredefinedToResponseMarshallers._ // don't try this at home: val mm = m.asScalaCastOutput[akka.http.scaladsl.model.RequestEntity].map(_.httpEntity.asInstanceOf[akka.http.scaladsl.model.RequestEntity]) - implicit val mmm = fromEntityStreamingSupportAndEntityMarshaller[T, M](support.asScala, mm, null) + implicit val mmm: ToResponseMarshaller[akka.stream.scaladsl.Source[T, M]] = fromEntityStreamingSupportAndEntityMarshaller[T, M](support.asScala, mm, null) val response = ToResponseMarshallable(source.asScala) D.complete(response) } diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/PathDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/PathDirectives.scala index f774785ce6a..5a739d9c37b 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/PathDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/PathDirectives.scala @@ -282,7 +282,7 @@ abstract class PathDirectives extends ParameterDirectives { D.ignoreTrailingSlash { inner.get.delegate } } - private def unmarshal[T](t: Unmarshaller[String, T], inner: JFunction[T, Route]) = { element: String => + private def unmarshal[T](t: Unmarshaller[String, T], inner: JFunction[T, Route]) = { (element: String) => D.extractRequestContext { ctx => import ctx.executionContext import ctx.materializer diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/RouteDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/RouteDirectives.scala index a5adff87aea..fc589d5793d 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/RouteDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/RouteDirectives.scala @@ -22,12 +22,13 @@ import akka.http.scaladsl.server.RouteResult import akka.http.scaladsl.server.directives.{ RouteDirectives => D } import akka.http.scaladsl.util.FastFuture import akka.http.scaladsl.util.FastFuture._ +import scala.concurrent.ExecutionContext abstract class RouteDirectives extends RespondWithDirectives { import RoutingJavaMapping.Implicits._ // Don't try this at home – we only use it here for the java -> scala conversions - private implicit val conversionExecutionContext = ExecutionContexts.sameThreadExecutionContext + private implicit val conversionExecutionContext: ExecutionContext = ExecutionContexts.sameThreadExecutionContext /** * Java-specific call added so you can chain together multiple alternate routes using comma, @@ -249,7 +250,7 @@ abstract class RouteDirectives extends RespondWithDirectives { */ @CorrespondsTo("complete") def completeWithFuture(value: CompletionStage[HttpResponse]) = RouteAdapter { - D.complete(value.asScala.fast.map(_.asScala).recover(unwrapCompletionException)) + D.complete(value.asScala.fast.map((h: HttpResponse) => h.asScala).recover(unwrapCompletionException)) } /** @@ -257,7 +258,7 @@ abstract class RouteDirectives extends RespondWithDirectives { */ @CorrespondsTo("complete") def completeOKWithFuture(value: CompletionStage[RequestEntity]) = RouteAdapter { - D.complete(value.asScala.fast.map(_.asScala).recover(unwrapCompletionException)) + D.complete(value.asScala.fast.map((r: RequestEntity) => r.asScala).recover(unwrapCompletionException)) } /** @@ -273,7 +274,7 @@ abstract class RouteDirectives extends RespondWithDirectives { */ @CorrespondsTo("complete") def completeWithFutureStatus(status: CompletionStage[StatusCode]): Route = RouteAdapter { - D.complete(status.asScala.fast.map(_.asScala).recover(unwrapCompletionException)) + D.complete(status.asScala.fast.map((s: StatusCode) => s.asScala).recover(unwrapCompletionException)) } /** @@ -297,7 +298,7 @@ abstract class RouteDirectives extends RespondWithDirectives { */ def handle(handler: akka.japi.function.Function[HttpRequest, CompletionStage[HttpResponse]]): Route = { import akka.http.impl.util.JavaMapping._ - RouteAdapter { ctx => handler(ctx.request).asScala.fast.map(response => RouteResult.Complete(response.asScala)) } + RouteAdapter { ctx => handler(ctx.request).asScala.fast.map((response: HttpResponse) => RouteResult.Complete(response.asScala)) } } /** diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/SecurityDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/SecurityDirectives.scala index 2980e94dd2e..49ee0556d3a 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/SecurityDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/SecurityDirectives.scala @@ -235,7 +235,7 @@ abstract class SecurityDirectives extends SchemeDirectives { authenticator: JFunction[Optional[HttpCredentials], CompletionStage[Either[HttpChallenge, T]]], inner: JFunction[T, Route]): Route = RouteAdapter { D.extractExecutionContext { implicit ctx => - val scalaAuthenticator = { cred: Option[scaladsl.model.headers.HttpCredentials] => + val scalaAuthenticator = { (cred: Option[scaladsl.model.headers.HttpCredentials]) => authenticator.apply(cred.map(_.asJava).asJava).toScala.map(_.left.map(_.asScala)) } @@ -254,7 +254,7 @@ abstract class SecurityDirectives extends SchemeDirectives { authenticator: JFunction[Optional[C], CompletionStage[Either[HttpChallenge, T]]], inner: JFunction[T, Route]): Route = RouteAdapter { D.extractExecutionContext { implicit ctx => - val scalaAuthenticator = { cred: Option[scaladsl.model.headers.HttpCredentials] => + val scalaAuthenticator = { (cred: Option[scaladsl.model.headers.HttpCredentials]) => authenticator.apply(cred.filter(c.isInstance).map(_.asJava).asJava.asInstanceOf[Optional[C]]).toScala.map(_.left.map(_.asScala)) // TODO make sure cast is safe } diff --git a/akka-http/src/main/scala/akka/http/javadsl/server/directives/WebSocketDirectives.scala b/akka-http/src/main/scala/akka/http/javadsl/server/directives/WebSocketDirectives.scala index 00119ee7fec..d72c08153c6 100644 --- a/akka-http/src/main/scala/akka/http/javadsl/server/directives/WebSocketDirectives.scala +++ b/akka-http/src/main/scala/akka/http/javadsl/server/directives/WebSocketDirectives.scala @@ -10,7 +10,6 @@ import java.util.Optional import java.util.function.{ Function => JFunction } import akka.NotUsed -import scala.collection.JavaConverters._ import akka.http.scaladsl.model.{ ws => s } import akka.http.javadsl.model.ws.Message import akka.http.javadsl.model.ws.UpgradeToWebSocket @@ -50,7 +49,8 @@ abstract class WebSocketDirectives extends SecurityDirectives { * this is a WebSocket request. Rejects with an [[ExpectedWebSocketRequestRejection]], otherwise. */ def extractOfferedWsProtocols(inner: JFunction[JList[String], Route]): Route = RouteAdapter { - D.extractOfferedWsProtocols { list => + import scala.collection.JavaConverters._ + D.extractOfferedWsProtocols { (list: Seq[String]) => inner.apply(list.asJava).delegate } } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/PathDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/PathDirectives.scala index 11b90cfe4b6..b966cf2f7dd 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/PathDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/PathDirectives.scala @@ -51,7 +51,7 @@ trait PathDirectives extends PathMatchers with ImplicitPathMatcherConstruction w def rawPathPrefix[L](pm: PathMatcher[L]): Directive[L] = { implicit val LIsTuple = pm.ev extract(ctx => pm(ctx.unmatchedPath)).flatMap { - case Matched(rest, values) => tprovide(values) & mapRequestContext(_ withUnmatchedPath rest) + case Matched(rest, values) => tprovide(values)(LIsTuple) & mapRequestContext(_ withUnmatchedPath rest) case Unmatched => reject } } @@ -90,7 +90,7 @@ trait PathDirectives extends PathMatchers with ImplicitPathMatcherConstruction w def pathSuffix[L](pm: PathMatcher[L]): Directive[L] = { implicit val LIsTuple = pm.ev extract(ctx => pm(ctx.unmatchedPath.reverse)).flatMap { - case Matched(rest, values) => tprovide(values) & mapRequestContext(_.withUnmatchedPath(rest.reverse)) + case Matched(rest, values) => tprovide(values)(LIsTuple) & mapRequestContext(_.withUnmatchedPath(rest.reverse)) case Unmatched => reject } } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/settings/RoutingSettings.scala b/akka-http/src/main/scala/akka/http/scaladsl/settings/RoutingSettings.scala index 14b9ba003f3..5e6a449e9e4 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/settings/RoutingSettings.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/settings/RoutingSettings.scala @@ -24,16 +24,16 @@ abstract class RoutingSettings private[akka] () extends akka.http.javadsl.settin def fileIODispatcher: String /* Java APIs */ - def getVerboseErrorMessages: Boolean = verboseErrorMessages - def getFileGetConditional: Boolean = fileGetConditional - def getRenderVanityFooter: Boolean = renderVanityFooter - def getRangeCountLimit: Int = rangeCountLimit - def getRangeCoalescingThreshold: Long = rangeCoalescingThreshold - def getDecodeMaxBytesPerChunk: Int = decodeMaxBytesPerChunk - def getDecodeMaxSize: Long = decodeMaxSize + def getVerboseErrorMessages: Boolean = this.verboseErrorMessages + def getFileGetConditional: Boolean = this.fileGetConditional + def getRenderVanityFooter: Boolean = this.renderVanityFooter + def getRangeCountLimit: Int = this.rangeCountLimit + def getRangeCoalescingThreshold: Long = this.rangeCoalescingThreshold + def getDecodeMaxBytesPerChunk: Int = this.decodeMaxBytesPerChunk + def getDecodeMaxSize: Long = this.decodeMaxSize @deprecated("binary compatibility method. Use `akka.stream.materializer.blocking-io-dispatcher` to configure the dispatcher", since = "10.1.6") @Deprecated - def getFileIODispatcher: String = fileIODispatcher + def getFileIODispatcher: String = this.fileIODispatcher override def withVerboseErrorMessages(verboseErrorMessages: Boolean): RoutingSettings = self.copy(verboseErrorMessages = verboseErrorMessages) override def withFileGetConditional(fileGetConditional: Boolean): RoutingSettings = self.copy(fileGetConditional = fileGetConditional) diff --git a/build.sbt b/build.sbt index ea571f565a1..c8ea71317f7 100644 --- a/build.sbt +++ b/build.sbt @@ -130,6 +130,13 @@ val scalaMacroSupport = Seq( }), ) +val scala3MigrationModeOption = + scalacOptions ++= { + if (scalaVersion.value startsWith "3") + Seq("-source:3.0-migration") + else + Nil + } lazy val parsing = project("akka-parsing") .settings(commonSettings) @@ -157,14 +164,7 @@ lazy val httpCore = project("akka-http-core") if (System.getProperty("akka.http.test-against-akka-main", "false") == "true") AkkaDependency.masterSnapshot else AkkaDependency.default ) - .settings( - scalacOptions ++= { - if (scalaVersion.value startsWith "3") - Seq("-source", "3.0-migration") - else - Nil - }, - ) + .settings(scala3MigrationModeOption) .settings(Dependencies.httpCore) .settings(VersionGenerator.versionSettings) .settings(scalaMacroSupport) @@ -184,7 +184,6 @@ lazy val http = project("akka-http") .settings(scalaMacroSupport) .enablePlugins(BootstrapGenjavadoc, BoilerplatePlugin) .enablePlugins(ReproducibleBuildsPlugin) - .enablePlugins(NoScala3) // FIXME def gustavDir(kind: String) = Def.task { val ver = From 0a979b87f0fb67585b94a21801ddff9090df7eb4 Mon Sep 17 00:00:00 2001 From: hughsimpson Date: Mon, 11 Apr 2022 13:05:59 +0100 Subject: [PATCH 24/51] scala3: compile akka-http-core and pass all its tests (#4097) --- .../impl/model/parser/Base64Parsing.scala | 90 ---- .../http/impl/model/parser/CommonRules.scala | 475 ------------------ .../http/impl/model/parser/HeaderParser.scala | 230 --------- .../impl/model/parser/StringBuilding.scala | 68 --- .../http/impl/model/parser/UriParser.scala | 254 ---------- .../akka/http/scaladsl/model/HttpHeader.scala | 125 ----- .../model/headers/ProductVersion.scala | 39 -- .../model/parser/AcceptCharsetHeader.scala | 2 +- .../model/parser/AcceptEncodingHeader.scala | 8 +- .../http/impl/model/parser/AcceptHeader.scala | 2 +- .../model/parser/AcceptLanguageHeader.scala | 2 +- .../impl/model/parser/Base64Parsing.scala | 0 .../model/parser/CacheControlHeader.scala | 0 .../impl/model/parser/CommonActions.scala | 0 .../http/impl/model/parser/CommonRules.scala | 9 +- .../parser/ContentDispositionHeader.scala | 2 +- .../impl/model/parser/ContentTypeHeader.scala | 2 +- .../http/impl/model/parser/HeaderParser.scala | 4 +- .../impl/model/parser/IpAddressParsing.scala | 0 .../http/impl/model/parser/LinkHeader.scala | 18 +- .../impl/model/parser/SimpleHeaders.scala | 6 +- .../impl/model/parser/StringBuilding.scala | 0 .../http/impl/model/parser/UriParser.scala | 2 +- .../impl/model/parser/WebSocketHeaders.scala | 2 +- .../akka/http/scaladsl/model/HttpHeader.scala | 0 .../model/headers/ProductVersion.scala | 0 .../scaladsl/settings/ServerSettings.scala | 2 +- .../akka/http/ConfigSpec.scala | 0 .../akka/http/HashCodeCollider.scala | 0 .../client/ClientCancellationSpec.scala | 0 .../engine/client/ConnectionPoolSpec.scala | 2 +- .../HighLevelOutgoingConnectionSpec.scala | 0 .../client/HostConnectionPoolSpec.scala | 2 +- .../engine/client/HttpConfigurationSpec.scala | 0 .../client/HttpsProxyGraphStageSpec.scala | 0 .../LowLevelOutgoingConnectionSpec.scala | 9 +- .../engine/client/PrepareResponseSpec.scala | 10 +- .../client/ResponseParsingMergeSpec.scala | 2 +- .../client/TlsEndpointVerificationSpec.scala | 0 .../engine/client/pool/SlotStateSpec.scala | 0 .../impl/engine/parsing/BoyerMooreSpec.scala | 0 .../ContentLengthHeaderParserSpec.scala | 0 .../engine/parsing/HttpHeaderParserSpec.scala | 0 .../parsing/HttpHeaderParserTestBed.scala | 2 +- .../engine/parsing/RequestParserSpec.scala | 4 +- .../engine/parsing/ResponseParserSpec.scala | 0 .../rendering/RequestRendererSpec.scala | 4 +- .../rendering/ResponseRendererSpec.scala | 4 +- .../server/HttpServerBug21008Spec.scala | 0 .../impl/engine/server/HttpServerSpec.scala | 2 +- .../server/HttpServerTestSetupBase.scala | 2 +- .../HttpServerWithExplicitSchedulerSpec.scala | 0 .../engine/server/PrepareRequestsSpec.scala | 8 +- .../akka/http/impl/engine/ws/BitBuilder.scala | 2 +- .../impl/engine/ws/ByteStringSinkProbe.scala | 0 .../impl/engine/ws/EchoTestClientApp.scala | 4 +- .../http/impl/engine/ws/FramingSpec.scala | 0 .../http/impl/engine/ws/MessageSpec.scala | 2 +- .../http/impl/engine/ws/Utf8CodingSpecs.scala | 0 .../impl/engine/ws/WSClientAutobahnTest.scala | 4 +- .../impl/engine/ws/WSServerAutobahnTest.scala | 4 +- .../http/impl/engine/ws/WSTestSetupBase.scala | 2 +- .../http/impl/engine/ws/WSTestUtils.scala | 0 .../impl/engine/ws/WebSocketClientSpec.scala | 2 +- .../engine/ws/WebSocketIntegrationSpec.scala | 6 +- .../impl/engine/ws/WebSocketServerSpec.scala | 0 .../impl/model/parser/HttpHeaderSpec.scala | 12 +- .../impl/util/AkkaSpecWithMaterializer.scala | 4 +- .../akka/http/impl/util/BenchUtils.scala | 0 .../impl/util/ByteStringParserInputSpec.scala | 0 .../akka/http/impl/util/CollectionStage.scala | 0 .../http/impl/util/ExampleHttpContexts.scala | 0 .../http/impl/util/One2OneBidiFlowSpec.scala | 6 +- .../akka/http/impl/util/RenderingSpec.scala | 0 .../akka/http/impl/util/StreamUtilsSpec.scala | 5 +- .../http/impl/util/WithLogCapturing.scala | 0 .../akka/http/javadsl/ConnectHttpSpec.scala | 0 .../http/javadsl/ConnectionContextSpec.scala | 0 .../http/javadsl/HttpExtensionApiSpec.scala | 0 .../http/javadsl/JavaInitializationSpec.scala | 0 .../akka/http/javadsl/model/JavaApiSpec.scala | 0 .../javadsl/model/JavaApiTestCaseSpecs.scala | 0 .../http/javadsl/model/MultipartsSpec.scala | 2 +- .../model/headers/HttpCookieSpec.scala | 0 .../akka/http/scaladsl/ClientServerSpec.scala | 6 +- .../akka/http/scaladsl/ClientSpec.scala | 4 +- ...lientTransportWithCustomResolverSpec.scala | 0 .../scaladsl/GracefulTerminationSpec.scala | 6 +- .../akka/http/scaladsl/TestClient.scala | 4 +- .../akka/http/scaladsl/TestServer.scala | 4 +- .../scaladsl/TightRequestTimeoutSpec.scala | 6 +- .../http/scaladsl/model/DateTimeSpec.scala | 0 .../scaladsl/model/EntityDiscardingSpec.scala | 0 .../http/scaladsl/model/HttpEntitySpec.scala | 0 .../http/scaladsl/model/HttpMessageSpec.scala | 0 .../http/scaladsl/model/HttpMethodsSpec.scala | 0 .../http/scaladsl/model/MultipartSpec.scala | 0 .../scaladsl/model/SerializabilitySpec.scala | 0 .../http/scaladsl/model/TurkishISpec.scala | 0 .../akka/http/scaladsl/model/UriSpec.scala | 12 +- .../scaladsl/model/headers/HeaderSpec.scala | 0 .../model/sse/ServerSentEventSpec.scala | 0 .../ClientConnectionSettingsSpec.scala | 0 .../settings/ConnectionPoolSettingsSpec.scala | 0 .../settings/Http2CommonSettingsSpec.scala | 0 .../settings/PreviewServerSettingsSpec.scala | 0 .../settings/ServerSettingsSpec.scala | 0 .../settings/SettingsEqualitySpec.scala | 0 .../http/scaladsl/util/FastFutureSpec.scala | 0 .../akka/stream/testkit/Utils.scala | 0 .../akka/testkit/AkkaSpec.scala | 4 +- .../akka/testkit/Coroner.scala | 0 .../http/HttpModelIntegrationSpec.scala | 4 +- .../akka/parboiled2/support/TailSwitch.scala | 8 +- project/Dependencies.scala | 2 +- 115 files changed, 119 insertions(+), 1389 deletions(-) delete mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala delete mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala delete mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala delete mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala delete mode 100644 akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala delete mode 100644 akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala delete mode 100644 akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/AcceptCharsetHeader.scala (94%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/AcceptEncodingHeader.scala (74%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/AcceptHeader.scala (97%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/AcceptLanguageHeader.scala (93%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/Base64Parsing.scala (100%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/CacheControlHeader.scala (100%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/CommonActions.scala (100%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/CommonRules.scala (98%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/ContentDispositionHeader.scala (97%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/ContentTypeHeader.scala (97%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/HeaderParser.scala (98%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/IpAddressParsing.scala (100%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/LinkHeader.scala (85%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/SimpleHeaders.scala (98%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/StringBuilding.scala (100%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/UriParser.scala (99%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/impl/model/parser/WebSocketHeaders.scala (97%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/scaladsl/model/HttpHeader.scala (100%) rename akka-http-core/src/main/{scala-2 => scala}/akka/http/scaladsl/model/headers/ProductVersion.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/ConfigSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/HashCodeCollider.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/ClientCancellationSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/ConnectionPoolSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/HostConnectionPoolSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/HttpConfigurationSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/PrepareResponseSpec.scala (95%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala (98%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/client/pool/SlotStateSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/parsing/BoyerMooreSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala (93%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/parsing/RequestParserSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/parsing/ResponseParserSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/rendering/RequestRendererSpec.scala (98%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/rendering/ResponseRendererSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/server/HttpServerBug21008Spec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/server/HttpServerSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/server/HttpServerTestSetupBase.scala (96%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/server/PrepareRequestsSpec.scala (96%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/BitBuilder.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/ByteStringSinkProbe.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/EchoTestClientApp.scala (94%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/FramingSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/MessageSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/Utf8CodingSpecs.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WSClientAutobahnTest.scala (98%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WSServerAutobahnTest.scala (93%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WSTestSetupBase.scala (98%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WSTestUtils.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WebSocketClientSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala (96%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/engine/ws/WebSocketServerSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/model/parser/HttpHeaderSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/AkkaSpecWithMaterializer.scala (91%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/BenchUtils.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/ByteStringParserInputSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/CollectionStage.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/ExampleHttpContexts.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/One2OneBidiFlowSpec.scala (97%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/RenderingSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/StreamUtilsSpec.scala (95%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/impl/util/WithLogCapturing.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/ConnectHttpSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/ConnectionContextSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/HttpExtensionApiSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/JavaInitializationSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/model/JavaApiSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/model/MultipartsSpec.scala (97%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/javadsl/model/headers/HttpCookieSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/ClientServerSpec.scala (99%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/ClientSpec.scala (92%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/GracefulTerminationSpec.scala (98%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/TestClient.scala (96%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/TestServer.scala (95%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/TightRequestTimeoutSpec.scala (89%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/DateTimeSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/EntityDiscardingSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/HttpEntitySpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/HttpMessageSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/HttpMethodsSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/MultipartSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/SerializabilitySpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/TurkishISpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/UriSpec.scala (98%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/headers/HeaderSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/settings/ServerSettingsSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/settings/SettingsEqualitySpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/http/scaladsl/util/FastFutureSpec.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/stream/testkit/Utils.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/akka/testkit/AkkaSpec.scala (95%) rename akka-http-core/src/test/{scala-2 => scala}/akka/testkit/Coroner.scala (100%) rename akka-http-core/src/test/{scala-2 => scala}/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala (98%) diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala deleted file mode 100644 index ae1f9ecaf9c..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/Base64Parsing.scala +++ /dev/null @@ -1,90 +0,0 @@ -/* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev - * - * 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 - * - * http://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 akka.http.impl.model.parser - -import akka.annotation.InternalApi -import akka.parboiled2.util.Base64 -import akka.parboiled2._ - -/** - * INTERNAL API - * - * Rules for parsing Base-64 encoded strings. - */ -@InternalApi -private[parser] trait Base64Parsing { this: Parser => - import Base64Parsing._ - - /** - * Parses an RFC4045-encoded string and decodes it onto the value stack. - */ - def rfc2045String: Rule1[Array[Byte]] = base64StringOrBlock(rfc2045Alphabet, rfc2045StringDecoder) - - /** - * Parses an RFC4045-encoded string potentially containing newlines and decodes it onto the value stack. - */ - def rfc2045Block: Rule1[Array[Byte]] = base64StringOrBlock(rfc2045Alphabet, rfc2045BlockDecoder) - - /** - * Parses a akka.parboiled2.util.Base64.custom()-encoded string and decodes it onto the value stack. - */ - def base64CustomString: Rule1[Array[Byte]] = base64StringOrBlock(customAlphabet, customStringDecoder) - - /** - * Parses a akka.parboiled2.util.Base64.custom()-encoded string potentially containing newlines - * and decodes it onto the value stack. - */ - def base64CustomBlock: Rule1[Array[Byte]] = base64StringOrBlock(customAlphabet, customBlockDecoder) - - /** - * Parses a BASE64-encoded string with the given alphabet and decodes it onto the value - * stack using the given codec. - */ - def base64StringOrBlock(alphabet: CharPredicate, decoder: Decoder): Rule1[Array[Byte]] = { - val start = cursor - rule { - oneOrMore(alphabet) ~ run { - decoder(input.sliceCharArray(start, cursor)) match { - case null => MISMATCH - case bytes => push(bytes) - } - } - } - } -} - -/** INTERNAL API */ -@InternalApi -private[http] object Base64Parsing { - type Decoder = Array[Char] => Array[Byte] - - val rfc2045Alphabet = CharPredicate(Base64.rfc2045().getAlphabet).asMaskBased - val customAlphabet = CharPredicate(Base64.custom().getAlphabet).asMaskBased - - val rfc2045StringDecoder: Decoder = decodeString(Base64.rfc2045()) - val customStringDecoder: Decoder = decodeString(Base64.custom()) - - val rfc2045BlockDecoder: Decoder = decodeBlock(Base64.rfc2045()) - val customBlockDecoder: Decoder = decodeBlock(Base64.custom()) - - private val base64url = new Base64("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_=") - /** as described in RFC4648 5. - https://tools.ietf.org/html/rfc4648#section-5 */ - val base64UrlStringDecoder: Decoder = decodeString(base64url) - - def decodeString(codec: Base64)(chars: Array[Char]): Array[Byte] = codec.decodeFast(chars) - def decodeBlock(codec: Base64)(chars: Array[Char]): Array[Byte] = codec.decode(chars) -} diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala deleted file mode 100644 index 64fd5f728c2..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/CommonRules.scala +++ /dev/null @@ -1,475 +0,0 @@ -/* - * Copyright (C) 2009-2021 Lightbend Inc. - */ - -package akka.http.impl.model.parser - -import scala.collection.immutable -import scala.collection.immutable.TreeMap - -import akka.http.scaladsl.model._ -import akka.http.scaladsl.model.headers._ -import akka.parboiled2._ -import akka.parboiled2.support.hlist._ - -private[parser] trait CommonRules { this: Parser with StringBuilding => - import CharacterClasses._ - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7230#section-1.2 referencing - // http://tools.ietf.org/html/rfc5234#appendix-B.1 - // ****************************************************************************************** - def CRLF = rule { CR ~ LF } - - def OCTET = rule { ANY } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7230#section-3.2.3 - // ****************************************************************************************** - - def OWS = rule { zeroOrMore(optional(CRLF) ~ oneOrMore(WSP)) } // extended with `obs-fold` - - def RWS = rule { oneOrMore(optional(CRLF) ~ oneOrMore(WSP)) } // extended with `obs-fold` - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7230#section-3.2.6 - // ****************************************************************************************** - def word = rule { token | `quoted-string` } - - def token: Rule1[String] = rule { capture(token0) ~ OWS } - - def `quoted-string`: Rule1[String] = rule { - DQUOTE ~ clearSB() ~ zeroOrMore(qdtext ~ appendSB() | `quoted-pair`) ~ push(sb.toString) ~ DQUOTE ~ OWS - } - - def qdtext = rule { `qdtext-base` | `obs-text` } - - def `obs-text` = rule { "\u0080" - "\uFFFE" } - - def `quoted-pair` = rule { '\\' ~ (`quotable-base` | `obs-text`) ~ appendSB() } - - // builds a string via the StringBuilding StringBuilder - def comment(maxNesting: Int = 10): Rule0 = rule { - ws('(') ~ clearSB() ~ zeroOrMore(ctext | `quoted-cpair` | `nested-comment`(maxNesting)) ~ ws(')') - } - - def `nested-comment`(maxNesting: Int) = - if (maxNesting == 0) throw new ParsingException(ErrorInfo("Illegal header value", "Header comment nested too deeply")) - else { - var saved: String = null - rule { &('(') ~ run { saved = sb.toString } ~ (comment(maxNesting - 1) ~ prependSB(saved + " (") ~ appendSB(')') | setSB(saved) ~ test(false)) } - } - - def ctext = rule { (`ctext-base` | `obs-text`) ~ appendSB() } - - def `quoted-cpair` = `quoted-pair` - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7234#section-5.3 - // ****************************************************************************************** - - def `expires-date`: Rule1[DateTime] = ??? /*rule { - (`HTTP-date` | zeroOrMore(ANY) ~ push(DateTime.MinValue)) ~ OWS - }*/ - /* - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7231#section-7.1.1.1 - // but more lenient where we have already seen differing implementations in the field - // ****************************************************************************************** - - def `HTTP-date`: Rule1[DateTime] = rule { - (`IMF-fixdate` | `asctime-date` | '0' ~ push(DateTime.MinValue)) ~ OWS - } - - def `IMF-fixdate` = rule { // mixture of the spec-ed `IMF-fixdate` and `rfc850-date` - (`day-name-l` | `day-name`) ~ ", " ~ (date1 | date2) ~ ' ' ~ `time-of-day` ~ ' ' ~ ("GMT" | "UTC") ~> { - (wkday, day, month, year, hour, min, sec) => createDateTime(year, month, day, hour, min, sec, wkday) - } - } - - def `day-name` = rule( - "Sun" ~ push(0) | "Mon" ~ push(1) | "Tue" ~ push(2) | "Wed" ~ push(3) | "Thu" ~ push(4) | "Fri" ~ push(5) | "Sat" ~ push(6)) - - def date1 = rule { day ~ `date-sep` ~ month ~ `date-sep` ~ year } - - def day = rule { digit2 | digit } - - def month = rule( - "Jan" ~ push(1) | "Feb" ~ push(2) | "Mar" ~ push(3) | "Apr" ~ push(4) | "May" ~ push(5) | "Jun" ~ push(6) | "Jul" ~ push(7) | - "Aug" ~ push(8) | "Sep" ~ push(9) | "Oct" ~ push(10) | "Nov" ~ push(11) | "Dec" ~ push(12)) - - def year = rule { digit4 | digit2 ~> (y => if (y <= 69) y + 2000 else y + 1900) } - - def `time-of-day` = rule { hour ~ ':' ~ minute ~ ':' ~ second } - def hour = rule { digit2 } - def minute = rule { digit2 } - def second = rule { digit2 } - - // def `obs-date` = rule { `rfc850-date` | `asctime-date` } - - // def `rfc850-date` = rule { `day-name-l` ~ ", " ~ date2 ~ ' ' ~ `time-of-day` ~ " GMT" } - - // per #17714, parse two digit year to https://tools.ietf.org/html/rfc6265#section-5.1.1 - def date2 = rule { day ~ '-' ~ month ~ '-' ~ (digit2 ~> (y => if (y <= 69) y + 2000 else y + 1900)) } - - def `day-name-l` = rule( - "Sunday" ~ push(0) | "Monday" ~ push(1) | "Tuesday" ~ push(2) | "Wednesday" ~ push(3) | "Thursday" ~ push(4) | - "Friday" ~ push(5) | "Saturday" ~ push(6)) - - def `asctime-date` = rule { - `day-name` ~ ' ' ~ date3 ~ ' ' ~ `time-of-day` ~ ' ' ~ year ~> { - (wkday, month, day, hour, min, sec, year) => createDateTime(year, month, day, hour, min, sec, wkday) - } - } - - def date3 = rule { month ~ ' ' ~ (digit2 | ' ' ~ digit) } -*/ - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7231#section-5.3.1 - // ****************************************************************************************** - - def weight = rule { ws(';') ~ ws('q') ~ ws('=') ~ qvalue } // a bit more lenient than the spec - - def qvalue = rule { // a bit more lenient than the spec - capture('0' ~ optional('.' ~ zeroOrMore(DIGIT)) - | '.' ~ oneOrMore(DIGIT) - | '1' ~ optional('.' ~ zeroOrMore('0'))) ~> (_.toFloat) ~ OWS - } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7231#section-3.1.1.1 - // ****************************************************************************************** - - def `media-type`: RuleN[String :: String :: Seq[(String, String)] :: HNil] = rule { - `type` ~ '/' ~ subtype ~ zeroOrMore(ws(';') ~ parameter) - } - - def `type` = rule { token } - - def subtype = rule { token } - - def parameter = rule { attribute ~ ws('=') ~ value ~> ((_, _)) } - - def attribute = rule { token } - - def value = rule { word } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc4647#section-2.1 - // ****************************************************************************************** - def language = rule { - `primary-tag` ~ zeroOrMore('-' ~ `sub-tag`) ~> (Language(_, _)) - } - - def `primary-tag` = rule { capture(oneOrMore(ALPHA)) ~ OWS } - - def `sub-tag` = rule { capture(oneOrMore(ALPHANUM)) ~ OWS } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc4647#section-2.1 - // ****************************************************************************************** - - def `auth-scheme` = rule { token } - - def `auth-param` = rule { token ~ ws('=') ~ word } - - def `token68` = rule { capture(oneOrMore(`token68-start`) ~ zeroOrMore('=')) ~ OWS } - - def challenge = rule { - `challenge-or-credentials` ~> { (scheme, tokenAndParams) => - tokenAndParams match { - case ("", Nil) => HttpChallenge(scheme, None) - case (token, Nil) => HttpChallenge(scheme, None, Map("" -> token)) - case (_, params) => { - val (realms, otherParams) = params.partition(_._1 equalsIgnoreCase "realm") - HttpChallenge(scheme, realms.headOption.map(_._2), TreeMap(otherParams: _*)) - } - } - } - } - - def `challenge-or-credentials`: Rule2[String, (String, Seq[(String, String)])] = rule { - `auth-scheme` ~ ( - oneOrMore(`auth-param` ~> (_ -> _)).separatedBy(listSep) ~> (x => ("", x)) - | `token68` ~> (x => (x, Nil)) - | push(("", Nil))) - } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7234#section-1.2.1 - // ****************************************************************************************** - - def `delta-seconds` = rule { longNumberCappedAtIntMaxValue } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7232#section-2.3 - // ****************************************************************************************** - - def `entity-tag` = rule { - ("W/" ~ push(true) | push(false)) ~ `opaque-tag` ~> ((weak, tag) => EntityTag(tag, weak)) - } - - def `opaque-tag` = rule { '"' ~ capture(zeroOrMore(`etagc-base` | `obs-text`)) ~ '"' } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7235#section-2.1 - // ****************************************************************************************** - def credentials = rule { - `basic-credential-def` | `oauth2-bearer-token` | `generic-credentials` - } - - def `basic-credential-def` = rule { - ignoreCase("basic") ~ OWS ~ `basic-cookie` ~> (BasicHttpCredentials(_)) - } - - def `basic-cookie` = rule { `token68` } - - // http://tools.ietf.org/html/rfc6750#section-2.1 - def `oauth2-bearer-token` = rule { - ignoreCase("bearer") ~ OWS ~ `token68` ~> (OAuth2BearerToken(_)) - } - - def `generic-credentials` = rule { - `challenge-or-credentials` ~> ((scheme, tokenAndParams) => { - val (token, params) = tokenAndParams - GenericHttpCredentials(scheme, token, TreeMap(params: _*)) - }) - } - - /** - * Either `Some(cookiePair)` if the cookie pair is parsable using the giving cookie parsing mode - * or None, otherwise. - */ - def `optional-cookie-pair`: Rule1[Option[HttpCookiePair]] = rule { - (`cookie-pair` ~ &(`cookie-separator`) ~> (Some(_: HttpCookiePair))) | - // fallback that parses and discards everything until the next semicolon - (zeroOrMore(!`cookie-separator` ~ ANY) ~ &(`cookie-separator`) ~ push(None)) - } - - def `cookie-pair`: Rule1[HttpCookiePair] = rule { - `cookie-name` ~ ws('=') ~ `cookie-value` ~> (createCookiePair _) - } - - def `cookie-name` = rule { token } - - // abstract methods need to be implemented depending on actual cookie parsing mode - def `cookie-value`: Rule1[String] - def createCookiePair(name: String, value: String): HttpCookiePair - - // ****************************************************************************************** - // https://tools.ietf.org/html/rfc6265#section-4.1.1 - // ****************************************************************************************** - def `cookie-value-rfc-6265` = rule { - ('"' ~ capture(zeroOrMore(`cookie-octet-rfc-6265`)) ~ '"' | capture(zeroOrMore(`cookie-octet-rfc-6265`))) ~ OWS - } - - def `cookie-value-raw` = rule { - capture(zeroOrMore(`cookie-octet-raw`)) ~ OWS - } - - def `cookie-av` = rule { - `expires-av` | `max-age-av` | `domain-av` | `path-av` | `same-site-av` | `secure-av` | `httponly-av` | `extension-av` - } - - def `expires-av` = rule { - ignoreCase("expires=") ~ OWS ~ `expires-date` ~> { (c: HttpCookie, dt: DateTime) => c.withExpires(dt) } - } - - def `max-age-av` = rule { - ignoreCase("max-age=") ~ OWS ~ longNumberCappedAtIntMaxValue ~> { (c: HttpCookie, seconds: Long) => c.withMaxAge(seconds) } - } - - def `domain-av` = rule { - ignoreCase("domain=") ~ OWS ~ `domain-value` ~> { (c: HttpCookie, domainName: String) => c.withDomain(domainName) } - } - - // https://tools.ietf.org/html/rfc1034#section-3.5 relaxed by https://tools.ietf.org/html/rfc1123#section-2 - // to also allow digits at the start of a label - def `domain-value` = rule { - optional('.') ~ capture(oneOrMore(oneOrMore(oneOrMore(ALPHANUM)).separatedBy('-')).separatedBy('.')) ~ OWS - } - - def `path-av` = rule { - ignoreCase("path=") ~ OWS ~ `path-value` ~> { (c: HttpCookie, pathValue: String) => c.withPath(pathValue) } - } - - // http://www.rfc-editor.org/errata_search.php?rfc=6265 - def `path-value` = rule { - capture(zeroOrMore(`av-octet`)) ~ OWS - } - - def `same-site-av` = rule { - ignoreCase("samesite=") ~ OWS ~ `same-site-value` ~> { (c: HttpCookie, sameSiteValue: String) => c.withSameSite(sameSite = SameSite(sameSiteValue)) } - } - - def `same-site-value` = rule { - capture(ignoreCase("lax") | ignoreCase("strict") | ignoreCase("none")) ~ OWS - } - - def `secure-av` = rule { - ignoreCase("secure") ~ OWS ~> { (cookie: HttpCookie) => cookie.withSecure(true) } - } - - def `httponly-av` = rule { - ignoreCase("httponly") ~ OWS ~> { (cookie: HttpCookie) => cookie.withHttpOnly(true) } - } - - // http://www.rfc-editor.org/errata_search.php?rfc=6265 - def `extension-av` = rule { - !(ignoreCase("expires=") - | ignoreCase("max-age=") - | ignoreCase("domain=") - | ignoreCase("path=") - | ignoreCase("samesite=") - | ignoreCase("secure") - | ignoreCase("httponly")) ~ - capture(zeroOrMore(`av-octet`)) ~ OWS ~> { (c: HttpCookie, s: String) => c.withExtension(s) } - } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc6454#section-7.1 - // ****************************************************************************************** - def `origin-list-or-null` = rule { - "null" ~ OWS ~ push(immutable.Seq.empty[HttpOrigin]) | `origin-list` - } - - def `origin-list` = rule { - oneOrMore(capture(oneOrMore(VCHAR)) ~> (HttpOrigin(_))).separatedBy(SP) ~ OWS // offload to URL parser - } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7233#appendix-D - // ****************************************************************************************** - - def `byte-content-range` = rule { `bytes-unit` ~ (`byte-range-resp` | `unsatisfied-range`) } - - def `byte-range` = rule { - `first-byte-pos` ~ ws('-') ~ `last-byte-pos` - } - - def `byte-range-resp` = rule { - `byte-range` ~ ws('/') ~ (`complete-length` ~> (Some(_)) | ws('*') ~ push(None)) ~> (ContentRange(_, _, _)) - } - - def `byte-range-set` = rule { - zeroOrMore(ws(',')) ~ oneOrMore(`byte-range-spec` | `suffix-byte-range-spec`).separatedBy(listSep) - } - - def `byte-range-spec` = rule { - `first-byte-pos` ~ ws('-') ~ (`last-byte-pos` ~> (ByteRange(_: Long, _)) | run(ByteRange.fromOffset(_))) - } - - def `byte-ranges-specifier` = rule { `bytes-unit` ~ ws('=') ~ `byte-range-set` } - - def `bytes-unit` = rule { "bytes" ~ OWS ~ push(RangeUnits.Bytes) } - - def `complete-length` = rule { longNumberCapped } - - def `first-byte-pos` = rule { longNumberCapped } - - def `last-byte-pos` = rule { longNumberCapped } - - def `other-content-range` = rule { `other-range-unit` ~ `other-range-resp` } - - def `other-range-resp` = rule { capture(zeroOrMore(ANY)) ~> (ContentRange.Other(_)) } - - def `other-range-set` = rule { oneOrMore(VCHAR) ~ OWS } - - def `other-range-unit` = rule { token ~> (RangeUnits.Other(_)) } - - def `other-ranges-specifier` = rule { `other-range-unit` ~ ws('=') ~ `other-range-set` } - - def `range-unit` = rule { `bytes-unit` | `other-range-unit` } - - def `suffix-byte-range-spec` = rule { '-' ~ `suffix-length` ~> (ByteRange.suffix(_)) } - - def `suffix-length` = rule { longNumberCapped } - - def `unsatisfied-range` = rule { '*' ~ '/' ~ `complete-length` ~> (ContentRange.Unsatisfiable(_)) } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7231#section-5.5.3 - // ****************************************************************************************** - - def product = rule { token ~ (ws('/') ~ `product-version` | push("")) } - - def `product-version` = rule { token } - - def `product-or-comment`: Rule1[ProductVersion] = rule( - product ~ comment() ~> (ProductVersion(_, _, sb.toString)) - | product ~> (ProductVersion(_, _)) - | comment() ~ push(ProductVersion("", "", sb.toString))) - - def products: Rule1[Seq[ProductVersion]] = rule { - `product-or-comment` ~ zeroOrMore(`product-or-comment`) ~> (_ +: _) - } - - // ****************************************************************************************** - // http://tools.ietf.org/html/rfc7230#section-4 - // ****************************************************************************************** - - def `transfer-coding`: Rule1[TransferEncoding] = rule( - ignoreCase("chunked") ~ OWS ~ push(TransferEncodings.chunked) - | ignoreCase("gzip") ~ OWS ~ push(TransferEncodings.gzip) - | ignoreCase("deflate") ~ OWS ~ push(TransferEncodings.deflate) - | ignoreCase("compress") ~ OWS ~ push(TransferEncodings.compress) - | ignoreCase("trailers") ~ OWS ~ push(TransferEncodings.trailers) - | `transfer-extension`) - - def `transfer-extension`: Rule1[TransferEncodings.Extension] = rule { - token ~ zeroOrMore(ws(';') ~ `transfer-parameter`) ~> (p => TreeMap(p: _*)) ~> (TransferEncodings.Extension(_, _)) - } - - def `transfer-parameter` = rule { token ~ ws('=') ~ word ~> (_ -> _) } - - // ****************************************************************************************** - // helpers - // ****************************************************************************************** - def token0: Rule0 = rule { oneOrMore(tchar) } - - def listSep: Rule0 = rule { ',' ~ OWS } - - def digit: Rule1[Int] = rule { DIGIT ~ push(digitInt(lastChar)) } - - def digit2: Rule1[Int] = rule { DIGIT ~ DIGIT ~ push(digitInt(charAt(-2)) * 10 + digitInt(lastChar)) } - - def digit4: Rule1[Int] = rule { - DIGIT ~ DIGIT ~ DIGIT ~ DIGIT ~ push(digitInt(charAt(-4)) * 1000 + digitInt(charAt(-3)) * 100 + digitInt(charAt(-2)) * 10 + digitInt(lastChar)) - } - - def ws(c: Char): Rule0 = rule { c ~ OWS } - def ws(s: String): Rule0 = rule { s ~ OWS } - - // parses a potentially long series of digits and extracts its Long value capping at Int.MaxValue in case of overflows - def longNumberCappedAtIntMaxValue: Rule1[Long] = rule { - capture((1 to 11).times(DIGIT)) ~> (s => math.min(s.toLong, Int.MaxValue)) ~ zeroOrMore(DIGIT) ~ OWS - } - - // parses a potentially long series of digits and extracts its Long value capping at 999,999,999,999,999,999 in case of overflows - def longNumberCapped: Rule1[Long] = rule( - (capture((1 to 18).times(DIGIT)) ~ !DIGIT ~> (_.toLong) - | oneOrMore(DIGIT) ~ push(999999999999999999L)) ~ OWS) - - private def digitInt(c: Char): Int = c - '0' - - private def createDateTime(year: Int, month: Int, day: Int, hour: Int, min: Int, sec: Int, wkday: Int): DateTime = { - val dt = DateTime(year, month, day, hour, min, sec) - if (dt.weekday != wkday) - throw ParsingException(s"Illegal weekday in date $dt: is '${DateTime.weekday(wkday)}' but " + - s"should be '${DateTime.weekday(dt.weekday)}'") - dt - } - - def httpMethodDef: Rule1[HttpMethod] = rule { - token ~> { s => - HttpMethods.getForKey(s) match { - case Some(m) => m - case None => HttpMethod.custom(s) - } - } - } - - def newUriParser(input: ParserInput): UriParser - def uriReference: Rule1[Uri] = rule { runSubParser(newUriParser(_).`URI-reference-pushed`) } -} - diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala deleted file mode 100644 index af38548c4cb..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/HeaderParser.scala +++ /dev/null @@ -1,230 +0,0 @@ -/* - * Copyright (C) 2009-2021 Lightbend Inc. - */ - -package akka.http.impl.model.parser - -import akka.annotation.InternalApi -import akka.http.scaladsl.settings.ParserSettings -import akka.http.scaladsl.settings.ParserSettings.CookieParsingMode -import akka.http.scaladsl.settings.ParserSettings.{ IllegalResponseHeaderValueProcessingMode, IllegalResponseHeaderNameProcessingMode } -import akka.http.scaladsl.model.headers.HttpCookiePair -import akka.util.ConstantFun - -import scala.util.control.NonFatal -import akka.http.impl.util.SingletonException -import akka.parboiled2._ -import akka.parboiled2.support.hlist._ -import akka.http.scaladsl.model._ - -/** - * INTERNAL API. - */ -//@InternalApi -//private[http] class HeaderParser( -// val input: ParserInput, -// settings: HeaderParser.Settings = HeaderParser.DefaultSettings) -// extends Parser with DynamicRuleHandler[HeaderParser, HttpHeader :: HNil] -// with CommonRules -// with AcceptCharsetHeader -// with AcceptEncodingHeader -// with AcceptHeader -// with AcceptLanguageHeader -// with CacheControlHeader -// with ContentDispositionHeader -// with ContentTypeHeader -// with CommonActions -// with IpAddressParsing -// with LinkHeader -// with SimpleHeaders -// with StringBuilding -// with WebSocketHeaders { -// import CharacterClasses._ -// -// override def customMediaTypes = settings.customMediaTypes -// protected def maxCommentParsingDepth: Int = settings.maxCommentParsingDepth -// -// // http://www.rfc-editor.org/errata_search.php?rfc=7230 errata id 4189 -// def `header-field-value`: Rule1[String] = rule { -// FWS ~ clearSB() ~ `field-value` ~ FWS ~ EOI ~ push(sb.toString) -// } -// def `field-value` = { -// var fwsStart = cursor -// rule { -// zeroOrMore(`field-value-chunk`).separatedBy { // zeroOrMore because we need to also accept empty values -// run { fwsStart = cursor } ~ FWS ~ &(`field-value-char`) ~ run { if (cursor > fwsStart) sb.append(' ') } -// } -// } -// } -// def `field-value-chunk` = rule { oneOrMore(`field-value-char` ~ appendSB()) } -// def `field-value-char` = rule { VCHAR | `obs-text` } -// def FWS = rule { zeroOrMore(WSP) ~ zeroOrMore(`obs-fold`) } -// def `obs-fold` = rule { CRLF ~ oneOrMore(WSP) } -// -// ///////////////// DynamicRuleHandler ////////////// -// -// override type Result = HeaderParser.Result -// def parser: HeaderParser = this -// def success(result: HttpHeader :: HNil): Result = HeaderParser.Success(result.head) -// def parseError(error: ParseError): HeaderParser.Failure = { -// val formatter = new ErrorFormatter(showLine = false) -// HeaderParser.Failure(ErrorInfo(formatter.format(error, input), formatter.formatErrorLine(error, input))) -// } -// def failure(error: Throwable): HeaderParser.Failure = -// HeaderParser.Failure { -// error match { -// case IllegalUriException(info) => info -// case NonFatal(e) => ErrorInfo.fromCompoundString(e.getMessage) -// } -// } -// def ruleNotFound(ruleName: String): Result = HeaderParser.RuleNotFound -// -// def newUriParser(input: ParserInput): UriParser = new UriParser(input, uriParsingMode = settings.uriParsingMode) -// -// def `cookie-value`: Rule1[String] = -// settings.cookieParsingMode match { -// case CookieParsingMode.RFC6265 => rule { `cookie-value-rfc-6265` } -// case CookieParsingMode.Raw => rule { `cookie-value-raw` } -// } -// -// def createCookiePair(name: String, value: String): HttpCookiePair = settings.cookieParsingMode match { -// case CookieParsingMode.RFC6265 => HttpCookiePair(name, value) -// case CookieParsingMode.Raw => HttpCookiePair.raw(name, value) -// } -//} - -/** - * INTERNAL API. - */ -@InternalApi -private[http] object HeaderParser { - sealed trait Result - case class Success(header: HttpHeader) extends Result - case class Failure(info: ErrorInfo) extends Result - case object RuleNotFound extends Result - - object EmptyCookieException extends SingletonException("Cookie header contained no parsable cookie values.") - - def lookupParser(headerName: String, settings: Settings = DefaultSettings): Option[String => HeaderParser.Result] = - ??? - // dispatch.lookup(headerName).map { runner => (value: String) => - // import akka.parboiled2.EOI - // val v = value + EOI // this makes sure the parser isn't broken even if there's no trailing garbage in this value - // val parser = new HeaderParser(v, settings) - // runner(parser) match { - // case r @ Success(_) if parser.cursor == v.length => r - // case r @ Success(_) => - // Failure(ErrorInfo( - // "Header parsing error", - // s"Rule for $headerName accepted trailing garbage. Is the parser missing a trailing EOI?")) - // case Failure(e) => Failure(e.copy(summary = e.summary.filterNot(_ == EOI), detail = e.detail.filterNot(_ == EOI))) - // case RuleNotFound => RuleNotFound - // } - // } - - def parseFull(headerName: String, value: String, settings: Settings = DefaultSettings): HeaderParser.Result = - lookupParser(headerName, settings).map(_(value)).getOrElse(HeaderParser.RuleNotFound) - - def ruleNames: Seq[String] = ??? - // val (dispatch, ruleNames) = DynamicRuleDispatch[HeaderParser, HttpHeader :: HNil]( - // "accept", - // "accept-charset", - // "accept-encoding", - // "accept-language", - // "accept-ranges", - // "access-control-allow-credentials", - // "access-control-allow-headers", - // "access-control-allow-methods", - // "access-control-allow-origin", - // "access-control-expose-headers", - // "access-control-max-age", - // "access-control-request-headers", - // "access-control-request-method", - // "accept", - // "age", - // "allow", - // "authorization", - // "cache-control", - // "connection", - // "content-disposition", - // "content-encoding", - // "content-length", - // "content-location", - // "content-range", - // "content-type", - // "cookie", - // "date", - // "etag", - // "expect", - // "expires", - // "host", - // "if-match", - // "if-modified-since", - // "if-none-match", - // "if-range", - // "if-unmodified-since", - // "last-modified", - // "link", - // "location", - // "origin", - // "proxy-authenticate", - // "proxy-authorization", - // "range", - // "referer", - // "retry-after", - // "server", - // "sec-websocket-accept", - // "sec-websocket-extensions", - // "sec-websocket-key", - // "sec-websocket-protocol", - // "sec-websocket-version", - // "set-cookie", - // "strict-transport-security", - // "te", - // "transfer-encoding", - // "upgrade", - // "user-agent", - // "www-authenticate", - // "x-forwarded-for", - // "x-forwarded-host", - // "x-forwarded-proto", - // "x-real-ip") - - abstract class Settings { - def uriParsingMode: Uri.ParsingMode - def cookieParsingMode: ParserSettings.CookieParsingMode - def customMediaTypes: MediaTypes.FindCustom - def maxCommentParsingDepth: Int - def illegalResponseHeaderNameProcessingMode: IllegalResponseHeaderNameProcessingMode - def illegalResponseHeaderValueProcessingMode: IllegalResponseHeaderValueProcessingMode - } - def Settings( - uriParsingMode: Uri.ParsingMode = Uri.ParsingMode.Relaxed, - cookieParsingMode: ParserSettings.CookieParsingMode = ParserSettings.CookieParsingMode.RFC6265, - customMediaTypes: MediaTypes.FindCustom = ConstantFun.scalaAnyTwoToNone, - maxCommentParsingDepth: Int = 5, - modeValue: IllegalResponseHeaderValueProcessingMode = ParserSettings.IllegalResponseHeaderValueProcessingMode.Error, - modeName: IllegalResponseHeaderNameProcessingMode = ParserSettings.IllegalResponseHeaderNameProcessingMode.Error): Settings = { - - val _uriParsingMode = uriParsingMode - val _cookieParsingMode = cookieParsingMode - val _customMediaTypes = customMediaTypes - val _maxCommentParsingDepth = maxCommentParsingDepth - val _illegalResponseHeaderValueProcessingMode = modeValue - val _illegalResponseHeaderNameProcessingMode = modeName - - new Settings { - def uriParsingMode: Uri.ParsingMode = _uriParsingMode - def cookieParsingMode: CookieParsingMode = _cookieParsingMode - def customMediaTypes: MediaTypes.FindCustom = _customMediaTypes - def maxCommentParsingDepth: Int = _maxCommentParsingDepth - - def illegalResponseHeaderValueProcessingMode: IllegalResponseHeaderValueProcessingMode = - _illegalResponseHeaderValueProcessingMode - - def illegalResponseHeaderNameProcessingMode: IllegalResponseHeaderNameProcessingMode = - _illegalResponseHeaderNameProcessingMode - } - } - val DefaultSettings: Settings = Settings() -} diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala deleted file mode 100644 index 3e95c2a99af..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/StringBuilding.scala +++ /dev/null @@ -1,68 +0,0 @@ -/* - * Copyright (C) 2009-2017 Mathias Doenitz, Alexander Myltsev - * - * 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 - * - * http://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 akka.http.impl.model.parser - -import akka.parboiled2._ - -/** - * For certain high-performance use-cases it is better to construct Strings - * that the parser is to produce/extract from the input in a char-by-char fashion. - * - * Mixing this trait into your parser gives you a simple facility to support this. - */ -private[parser] trait StringBuilding { this: Parser => - protected val sb = new java.lang.StringBuilder - - def clearSB(): Rule0 = rule { run(sb.setLength(0)) } - - def appendSB(): Rule0 = rule { run(sb.append(lastChar)) } - - def appendSB(offset: Int): Rule0 = rule { run(sb.append(charAt(offset))) } - - def appendSB(c: Char): Rule0 = rule { run(sb.append(c)) } - - def appendSB(s: String): Rule0 = rule { run(sb.append(s)) } - - def prependSB(): Rule0 = rule { run(doPrepend(lastChar)) } - - def prependSB(offset: Int): Rule0 = rule { run(doPrepend(charAt(offset))) } - - def prependSB(c: Char): Rule0 = rule { run(doPrepend(c)) } - - def prependSB(s: String): Rule0 = rule { run(doPrepend(s)) } - - def setSB(s: String): Rule0 = rule { run(doSet(s)) } - - private def doPrepend(c: Char): Unit = { - val saved = sb.toString - sb.setLength(0) - sb.append(c) - sb.append(saved) - } - - private def doPrepend(s: String): Unit = { - val saved = sb.toString - sb.setLength(0) - sb.append(s) - sb.append(saved) - } - - private def doSet(s: String): Unit = { - sb.setLength(0) - sb.append(s) - } -} diff --git a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala b/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala deleted file mode 100644 index 5d237afc903..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/impl/model/parser/UriParser.scala +++ /dev/null @@ -1,254 +0,0 @@ -/* - * Copyright (C) 2009-2021 Lightbend Inc. - */ - -package akka.http.impl.model.parser - -import java.nio.charset.Charset - -import akka.parboiled2._ -import akka.http.impl.util.{ StringRendering, enhanceString_ } -import akka.http.scaladsl.model.{ Uri, UriRendering } -import akka.http.scaladsl.model.headers.HttpOrigin -import Parser.DeliveryScheme.Either -import Uri._ -import akka.annotation.InternalApi - -/** - * INTERNAL API - * - * http://tools.ietf.org/html/rfc3986 - */ -@InternalApi -private[http] final class UriParser( - private[this] var _input: ParserInput, - val uriParsingCharset: Charset, - val uriParsingMode: Uri.ParsingMode, - val maxValueStackSize: Int) extends Parser(maxValueStackSize = maxValueStackSize) /*with IpAddressParsing with StringBuilding*/ { - import CharacterClasses._ - - override def input: ParserInput = _input - - def this( - input: ParserInput, - uriParsingCharset: Charset = UTF8, - uriParsingMode: Uri.ParsingMode = Uri.ParsingMode.Relaxed) = - this(input, uriParsingCharset, uriParsingMode, 1024) - - def parseAbsoluteUri(): Uri = ??? - - def parseUriReference(): Uri = ??? - - def parseAndResolveUriReference(base: Uri): Uri = ??? - - def parseOrigin(): HttpOrigin = ??? - - def parseHost(): Host = ??? - - /** - * @return a 'raw' (percent-encoded) query string that does not contain invalid characters. - */ - def parseRawQueryString(): String = ??? - - /** - * @param rawQueryString 'raw' (percent-encoded) query string that in Relaxed mode may contain characters not allowed - * by https://tools.ietf.org/html/rfc3986#section-3.4 but is guaranteed not to have invalid percent-encoded characters - * @return a 'raw' (percent-encoded) query string that does not contain invalid characters. - */ - def parseSafeRawQueryString(rawQueryString: String): String = uriParsingMode match { - case Uri.ParsingMode.Strict => - // Cannot contain invalid characters in strict mode - rawQueryString - case Uri.ParsingMode.Relaxed => - // Percent-encode invalid characters - UriRendering.encode(new StringRendering, rawQueryString, uriParsingCharset, `query-fragment-char` ++ '%', false).get - } - - def parseQuery(): Query = ??? - - def parseAuthority(): Authority = ??? - /*rule(authority ~ EOI).run() match { - case Right(_) => Authority(_host, _port, _userinfo) - case Left(error) => fail(error, "authority") - }*/ - - // def fail(error: ParseError, target: String): Nothing = { - // val formatter = new ErrorFormatter(showLine = false) - // Uri.fail(s"Illegal $target: " + formatter.format(error, input), formatter.formatErrorLine(error, input)) - // } - // - // private[this] val `path-segment-char` = uriParsingMode match { - // case Uri.ParsingMode.Strict => `pchar-base` - // case _ => `relaxed-path-segment-char` - // } - // private[this] val `query-char` = uriParsingMode match { - // case Uri.ParsingMode.Strict => `query-fragment-char` - // case _ => `relaxed-query-char` - // } - // private[this] val `query-key-char` = uriParsingMode match { - // case Uri.ParsingMode.Strict => `strict-query-key-char` - // case Uri.ParsingMode.Relaxed => `relaxed-query-key-char` - // } - // private[this] val `query-value-char` = uriParsingMode match { - // case Uri.ParsingMode.Strict => `strict-query-value-char` - // case Uri.ParsingMode.Relaxed => `relaxed-query-value-char` - // } - // private[this] val `fragment-char` = uriParsingMode match { - // case Uri.ParsingMode.Strict => `query-fragment-char` - // case _ => `relaxed-fragment-char` - // } - // - // // New vars need to be reset in `reset` below - // private[this] var _scheme = "" - // private[this] var _userinfo = "" - // private[this] var _host: Host = Host.Empty - // private[this] var _port: Int = 0 - // private[this] var _path: Path = Path.Empty - // /** - // * Percent-encoded. When in in 'relaxed' mode, characters not permitted by https://tools.ietf.org/html/rfc3986#section-3.4 - // * are already automatically percent-encoded here - // */ - // private[this] var _rawQueryString: Option[String] = None - // private[this] var _fragment: Option[String] = None - // - // /** Allows to reuse this parser. */ - // def reset(newInput: ParserInput): Unit = { - // _input = newInput - // _scheme = "" - // _userinfo = "" - // _host = Host.Empty - // _port = 0 - // _path = Path.Empty - // _rawQueryString = None - // _fragment = None - // _firstPercentIx = -1 - // } - // - // private[this] def setScheme(scheme: String): Unit = _scheme = scheme - // private[this] def setUserInfo(userinfo: String): Unit = _userinfo = userinfo - // private[this] def setHost(host: Host): Unit = _host = host - // private[this] def setPort(port: Int): Unit = _port = port - // private[this] def setPath(path: Path): Unit = _path = path - // private[this] def setRawQueryString(rawQueryString: String): Unit = _rawQueryString = Some(parseSafeRawQueryString(rawQueryString)) - // private[this] def setFragment(fragment: String): Unit = _fragment = Some(fragment) - // - // // http://tools.ietf.org/html/rfc3986#appendix-A - // - // def URI = rule { scheme ~ ':' ~ `hier-part` ~ optional('?' ~ rawQueryString) ~ optional('#' ~ fragment) } - // - // def origin = rule { scheme ~ ':' ~ '/' ~ '/' ~ hostAndPort } - // - // def `hier-part` = rule( - // '/' ~ '/' ~ authority ~ `path-abempty` - // | `path-absolute` - // | `path-rootless` - // | `path-empty`) - // - // def `URI-reference` = rule { URI | `relative-ref` } - // - def `URI-reference-pushed`: Rule1[Uri] = ??? // rule { `URI-reference` ~ push(createUriReference()) } - // - // def `absolute-URI` = rule { scheme ~ ':' ~ `hier-part` ~ optional('?' ~ rawQueryString) } - // - // def `relative-ref` = rule { `relative-part` ~ optional('?' ~ rawQueryString) ~ optional('#' ~ fragment) } - // - // def `relative-part` = rule( - // '/' ~ '/' ~ authority ~ `path-abempty` - // | `path-absolute` - // | `path-noscheme` - // | `path-empty`) - // - // def scheme = rule( - // 'h' ~ 't' ~ 't' ~ 'p' ~ (&(':') ~ run(setScheme("http")) | 's' ~ &(':') ~ run(setScheme("https"))) - // | clearSB() ~ ALPHA ~ appendLowered() ~ zeroOrMore(`scheme-char` ~ appendLowered()) ~ &(':') ~ run(setScheme(sb.toString))) - // - // def `scheme-pushed` = rule { oneOrMore(`scheme-char` ~ appendLowered()) ~ run(setScheme(sb.toString)) ~ push(_scheme) } - // - // def authority = rule { optional(userinfo) ~ hostAndPort } - // - // def userinfo = rule { - // clearSBForDecoding() ~ zeroOrMore(`userinfo-char` ~ appendSB() | `pct-encoded`) ~ '@' ~ run(setUserInfo(getDecodedString())) - // } - // - // def hostAndPort = rule { host ~ optional(':' ~ port) } - // - // def `hostAndPort-pushed` = rule { hostAndPort ~ push(_host) ~ push(_port) } - // - // def host = rule { `IP-literal` | ipv4Host | `reg-name` } - // - // /** A relaxed host rule to use in `parseHost` that also recognizes IPv6 address without the brackets. */ - // def relaxedHost = rule { `IP-literal` | ipv6Host | ipv4Host | `reg-name` } - // - // def port = rule { - // DIGIT ~ run(setPort(lastChar - '0')) ~ optional( - // DIGIT ~ run(setPort(10 * _port + lastChar - '0')) ~ optional( - // DIGIT ~ run(setPort(10 * _port + lastChar - '0')) ~ optional( - // DIGIT ~ run(setPort(10 * _port + lastChar - '0')) ~ optional( - // DIGIT ~ run(setPort(10 * _port + lastChar - '0')))))) - // } - // - // def `IP-literal` = rule { '[' ~ ipv6Host ~ ']' } // IPvFuture not currently recognized - // - // def ipv4Host = rule { capture(`ip-v4-address`) ~ &(colonSlashEOI) ~> ((b, a) => _host = IPv4Host(b, a)) } - // def ipv6Host = rule { capture(`ip-v6-address`) ~> ((b, a) => setHost(IPv6Host(b, a))) } - // - // def `reg-name` = rule( - // clearSBForDecoding() ~ oneOrMore(`lower-reg-name-char` ~ appendSB() | UPPER_ALPHA ~ appendLowered() | `pct-encoded`) ~ - // run(setHost(NamedHost(getDecodedStringAndLowerIfEncoded(UTF8)))) - // | run(setHost(Host.Empty))) - // - // def `path-abempty` = rule { clearSB() ~ slashSegments ~ savePath() } - // def `path-absolute` = rule { clearSB() ~ '/' ~ appendSB('/') ~ optional(`segment-nz` ~ slashSegments) ~ savePath() } - // def `path-noscheme` = rule { clearSB() ~ `segment-nz-nc` ~ slashSegments ~ savePath() } - // def `path-rootless` = rule { clearSB() ~ `segment-nz` ~ slashSegments ~ savePath() } - // def `path-empty` = rule { MATCH } - // - // def slashSegments = rule { zeroOrMore('/' ~ appendSB('/') ~ segment) } - // - // def segment = rule { zeroOrMore(pchar) } - // def `segment-nz` = rule { oneOrMore(pchar) } - // def `segment-nz-nc` = rule { oneOrMore(!':' ~ pchar) } - // - // def pchar = rule { `path-segment-char` ~ appendSB() | `pct-encoded` } - // - // def rawQueryString = rule { - // clearSB() ~ oneOrMore(`query-char` ~ appendSB() | `pct-encoded`) ~ run(setRawQueryString(sb.toString)) | run(setRawQueryString("")) - // } - - // https://www.w3.org/TR/html401/interact/forms.html#h-17.13.4.1 - def query: Rule1[Query] = ??? - - def fragment = ??? - - def `pct-encoded` = ??? - - //////////////////////////// ADDITIONAL HTTP-SPECIFIC RULES ////////////////////////// - - // http://tools.ietf.org/html/rfc7230#section-2.7 - def `absolute-path` = ??? - - // http://tools.ietf.org/html/rfc7230#section-5.3 - def `request-target` = ??? - - def parseHttpRequestTarget(): Uri = ??? - - /////////////////////////// ADDITIONAL HTTP/2-SPECIFIC RULES ///////////////////////// - - // https://tools.ietf.org/html/rfc7540#section-8.1.2.3 - // https://tools.ietf.org/html/rfc3986#section-3.2 - without deprecated userinfo - def `http2-authority-pseudo-header` = ??? - - def parseHttp2AuthorityPseudoHeader(): Uri.Authority = ??? - - // https://tools.ietf.org/html/rfc7540#section-8.1.2.3 - def `http2-path-pseudo-header` = ??? - - /** - * @return path and percent-encoded query string. When in in 'relaxed' mode, characters not permitted by https://tools.ietf.org/html/rfc3986#section-3.4 - * are already automatically percent-encoded here - */ - def parseHttp2PathPseudoHeader(): (Uri.Path, Option[String]) = ??? - - /** Allows to reuse this parser. */ - def reset(newInput: ParserInput): Unit = ??? -} diff --git a/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala b/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala deleted file mode 100644 index 458019c510a..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/HttpHeader.scala +++ /dev/null @@ -1,125 +0,0 @@ -/* - * Copyright (C) 2009-2021 Lightbend Inc. - */ - -package akka.http.scaladsl.model - -import akka.annotation.InternalApi - -import scala.util.{ Failure, Success } -import akka.parboiled2.ParseError -import akka.http.impl.util.ToStringRenderable -import akka.http.impl.model.parser.{ CharacterClasses, HeaderParser } -import akka.http.javadsl.{ model => jm } -import akka.http.scaladsl.model.headers._ -import akka.util.OptionVal - -import scala.collection.immutable - -/** - * Marker trait for headers which contain portentially secret / sensitive information. - * - * Mixing this trait will make `toString` to return the name of the header thus avoiding any - * detail leak. - */ -trait SensitiveHttpHeader { - this: HttpHeader => - - // This header is tagged as potentially containing personal sensitive information - final override def toString: String = name -} - -/** - * The model of an HTTP header. In its most basic form headers are simple name-value pairs. Header names - * are compared in a case-insensitive way. - */ -abstract class HttpHeader extends jm.HttpHeader with ToStringRenderable { - def name: String - def value: String - def lowercaseName: String - def is(nameInLowerCase: String): Boolean = lowercaseName == nameInLowerCase - def isNot(nameInLowerCase: String): Boolean = lowercaseName != nameInLowerCase - - def unsafeToString: String = super.toString -} - -object HttpHeader { - /** - * Extract name and value from a header. - * CAUTION: The name must be matched in *all-lowercase*!. - */ - def unapply(header: HttpHeader): Option[(String, String)] = Some((header.lowercaseName, header.value)) - - /** - * Attempts to parse the given header name and value string into a header model instance. - * - * This process has several possible outcomes: - * - * 1. The header name corresponds to a properly modelled header and - * a) the value is valid for this header type. - * In this case the method returns a `ParsingResult.Ok` with the respective header instance and no errors. - * b) the value consists of a number elements, some of which valid and some invalid, and the header type supports - * partial value parsing. In this case the method returns a `ParsingResult.Ok` with the respective header - * instance holding the valid value elements and an [[ErrorInfo]] for each invalid value. - * c) the value has invalid elements and the header type doesn't support partial value parsing. - * In this case the method returns a `ParsingResult.Ok` with a [[akka.http.scaladsl.model.headers.RawHeader]] instance and - * a single [[ErrorInfo]] for the value parsing problem. - * - * 2. The header name does not correspond to a properly modelled header but the header name and the value are both - * syntactically legal according to the basic header requirements from the HTTP specification. - * (http://tools.ietf.org/html/rfc7230#section-3.2) - * In this case the method returns a `ParsingResult.Ok` with a [[akka.http.scaladsl.model.headers.RawHeader]] instance and no errors. - * - * 3. The header name or value are illegal according to the basic requirements for HTTP headers - * (http://tools.ietf.org/html/rfc7230#section-3.2). In this case the method returns a `ParsingResult.Error`. - */ - def parse(name: String, value: String, settings: HeaderParser.Settings = HeaderParser.DefaultSettings): ParsingResult = - if (name.forall(c => CharacterClasses.tchar(c))) { - import akka.parboiled2.Parser.DeliveryScheme.Try - /*val parser = new HeaderParser(value, settings) - parser.`header-field-value`.run() match { - case Success(preProcessedValue) => - HeaderParser.parseFull(name.toLowerCase, preProcessedValue, settings) match { - case HeaderParser.Success(header) => ParsingResult.Ok(header, Nil) - case HeaderParser.Failure(info) => - val errors = info.withSummaryPrepended(s"Illegal HTTP header '$name'") :: Nil - ParsingResult.Ok(RawHeader(name, preProcessedValue), errors) - case HeaderParser.RuleNotFound => ParsingResult.Ok(RawHeader(name, preProcessedValue), Nil) - } - case Failure(error) => - val info = (error match { - case e: ParseError => parser.parseError(e) - case e => parser.failure(e) - }).info - ParsingResult.Error(info.withSummaryPrepended(s"Illegal HTTP header value")) - }*/ ??? - } else ParsingResult.Error(ErrorInfo(s"Illegal HTTP header name", name)) - - /** INTERNAL API */ - @InternalApi - private[akka] def fastFind[T >: Null <: jm.HttpHeader](clazz: Class[T], headers: immutable.Seq[HttpHeader]): OptionVal[T] = { - val it = headers.iterator - while (it.hasNext) it.next() match { - case h if clazz.isInstance(h) => return OptionVal.Some[T](h.asInstanceOf[T]) - case _ => // continue ... - } - OptionVal.None - } - - sealed trait ParsingResult { - def errors: List[ErrorInfo] - } - - object ParsingResult { - /** - * The parsing run produced a result. If there were parsing errors (which did not prevent the run from - * completing) they are reported in the given error list. - */ - final case class Ok(header: HttpHeader, errors: List[ErrorInfo]) extends ParsingResult - - /** - * The parsing run failed due to a fatal parsing error. - */ - final case class Error(error: ErrorInfo) extends ParsingResult { def errors = error :: Nil } - } -} diff --git a/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala b/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala deleted file mode 100644 index 6720dfa7d66..00000000000 --- a/akka-http-core/src/main/scala-3/akka/http/scaladsl/model/headers/ProductVersion.scala +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright (C) 2009-2021 Lightbend Inc. - */ - -package akka.http.scaladsl.model.headers - -import scala.collection.immutable -import scala.util.{ Failure, Success } -import akka.parboiled2.ParseError -import akka.http.javadsl.{ model => jm } -import akka.http.impl.model.parser.HeaderParser -import akka.http.impl.util._ - -final case class ProductVersion(product: String = "", version: String = "", comment: String = "") extends jm.headers.ProductVersion with ValueRenderable { - def render[R <: Rendering](r: R): r.type = { - r ~~ product - if (!version.isEmpty) r ~~ '/' ~~ version - if (!comment.isEmpty) { - if (!product.isEmpty || !version.isEmpty) r ~~ ' ' - r ~~ '(' ~~ comment ~~ ')' - } - r - } -} - -object ProductVersion { - implicit val productsRenderer: Renderer[immutable.Seq[ProductVersion]] = Renderer.seqRenderer[ProductVersion](separator = " ") - - /** parses a string of multiple ProductVersions */ - def parseMultiple(string: String): immutable.Seq[ProductVersion] = ??? /*{ - val parser = new HeaderParser(string) - def fail(msg: String) = throw new IllegalArgumentException(s"'$string' is not a legal sequence of ProductVersions: $msg") - parser.products.run() match { - case Success(x) => immutable.Seq(x: _*) - case Failure(e: ParseError) => fail(parser.formatError(e)) - case Failure(e) => fail(e.getMessage) - } - }*/ -} diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptCharsetHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptCharsetHeader.scala similarity index 94% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptCharsetHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptCharsetHeader.scala index 0336709eb47..40a3b2d1bfb 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptCharsetHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptCharsetHeader.scala @@ -8,7 +8,7 @@ import akka.parboiled2.Parser import akka.http.scaladsl.model.headers.`Accept-Charset` import akka.http.scaladsl.model.HttpCharsetRange -private[parser] trait AcceptCharsetHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait AcceptCharsetHeader { this: Parser with CommonRules with CommonActions with StringBuilding => // http://tools.ietf.org/html/rfc7231#section-5.3.3 def `accept-charset` = rule { diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptEncodingHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptEncodingHeader.scala similarity index 74% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptEncodingHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptEncodingHeader.scala index 90958c3f896..12444acc20f 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptEncodingHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptEncodingHeader.scala @@ -7,7 +7,7 @@ package akka.http.impl.model.parser import akka.parboiled2.Parser import akka.http.scaladsl.model.headers._ -private[parser] trait AcceptEncodingHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait AcceptEncodingHeader { this: Parser with CommonRules with CommonActions with StringBuilding => // http://tools.ietf.org/html/rfc7231#section-5.3.4 def `accept-encoding` = rule { @@ -23,8 +23,8 @@ private[parser] trait AcceptEncodingHeader { this: Parser with CommonRules with } } - def codings = rule { ws('*') ~ push(HttpEncodingRange.`*`) | token ~> getEncoding } + def codings = rule { ws('*') ~ push(HttpEncodingRange.`*`) | token ~> getEncoding _ } - private val getEncoding: String => HttpEncodingRange = - name => HttpEncodingRange(HttpEncodings.getForKeyCaseInsensitive(name) getOrElse HttpEncoding.custom(name)) + private def getEncoding(name: String): HttpEncodingRange = + HttpEncodingRange(HttpEncodings.getForKeyCaseInsensitive(name) getOrElse HttpEncoding.custom(name)) } diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptHeader.scala similarity index 97% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptHeader.scala index c3decced168..a36dd7c59c1 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptHeader.scala @@ -11,7 +11,7 @@ import akka.http.scaladsl.model.headers._ import akka.http.scaladsl.model.{ MediaRange, MediaRanges } import akka.http.impl.util._ -private[parser] trait AcceptHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait AcceptHeader { this: Parser with CommonRules with CommonActions with StringBuilding => import CharacterClasses._ // http://tools.ietf.org/html/rfc7231#section-5.3.2 diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptLanguageHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptLanguageHeader.scala similarity index 93% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptLanguageHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptLanguageHeader.scala index 005c78e9881..a65dc19ee3b 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/AcceptLanguageHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/AcceptLanguageHeader.scala @@ -7,7 +7,7 @@ package akka.http.impl.model.parser import akka.parboiled2.Parser import akka.http.scaladsl.model.headers._ -private[parser] trait AcceptLanguageHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait AcceptLanguageHeader { this: Parser with CommonRules with CommonActions with StringBuilding => // http://tools.ietf.org/html/rfc7231#section-5.3.5 def `accept-language` = rule { diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/Base64Parsing.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/Base64Parsing.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/Base64Parsing.scala diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CacheControlHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CacheControlHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/CacheControlHeader.scala diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonActions.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonActions.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonActions.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonActions.scala diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonRules.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala similarity index 98% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonRules.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala index 5bcb8d4f05f..8940702343c 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/CommonRules.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/CommonRules.scala @@ -12,7 +12,8 @@ import akka.http.scaladsl.model.headers._ import akka.parboiled2._ import akka.parboiled2.support.hlist._ -private[parser] trait CommonRules { this: HeaderParser with Parser with StringBuilding => +private[parser] trait CommonRules { this: Parser with StringBuilding => + protected def maxCommentParsingDepth: Int import CharacterClasses._ // ****************************************************************************************** @@ -226,7 +227,7 @@ private[parser] trait CommonRules { this: HeaderParser with Parser with StringBu // http://tools.ietf.org/html/rfc6750#section-2.1 def `oauth2-bearer-token` = rule { - ignoreCase("bearer") ~ OWS ~ `token68` ~> OAuth2BearerToken + ignoreCase("bearer") ~ OWS ~ `token68` ~> (OAuth2BearerToken(_)) } def `generic-credentials` = rule { @@ -371,11 +372,11 @@ private[parser] trait CommonRules { this: HeaderParser with Parser with StringBu def `other-content-range` = rule { `other-range-unit` ~ `other-range-resp` } - def `other-range-resp` = rule { capture(zeroOrMore(ANY)) ~> ContentRange.Other } + def `other-range-resp` = rule { capture(zeroOrMore(ANY)) ~> (ContentRange.Other(_)) } def `other-range-set` = rule { oneOrMore(VCHAR) ~ OWS } - def `other-range-unit` = rule { token ~> RangeUnits.Other } + def `other-range-unit` = rule { token ~> (RangeUnits.Other(_)) } def `other-ranges-specifier` = rule { `other-range-unit` ~ ws('=') ~ `other-range-set` } diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentDispositionHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentDispositionHeader.scala similarity index 97% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentDispositionHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentDispositionHeader.scala index a8161b83894..05b9a2b5c14 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentDispositionHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentDispositionHeader.scala @@ -16,7 +16,7 @@ import akka.http.scaladsl.model.Uri import java.nio.charset.Charset -private[parser] trait ContentDispositionHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait ContentDispositionHeader { this: Parser with CommonRules with CommonActions with StringBuilding => // http://tools.ietf.org/html/rfc6266#section-4.1 def `content-disposition` = rule { diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentTypeHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentTypeHeader.scala similarity index 97% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentTypeHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentTypeHeader.scala index e92d0828081..6a2a0d699ff 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/ContentTypeHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/ContentTypeHeader.scala @@ -10,7 +10,7 @@ import scala.collection.immutable.TreeMap import akka.parboiled2.Parser import akka.http.scaladsl.model._ -private[parser] trait ContentTypeHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait ContentTypeHeader { this: Parser with CommonRules with CommonActions with StringBuilding => // http://tools.ietf.org/html/rfc7231#section-3.1.1.5 def `content-type` = rule { diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/HeaderParser.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala similarity index 98% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/HeaderParser.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala index 56d88424676..950a163bd2c 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/HeaderParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/HeaderParser.scala @@ -105,7 +105,7 @@ private[http] object HeaderParser { object EmptyCookieException extends SingletonException("Cookie header contained no parsable cookie values.") - def lookupParser(headerName: String, settings: Settings = DefaultSettings): Option[String => HeaderParser#Result] = + def lookupParser(headerName: String, settings: Settings = DefaultSettings): Option[String => HeaderParser.Result] = dispatch.lookup(headerName).map { runner => (value: String) => import akka.parboiled2.EOI val v = value + EOI // this makes sure the parser isn't broken even if there's no trailing garbage in this value @@ -121,7 +121,7 @@ private[http] object HeaderParser { } } - def parseFull(headerName: String, value: String, settings: Settings = DefaultSettings): HeaderParser#Result = + def parseFull(headerName: String, value: String, settings: Settings = DefaultSettings): HeaderParser.Result = lookupParser(headerName, settings).map(_(value)).getOrElse(HeaderParser.RuleNotFound) val (dispatch, ruleNames) = DynamicRuleDispatch[HeaderParser, HttpHeader :: HNil]( diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/IpAddressParsing.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/IpAddressParsing.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/IpAddressParsing.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/IpAddressParsing.scala diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/LinkHeader.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/LinkHeader.scala similarity index 85% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/LinkHeader.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/LinkHeader.scala index 4acb69c22e2..a71f7f1fe93 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/LinkHeader.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/LinkHeader.scala @@ -12,7 +12,7 @@ import akka.parboiled2.Parser import akka.http.scaladsl.model.{ ParsingException, IllegalUriException } import akka.http.scaladsl.model.headers._ -private[parser] trait LinkHeader { this: Parser with CommonRules with CommonActions => +private[parser] trait LinkHeader { this: Parser with CommonRules with CommonActions with StringBuilding => import CharacterClasses._ // http://tools.ietf.org/html/rfc5988#section-5 @@ -25,14 +25,14 @@ private[parser] trait LinkHeader { this: Parser with CommonRules with CommonActi } def `link-param` = rule( - ws("rel") ~ ws('=') ~ `relation-types` ~> LinkParams.rel - | ws("anchor") ~ ws('=') ~ ws('"') ~ UriReference('"') ~ ws('"') ~> LinkParams.anchor - | ws("rev") ~ ws('=') ~ `relation-types` ~> LinkParams.rev - | ws("hreflang") ~ ws('=') ~ language ~> LinkParams.hreflang - | ws("media") ~ ws('=') ~ word ~> LinkParams.media - | ws("title") ~ ws('=') ~ word ~> LinkParams.title - | ws("title*") ~ ws('=') ~ word ~> LinkParams.`title*` // support full `ext-value` notation from http://tools.ietf.org/html/rfc5987#section-3.2.1 - | ws("type") ~ ws('=') ~ (ws('"') ~ `link-media-type` ~ ws('"') | `link-media-type`) ~> LinkParams.`type`) + ws("rel") ~ ws('=') ~ `relation-types` ~> LinkParams.rel.apply _ + | ws("anchor") ~ ws('=') ~ ws('"') ~ UriReference('"') ~ ws('"') ~> LinkParams.anchor.apply _ + | ws("rev") ~ ws('=') ~ `relation-types` ~> LinkParams.rev.apply _ + | ws("hreflang") ~ ws('=') ~ language ~> LinkParams.hreflang.apply _ + | ws("media") ~ ws('=') ~ word ~> LinkParams.media.apply _ + | ws("title") ~ ws('=') ~ word ~> LinkParams.title.apply _ + | ws("title*") ~ ws('=') ~ word ~> LinkParams.`title*`.apply _ // support full `ext-value` notation from http://tools.ietf.org/html/rfc5987#section-3.2.1 + | (ws("type") ~ ws('=') ~ (ws('"') ~ `link-media-type` ~ ws('"') | `link-media-type`) ~> LinkParams.`type`.apply _)) // TODO: support `link-extension` def `relation-types` = rule( diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/SimpleHeaders.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/SimpleHeaders.scala similarity index 98% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/SimpleHeaders.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/SimpleHeaders.scala index 617af5fac58..3bc7c9e084a 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/SimpleHeaders.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/SimpleHeaders.scala @@ -15,7 +15,7 @@ import akka.http.scaladsl.model.headers._ * All header rules that require more than one single rule are modelled in their own trait. */ @InternalApi -private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonActions with IpAddressParsing => +private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonActions with IpAddressParsing with StringBuilding => // http://tools.ietf.org/html/rfc7233#section-2.3 def `accept-ranges` = rule { @@ -100,14 +100,14 @@ private[parser] trait SimpleHeaders { this: Parser with CommonRules with CommonA // http://tools.ietf.org/html/rfc7233#section-4.2 def `content-range` = rule { - (`byte-content-range` | `other-content-range`) ~ EOI ~> (`Content-Range`(_, _)) + (`byte-content-range` ~ EOI ~> (`Content-Range`(_, _)) | `other-content-range` ~ EOI ~> (`Content-Range`(_, _))) } // https://tools.ietf.org/html/rfc6265#section-4.2 def `cookie` = rule { oneOrMore(`optional-cookie-pair`).separatedBy(';' ~ OWS) ~ EOI ~> { pairs => val validPairs = pairs.collect { case Some(p) => p } - `Cookie` { + `Cookie`.apply { if (validPairs.nonEmpty) validPairs // Parsing infrastructure requires to return an HttpHeader value here but it is not possible // to create a Cookie header without elements, so we throw here. This will 1) log a warning diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/StringBuilding.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/StringBuilding.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/StringBuilding.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/StringBuilding.scala diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/UriParser.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/UriParser.scala similarity index 99% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/UriParser.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/UriParser.scala index 6617106cfe8..0c32670a1b1 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/UriParser.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/UriParser.scala @@ -259,7 +259,7 @@ private[http] final class UriParser( // has a max value-stack depth of 3 def keyValuePairsWithLimitedStackUse: Rule1[Query] = rule { keyValuePair ~> { (key, value) => Query.Cons(key, value, Query.Empty) } ~ { - zeroOrMore('&' ~ keyValuePair ~> { (prefix: Query, key, value) => Query.Cons(key, value, prefix) }) ~> + zeroOrMore('&' ~ keyValuePair ~> { (prefix: Query.Cons, key, value) => Query.Cons(key, value, prefix) }) ~> (_.reverse) } } diff --git a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/WebSocketHeaders.scala b/akka-http-core/src/main/scala/akka/http/impl/model/parser/WebSocketHeaders.scala similarity index 97% rename from akka-http-core/src/main/scala-2/akka/http/impl/model/parser/WebSocketHeaders.scala rename to akka-http-core/src/main/scala/akka/http/impl/model/parser/WebSocketHeaders.scala index ececf27182b..6934a3966ff 100644 --- a/akka-http-core/src/main/scala-2/akka/http/impl/model/parser/WebSocketHeaders.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/model/parser/WebSocketHeaders.scala @@ -8,7 +8,7 @@ import akka.http.scaladsl.model.headers._ import akka.parboiled2._ // see grammar at http://tools.ietf.org/html/rfc6455#section-4.3 -private[parser] trait WebSocketHeaders { this: Parser with CommonRules with CommonActions => +private[parser] trait WebSocketHeaders { this: Parser with CommonRules with CommonActions with StringBuilding => import CharacterClasses._ import Base64Parsing.rfc2045Alphabet diff --git a/akka-http-core/src/main/scala-2/akka/http/scaladsl/model/HttpHeader.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpHeader.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/scaladsl/model/HttpHeader.scala rename to akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpHeader.scala diff --git a/akka-http-core/src/main/scala-2/akka/http/scaladsl/model/headers/ProductVersion.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/ProductVersion.scala similarity index 100% rename from akka-http-core/src/main/scala-2/akka/http/scaladsl/model/headers/ProductVersion.scala rename to akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/ProductVersion.scala diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala index a0caa791b45..80b1b53097d 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala @@ -108,7 +108,7 @@ abstract class ServerSettings private[akka] () extends akka.http.javadsl.setting override def withDefaultHttpsPort(newValue: Int): ServerSettings = self.copy(defaultHttpsPort = newValue) override def withTerminationDeadlineExceededResponse(response: akka.http.javadsl.model.HttpResponse): ServerSettings = self.copy(terminationDeadlineExceededResponse = response.asScala) - override def withParsingErrorHandler(newValue: String) = self.copy(parsingErrorHandler = newValue) + override def withParsingErrorHandler(newValue: String): ServerSettings = self.copy(parsingErrorHandler = newValue) override def withStreamCancellationDelay(newValue: FiniteDuration): ServerSettings = self.copy(streamCancellationDelay = newValue) // overloads for Scala idiomatic use diff --git a/akka-http-core/src/test/scala-2/akka/http/ConfigSpec.scala b/akka-http-core/src/test/scala/akka/http/ConfigSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/ConfigSpec.scala rename to akka-http-core/src/test/scala/akka/http/ConfigSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/HashCodeCollider.scala b/akka-http-core/src/test/scala/akka/http/HashCodeCollider.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/HashCodeCollider.scala rename to akka-http-core/src/test/scala/akka/http/HashCodeCollider.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ClientCancellationSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ClientCancellationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ClientCancellationSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/ClientCancellationSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ConnectionPoolSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ConnectionPoolSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala index 1de1b5fd93f..16e7d757b38 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ConnectionPoolSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala @@ -666,7 +666,7 @@ class NewConnectionPoolSpec extends AkkaSpecWithMaterializer(""" val sink = if (autoAccept) Sink.foreach[Http.IncomingConnection](handleConnection) else Sink.fromSubscriber(incomingConnections) val binding = - Tcp() + Tcp.apply .bind("localhost", 0, idleTimeout = serverSettings.timeouts.idleTimeout) .map { c => val layer = Http().serverLayer(serverSettings, log = log) diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/HighLevelOutgoingConnectionSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HostConnectionPoolSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HostConnectionPoolSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala index 8831ed45f1b..0fd67db2ece 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HostConnectionPoolSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala @@ -833,7 +833,7 @@ class HostConnectionPoolSpec extends AkkaSpecWithMaterializer( // 2. when client connection was established, grab server connection as well and attach to proxies // (cannot be implemented with just mapMaterializedValue because there's no transposing constructor for BidiFlow) BidiFlow.fromGraph( - GraphDSL.create(Sink.asPublisher[HttpResponse](fanout = false), Source.asSubscriber[HttpRequest], clientConnectionFlow(serverBinding, connectionKillSwitch))((_, _, _)) { implicit builder => (resIn, reqOut, client) => + GraphDSL.createGraph(Sink.asPublisher[HttpResponse](fanout = false), Source.asSubscriber[HttpRequest], clientConnectionFlow(serverBinding, connectionKillSwitch))((_, _, _)) { implicit builder => (resIn, reqOut, client) => import GraphDSL.Implicits._ builder.materializedValue ~> Sink.foreach[(Publisher[HttpResponse], Subscriber[HttpRequest], Future[Http.OutgoingConnection])] { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpConfigurationSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpConfigurationSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpConfigurationSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/HttpsProxyGraphStageSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala index 4814da91bd8..303a857479a 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/LowLevelOutgoingConnectionSpec.scala @@ -4,10 +4,12 @@ package akka.http.impl.engine.client -import com.typesafe.config.ConfigFactory +import scala.concurrent.ExecutionContext +import com.typesafe.config.ConfigFactory import scala.concurrent.duration._ import scala.reflect.ClassTag + import org.scalatest.Inside import akka.http.scaladsl.settings.ClientConnectionSettings import akka.util.ByteString @@ -21,10 +23,11 @@ import akka.http.scaladsl.model.HttpMethods._ import akka.http.scaladsl.model._ import akka.http.scaladsl.model.headers._ import akka.http.impl.util._ +import akka.http.scaladsl.Http import akka.testkit._ class LowLevelOutgoingConnectionSpec extends AkkaSpecWithMaterializer with Inside { - implicit val dispatcher = system.dispatcher + implicit val dispatcher: ExecutionContext = system.dispatcher "The connection-level client implementation" should { @@ -1003,7 +1006,7 @@ class LowLevelOutgoingConnectionSpec extends AkkaSpecWithMaterializer with Insid val netOut = TestSubscriber.manualProbe[ByteString]() val netIn = TestPublisher.manualProbe[ByteString]() - RunnableGraph.fromGraph(GraphDSL.create(OutgoingConnectionBlueprint(Host("example.com"), settings, NoLogging)) { implicit b => client => + RunnableGraph.fromGraph(GraphDSL.createGraph(OutgoingConnectionBlueprint(Host("example.com"), settings, NoLogging)) { implicit b => client => import GraphDSL.Implicits._ Source.fromPublisher(netIn) ~> Flow[ByteString].map(SessionBytes(null, _)) ~> client.in2 client.out1 ~> Flow[SslTlsOutbound].collect { case SendBytes(x) => x } ~> Sink.fromSubscriber(netOut) diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/PrepareResponseSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/PrepareResponseSpec.scala similarity index 95% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/PrepareResponseSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/PrepareResponseSpec.scala index b2be86dff7e..6c2c7a88805 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/PrepareResponseSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/PrepareResponseSpec.scala @@ -48,7 +48,7 @@ class PrepareResponseSpec extends AkkaSpec { "The PrepareRequest stage" should { "not lose demand that comes in while streaming entity" in { - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.ResponseOutput]() val responseProbe = TestSubscriber.manualProbe[HttpResponse]() @@ -93,7 +93,7 @@ class PrepareResponseSpec extends AkkaSpec { } "not lose demand that comes in while handling strict entity" in { - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.ResponseOutput]() val responseProbe = TestSubscriber.manualProbe[HttpResponse]() @@ -129,7 +129,7 @@ class PrepareResponseSpec extends AkkaSpec { "complete entity stream then complete stage when downstream cancels" in { // to make it possible to cancel a big file download for example // without downloading the entire response first - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.ResponseOutput]() val responseProbe = TestSubscriber.manualProbe[HttpResponse]() @@ -170,7 +170,7 @@ class PrepareResponseSpec extends AkkaSpec { } "complete stage when downstream cancels before end of strict request has arrived" in { - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.ResponseOutput]() val responseProbe = TestSubscriber.manualProbe[HttpResponse]() @@ -198,7 +198,7 @@ class PrepareResponseSpec extends AkkaSpec { } "cancel entire stage when the entity stream is canceled" in { - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.ResponseOutput]() val responseProbe = TestSubscriber.manualProbe[HttpResponse]() diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala similarity index 98% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala index 2a0051ac709..5f3c4c31781 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ResponseParsingMergeSpec.scala @@ -24,7 +24,7 @@ class ResponseParsingMergeSpec extends AkkaSpec { "The ResponseParsingMerge stage" should { "not lose entity truncation errors on upstream finish" in { - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() val inBypassProbe = TestPublisher.manualProbe[OutgoingConnectionBlueprint.BypassData]() val inSessionBytesProbe = TestPublisher.manualProbe[SessionBytes]() diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/TlsEndpointVerificationSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/client/pool/SlotStateSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/pool/SlotStateSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/client/pool/SlotStateSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/pool/SlotStateSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/BoyerMooreSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/BoyerMooreSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/BoyerMooreSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/parsing/BoyerMooreSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ContentLengthHeaderParserSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala similarity index 93% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala index dab38030128..4952d084973 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/HttpHeaderParserTestBed.scala @@ -16,7 +16,7 @@ object HttpHeaderParserTestBed extends App { akka.http.parsing.max-header-name-length = 20 akka.http.parsing.max-header-value-length = 21 akka.http.parsing.header-cache.Host = 300""") - val system = ActorSystem("HttpHeaderParserTestBed", testConf) + val system: ActorSystem = ActorSystem("HttpHeaderParserTestBed", testConf) val parser = HttpHeaderParser.prime { HttpHeaderParser.unprimed(ParserSettings(system), system.log, warnOnIllegalHeader = info => system.log.warning(info.formatPretty)) diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/RequestParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/RequestParserSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala index 790dc4b06c0..33aa4591de4 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/RequestParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/RequestParserSpec.scala @@ -44,11 +44,11 @@ abstract class RequestParserSpec(mode: String, newLine: String) extends AnyFreeS akka.http.parsing.max-header-value-length = 32 akka.http.parsing.max-uri-length = 40 akka.http.parsing.max-content-length = infinite""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) import system.dispatcher val BOLT = HttpMethod.custom("BOLT", safe = false, idempotent = true, requestEntityAcceptance = Expected) - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() s"The request parsing logic should (mode: $mode)" - { "properly parse a request" - { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ResponseParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/parsing/ResponseParserSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/RequestRendererSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/RequestRendererSpec.scala similarity index 98% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/RequestRendererSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/rendering/RequestRendererSpec.scala index 0db426046f8..a2486cd0b6c 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/RequestRendererSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/RequestRendererSpec.scala @@ -29,10 +29,10 @@ class RequestRendererSpec extends AnyFreeSpec with Matchers with BeforeAndAfterA val testConf: Config = ConfigFactory.parseString(""" akka.event-handlers = ["akka.testkit.TestEventListener"] akka.loglevel = WARNING""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) import system.dispatcher - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() "The request preparation logic should" - { "properly render an unchunked" - { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/ResponseRendererSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/ResponseRendererSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala index 53ccf0a9e9d..43966e0e47c 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/rendering/ResponseRendererSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/rendering/ResponseRendererSpec.scala @@ -31,10 +31,10 @@ class ResponseRendererSpec extends AnyFreeSpec with Matchers with BeforeAndAfter val testConf: Config = ConfigFactory.parseString(""" akka.event-handlers = ["akka.testkit.TestEventListener"] akka.loglevel = WARNING""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) val ServerOnTheMove = StatusCodes.custom(330, "Server on the move") - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() "The response preparation logic should properly render" - { "a response with no body," - { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerBug21008Spec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerBug21008Spec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerBug21008Spec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerBug21008Spec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala index fad7ca357c9..2c610dc47d8 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerSpec.scala @@ -48,7 +48,7 @@ class HttpServerSpec extends AkkaSpec( akka.http.server.log-unencrypted-network-bytes = 100 akka.http.server.request-timeout = infinite """) with Inside with WithLogCapturing { spec => - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() "The server implementation" should { "deliver an empty request as soon as all headers are received" in assertAllStagesStopped(new TestSetup { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerTestSetupBase.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala similarity index 96% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerTestSetupBase.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala index 14157bc1f5b..b7415475a14 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerTestSetupBase.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerTestSetupBase.scala @@ -36,7 +36,7 @@ abstract class HttpServerTestSetupBase { val netIn = TestPublisher.probe[ByteString]() val netOut = ByteStringSinkProbe() - RunnableGraph.fromGraph(GraphDSL.create(modifyServer(Http().serverLayer(settings))) { implicit b => server => + RunnableGraph.fromGraph(GraphDSL.createGraph(modifyServer(Http().serverLayer(settings))) { implicit b => server => import GraphDSL.Implicits._ Source.fromPublisher(netIn) ~> Flow[ByteString].map(SessionBytes(null, _)) ~> server.in2 server.out1 ~> Flow[SslTlsOutbound].collect { case SendBytes(x) => x }.buffer(1, OverflowStrategy.backpressure) ~> netOut.sink diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/server/HttpServerWithExplicitSchedulerSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/PrepareRequestsSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/server/PrepareRequestsSpec.scala similarity index 96% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/server/PrepareRequestsSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/server/PrepareRequestsSpec.scala index 8ceb223bd2c..911e0a1490b 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/server/PrepareRequestsSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/server/PrepareRequestsSpec.scala @@ -55,7 +55,7 @@ class PrepareRequestsSpec extends AkkaSpec { "The PrepareRequest stage" should { "not fail when there is demand from both streamed entity consumption and regular flow" in { - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() // covers bug #19623 where a reply before the streamed // body has been consumed causes pull/push twice val inProbe = TestPublisher.manualProbe[ParserOutput.RequestOutput]() @@ -115,7 +115,7 @@ class PrepareRequestsSpec extends AkkaSpec { } "not complete running entity stream when upstream cancels" in { - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.RequestOutput]() val upstreamProbe = TestSubscriber.manualProbe[HttpRequest]() @@ -166,7 +166,7 @@ class PrepareRequestsSpec extends AkkaSpec { "complete stage if chunked stream is completed without reaching end of chunks" in { // a bit unsure about this, but to document the assumption - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.RequestOutput]() val upstreamProbe = TestSubscriber.manualProbe[HttpRequest]() @@ -207,7 +207,7 @@ class PrepareRequestsSpec extends AkkaSpec { } "cancel the stage when the entity stream is canceled" in { - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() val inProbe = TestPublisher.manualProbe[ParserOutput.RequestOutput]() val upstreamProbe = TestSubscriber.manualProbe[HttpRequest]() diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/BitBuilder.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/BitBuilder.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/BitBuilder.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/BitBuilder.scala index 5d0c9c46cc5..dce9036a15c 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/BitBuilder.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/BitBuilder.scala @@ -94,7 +94,7 @@ class BitSpecParser(val input: ParserInput) extends parboiled2.Parser { def zero: Rule1[BitElement] = rule { '0' ~ push(Zero) ~ ws } def one: Rule1[BitElement] = rule { '1' ~ push(One) ~ ws } def multi: Rule1[Multibit] = rule { - capture(oneOrMore('x' ~ ws)) ~> (_.count(_ == 'x')) ~ '=' ~ value ~ ws ~> Multibit + capture(oneOrMore('x' ~ ws)) ~> (_.count(_ == 'x')) ~ '=' ~ value ~ ws ~> Multibit.apply _ } def value: Rule1[Long] = rule { capture(oneOrMore(CharPredicate.HexDigit)) ~> ((str: String) => java.lang.Long.parseLong(str, 16)) diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/ByteStringSinkProbe.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/ByteStringSinkProbe.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/ByteStringSinkProbe.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/ByteStringSinkProbe.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/EchoTestClientApp.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/EchoTestClientApp.scala similarity index 94% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/EchoTestClientApp.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/EchoTestClientApp.scala index 3ec6fae3070..56d978a5345 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/EchoTestClientApp.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/EchoTestClientApp.scala @@ -22,9 +22,9 @@ import scala.util.{ Failure, Success } * An example App that runs a quick test against the websocket server at wss://echo.websocket.org */ object EchoTestClientApp extends App { - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() import system.dispatcher - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() def delayedCompletion(delay: FiniteDuration): Source[Nothing, NotUsed] = Source.single(1) diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/FramingSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/FramingSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/FramingSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/FramingSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/MessageSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/MessageSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/MessageSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/MessageSpec.scala index 1e519eccd03..a064340ba7d 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/MessageSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/MessageSpec.scala @@ -1066,7 +1066,7 @@ class MessageSpec extends AkkaSpecWithMaterializer( val hasMask = (header(1) & Protocol.MASK_MASK) != 0 val length7 = header(1) & Protocol.LENGTH_MASK - val length = length7 match { + val length: Long = length7 match { case 126 => val length16Bytes = expectNetworkData(2) (length16Bytes(0) & 0xff) << 8 | (length16Bytes(1) & 0xff) << 0 diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/Utf8CodingSpecs.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/Utf8CodingSpecs.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/Utf8CodingSpecs.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/Utf8CodingSpecs.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSClientAutobahnTest.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSClientAutobahnTest.scala similarity index 98% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSClientAutobahnTest.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSClientAutobahnTest.scala index 661dd78c6ee..409eee86670 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSClientAutobahnTest.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSClientAutobahnTest.scala @@ -17,9 +17,9 @@ import akka.http.scaladsl.model.Uri import akka.http.scaladsl.model.ws._ object WSClientAutobahnTest extends App { - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() import system.dispatcher - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() val Agent = "akka-http" val Parallelism = 4 diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSServerAutobahnTest.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSServerAutobahnTest.scala similarity index 93% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSServerAutobahnTest.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSServerAutobahnTest.scala index 54e75013304..b1ee5ac0735 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSServerAutobahnTest.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSServerAutobahnTest.scala @@ -20,8 +20,8 @@ import akka.stream.scaladsl.Flow import scala.io.StdIn object WSServerAutobahnTest extends App { - implicit val system = ActorSystem("WSServerTest") - implicit val fm = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem("WSServerTest") + implicit val fm: ActorMaterializer = ActorMaterializer() val host = System.getProperty("akka.ws-host", "127.0.0.1") val port = System.getProperty("akka.ws-port", "9001").toInt diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestSetupBase.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestSetupBase.scala similarity index 98% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestSetupBase.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestSetupBase.scala index 1aeaaec1c97..3ad5ff12919 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestSetupBase.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestSetupBase.scala @@ -80,7 +80,7 @@ trait WSTestSetupBase extends Matchers { val hasMask = (header(1) & Protocol.MASK_MASK) != 0 val length7 = header(1) & Protocol.LENGTH_MASK - val length = length7 match { + val length: Long = length7 match { case 126 => val length16Bytes = expectNetworkData(2) (length16Bytes(0) & 0xff) << 8 | (length16Bytes(1) & 0xff) << 0 diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestUtils.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestUtils.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WSTestUtils.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WSTestUtils.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketClientSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketClientSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala index 36dfcd1314b..6b49236e4e7 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketClientSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketClientSpec.scala @@ -358,7 +358,7 @@ class WebSocketClientSpec extends AkkaSpecWithMaterializer("akka.http.client.web val netIn = TestPublisher.probe[ByteString]() val graph = - RunnableGraph.fromGraph(GraphDSL.create(clientLayer) { implicit b => client => + RunnableGraph.fromGraph(GraphDSL.createGraph(clientLayer) { implicit b => client => import GraphDSL.Implicits._ Source.fromPublisher(netIn) ~> Flow[ByteString].map(SessionBytes(null, _)) ~> client.in2 client.out1 ~> Flow[SslTlsOutbound].collect { case SendBytes(x) => x } ~> netOut.sink diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala similarity index 96% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala index 7cf018202a4..f3dae997362 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala @@ -102,7 +102,7 @@ class WebSocketIntegrationSpec extends AkkaSpecWithMaterializer( Http().webSocketClientLayer(WebSocketRequest("ws://localhost:" + myPort)) .atop(TLSPlacebo()) .joinMat(completeOnlySwitch.via( - Tcp().outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)))(Keep.both) + Tcp.apply.outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)))(Keep.both) }(Keep.right) .toMat(TestSink.probe[Message])(Keep.both) .run() @@ -179,7 +179,7 @@ class WebSocketIntegrationSpec extends AkkaSpecWithMaterializer( .atop(TLSPlacebo()) // the resource leak of #19398 existed only for severed websocket connections .atopMat(KillSwitches.singleBidi[ByteString, ByteString])(Keep.right) - .join(Tcp().outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) + .join(Tcp.apply.outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) }(Keep.right) .toMat(Sink.foreach(_ => messages += 1))(Keep.both) .run() @@ -212,7 +212,7 @@ class WebSocketIntegrationSpec extends AkkaSpecWithMaterializer( Http().webSocketClientLayer(WebSocketRequest("ws://localhost:" + myPort)) .atop(TLSPlacebo()) .atopMat(KillSwitches.singleBidi[ByteString, ByteString])(Keep.right) - .join(Tcp().outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) + .join(Tcp.apply.outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) }(Keep.right) .toMat(Sink.fromSubscriber(clientMessageIn))(Keep.left) .run() diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketServerSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketServerSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/engine/ws/WebSocketServerSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketServerSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/model/parser/HttpHeaderSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/impl/model/parser/HttpHeaderSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala index 04fab2956dd..212bf1cb3d6 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/model/parser/HttpHeaderSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/model/parser/HttpHeaderSpec.scala @@ -160,7 +160,7 @@ class HttpHeaderSpec extends AnyFreeSpec with Matchers { Authorization(GenericHttpCredentials("NoTokenScheme", "")) "Authorization: QVFJQzV3TTJMWTRTZmN3Zk=" =!= ErrorInfo( - "Illegal HTTP header 'Authorization': Invalid input '=', expected auth-param, OWS, token68, 'EOI' or tchar (line 1, column 23)", + "Illegal HTTP header 'Authorization': Invalid input '=', expected tchar, OWS, auth-param, token68 or 'EOI' (line 1, column 23)", """QVFJQzV3TTJMWTRTZmN3Zk= | ^""".stripMarginWithNewline("\n")) } @@ -353,7 +353,9 @@ class HttpHeaderSpec extends AnyFreeSpec with Matchers { "If-Match dispatching" in { // https://github.com/akka/akka-http/issues/443 Check dispatching for "if-match" does not throw "RuleNotFound" import scala.util._ - val Failure(cause) = Try(HeaderParser.dispatch(null, "if-match")) + import akka.parboiled2.DynamicRuleHandler + import akka.parboiled2.support.hlist.{ ::, HNil } + val Failure(cause) = Try(HeaderParser.dispatch(null.asInstanceOf[DynamicRuleHandler[HeaderParser, HttpHeader :: HNil]], "if-match")) cause.getClass should be(classOf[NullPointerException]) } @@ -400,7 +402,7 @@ class HttpHeaderSpec extends AnyFreeSpec with Matchers { "Location: https://spray.io/{sec}" =!= Location(Uri("https://spray.io/{sec}")).renderedTo( "https://spray.io/%7Bsec%7D") "Location: https://spray.io/ sec" =!= ErrorInfo("Illegal HTTP header 'Location': Invalid input ' ', " + - "expected '/', 'EOI', '#', segment or '?' (line 1, column 18)", "https://spray.io/ sec\n ^") + "expected segment, '/', '?', '#' or 'EOI' (line 1, column 18)", "https://spray.io/ sec\n ^") } "Link" in { @@ -713,7 +715,7 @@ class HttpHeaderSpec extends AnyFreeSpec with Matchers { "X-Forwarded-For: ::" =!=> "0:0:0:0:0:0:0:0" "X-Forwarded-For: 1.2.3.4, akka.io" =!= ErrorInfo( - "Illegal HTTP header 'X-Forwarded-For': Invalid input 'k', expected HEXDIG, h8, ':', ch16o or cc (line 1, column 11)", + "Illegal HTTP header 'X-Forwarded-For': Invalid input 'k', expected HEXDIG, h8, ':', cc or ch16o (line 1, column 11)", "1.2.3.4, akka.io\n ^") } @@ -765,7 +767,7 @@ class HttpHeaderSpec extends AnyFreeSpec with Matchers { "X-Real-Ip: ::" =!=> "0:0:0:0:0:0:0:0" "X-Real-Ip: akka.io" =!= ErrorInfo( - "Illegal HTTP header 'X-Real-Ip': Invalid input 'k', expected HEXDIG, h8, ':', ch16o or cc (line 1, column 2)", + "Illegal HTTP header 'X-Real-Ip': Invalid input 'k', expected HEXDIG, h8, ':', cc or ch16o (line 1, column 2)", "akka.io\n ^") } diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/AkkaSpecWithMaterializer.scala b/akka-http-core/src/test/scala/akka/http/impl/util/AkkaSpecWithMaterializer.scala similarity index 91% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/AkkaSpecWithMaterializer.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/AkkaSpecWithMaterializer.scala index b6aecd35ed5..f94d0de1c4f 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/util/AkkaSpecWithMaterializer.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/util/AkkaSpecWithMaterializer.scala @@ -6,7 +6,7 @@ package akka.http.impl.util import akka.actor.ActorSystem import akka.http.scaladsl.Http -import akka.stream.{ ActorMaterializer, SystemMaterializer } +import akka.stream.{ ActorMaterializer, Materializer, SystemMaterializer } import akka.testkit.AkkaSpec import akka.testkit.EventFilter import com.typesafe.config.ConfigFactory @@ -25,7 +25,7 @@ abstract class AkkaSpecWithMaterializer(configOverrides: String) def this() = this("") - implicit val materializer = SystemMaterializer(system).materializer + implicit val materializer: Materializer = SystemMaterializer(system).materializer override protected def beforeTermination(): Unit = // don't log anything during shutdown, especially not AbruptTerminationExceptions diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/BenchUtils.scala b/akka-http-core/src/test/scala/akka/http/impl/util/BenchUtils.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/BenchUtils.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/BenchUtils.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/ByteStringParserInputSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/util/ByteStringParserInputSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/ByteStringParserInputSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/ByteStringParserInputSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/CollectionStage.scala b/akka-http-core/src/test/scala/akka/http/impl/util/CollectionStage.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/CollectionStage.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/CollectionStage.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/ExampleHttpContexts.scala b/akka-http-core/src/test/scala/akka/http/impl/util/ExampleHttpContexts.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/ExampleHttpContexts.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/ExampleHttpContexts.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/One2OneBidiFlowSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/util/One2OneBidiFlowSpec.scala similarity index 97% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/One2OneBidiFlowSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/One2OneBidiFlowSpec.scala index e8a4223128d..59056d6e160 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/util/One2OneBidiFlowSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/util/One2OneBidiFlowSpec.scala @@ -7,18 +7,18 @@ package akka.http.impl.util import java.util.concurrent.atomic.AtomicInteger import akka.NotUsed -import akka.stream.ActorMaterializer +import akka.stream.{ ActorMaterializer, Materializer } import akka.stream.scaladsl.{ Flow, Keep, Sink, Source } import akka.stream.testkit.Utils._ import akka.stream.testkit._ - import scala.concurrent.Await import scala.concurrent.duration._ + import akka.testkit._ import org.scalatest.concurrent.Eventually class One2OneBidiFlowSpec extends AkkaSpec with Eventually { - implicit val materializer = ActorMaterializer() + implicit val materializer: Materializer = ActorMaterializer() "A One2OneBidiFlow" must { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/RenderingSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/util/RenderingSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/RenderingSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/RenderingSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/StreamUtilsSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/util/StreamUtilsSpec.scala similarity index 95% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/StreamUtilsSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/StreamUtilsSpec.scala index d8feeac4874..426c1a68c38 100644 --- a/akka-http-core/src/test/scala-2/akka/http/impl/util/StreamUtilsSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/util/StreamUtilsSpec.scala @@ -4,18 +4,17 @@ package akka.http.impl.util -import akka.stream.{ ActorMaterializer, Attributes } +import akka.stream.{ ActorMaterializer, Attributes, Materializer } import akka.stream.scaladsl.{ Sink, Source } import akka.util.ByteString import akka.testkit._ import org.scalatest.concurrent.ScalaFutures - import scala.concurrent.Await import scala.concurrent.duration._ import scala.util.Failure class StreamUtilsSpec extends AkkaSpec with ScalaFutures { - implicit val materializer = ActorMaterializer() + implicit val materializer: Materializer = ActorMaterializer() "captureTermination" should { "signal completion" when { diff --git a/akka-http-core/src/test/scala-2/akka/http/impl/util/WithLogCapturing.scala b/akka-http-core/src/test/scala/akka/http/impl/util/WithLogCapturing.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/impl/util/WithLogCapturing.scala rename to akka-http-core/src/test/scala/akka/http/impl/util/WithLogCapturing.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectHttpSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/ConnectHttpSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectHttpSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/ConnectHttpSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectionContextSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/ConnectionContextSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/ConnectionContextSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/ConnectionContextSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/HttpExtensionApiSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/HttpExtensionApiSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/HttpExtensionApiSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/HttpExtensionApiSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/JavaInitializationSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/JavaInitializationSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/JavaInitializationSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/JavaInitializationSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala b/akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/model/JavaApiTestCaseSpecs.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/model/MultipartsSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/model/MultipartsSpec.scala similarity index 97% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/model/MultipartsSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/model/MultipartsSpec.scala index c1faae42c2f..4f2e61be34f 100644 --- a/akka-http-core/src/test/scala-2/akka/http/javadsl/model/MultipartsSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/javadsl/model/MultipartsSpec.scala @@ -25,7 +25,7 @@ class MultipartsSpec extends AnyWordSpec with Matchers with Inside with BeforeAn val testConf: Config = ConfigFactory.parseString(""" akka.event-handlers = ["akka.testkit.TestEventListener"] akka.loglevel = WARNING""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) val materializer = SystemMaterializer.get(system).materializer override def afterAll() = TestKit.shutdownActorSystem(system) diff --git a/akka-http-core/src/test/scala-2/akka/http/javadsl/model/headers/HttpCookieSpec.scala b/akka-http-core/src/test/scala/akka/http/javadsl/model/headers/HttpCookieSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/javadsl/model/headers/HttpCookieSpec.scala rename to akka-http-core/src/test/scala/akka/http/javadsl/model/headers/HttpCookieSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientServerSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala similarity index 99% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientServerSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala index 30d9c6937f4..67fa8a27fb6 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala @@ -695,7 +695,7 @@ abstract class ClientServerSpecBase(http2: Boolean) extends AkkaSpecWithMaterial Host: example.com """)) - .via(Tcp().outgoingConnection(hostname, port)) + .via(Tcp.apply.outgoingConnection(hostname, port)) .runWith(Sink.reduce[ByteString](_ ++ _)) Try(Await.result(result, 2.seconds).utf8String) match { case scala.util.Success(body) => fail(body) @@ -717,7 +717,7 @@ Host: example.com // Disable hostname verification as ExampleHttpContexts.exampleClientContext sets hostname as akka.example.org val sslConfigSettings = SSLConfigSettings().withLoose(SSLLooseConfig().withDisableHostnameVerification(true)) - val sslConfig = AkkaSSLConfig().withSettings(sslConfigSettings) + val sslConfig = AkkaSSLConfig.apply.withSettings(sslConfigSettings) val sslContext = { val certStore = KeyStore.getInstance(KeyStore.getDefaultType) certStore.load(null, null) @@ -930,7 +930,7 @@ Host: example.com "produce a useful error message when connecting to an endpoint speaking wrong protocol" in Utils.assertAllStagesStopped { val settings = ConnectionPoolSettings(system).withUpdatedConnectionSettings(_.withIdleTimeout(100.millis)) - val binding = Tcp().bindAndHandle(Flow[ByteString].map(_ => ByteString("hello world!")), "127.0.0.1", 0).futureValue + val binding = Tcp.apply.bindAndHandle(Flow[ByteString].map(_ => ByteString("hello world!")), "127.0.0.1", 0).futureValue val uri = "http://" + binding.localAddress.getHostString + ":" + binding.localAddress.getPort val ex = the[IllegalResponseException] thrownBy Await.result(Http().singleRequest(HttpRequest(uri = uri, method = HttpMethods.POST), settings = settings), 30.seconds) diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientSpec.scala similarity index 92% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/ClientSpec.scala index 862724af6fa..5cefc8b47b0 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientSpec.scala @@ -24,8 +24,8 @@ class ClientSpec extends AnyWordSpec with Matchers with BeforeAndAfterAll { windows-connection-abort-workaround-enabled = auto akka.log-dead-letters = OFF akka.http.server.request-timeout = infinite""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) - implicit val materializer = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) + implicit val materializer: ActorMaterializer = ActorMaterializer() override def afterAll() = TestKit.shutdownActorSystem(system) diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/ClientTransportWithCustomResolverSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/GracefulTerminationSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/GracefulTerminationSpec.scala similarity index 98% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/GracefulTerminationSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/GracefulTerminationSpec.scala index c06a926ca0d..0a989b730ad 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/GracefulTerminationSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/GracefulTerminationSpec.scala @@ -24,7 +24,7 @@ import org.scalactic.Tolerance import org.scalatest.concurrent.Eventually import scala.concurrent.duration._ -import scala.concurrent.{ Await, Future, Promise } +import scala.concurrent.{ Await, ExecutionContext, Future, Promise } import scala.util.{ Failure, Success, Try } class GracefulTerminationSpec @@ -35,9 +35,9 @@ class GracefulTerminationSpec akka.http.client.log-unencrypted-network-bytes = 200 """) with Tolerance with Eventually { - implicit lazy val dispatcher = system.dispatcher + implicit lazy val dispatcher: ExecutionContext = system.dispatcher - implicit override val patience = PatienceConfig(5.seconds.dilated(system), 200.millis) + implicit override val patience: PatienceConfig = PatienceConfig(5.seconds.dilated(system), 200.millis) "Unbinding" should { "not allow new connections" in new TestSetup { diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/TestClient.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/TestClient.scala similarity index 96% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/TestClient.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/TestClient.scala index ec02fbb0729..28895d46e6d 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/TestClient.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/TestClient.scala @@ -25,8 +25,8 @@ object TestClient extends App { akka.loglevel = DEBUG akka.log-dead-letters = off akka.io.tcp.trace-logging = off""") - implicit val system = ActorSystem("ServerTest", testConf) - implicit val fm = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem("ServerTest", testConf) + implicit val fm: ActorMaterializer = ActorMaterializer() import system.dispatcher installEventStreamLoggerFor[UnhandledMessage] diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/TestServer.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/TestServer.scala similarity index 95% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/TestServer.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/TestServer.scala index 027189080d9..8688a5cc461 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/TestServer.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/TestServer.scala @@ -30,13 +30,13 @@ object TestServer extends App { akka.actor.serialize-messages = off akka.actor.default-dispatcher.throughput = 1000 """) - implicit val system = ActorSystem("ServerTest", testConf) + implicit val system: ActorSystem = ActorSystem("ServerTest", testConf) val settings = ActorMaterializerSettings(system) .withFuzzing(false) // .withSyncProcessingLimit(Int.MaxValue) .withInputBuffer(128, 128) - implicit val fm = ActorMaterializer(settings) + implicit val fm: ActorMaterializer = ActorMaterializer(settings) try { val binding = Http().newServerAt("localhost", 9001).bindSync { case req @ HttpRequest(GET, Uri.Path("/"), _, _, _) => diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/TightRequestTimeoutSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/TightRequestTimeoutSpec.scala similarity index 89% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/TightRequestTimeoutSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/TightRequestTimeoutSpec.scala index a449c34aad0..2e0754957da 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/TightRequestTimeoutSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/TightRequestTimeoutSpec.scala @@ -26,9 +26,9 @@ class TightRequestTimeoutSpec extends AnyWordSpec with Matchers with BeforeAndAf akka.log-dead-letters = OFF akka.http.server.request-timeout = 10ms""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) - implicit val materializer = ActorMaterializer() - implicit val patience = PatienceConfig(3.seconds.dilated) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) + implicit val materializer: ActorMaterializer = ActorMaterializer() + implicit val patience: PatienceConfig = PatienceConfig(3.seconds.dilated) override def afterAll() = TestKit.shutdownActorSystem(system) diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/DateTimeSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/DateTimeSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/EntityDiscardingSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/EntityDiscardingSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/EntityDiscardingSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/EntityDiscardingSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpEntitySpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpEntitySpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMessageSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMessageSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMessageSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMessageSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMethodsSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMethodsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/HttpMethodsSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpMethodsSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/MultipartSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/MultipartSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/MultipartSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/MultipartSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/SerializabilitySpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/SerializabilitySpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/SerializabilitySpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/SerializabilitySpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/TurkishISpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/TurkishISpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/TurkishISpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/TurkishISpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/UriSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/UriSpec.scala similarity index 98% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/UriSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/UriSpec.scala index 180fe726252..0af02379148 100644 --- a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/UriSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/model/UriSpec.scala @@ -351,13 +351,13 @@ class UriSpec extends AnyWordSpec with Matchers { //#query-strict-mode-exception-1 the[IllegalUriException] thrownBy strict("a^=b") shouldBe { IllegalUriException( - "Illegal query: Invalid input '^', expected '+', '=', query-char, 'EOI', '&' or pct-encoded (line 1, column 2)", + "Illegal query: Invalid input '^', expected '+', query-char, pct-encoded, '=', '&' or 'EOI' (line 1, column 2)", "a^=b\n" + " ^") } the[IllegalUriException] thrownBy strict("a;=b") shouldBe { IllegalUriException( - "Illegal query: Invalid input ';', expected '+', '=', query-char, 'EOI', '&' or pct-encoded (line 1, column 2)", + "Illegal query: Invalid input ';', expected '+', query-char, pct-encoded, '=', '&' or 'EOI' (line 1, column 2)", "a;=b\n" + " ^") } @@ -367,7 +367,7 @@ class UriSpec extends AnyWordSpec with Matchers { //double '=' in query string is invalid the[IllegalUriException] thrownBy strict("a=b=c") shouldBe { IllegalUriException( - "Illegal query: Invalid input '=', expected '+', query-char, 'EOI', '&' or pct-encoded (line 1, column 4)", + "Illegal query: Invalid input '=', expected '+', query-char, pct-encoded, '&' or 'EOI' (line 1, column 4)", "a=b=c\n" + " ^") } @@ -628,7 +628,7 @@ class UriSpec extends AnyWordSpec with Matchers { //illegal scheme the[IllegalUriException] thrownBy Uri("foö:/a") shouldBe { IllegalUriException( - "Illegal URI reference: Invalid input 'ö', expected scheme-char, 'EOI', '#', ':', '?', slashSegments or pchar (line 1, column 3)", + "Illegal URI reference: Invalid input 'ö', expected scheme-char, ':', pchar, slashSegments, '?', '#' or 'EOI' (line 1, column 3)", "foö:/a\n" + " ^") } @@ -675,7 +675,7 @@ class UriSpec extends AnyWordSpec with Matchers { // illegal path the[IllegalUriException] thrownBy Uri("http://www.example.com/name with spaces/") shouldBe { IllegalUriException( - "Illegal URI reference: Invalid input ' ', expected '/', 'EOI', '#', '?' or pchar (line 1, column 28)", + "Illegal URI reference: Invalid input ' ', expected pchar, '/', '?', '#' or 'EOI' (line 1, column 28)", "http://www.example.com/name with spaces/\n" + " ^") } @@ -683,7 +683,7 @@ class UriSpec extends AnyWordSpec with Matchers { // illegal path with control character the[IllegalUriException] thrownBy Uri("http:///with\newline") shouldBe { IllegalUriException( - "Illegal URI reference: Invalid input '\\n', expected '/', 'EOI', '#', '?' or pchar (line 1, column 13)", + "Illegal URI reference: Invalid input '\\n', expected pchar, '/', '?', '#' or 'EOI' (line 1, column 13)", "http:///with\n" + " ^") } diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/headers/HeaderSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/headers/HeaderSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/headers/HeaderSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/headers/HeaderSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/model/sse/ServerSentEventSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/settings/ClientConnectionSettingsSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/settings/ConnectionPoolSettingsSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/settings/Http2CommonSettingsSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/settings/PreviewServerSettingsSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ServerSettingsSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/settings/ServerSettingsSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/ServerSettingsSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/settings/ServerSettingsSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/SettingsEqualitySpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/settings/SettingsEqualitySpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/settings/SettingsEqualitySpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/settings/SettingsEqualitySpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/http/scaladsl/util/FastFutureSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/util/FastFutureSpec.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/http/scaladsl/util/FastFutureSpec.scala rename to akka-http-core/src/test/scala/akka/http/scaladsl/util/FastFutureSpec.scala diff --git a/akka-http-core/src/test/scala-2/akka/stream/testkit/Utils.scala b/akka-http-core/src/test/scala/akka/stream/testkit/Utils.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/stream/testkit/Utils.scala rename to akka-http-core/src/test/scala/akka/stream/testkit/Utils.scala diff --git a/akka-http-core/src/test/scala-2/akka/testkit/AkkaSpec.scala b/akka-http-core/src/test/scala/akka/testkit/AkkaSpec.scala similarity index 95% rename from akka-http-core/src/test/scala-2/akka/testkit/AkkaSpec.scala rename to akka-http-core/src/test/scala/akka/testkit/AkkaSpec.scala index 94c0e444d17..7318606b5e1 100644 --- a/akka-http-core/src/test/scala-2/akka/testkit/AkkaSpec.scala +++ b/akka-http-core/src/test/scala/akka/testkit/AkkaSpec.scala @@ -60,7 +60,7 @@ abstract class AkkaSpec(_system: ActorSystem) extends TestKit(_system) with AnyWordSpecLike with Matchers with BeforeAndAfterAll with WatchedByCoroner with TypeCheckedTripleEquals with ScalaFutures { - implicit val patience = PatienceConfig(testKitSettings.DefaultTimeout.duration) + implicit val patience: PatienceConfig = PatienceConfig(testKitSettings.DefaultTimeout.duration) def this(config: Config) = this(ActorSystem( AkkaSpec.getCallerName(getClass), @@ -72,7 +72,7 @@ abstract class AkkaSpec(_system: ActorSystem) def this() = this(ActorSystem(AkkaSpec.getCallerName(getClass), AkkaSpec.testConf)) - val log: LoggingAdapter = Logging(system, this.getClass) + val log: LoggingAdapter = Logging(system, this.getClass.asInstanceOf[Class[Any]]) override val invokeBeforeAllAndAfterAllEvenIfNoTestsAreExpected = true diff --git a/akka-http-core/src/test/scala-2/akka/testkit/Coroner.scala b/akka-http-core/src/test/scala/akka/testkit/Coroner.scala similarity index 100% rename from akka-http-core/src/test/scala-2/akka/testkit/Coroner.scala rename to akka-http-core/src/test/scala/akka/testkit/Coroner.scala diff --git a/akka-http-core/src/test/scala-2/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala b/akka-http-core/src/test/scala/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala similarity index 98% rename from akka-http-core/src/test/scala-2/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala rename to akka-http-core/src/test/scala/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala index 98fbb82fa31..49adef32603 100644 --- a/akka-http-core/src/test/scala-2/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala +++ b/akka-http-core/src/test/scala/io/akka/integrationtest/http/HttpModelIntegrationSpec.scala @@ -42,11 +42,11 @@ class HttpModelIntegrationSpec extends AnyWordSpec with Matchers with BeforeAndA val testConf: Config = ConfigFactory.parseString(""" akka.event-handlers = ["akka.testkit.TestEventListener"] akka.loglevel = WARNING""") - implicit val system = ActorSystem(getClass.getSimpleName, testConf) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) override def afterAll() = TestKit.shutdownActorSystem(system) - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() "External HTTP libraries" should { diff --git a/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala b/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala index 7a6485f165a..3fbf35896f2 100644 --- a/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala +++ b/akka-parsing/src/main/scala-3/akka/parboiled2/support/TailSwitch.scala @@ -74,6 +74,12 @@ object TailSwitch { type Aux[L <: HList, LI <: HList, T <: HList, TI <: HList, R <: HList, RI <: HList, Out0] = TailSwitch[L, T, R] { type Out = Out0 } - implicit def tailSwitch[L <: HList, T <: HList, R <: HList] + implicit def tailSwitch[L <: _ :: _, T <: _ :: _, R <: HList] : TailSwitch[L, T, R] { type Out = TailSwitch0[L, L, T, T, R, HNil] } = `n/a` + /// Optimisations to reduce compilation times to something tolerable + implicit def tailSwitch0: TailSwitch[HNil, HNil, HNil] { type Out = HNil } = `n/a` + implicit def tailSwitch1[T <: _ :: _]: TailSwitch[HNil, T, HNil] { type Out = HNil } = `n/a` + implicit def tailSwitch2[L <: _ :: _, R <: _ :: _]: TailSwitch[L, HNil, R] { type Out = Prepend0[L, R] } = `n/a` + implicit def tailSwitch3[L <: _ :: _]: TailSwitch[L, HNil, HNil] { type Out = L } = `n/a` + implicit def tailSwitch4[T <: HList, R <: _ :: _]: TailSwitch[HNil, T, R] { type Out = R } = `n/a` } diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 1718a98a77b..b1a20619bb8 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -27,7 +27,7 @@ object Dependencies { val scala212Version = "2.12.15" val scala213Version = "2.13.8" - val scala3Version = "3.1.1" + val scala3Version = "3.1.2" val allScalaVersions = // FIXME: can be simplified when Akka 2.5 is dropped if (AkkaDependency.akkaVersion startsWith "2.6.") From 78c8cbdd2cd3f7fa0c496a2404ab67d510427044 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 14:21:23 +0200 Subject: [PATCH 25/51] build: disable 2.12 building for now Because we removed the `@pre213` versions of some methods, 2.12 doesn't work for now --- .github/workflows/validate-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-and-test.yml b/.github/workflows/validate-and-test.yml index 868d25690f8..edf68d47818 100644 --- a/.github/workflows/validate-and-test.yml +++ b/.github/workflows/validate-and-test.yml @@ -53,7 +53,7 @@ jobs: strategy: fail-fast: false matrix: - SCALA_VERSION: [2.12, 2.13, 3] + SCALA_VERSION: [2.13, 3] JABBA_JDK: [1.8] steps: - name: Checkout From 8fb728a70e96c0bc50f629ae93e31eb6827e9100 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 14:35:02 +0200 Subject: [PATCH 26/51] build: also increase minimum Akka version for docs Otherwise, running the tests will fail if no explicit Akka version is passed on the sbt command line --- project/AkkaDependency.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/AkkaDependency.scala b/project/AkkaDependency.scala index 95c8a6042bc..4f3172a8f4d 100644 --- a/project/AkkaDependency.scala +++ b/project/AkkaDependency.scala @@ -46,7 +46,7 @@ object AkkaDependency { // Default version updated only when needed, https://doc.akka.io//docs/akka/current/project/downstream-upgrade-strategy.html val minimumExpectedAkkaVersion = "2.6.18" val default = akkaDependency(defaultVersion = minimumExpectedAkkaVersion) - val minimumExpectedAkka26Version = "2.6.8" + val minimumExpectedAkka26Version = "2.6.18" val docs = akkaDependency(defaultVersion = minimumExpectedAkka26Version) lazy val masterSnapshot = Artifact(determineLatestSnapshot(), true) From 2c00be62d0d1927efb594bcf5caacb9710911e17 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 14:39:26 +0200 Subject: [PATCH 27/51] build: fix aggregation for Scala 3 To make the PR validation pass (hopefully) Before, intermediate aggregations still pulled Scala 3 for their submodule. --- build.sbt | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/build.sbt b/build.sbt index c8ea71317f7..157a7f3584e 100644 --- a/build.sbt +++ b/build.sbt @@ -71,7 +71,7 @@ lazy val root = Project( id = "akka-http-root", base = file(".") ) - .enablePlugins(UnidocRoot, NoPublish, PublishRsyncPlugin, AggregatePRValidation) + .enablePlugins(UnidocRoot, NoPublish, PublishRsyncPlugin, AggregatePRValidation, NoScala3) .disablePlugins(MimaPlugin) .settings( // Unidoc doesn't like macro definitions @@ -130,7 +130,7 @@ val scalaMacroSupport = Seq( }), ) -val scala3MigrationModeOption = +val scala3MigrationModeOption = scalacOptions ++= { if (scalaVersion.value startsWith "3") Seq("-source:3.0-migration") @@ -295,7 +295,7 @@ lazy val httpJmhBench = project("akka-http-bench-jmh") lazy val httpMarshallersScala = project("akka-http-marshallers-scala") .settings(commonSettings) - .enablePlugins(NoPublish/*, AggregatePRValidation*/) + .enablePlugins(NoPublish, NoScala3 /*FIXME */ /*, AggregatePRValidation*/) .disablePlugins(MimaPlugin) .aggregate(httpSprayJson, httpXml) @@ -315,7 +315,7 @@ lazy val httpSprayJson = lazy val httpMarshallersJava = project("akka-http-marshallers-java") .settings(commonSettings) - .enablePlugins(NoPublish/*, AggregatePRValidation*/) + .enablePlugins(NoPublish, NoScala3 /*FIXME */ /*, AggregatePRValidation*/) .disablePlugins(MimaPlugin) .aggregate(httpJackson) @@ -507,7 +507,7 @@ lazy val compatibilityTests = Project("akka-http-compatibility-tests", file("akk ) lazy val billOfMaterials = Project("bill-of-materials", file("akka-http-bill-of-materials")) - .enablePlugins(BillOfMaterialsPlugin) + .enablePlugins(BillOfMaterialsPlugin, NoScala3 /* FIXME */) .disablePlugins(MimaPlugin) .settings( name := "akka-http-bom", From d36bd2720189031210acb7150308fe35d24ab7ed Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 14:50:35 +0200 Subject: [PATCH 28/51] parsing: fix copyright headers --- akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala | 2 +- .../src/main/scala-3/akka/http/ccompat/pre213macro.scala | 2 +- .../src/main/scala-3/akka/http/ccompat/since213macro.scala | 2 +- akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala b/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala index 0a06bb096d8..bc6806ff5b3 100644 --- a/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala +++ b/akka-parsing/src/main/scala-2/akka/macros/LogHelperMacro.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Lightbend Inc. + * Copyright (C) 2021-2022 Lightbend Inc. */ package akka.macros diff --git a/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala b/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala index 91d936c0153..1b55bf70f0a 100644 --- a/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala +++ b/akka-parsing/src/main/scala-3/akka/http/ccompat/pre213macro.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 Lightbend Inc. + * Copyright (C) 2019-2022 Lightbend Inc. */ package akka.http.ccompat diff --git a/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala b/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala index 5dc84ee1599..77ceef0c801 100644 --- a/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala +++ b/akka-parsing/src/main/scala-3/akka/http/ccompat/since213macro.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2019-2021 Lightbend Inc. + * Copyright (C) 2019-2022 Lightbend Inc. */ package akka.http.ccompat diff --git a/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala b/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala index dfed8febb33..0589b5bac27 100644 --- a/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala +++ b/akka-parsing/src/main/scala-3/akka/macros/LogHelperMacro.scala @@ -1,5 +1,5 @@ /* - * Copyright (C) 2021 Lightbend Inc. + * Copyright (C) 2021-2022 Lightbend Inc. */ package akka.macros From 2293252797f0aef0dcf44f8b97d86475e97d202b Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 15:06:02 +0200 Subject: [PATCH 29/51] caching: fix cached execution and test (#4099) The `asyncRoute & ...` dconstruction id not work as expected and also using `check` in tests starved threads themselves. Refs #4092, update to #4093 --- .../server/directives/CachingDirectives.scala | 24 ++++++------------- .../directives/CachingDirectivesSpec.scala | 16 ++++++------- 2 files changed, 14 insertions(+), 26 deletions(-) diff --git a/akka-http-caching/src/main/scala/akka/http/scaladsl/server/directives/CachingDirectives.scala b/akka-http-caching/src/main/scala/akka/http/scaladsl/server/directives/CachingDirectives.scala index a57765a040b..f18f8fcbf6a 100644 --- a/akka-http-caching/src/main/scala/akka/http/scaladsl/server/directives/CachingDirectives.scala +++ b/akka-http-caching/src/main/scala/akka/http/scaladsl/server/directives/CachingDirectives.scala @@ -49,13 +49,13 @@ trait CachingDirectives { // Do directive processing asynchronously to avoid locking the cache accidentally (#4092) // This will be slightly slower, but the rational here is that caching is used for slower kind of processing // anyway so the performance hit should be acceptable. - CachingDirectives.asyncRoute & - mapInnerRoute { route => ctx => - keyer.lift(ctx) match { - case Some(key) => cache.apply(key, () => route(ctx)) - case None => route(ctx) - } + Directive { inner => ctx => + import ctx.executionContext + keyer.lift(ctx) match { + case Some(key) => cache.apply(key, () => Future(inner(())(ctx)).flatten) + case None => inner(())(ctx) } + } /** * Creates an [[LfuCache]] with default settings obtained from the system's configuration. @@ -70,14 +70,4 @@ trait CachingDirectives { LfuCache[K, RouteResult](settings) } -object CachingDirectives extends CachingDirectives { - /** - * Run all route processing asynchronously. - */ - private[CachingDirectives] def asyncRoute: Directive0 = - Directive { inner => ctx => - import ctx.executionContext - Future { inner(()) } - .flatMap(route => route(ctx)) - } -} +object CachingDirectives extends CachingDirectives diff --git a/akka-http-caching/src/test/scala/akka/http/scaladsl/server/directives/CachingDirectivesSpec.scala b/akka-http-caching/src/test/scala/akka/http/scaladsl/server/directives/CachingDirectivesSpec.scala index 8c7eb1fea25..6fe07459701 100644 --- a/akka-http-caching/src/test/scala/akka/http/scaladsl/server/directives/CachingDirectivesSpec.scala +++ b/akka-http-caching/src/test/scala/akka/http/scaladsl/server/directives/CachingDirectivesSpec.scala @@ -6,18 +6,17 @@ package akka.http.scaladsl.server.directives import akka.http.caching.scaladsl.{ CachingSettings, LfuCacheSettings } import akka.http.impl.util._ -import akka.http.scaladsl.model.{ HttpResponse, Uri } -import akka.http.scaladsl.model.headers._ +import akka.http.scaladsl.model.HttpMethods.GET import akka.http.scaladsl.model.headers.CacheDirectives._ +import akka.http.scaladsl.model.headers._ +import akka.http.scaladsl.model.{ HttpResponse, Uri } import akka.http.scaladsl.server.Directives._ -import akka.http.scaladsl.server.{ ExceptionHandler, RequestContext } +import akka.http.scaladsl.server.{ ExceptionHandler, RequestContext, RouteResult } import akka.http.scaladsl.testkit.ScalatestRouteTest -import akka.http.scaladsl.model.HttpMethods.GET +import akka.testkit._ import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec -import akka.testkit._ - import scala.concurrent.Future import scala.concurrent.duration._ @@ -101,11 +100,10 @@ class CachingDirectivesSpec extends AnyWordSpec with Matchers with ScalatestRout } implicit val executor = system.dispatcher + val routeFunc = RouteResult.routeToFunction(route) Future.traverse(1 to 1000) { i => - Future { - Get(s"/$i") ~> route ~> check {} // check blocks to wait for result - } + routeFunc(Get(s"/$i")) }.awaitResult(10.second.dilated) } } From 901f51234666a35658688d4237ad64042f169b53 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 15:19:19 +0200 Subject: [PATCH 30/51] build: use simpler PR validation task for now The sophisticated version doesn't know about filtering out projects with unsupported Scala versions. --- .github/workflows/validate-and-test.yml | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/validate-and-test.yml b/.github/workflows/validate-and-test.yml index edf68d47818..36ceccb293b 100644 --- a/.github/workflows/validate-and-test.yml +++ b/.github/workflows/validate-and-test.yml @@ -81,7 +81,8 @@ jobs: # Quick testing for PR validation - name: Validate pull request for JDK ${{ matrix.JABBA_JDK }}, Scala ${{ matrix.SCALA_VERSION }} if: ${{ github.event_name == 'pull_request' }} - run: sbt -Dakka.http.parallelExecution=false -Dakka.test.timefactor=2 "+~ ${{ matrix.SCALA_VERSION }} validatePullRequest" + # FIXME: revert back to `validatePullRequest` task, when all modules support Scala 3 + run: sbt -Dakka.http.parallelExecution=false -Dakka.test.timefactor=2 "+~ ${{ matrix.SCALA_VERSION }} executePullRequestValidation" # Full testing for pushes - name: Run all tests JDK ${{ matrix.JABBA_JDK }}, Scala ${{ matrix.SCALA_VERSION }} From 495adb79682052be0f760e30c4b9da7a14da089c Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 14:50:00 +0200 Subject: [PATCH 31/51] testkit: enable Scala 3 --- .../akka/http/scaladsl/testkit/RouteTest.scala | 10 +++++----- .../http/scaladsl/testkit/RouteTestTimeout.scala | 2 +- .../scaladsl/testkit/ScalatestRouteTestSpec.scala | 3 ++- .../scaladsl/testkit/Specs2RouteTestSpec.scala | 3 ++- build.sbt | 1 - project/Dependencies.scala | 15 +++++++++------ 6 files changed, 19 insertions(+), 15 deletions(-) diff --git a/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala b/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala index 812d499bccc..30eb2e59766 100644 --- a/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala +++ b/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTest.scala @@ -16,7 +16,7 @@ import akka.http.scaladsl.settings.RoutingSettings import akka.http.scaladsl.settings.ServerSettings import akka.http.scaladsl.unmarshalling._ import akka.http.scaladsl.util.FastFuture._ -import akka.stream.SystemMaterializer +import akka.stream.{ Materializer, SystemMaterializer } import akka.stream.scaladsl.Source import akka.testkit.TestKit import akka.util.ConstantFun @@ -24,7 +24,7 @@ import com.typesafe.config.{ Config, ConfigFactory } import scala.collection.immutable import scala.concurrent.duration._ -import scala.concurrent.{ Await, ExecutionContext, Future } +import scala.concurrent.{ Await, ExecutionContext, ExecutionContextExecutor, Future } import scala.reflect.ClassTag import scala.util.DynamicVariable @@ -47,9 +47,9 @@ trait RouteTest extends RequestBuilding with WSTestRequestBuilding with RouteTes val config = if (source.isEmpty) ConfigFactory.empty() else ConfigFactory.parseString(source) config.withFallback(ConfigFactory.load()) } - implicit val system = createActorSystem() - implicit def executor = system.dispatcher - implicit val materializer = SystemMaterializer(system).materializer + implicit val system: ActorSystem = createActorSystem() + implicit def executor: ExecutionContextExecutor = system.dispatcher + implicit val materializer: Materializer = SystemMaterializer(system).materializer def cleanUp(): Unit = TestKit.shutdownActorSystem(system) diff --git a/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTestTimeout.scala b/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTestTimeout.scala index 738bfe74514..19276d293f9 100644 --- a/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTestTimeout.scala +++ b/akka-http-testkit/src/main/scala/akka/http/scaladsl/testkit/RouteTestTimeout.scala @@ -11,5 +11,5 @@ import akka.testkit._ case class RouteTestTimeout(duration: FiniteDuration) object RouteTestTimeout { - implicit def default(implicit system: ActorSystem) = RouteTestTimeout(1.second.dilated) + implicit def default(implicit system: ActorSystem): RouteTestTimeout = RouteTestTimeout(1.second.dilated) } diff --git a/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/ScalatestRouteTestSpec.scala b/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/ScalatestRouteTestSpec.scala index 93bb0d3c70f..4dcde5a8638 100644 --- a/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/ScalatestRouteTestSpec.scala +++ b/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/ScalatestRouteTestSpec.scala @@ -14,6 +14,7 @@ import akka.http.scaladsl.model._ import StatusCodes._ import HttpMethods._ import Directives._ +import akka.actor.ActorRef import akka.stream.scaladsl.Source import org.scalatest.exceptions.TestFailedException import headers.`X-Forwarded-Proto` @@ -101,7 +102,7 @@ class ScalatestRouteTestSpec extends AnyFreeSpec with Matchers with ScalatestRou case object Command val service = TestProbe() val handler = TestProbe() - implicit def serviceRef = service.ref + implicit def serviceRef: ActorRef = service.ref implicit val askTimeout: Timeout = 1.second.dilated val result = diff --git a/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/Specs2RouteTestSpec.scala b/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/Specs2RouteTestSpec.scala index cf7be39facb..f3405a9c284 100644 --- a/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/Specs2RouteTestSpec.scala +++ b/akka-http-testkit/src/test/scala/akka/http/scaladsl/testkit/Specs2RouteTestSpec.scala @@ -4,6 +4,7 @@ package akka.http.scaladsl.testkit +import akka.actor.ActorRef import akka.http.scaladsl.model.HttpMethods._ import akka.http.scaladsl.model.StatusCodes._ import akka.http.scaladsl.model._ @@ -54,7 +55,7 @@ class Specs2RouteTestSpec extends Specification with Specs2RouteTest { case object Command val service = TestProbe() val handler = TestProbe() - implicit def serviceRef = service.ref + implicit def serviceRef: ActorRef = service.ref implicit val askTimeout: Timeout = 1.second val result = diff --git a/build.sbt b/build.sbt index 157a7f3584e..1faacbd8e07 100644 --- a/build.sbt +++ b/build.sbt @@ -251,7 +251,6 @@ lazy val httpTestkit = project("akka-http-testkit") .enablePlugins(BootstrapGenjavadoc, MultiNodeScalaTest, ScaladocNoVerificationOfDiagrams) .enablePlugins(ReproducibleBuildsPlugin) .disablePlugins(MimaPlugin) // testkit, no bin compat guaranteed - .enablePlugins(NoScala3) // FIXME lazy val httpTests = project("akka-http-tests") .settings(commonSettings) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index b1a20619bb8..115e2e9da62 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -81,7 +81,14 @@ object Dependencies { object Test { val sprayJson = Compile.sprayJson % "test" // ApacheV2 val junit = Compile.junit % "test" // Common Public License 1.0 - val specs2 = "org.specs2" %% "specs2-core" % specs2Version % "test" // MIT + val specs2 = { + val specs2 = "org.specs2" %% "specs2-core" // MIT + ScalaVersionDependentModuleID.versioned { + case v if v.startsWith("2.") => specs2 % "4.10.6" + case _ => specs2 % "4.15.0" + } + } + val scalacheck = "org.scalacheck" %% "scalacheck" % scalaCheckVersion % "test" // New BSD val junitIntf = "com.github.sbt" % "junit-interface" % "0.13.3" % "test" // MIT @@ -123,11 +130,7 @@ object Dependencies { lazy val httpTestkit = Seq( versionDependentDeps( - ScalaVersionDependentModuleID.fromPF { - // FIXME: ultimately, we might update to a Scala 3 compatible version of specs2 - // for now disable specs2 support in the Scala 3 akka-http-testkit - case v if v startsWith "2." => Test.specs2.withConfigurations(Some("provided; test")) - } + Test.specs2 % "provided; test" ), l ++= Seq( Test.junit, Test.junitIntf, Compile.junit % "provided", From 0e11df51c57efc9a0184e17830feaed5f44a5a62 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Mon, 11 Apr 2022 15:39:22 +0200 Subject: [PATCH 32/51] caching: enable Scala 3 support --- .../akka/http/caching/scaladsl/LfuCacheSettings.scala | 8 ++++---- .../javadsl/server/directives/CachingDirectives.scala | 2 +- .../scala/akka/http/caching/ExpiringLfuCacheSpec.scala | 8 +++++--- build.sbt | 1 - 4 files changed, 10 insertions(+), 9 deletions(-) diff --git a/akka-http-caching/src/main/scala/akka/http/caching/scaladsl/LfuCacheSettings.scala b/akka-http-caching/src/main/scala/akka/http/caching/scaladsl/LfuCacheSettings.scala index 760b1e83071..3f50e3dfb08 100644 --- a/akka-http-caching/src/main/scala/akka/http/caching/scaladsl/LfuCacheSettings.scala +++ b/akka-http-caching/src/main/scala/akka/http/caching/scaladsl/LfuCacheSettings.scala @@ -22,10 +22,10 @@ abstract class LfuCacheSettings private[http] () extends javadsl.LfuCacheSetting def timeToLive: Duration def timeToIdle: Duration - final def getMaxCapacity: Int = maxCapacity - final def getInitialCapacity: Int = initialCapacity - final def getTimeToLive: Duration = timeToLive - final def getTimeToIdle: Duration = timeToIdle + final def getMaxCapacity: Int = self.maxCapacity + final def getInitialCapacity: Int = self.initialCapacity + final def getTimeToLive: Duration = self.timeToLive + final def getTimeToIdle: Duration = self.timeToIdle override def withMaxCapacity(newMaxCapacity: Int): LfuCacheSettings = self.copy(maxCapacity = newMaxCapacity) override def withInitialCapacity(newInitialCapacity: Int): LfuCacheSettings = self.copy(initialCapacity = newInitialCapacity) diff --git a/akka-http-caching/src/main/scala/akka/http/javadsl/server/directives/CachingDirectives.scala b/akka-http-caching/src/main/scala/akka/http/javadsl/server/directives/CachingDirectives.scala index c0ab6699463..6b144721e08 100644 --- a/akka-http-caching/src/main/scala/akka/http/javadsl/server/directives/CachingDirectives.scala +++ b/akka-http-caching/src/main/scala/akka/http/javadsl/server/directives/CachingDirectives.scala @@ -17,7 +17,7 @@ object CachingDirectives { import akka.http.scaladsl.server.directives.{ CachingDirectives => D } - private implicit def routeResultCacheMapping[K] = + private implicit def routeResultCacheMapping[K]: JavaMapping[Cache[K, RouteResult], akka.http.caching.scaladsl.Cache[K, akka.http.scaladsl.server.RouteResult]] = CacheJavaMapping.cacheMapping[K, RouteResult, K, akka.http.scaladsl.server.RouteResult] /** diff --git a/akka-http-caching/src/test/scala/akka/http/caching/ExpiringLfuCacheSpec.scala b/akka-http-caching/src/test/scala/akka/http/caching/ExpiringLfuCacheSpec.scala index 3b4e1f8bbaa..47cef01ede8 100755 --- a/akka-http-caching/src/test/scala/akka/http/caching/ExpiringLfuCacheSpec.scala +++ b/akka-http-caching/src/test/scala/akka/http/caching/ExpiringLfuCacheSpec.scala @@ -48,12 +48,14 @@ class ExpiringLfuCacheSpec extends AnyWordSpec with Matchers with BeforeAndAfter "return Futures on uncached values during evaluation and replace these with the value afterwards" in { val cache = lfuCache[String]() val latch = new CountDownLatch(1) - val future1 = cache(1, (promise: Promise[String]) => + val future1 = cache(1, { (promise: Promise[String]) => Future { latch.await() promise.success("A") } - ) + // (block autoformat) + () // provide Unit result automatically to hand-hold Scala 3 overload selection + }) val future2 = cache.get(1, () => "") latch.countDown() @@ -150,7 +152,7 @@ class ExpiringLfuCacheSpec extends AnyWordSpec with Matchers with BeforeAndAfter } }, 10.second) - views.transpose.foreach { ints: Seq[Int] => + views.transpose.foreach { (ints: Seq[Int]) => ints.filter(_ != 0).reduceLeft((a, b) => if (a == b) a else 0) should not be 0 } } diff --git a/build.sbt b/build.sbt index 1faacbd8e07..ffc3f6108bc 100644 --- a/build.sbt +++ b/build.sbt @@ -336,7 +336,6 @@ lazy val httpCaching = project("akka-http-caching") .settings(Dependencies.httpCaching) .dependsOn(http, httpCore, httpTestkit % "test") .enablePlugins(BootstrapGenjavadoc) - .enablePlugins(NoScala3) // FIXME def project(name: String) = Project(id = name, base = file(name)) From 8090ebc20d3e6e59c66284700589b9bb9e7ca160 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Mon, 25 Apr 2022 11:36:44 +0200 Subject: [PATCH 33/51] docs: use correct 'skip-packages' scalac option on Scala 3 (#4109) --- project/Doc.scala | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/project/Doc.scala b/project/Doc.scala index 681b0a8f625..4b407a59885 100644 --- a/project/Doc.scala +++ b/project/Doc.scala @@ -63,11 +63,15 @@ object Scaladoc extends AutoPlugin { "-sourcepath", base.getAbsolutePath, "-doc-title", "Akka HTTP", "-doc-version", ver, - // Workaround https://issues.scala-lang.org/browse/SI-10028 - "-skip-packages", "akka.pattern:org.specs2", "-doc-canonical-base-url", "https://doc.akka.io/api/akka-http/current/" ) ++ - plugins.map(plugin => "-Xplugin:" + plugin) + plugins.map(plugin => "-Xplugin:" + plugin) ++ + // Workaround https://issues.scala-lang.org/browse/SI-10028 + (if (scalaBinaryVersion == "3") + // https://github.com/lampepfl/dotty/issues/14939 + List("-skip-packages:akka.pattern:org.specs2") + else + List("-skip-packages", "akka.pattern:org.specs2")) CliOptions.scaladocDiagramsEnabled.ifTrue("-diagrams").toList ::: opts } From de551668ec84f748034e8326ff9ea888dff841d4 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Mon, 25 Apr 2022 11:51:46 +0200 Subject: [PATCH 34/51] http2: enable Scala 3 for akka-http2-support (#4108) --- .../engine/http2/H2SpecIntegrationSpec.scala | 4 ++-- .../impl/engine/http2/H2cUpgradeSpec.scala | 4 ++-- .../impl/engine/http2/Http2ClientSpec.scala | 7 +++--- .../impl/engine/http2/Http2ServerSpec.scala | 8 ++++--- .../engine/http2/ProtocolSwitchSpec.scala | 4 +++- .../engine/http2/RequestParsingSpec.scala | 22 +++++++++---------- .../impl/engine/http2/TelemetrySpiSpec.scala | 3 ++- .../http2/WithInPendingUntilFixed.scala | 16 -------------- .../engine/http2/WithPriorKnowledgeSpec.scala | 2 +- .../http2/framing/Http2FramingSpec.scala | 2 +- .../akka/http/scaladsl/Http2ServerTest.scala | 2 +- build.sbt | 1 - 12 files changed, 32 insertions(+), 43 deletions(-) delete mode 100644 akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithInPendingUntilFixed.scala diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2SpecIntegrationSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2SpecIntegrationSpec.scala index 1b9852450eb..5f9e2e49210 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2SpecIntegrationSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2SpecIntegrationSpec.scala @@ -10,7 +10,7 @@ import java.util.concurrent.atomic.AtomicBoolean import akka.http.impl.util.{ ExampleHttpContexts, WithLogCapturing } import akka.http.scaladsl.Http import akka.http.scaladsl.server.Directives -import akka.stream.ActorMaterializer +import akka.stream.{ ActorMaterializer, Materializer } import akka.testkit._ import akka.util.ByteString import org.scalatest.concurrent.ScalaFutures @@ -36,7 +36,7 @@ class H2SpecIntegrationSpec extends AkkaSpec( """) with Directives with ScalaFutures with WithLogCapturing { implicit val ec: ExecutionContext = system.dispatcher - implicit val mat = ActorMaterializer() + implicit val mat: Materializer = ActorMaterializer() override def expectedTestDuration = 5.minutes // because slow jenkins, generally finishes below 1 or 2 minutes diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2cUpgradeSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2cUpgradeSpec.scala index 3eb1ac8c077..6eb9eaa22ab 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2cUpgradeSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/H2cUpgradeSpec.scala @@ -51,7 +51,7 @@ class H2cUpgradeSpec extends AkkaSpecWithMaterializer(""" testWith(settings) } - def testWith(settings: String) { + def testWith(settings: String) = { val upgradeRequest = s"""GET / HTTP/1.1 Host: localhost @@ -62,7 +62,7 @@ HTTP2-Settings: $settings val frameProbe = Http2FrameProbe() Source.single(ByteString(upgradeRequest)).concat(Source.maybe) - .via(Tcp().outgoingConnection(binding.localAddress.getHostName, binding.localAddress.getPort)) + .via(Tcp(system).outgoingConnection(binding.localAddress.getHostName, binding.localAddress.getPort)) .runWith(frameProbe.sink) @tailrec def readToEndOfHeader(currentlyRead: String = ""): String = diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ClientSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ClientSpec.scala index c17031f19c7..c76aec5e077 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ClientSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ClientSpec.scala @@ -42,9 +42,10 @@ import org.scalatest.concurrent.Eventually import org.scalatest.concurrent.PatienceConfiguration.Timeout import javax.net.ssl.SSLContext -import scala.collection.immutable +import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.concurrent.duration._ +import scala.collection.immutable /** * This tests the http2 client protocol logic. @@ -60,7 +61,7 @@ class Http2ClientSpec extends AkkaSpecWithMaterializer(""" akka.http.client.http2.log-frames = on akka.http.client.http2.completion-timeout = 500ms """) - with WithInPendingUntilFixed with Eventually { + with Eventually { override implicit val patience = PatienceConfig(5.seconds, 5.seconds) override def failOnSevereMessages: Boolean = true @@ -932,7 +933,7 @@ class Http2ClientSpec extends AkkaSpecWithMaterializer(""" } protected /* To make ByteFlag warnings go away */ abstract class TestSetupWithoutHandshake { - implicit def ec = system.dispatcher + implicit def ec: ExecutionContext = system.dispatcher private lazy val responseIn = TestSubscriber.probe[HttpResponse]() private lazy val requestOut = TestPublisher.probe[HttpRequest]() diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ServerSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ServerSpec.scala index 5268be3c97f..da2861f6b63 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ServerSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/Http2ServerSpec.scala @@ -41,6 +41,7 @@ import org.scalatest.concurrent.PatienceConfiguration.Timeout import scala.collection.immutable import scala.concurrent.duration._ import scala.concurrent.Await +import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.concurrent.Promise @@ -57,7 +58,7 @@ class Http2ServerSpec extends AkkaSpecWithMaterializer(""" akka.http.server.remote-address-header = on akka.http.server.http2.log-frames = on """) - with WithInPendingUntilFixed with Eventually { + with Eventually { override def failOnSevereMessages: Boolean = true "The Http/2 server implementation" should { @@ -1387,13 +1388,14 @@ class Http2ServerSpec extends AkkaSpecWithMaterializer(""" } "reject incoming frames on already half-closed substream" in pending - "reject even-numbered client-initiated substreams" inPendingUntilFixed new SimpleRequestResponseRoundtripSetup { + "reject even-numbered client-initiated substreams" in pending /* new SimpleRequestResponseRoundtripSetup { network.sendHEADERS(2, endStream = true, endHeaders = true, HPackSpecExamples.C41FirstRequestWithHuffman) network.expectGOAWAY() // after GOAWAY we expect graceful completion after x amount of time // TODO: completion logic, wait?! expectGracefulCompletion() } + */ "reject all other frames while waiting for CONTINUATION frames" in pending @@ -1665,7 +1667,7 @@ class Http2ServerSpec extends AkkaSpecWithMaterializer(""" } protected /* To make ByteFlag warnings go away */ abstract class TestSetupWithoutHandshake { - implicit def ec = system.dispatcher + implicit def ec: ExecutionContext = system.dispatcher private val framesOut: Http2FrameProbe = Http2FrameProbe() private val toNet = framesOut.plainDataProbe diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/ProtocolSwitchSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/ProtocolSwitchSpec.scala index 6a90250afee..3154b09dfa5 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/ProtocolSwitchSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/ProtocolSwitchSpec.scala @@ -9,6 +9,7 @@ import akka.Done import akka.http.impl.engine.server.ServerTerminator import akka.http.scaladsl.Http import akka.stream.ActorMaterializer +import akka.stream.Materializer import akka.stream.OverflowStrategy import akka.stream.QueueOfferResult.Enqueued import akka.stream.TLSProtocol._ @@ -22,10 +23,11 @@ import akka.testkit.AkkaSpec import org.scalatest.exceptions.TestFailedException import org.scalatest.time.{ Milliseconds, Seconds, Span } +import scala.concurrent.ExecutionContext import scala.concurrent.duration.FiniteDuration class ProtocolSwitchSpec extends AkkaSpec { - implicit val mat = ActorMaterializer() + implicit val mat: Materializer = ActorMaterializer() override implicit val patience: PatienceConfig = PatienceConfig(timeout = Span(2, Seconds), interval = Span(50, Milliseconds)) diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/RequestParsingSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/RequestParsingSpec.scala index 2f697530fc1..4ca9f169381 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/RequestParsingSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/RequestParsingSpec.scala @@ -95,7 +95,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe ":scheme" -> "https", ":path" -> "/" ) - forAll(0 until pseudoHeaders.length) { insertPoint: Int => + forAll(pseudoHeaders.indices: Seq[Int]) { (insertPoint: Int) => // Insert the Foo header so it occurs before at least one pseudo-header val (before, after) = pseudoHeaders.splitAt(insertPoint) val modified = before ++ Vector("Foo" -> "bar") ++ after @@ -151,7 +151,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe "parse the ':method' pseudo-header correctly" in { val methods = Seq("GET", "POST", "DELETE", "OPTIONS") - forAll(methods) { method: String => + forAll(methods) { (method: String) => val request: HttpRequest = parse( keyValuePairs = Vector( ":method" -> method, @@ -174,7 +174,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe // We're restricted in what we can test because the HttpRequest class // can't be constructed with any other schemes. val schemes = Seq("http", "https", "ws", "wss") - forAll(schemes) { scheme: String => + forAll(schemes) { (scheme: String) => val request: HttpRequest = parse( keyValuePairs = Vector( ":method" -> "POST", @@ -245,8 +245,8 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe "cnn.example.com&story=breaking_news@10.0.0.1" ) val schemes = Seq("http", "https") - forAll(schemes) { scheme: String => - forAll(authorities) { authority: String => + forAll(schemes) { (scheme: String) => + forAll(authorities) { (authority: String) => val exception = the[Exception] thrownBy (parse( keyValuePairs = Vector( ":method" -> "POST", @@ -332,7 +332,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe "?", "&", "=", "#", ":", "?", "#", "[", "]", "@", " ", "http://localhost/foo" ) - forAll(invalidAbsolutePaths) { absPath: String => + forAll(invalidAbsolutePaths) { (absPath: String) => val exception = the[ParsingException] thrownBy (parsePath(absPath)) exception.getMessage should include("http2-path-pseudo-header") } @@ -343,7 +343,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe // Illegal for path-absolute in RFC3986 to start with multiple slashes "//", "//x" ) - forAll(invalidAbsolutePaths) { absPath: String => + forAll(invalidAbsolutePaths) { (absPath: String) => val exception = the[ParsingException] thrownBy (parsePath(absPath, uriParsingMode = Uri.ParsingMode.Strict)) exception.getMessage should include("http2-path-pseudo-header") } @@ -375,7 +375,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe // How form-encoded query strings are parsed is not strictly part of the HTTP/2 and URI RFCs, // but lets do a quick sanity check to ensure that form-encoded query strings are correctly // parsed into values further up the parsing stack. - optParsedQuery.foreach { expectedParsedQuery: Uri.Query => + optParsedQuery.foreach { (expectedParsedQuery: Uri.Query) => uri.query() should contain theSameElementsAs (expectedParsedQuery) } } @@ -388,7 +388,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe ) forAll(absolutePaths.take(3)) { case (inputPath, _) => - forAll(invalidQueries) { query: String => + forAll(invalidQueries) { (query: String) => shouldThrowMalformedRequest(parsePath(inputPath + "?" + query, uriParsingMode = Uri.ParsingMode.Strict)) } } @@ -414,7 +414,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe "reject empty ':path' pseudo-headers for http and https" in pendingUntilFixed { val schemes = Seq("http", "https") - forAll(schemes) { scheme: String => + forAll(schemes) { (scheme: String) => shouldThrowMalformedRequest(parse( keyValuePairs = Vector( ":method" -> "POST", @@ -440,7 +440,7 @@ class RequestParsingSpec extends AkkaSpecWithMaterializer with Inside with Inspe "reject requests without a mandatory pseudo-headers" in { val mandatoryPseudoHeaders = Seq(":method", ":scheme", ":path") - forAll(mandatoryPseudoHeaders) { name: String => + forAll(mandatoryPseudoHeaders) { (name: String) => val thrown = shouldThrowMalformedRequest(parse( keyValuePairs = Vector( ":scheme" -> "https", diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/TelemetrySpiSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/TelemetrySpiSpec.scala index addeeca87da..5ef11662848 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/TelemetrySpiSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/TelemetrySpiSpec.scala @@ -211,7 +211,8 @@ abstract class TelemetrySpiSpec(useTls: Boolean) extends AkkaSpecWithMaterialize val connId = telemetryProbe.expectMsgType[ConnectionId] // ... and a request flies in via _that_ connection. telemetryProbe.expectMsg("request-seen") - telemetryProbe.expectMsgType[ConnectionId] should ===(connId) + val requestConnId = telemetryProbe.expectMsgType[ConnectionId] + requestConnId should ===(connId) // The server sends the response... telemetryProbe.expectMsg("response-seen") diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithInPendingUntilFixed.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithInPendingUntilFixed.scala deleted file mode 100644 index bc568740dd8..00000000000 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithInPendingUntilFixed.scala +++ /dev/null @@ -1,16 +0,0 @@ -/* - * Copyright (C) 2009-2022 Lightbend Inc. - */ - -package akka.http.impl.engine.http2 - -import org.scalactic.source -import org.scalatest.wordspec.AnyWordSpecLike - -/** Adds `"test" inPendingUntilFixed {...}` which is equivalent to `"test" in pendingUntilFixed({...})` */ -trait WithInPendingUntilFixed extends AnyWordSpecLike { - implicit class InPendingUntilFixed(val str: String) { - def inPendingUntilFixed(f: => Any /* Assertion */ )(implicit pos: source.Position): Unit = - str.in(pendingUntilFixed(f))(pos) - } -} diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithPriorKnowledgeSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithPriorKnowledgeSpec.scala index 4aa6e980f76..af1c5df9048 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithPriorKnowledgeSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/WithPriorKnowledgeSpec.scala @@ -40,7 +40,7 @@ class WithPriorKnowledgeSpec extends AkkaSpecWithMaterializer(""" val source = Source.queue[String](1000, OverflowStrategy.fail) .map(str => ByteString(Base64.getDecoder.decode(str))) - .via(Tcp().outgoingConnection(host, port)) + .via(Tcp(system).outgoingConnection(host, port)) .toMat(fromServer.sink)(Keep.left) .run() diff --git a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/framing/Http2FramingSpec.scala b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/framing/Http2FramingSpec.scala index e2571ccda92..308006f9ca7 100644 --- a/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/framing/Http2FramingSpec.scala +++ b/akka-http2-support/src/test/scala/akka/http/impl/engine/http2/framing/Http2FramingSpec.scala @@ -494,7 +494,7 @@ class Http2FramingSpec extends AkkaSpecWithMaterializer { } private def parseToEvents(bytes: Seq[ByteString]): immutable.Seq[FrameEvent] = - Source(bytes.toVector).via(new Http2FrameParsing(shouldReadPreface = false, Logging(system, getClass))).runWith(Sink.seq) + Source(bytes.toVector).via(new Http2FrameParsing(shouldReadPreface = false, Logging(system, classOf[Http2FramingSpec]))).runWith(Sink.seq) .awaitResult(1.second.dilated) private def renderToByteString(events: immutable.Seq[FrameEvent]): ByteString = Source(events).map(FrameRenderer.render).runFold(ByteString.empty)(_ ++ _) diff --git a/akka-http2-support/src/test/scala/akka/http/scaladsl/Http2ServerTest.scala b/akka-http2-support/src/test/scala/akka/http/scaladsl/Http2ServerTest.scala index fe3a0b6d641..aceb8ad6f2a 100644 --- a/akka-http2-support/src/test/scala/akka/http/scaladsl/Http2ServerTest.scala +++ b/akka-http2-support/src/test/scala/akka/http/scaladsl/Http2ServerTest.scala @@ -35,7 +35,7 @@ object Http2ServerTest extends App { akka.actor.default-dispatcher.fork-join-executor.parallelism-max=8 akka.http.server.preview.enable-http2 = true """) - implicit val system = ActorSystem("ServerTest", testConf) + implicit val system: ActorSystem = ActorSystem("ServerTest", testConf) implicit val ec: ExecutionContext = system.dispatcher def slowDown[T](millis: Int): T => Future[T] = { t => diff --git a/build.sbt b/build.sbt index ffc3f6108bc..7d5c911ff5e 100644 --- a/build.sbt +++ b/build.sbt @@ -233,7 +233,6 @@ lazy val http2Support = project("akka-http2-support") .enablePlugins(BootstrapGenjavadoc) .enablePlugins(ReproducibleBuildsPlugin) .disablePlugins(MimaPlugin) // experimental module still - .enablePlugins(NoScala3) // FIXME lazy val httpTestkit = project("akka-http-testkit") .settings(commonSettings) From 471a0f6267aa23b6bff69e18d2c0eab1b8eb4974 Mon Sep 17 00:00:00 2001 From: Jan Chyb <48855024+jchyb@users.noreply.github.com> Date: Mon, 25 Apr 2022 15:23:33 +0200 Subject: [PATCH 35/51] http-tests: allow to compile with Scala 3 with 3.0-migration option (#4107) --- .../sprayjson/SprayJsonSupportSpec.scala | 7 ++++--- .../http/AkkaHttpServerLatencyMultiNodeSpec.scala | 2 +- .../scala/akka/remote/testkit/MultiNodeConfig.scala | 6 +++--- .../akka/remote/testkit/PerfFlamesSupport.scala | 2 +- .../akka/http/scaladsl/CustomMediaTypesSpec.scala | 2 +- .../scala/akka/http/scaladsl/FormDataSpec.scala | 2 +- .../akka/http/scaladsl/TestSingleRequest.scala | 4 ++-- .../http/scaladsl/coding/CodecSpecSupport.scala | 4 ++-- .../sprayjson/SprayJsonSupportSpec.scala | 3 ++- .../FromStatusCodeAndXYZMarshallerSpec.scala | 3 ++- .../http/scaladsl/marshalling/MarshallingSpec.scala | 4 ++-- .../akka/http/scaladsl/server/BasicRouteSpecs.scala | 7 ++++--- .../http/scaladsl/server/ConnectionTestApp.scala | 4 ++-- .../DontLeakActorsOnFailingConnectionSpecs.scala | 7 ++++--- .../http/scaladsl/server/EntityStreamingSpec.scala | 13 ++++++++----- .../akka/http/scaladsl/server/SizeLimitSpec.scala | 6 +++--- .../akka/http/scaladsl/server/TcpLeakApp.scala | 6 +++--- .../akka/http/scaladsl/server/TestServer.scala | 10 ++++++---- .../server/directives/CodingDirectivesSpec.scala | 2 +- .../directives/FileAndResourceDirectivesSpec.scala | 2 +- .../directives/FileUploadDirectivesSpec.scala | 2 +- .../server/directives/FormFieldDirectivesSpec.scala | 4 +++- .../directives/MarshallingDirectivesSpec.scala | 2 +- .../server/directives/ParameterDirectivesSpec.scala | 7 ++++--- .../server/directives/RouteDirectivesSpec.scala | 12 ++++++++++-- .../server/directives/TimeoutDirectivesSpec.scala | 2 +- .../http/scaladsl/server/util/TupleOpsSpec.scala | 6 +++--- .../scaladsl/unmarshalling/UnmarshallingSpec.scala | 4 ++-- build.sbt | 5 +---- 29 files changed, 79 insertions(+), 61 deletions(-) diff --git a/akka-http-marshallers-scala/akka-http-spray-json/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala b/akka-http-marshallers-scala/akka-http-spray-json/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala index a9850540423..792b9bb7376 100644 --- a/akka-http-marshallers-scala/akka-http-spray-json/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala +++ b/akka-http-marshallers-scala/akka-http-spray-json/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala @@ -16,15 +16,16 @@ import org.scalatest.concurrent.ScalaFutures import spray.json.{ JsArray, JsString, JsValue } import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpec +import spray.json.RootJsonFormat class SprayJsonSupportSpec extends AnyWordSpec with Matchers with ScalaFutures { import SprayJsonSupport._ import SprayJsonSupportSpec._ import spray.json.DefaultJsonProtocol._ - implicit val exampleFormat = jsonFormat1(Example.apply) - implicit val sys = ActorSystem("SprayJsonSupportSpec") - implicit val mat = ActorMaterializer() + implicit val exampleFormat: RootJsonFormat[Example] = jsonFormat1(Example.apply) + implicit val sys: ActorSystem = ActorSystem("SprayJsonSupportSpec") + implicit val mat: ActorMaterializer = ActorMaterializer() implicit val ec: ExecutionContext = sys.dispatcher val TestString = "Contains all UTF-8 characters: 2-byte: £, 3-byte: ヨ, 4-byte: 😁, 4-byte as a literal surrogate pair: \uD83D\uDE01" diff --git a/akka-http-tests/src/multi-jvm/scala/akka/http/AkkaHttpServerLatencyMultiNodeSpec.scala b/akka-http-tests/src/multi-jvm/scala/akka/http/AkkaHttpServerLatencyMultiNodeSpec.scala index 3c7967274e5..4341f3ee378 100644 --- a/akka-http-tests/src/multi-jvm/scala/akka/http/AkkaHttpServerLatencyMultiNodeSpec.scala +++ b/akka-http-tests/src/multi-jvm/scala/akka/http/AkkaHttpServerLatencyMultiNodeSpec.scala @@ -244,7 +244,7 @@ class AkkaHttpServerLatencyMultiNodeSpec extends MultiNodeSpec(AkkaHttpServerLat runOn(loadGenerator) { info(s"${id} => running: $cmd") import akka.pattern.ask - implicit val timeout = Timeout(30.minutes) // we don't want to timeout here + implicit val timeout: Timeout = Timeout(30.minutes) // we don't want to timeout here val res = (loadGeneratorActor ? LoadGenCommand(cmd)).mapTo[LoadGenResults] val results = Await.result(res, timeout.duration) diff --git a/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/MultiNodeConfig.scala b/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/MultiNodeConfig.scala index e5349c07571..8b6a76d14cf 100644 --- a/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/MultiNodeConfig.scala +++ b/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/MultiNodeConfig.scala @@ -22,7 +22,7 @@ import akka.testkit.TestEvent._ import scala.concurrent.duration._ import akka.remote.testconductor.RoleName import akka.actor.RootActorPath -import akka.event.{ Logging, LoggingAdapter } +import akka.event.{ Logging, LogSource, LoggingAdapter } /** * Configure the role names and participants of the test, including configuration settings. @@ -261,13 +261,13 @@ abstract class MultiNodeSpec(val myself: RoleName, _system: ActorSystem, _roles: this(config.myself, ActorSystem(MultiNodeSpec.getCallerName(classOf[MultiNodeSpec]), ConfigFactory.load(config.config)), config.roles, config.deployments) - val log: LoggingAdapter = Logging(system, this.getClass) + val log: LoggingAdapter = Logging(system, this.getClass)(LogSource.fromClass) /** * Enrich `.await()` onto all Awaitables, using remaining duration from the innermost * enclosing `within` block or QueryTimeout. */ - implicit def awaitHelper[T](w: Awaitable[T]) = new AwaitHelper(w) + implicit def awaitHelper[T](w: Awaitable[T]): AwaitHelper[T] = new AwaitHelper(w) class AwaitHelper[T](w: Awaitable[T]) { def await: T = Await.result(w, remainingOr(testConductor.Settings.QueryTimeout.duration)) } diff --git a/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/PerfFlamesSupport.scala b/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/PerfFlamesSupport.scala index 51fe30cb169..ca8468db9a6 100644 --- a/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/PerfFlamesSupport.scala +++ b/akka-http-tests/src/multi-jvm/scala/akka/remote/testkit/PerfFlamesSupport.scala @@ -14,7 +14,7 @@ import scala.concurrent.duration._ /** * Support trait allowing trivially recording perf metrics from [[MultiNodeSpec]]s */ -private[akka] trait PerfFlamesSupport { _: MultiNodeSpec => +private[akka] trait PerfFlamesSupport { multiNodeSpec: MultiNodeSpec => /** * Runs `perf-java-flames` script on given node (JVM process). diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/CustomMediaTypesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/CustomMediaTypesSpec.scala index 5eb04a6a126..95083d039e6 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/CustomMediaTypesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/CustomMediaTypesSpec.scala @@ -17,7 +17,7 @@ import scala.concurrent.duration._ class CustomMediaTypesSpec extends AkkaSpec with ScalaFutures with Directives with RequestBuilding { - implicit val mat = ActorMaterializer() + implicit val mat: ActorMaterializer = ActorMaterializer() "Http" should { "find media types in a set if they differ in casing" in { diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/FormDataSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/FormDataSpec.scala index a1c9e4e9b3e..c80e93543d2 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/FormDataSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/FormDataSpec.scala @@ -11,7 +11,7 @@ import akka.http.scaladsl.model._ import akka.testkit.AkkaSpec class FormDataSpec extends AkkaSpec { - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() import system.dispatcher val formData = FormData(Map("surname" -> "Smith", "age" -> "42")) diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/TestSingleRequest.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/TestSingleRequest.scala index ee1184c5888..e5b8bc71a6e 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/TestSingleRequest.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/TestSingleRequest.scala @@ -19,8 +19,8 @@ object TestSingleRequest extends App { akka.log-dead-letters = off akka.stream.materializer.debug.fuzzing-mode = off """) - implicit val system = ActorSystem("ServerTest", testConf) - implicit val materializer = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem("ServerTest", testConf) + implicit val materializer: ActorMaterializer = ActorMaterializer() import system.dispatcher val url = StdIn.readLine("url? ") diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/coding/CodecSpecSupport.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/coding/CodecSpecSupport.scala index 8f9a2c8c89e..02a6c046cba 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/coding/CodecSpecSupport.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/coding/CodecSpecSupport.scala @@ -70,8 +70,8 @@ Consetetur sadipscing elitr, sed diam nonumy eirmod tempor invidunt ut labore et voluptua. At vero eos et accusam et justo duo dolores et ea rebum. Stet clita kasd gubergren, no sea takimata sanctus est Lorem ipsum dolor sit amet. Lorem ipsum dolor sit amet, consetetur sadipscing elitr, sed diam nonumy e""".replace("\r\n", "\n") - implicit val system = ActorSystem(getClass.getSimpleName) - implicit val materializer = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName) + implicit val materializer: ActorMaterializer = ActorMaterializer() override def afterAll() = TestKit.shutdownActorSystem(system) } diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala index cbd0df41d82..cfc01b5fee1 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/marshallers/sprayjson/SprayJsonSupportSpec.scala @@ -12,10 +12,11 @@ import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller import spray.json.{ JsValue, PrettyPrinter, JsonPrinter, DefaultJsonProtocol } import scala.collection.immutable.ListMap +import spray.json.RootJsonFormat class SprayJsonSupportSpec extends JsonSupportSpec { object EmployeeJsonProtocol extends DefaultJsonProtocol { - implicit val employeeFormat = jsonFormat5(Employee.apply) + implicit val employeeFormat: RootJsonFormat[Employee] = jsonFormat5(Employee.apply) } import EmployeeJsonProtocol._ diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/FromStatusCodeAndXYZMarshallerSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/FromStatusCodeAndXYZMarshallerSpec.scala index e1c8849ce81..80ff013cb35 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/FromStatusCodeAndXYZMarshallerSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/FromStatusCodeAndXYZMarshallerSpec.scala @@ -9,13 +9,14 @@ import akka.http.scaladsl.model.StatusCodes._ import akka.http.scaladsl.model.headers.Accept import akka.http.scaladsl.model.{ ContentTypes, MediaRanges, MediaTypes } import akka.http.scaladsl.server.{ Route, RoutingSpec } +import spray.json.RootJsonFormat class FromStatusCodeAndXYZMarshallerSpec extends RoutingSpec { case class ErrorInfo(errorMessage: String) // a somewhat arbitrary ErrorInfo marshaller that can either return a text or an application/json response implicit val errorInfoMarshaller: ToEntityMarshaller[ErrorInfo] = { import spray.json.DefaultJsonProtocol._ - implicit val errorInfoFormat = jsonFormat1(ErrorInfo.apply _) + implicit val errorInfoFormat: RootJsonFormat[ErrorInfo] = jsonFormat1(ErrorInfo.apply _) Marshaller.oneOf( Marshaller.StringMarshaller.compose[ErrorInfo](_.errorMessage), SprayJsonSupport.sprayJsonMarshaller(errorInfoFormat) diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/MarshallingSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/MarshallingSpec.scala index 5a311c28c76..5e5cc7630b4 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/MarshallingSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/marshalling/MarshallingSpec.scala @@ -25,8 +25,8 @@ import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers class MarshallingSpec extends AnyFreeSpec with Matchers with BeforeAndAfterAll with MultipartMarshallers with MarshallingTestUtils { - implicit val system = ActorSystem(getClass.getSimpleName) - implicit val materializer = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName) + implicit val materializer: ActorMaterializer = ActorMaterializer() import system.dispatcher override val testConfig = ConfigFactory.load() diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala index e395510bce6..609a88d3b1f 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala @@ -8,6 +8,7 @@ import akka.http.scaladsl.model import model.HttpMethods._ import model.StatusCodes import akka.testkit.EventFilter +import akka.http.scaladsl.server.util.ConstructFromTuple object BasicRouteSpecs { private[http] def defaultExnHandler500Error(message: String) = { @@ -148,7 +149,7 @@ class BasicRouteSpecs extends RoutingSpec { "extract one argument" in { case class MyNumber(i: Int) - val abcPath = path("abc" / IntNumber).as(MyNumber)(echoComplete) + val abcPath = path("abc" / IntNumber).as(ConstructFromTuple.instance1(MyNumber))(echoComplete) Get("/abc/5") ~> abcPath ~> check { responseAs[String] shouldEqual "MyNumber(5)" @@ -157,7 +158,7 @@ class BasicRouteSpecs extends RoutingSpec { "extract two arguments" in { case class Person(name: String, age: Int) - val personPath = path("person" / Segment / IntNumber).as(Person)(echoComplete) + val personPath = path("person" / Segment / IntNumber).as(ConstructFromTuple.instance2(Person))(echoComplete) Get("/person/john/38") ~> personPath ~> check { responseAs[String] shouldEqual "Person(john,38)" @@ -168,7 +169,7 @@ class BasicRouteSpecs extends RoutingSpec { require(i > 10) } - val abcPath = path("abc" / IntNumber).as(MyValidNumber)(echoComplete) + val abcPath = path("abc" / IntNumber).as(ConstructFromTuple.instance1(MyValidNumber))(echoComplete) Get("/abc/5") ~> abcPath ~> check { rejection shouldBe a[ValidationRejection] diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/ConnectionTestApp.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/ConnectionTestApp.scala index dc47a4b9e50..cc61465ccb9 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/ConnectionTestApp.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/ConnectionTestApp.scala @@ -27,9 +27,9 @@ object ConnectionTestApp { } """) - implicit val system = ActorSystem("ConnectionTest", testConf) + implicit val system: ActorSystem = ActorSystem("ConnectionTest", testConf) import system.dispatcher - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() val clientFlow = Http().superPool[Int]() diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala index c2849801d2a..72c4b965f86 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala @@ -23,6 +23,7 @@ import scala.concurrent.duration._ import scala.util.{ Failure, Success, Try } import org.scalatest.matchers.should.Matchers import org.scalatest.wordspec.AnyWordSpecLike +import akka.event.LogSource abstract class DontLeakActorsOnFailingConnectionSpecs(poolImplementation: String) extends AnyWordSpecLike with Matchers with BeforeAndAfterAll with WithLogCapturing { @@ -37,10 +38,10 @@ abstract class DontLeakActorsOnFailingConnectionSpecs(poolImplementation: String http.host-connection-pool.base-connection-backoff = 0 ms }""").withFallback(ConfigFactory.load()) - implicit val system = ActorSystem("DontLeakActorsOnFailingConnectionSpecs-" + poolImplementation, config) - implicit val materializer = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem("DontLeakActorsOnFailingConnectionSpecs-" + poolImplementation, config) + implicit val materializer: ActorMaterializer = ActorMaterializer() - val log = Logging(system, getClass) + val log = Logging(system, getClass)(LogSource.fromClass) "Http.superPool" should { diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/EntityStreamingSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/EntityStreamingSpec.scala index 12b5615dfe8..bff030b2f71 100755 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/EntityStreamingSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/EntityStreamingSpec.scala @@ -6,7 +6,6 @@ package akka.http.scaladsl.server import scala.concurrent.Future import scala.concurrent.duration._ - import akka.NotUsed import akka.http.scaladsl.common.{ EntityStreamingSupport, JsonEntityStreamingSupport } import akka.http.scaladsl.marshalling._ @@ -16,9 +15,10 @@ import akka.stream.scaladsl._ import akka.testkit._ import akka.util.ByteString import org.scalatest.concurrent.ScalaFutures +import spray.json.{ DefaultJsonProtocol, RootJsonFormat } class EntityStreamingSpec extends RoutingSpec with ScalaFutures { - implicit override val patience = PatienceConfig(5.seconds.dilated(system), 200.millis) + implicit override val patience: PatienceConfig = PatienceConfig(5.seconds.dilated(system), 200.millis) //#models case class Tweet(uid: Int, txt: String) @@ -35,8 +35,8 @@ class EntityStreamingSpec extends RoutingSpec with ScalaFutures { extends akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport with spray.json.DefaultJsonProtocol { - implicit val tweetFormat = jsonFormat2(Tweet.apply) - implicit val measurementFormat = jsonFormat2(Measurement.apply) + implicit val tweetFormat: RootJsonFormat[Tweet] = jsonFormat2(Tweet.apply) + implicit val measurementFormat: RootJsonFormat[Measurement] = jsonFormat2(Measurement.apply) } "spray-json-response-streaming" in { @@ -278,7 +278,10 @@ class EntityStreamingSpec extends RoutingSpec with ScalaFutures { .runFold(0) { (cnt, _) => cnt + 1 } complete { - measurementsSubmitted.map(n => Map("msg" -> s"""Total metrics received: $n""")) + // FIXME: workaround for Scala 3 which cannot figure out the right implicit for some reason + // Needs same name to avoid ambiguity in Scala 2 + implicit val mapFormat: RootJsonFormat[Map[String, String]] = DefaultJsonProtocol.mapFormat + measurementsSubmitted.map((n: Int) => Map[String, String]("msg" -> s"""Total metrics received: $n""")) } } } diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala index 3f13885386b..f5029546ea1 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala @@ -41,12 +41,12 @@ class SizeLimitSpec extends AnyWordSpec with Matchers with RequestBuilding with akka.http.server.parsing.max-content-length = $maxContentLength akka.http.routing.decode-max-size = $decodeMaxSize """) - implicit val system = ActorSystem(getClass.getSimpleName, testConf) + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName, testConf) import system.dispatcher - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() val random = new scala.util.Random(42) - implicit val defaultPatience = PatienceConfig(timeout = Span(2, Seconds), interval = Span(5, Millis)) + implicit val defaultPatience: PatienceConfig = PatienceConfig(timeout = Span(2, Seconds), interval = Span(5, Millis)) "a normal route" should { val route = path("noDirective") { diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TcpLeakApp.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TcpLeakApp.scala index 69e4e626c0a..4163ea0ef22 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TcpLeakApp.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TcpLeakApp.scala @@ -20,12 +20,12 @@ object TcpLeakApp extends App { akka.loglevel = DEBUG akka.log-dead-letters = on akka.io.tcp.trace-logging = on""") - implicit val system = ActorSystem("ServerTest", testConf) - implicit val fm = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem("ServerTest", testConf) + implicit val fm: ActorMaterializer = ActorMaterializer() import system.dispatcher - val tcpFlow = Tcp().outgoingConnection(new InetSocketAddress("127.0.0.1", 1234)).named("TCP-outgoingConnection") + val tcpFlow = Tcp(system).outgoingConnection(new InetSocketAddress("127.0.0.1", 1234)).named("TCP-outgoingConnection") List .fill(100)( Source diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TestServer.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TestServer.scala index 82ab8d5798a..c825c126de8 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TestServer.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/TestServer.scala @@ -18,6 +18,8 @@ import akka.http.scaladsl.common.EntityStreamingSupport import scala.concurrent.ExecutionContext import scala.concurrent.duration._ import scala.io.StdIn +import akka.http.scaladsl.common.JsonEntityStreamingSupport +import spray.json.RootJsonFormat object TestServer extends App { val testConf: Config = ConfigFactory.parseString(""" @@ -26,16 +28,16 @@ object TestServer extends App { akka.stream.materializer.debug.fuzzing-mode = off """) - implicit val system = ActorSystem("ServerTest", testConf) + implicit val system: ActorSystem = ActorSystem("ServerTest", testConf) implicit val ec: ExecutionContext = system.dispatcher - implicit val materializer = ActorMaterializer() + implicit val materializer: ActorMaterializer = ActorMaterializer() import spray.json.DefaultJsonProtocol._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ final case class Tweet(message: String) - implicit val tweetFormat = jsonFormat1(Tweet) + implicit val tweetFormat: RootJsonFormat[Tweet] = jsonFormat1(Tweet) - implicit val jsonStreaming = EntityStreamingSupport.json() + implicit val jsonStreaming: JsonEntityStreamingSupport = EntityStreamingSupport.json() import ScalaXmlSupport._ import Directives._ diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/CodingDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/CodingDirectivesSpec.scala index b99516e676b..15a234384d6 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/CodingDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/CodingDirectivesSpec.scala @@ -27,7 +27,7 @@ import scala.concurrent.duration._ class CodingDirectivesSpec extends RoutingSpec with Inside { - implicit val routeTestTimeout = RouteTestTimeout(3.seconds.dilated) + implicit val routeTestTimeout: RouteTestTimeout = RouteTestTimeout(3.seconds.dilated) val echoRequestContent: Route = { ctx => ctx.complete(ctx.request.entity.dataBytes.utf8String) } diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala index e0c0a79cd06..ee1deb47dd4 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileAndResourceDirectivesSpec.scala @@ -23,7 +23,7 @@ import akka.testkit._ class FileAndResourceDirectivesSpec extends RoutingSpec with Inspectors with Inside { // operations touch files, can be randomly hit by slowness - implicit val routeTestTimeout = RouteTestTimeout(3.seconds.dilated) + implicit val routeTestTimeout: RouteTestTimeout = RouteTestTimeout(3.seconds.dilated) // need to serve from the src directory, when sbt copies the resource directory over to the // target directory it will resolve symlinks in the process diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala index 11fdcfd3af6..7ea85e411c5 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala @@ -21,7 +21,7 @@ import scala.concurrent.duration._ class FileUploadDirectivesSpec extends RoutingSpec with Eventually { // tests touches filesystem, so reqs may take longer than the default of 1.second to complete - implicit val routeTimeout = RouteTestTimeout(6.seconds.dilated) + implicit val routeTimeout: RouteTestTimeout = RouteTestTimeout(6.seconds.dilated) "the storeUploadedFile directive" should { val data = s"${"42" * 1000000}" // ~2MB of data diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FormFieldDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FormFieldDirectivesSpec.scala index 912d6ac0e29..9cc8dab55b5 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FormFieldDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FormFieldDirectivesSpec.scala @@ -13,9 +13,11 @@ import akka.http.scaladsl.unmarshalling.Unmarshaller.HexInt import akka.http.scaladsl.model._ import akka.http.scaladsl.model.MediaTypes._ import akka.http.impl.util.BenchUtils +import akka.http.scaladsl.unmarshalling.FromEntityUnmarshaller +import scala.xml.NodeSeq class FormFieldDirectivesSpec extends RoutingSpec { - implicit val nodeSeqUnmarshaller = + implicit val nodeSeqUnmarshaller: FromEntityUnmarshaller[NodeSeq] = ScalaXmlSupport.nodeSeqUnmarshaller(`text/xml`, `text/html`, `text/plain`) val nodeSeq: xml.NodeSeq = yes diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala index 81b20aad4e5..11662832c1e 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MarshallingDirectivesSpec.scala @@ -225,7 +225,7 @@ class MarshallingDirectivesSpec extends RoutingSpec with Inside { "The marshalling infrastructure for JSON" should { import spray.json._ case class Foo(name: String) - implicit val fooFormat = jsonFormat1(Foo) + implicit val fooFormat: RootJsonFormat[Foo] = jsonFormat1(Foo) val foo = Foo("Hällö") "render JSON with UTF-8 encoding if no `Accept-Charset` request header is present" in { diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala index 9fc52d63822..7439cfc6d5c 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala @@ -9,6 +9,7 @@ import org.scalatest.Inside import akka.http.scaladsl.unmarshalling.Unmarshaller, Unmarshaller._ import akka.http.scaladsl.model.StatusCodes import org.scalatest.freespec.AnyFreeSpec +import akka.http.scaladsl.server.util.ConstructFromTuple class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with Inside { "when used with 'as[Int]' the parameter directive should" - { @@ -273,7 +274,7 @@ class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with I "extract a parameter value as Case Class" in { case class Color(red: Int, green: Int, blue: Int) Get("/?red=90&green=50&blue=0") ~> { - parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(Color) { color => + parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(ConstructFromTuple.instance3(Color)) { color => complete(s"${color.red} ${color.green} ${color.blue}") } } ~> check { responseAs[String] shouldEqual "90 50 0" } @@ -285,7 +286,7 @@ class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with I require(0 <= blue && blue <= 255) } Get("/?red=500&green=0&blue=0") ~> { - parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(Color) { color => + parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(ConstructFromTuple.instance3(Color)) { color => complete(s"${color.red} ${color.green} ${color.blue}") } } ~> check { @@ -299,7 +300,7 @@ class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with I require(0 <= blue && blue <= 255) } Get("/?red=0&green=0&blue=0") ~> { - parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(Color) { _ => + parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(ConstructFromTuple.instance3(Color)) { _ => throw new IllegalArgumentException } } ~> check { diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala index 6a6d883ac3e..43b30c0c02a 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/RouteDirectivesSpec.scala @@ -91,9 +91,17 @@ class RouteDirectivesSpec extends AnyWordSpec with GenericRoutingSpec { registerUser(name).map[ToResponseMarshallable] { case Registered(_) => HttpEntity.Empty case AlreadyRegistered => - import spray.json.DefaultJsonProtocol._ import SprayJsonSupport._ - StatusCodes.BadRequest -> Map("error" -> "User already Registered") + + // FIXME: Scala 3 workaround, which cannot figure out the implicit itself + // Needs to avoid importing more implicits accidentally from DefaultJsonProtocol to avoid ambiguity in + // Scala 2 + implicit val mapFormat: spray.json.RootJsonFormat[Map[String, String]] = { + import spray.json.DefaultJsonProtocol + import DefaultJsonProtocol._ + DefaultJsonProtocol.mapFormat + } + StatusCodes.BadRequest -> Map[String, String]("error" -> "User already Registered") } } } diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/TimeoutDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/TimeoutDirectivesSpec.scala index 20c6403b95f..6060350424c 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/TimeoutDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/TimeoutDirectivesSpec.scala @@ -14,7 +14,7 @@ import scala.concurrent.{ Future, Promise } class TimeoutDirectivesSpec extends RoutingSpec { - implicit val routeTestTimeout = RouteTestTimeout(5.seconds.dilated) + implicit val routeTestTimeout: RouteTestTimeout = RouteTestTimeout(5.seconds.dilated) "Request Timeout" should { "be configurable in routing layer" in { diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/util/TupleOpsSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/util/TupleOpsSpec.scala index 82e8e63f7ef..7234fdd81c0 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/util/TupleOpsSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/util/TupleOpsSpec.scala @@ -14,9 +14,9 @@ class TupleOpsSpec extends AnyWordSpec with Matchers { "support folding over tuples using a binary poly-function" in { object Funky extends BinaryPolyFunc { - implicit def step1 = at[Double, Int](_ + _) - implicit def step2 = at[Double, Symbol]((d, s) => (d + s.name.tail.toInt).toByte) - implicit def step3 = at[Byte, String]((byte, s) => byte + s.toLong) + implicit def step1: BinaryPolyFunc.Case[Double, Int, this.type] { type Out = Double } = at[Double, Int](_ + _) + implicit def step2: BinaryPolyFunc.Case[Double, Symbol, this.type] { type Out = Byte } = at[Double, Symbol]((d, s) => (d + s.name.tail.toInt).toByte) + implicit def step3: BinaryPolyFunc.Case[Byte, String, this.type] { type Out = Long } = at[Byte, String]((byte, s) => byte + s.toLong) } (1, Symbol("X2"), "3").foldLeft(0.0)(Funky) shouldEqual 6L } diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/unmarshalling/UnmarshallingSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/unmarshalling/UnmarshallingSpec.scala index e9893b03c04..ce506f6b064 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/unmarshalling/UnmarshallingSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/unmarshalling/UnmarshallingSpec.scala @@ -23,8 +23,8 @@ import org.scalatest.freespec.AnyFreeSpec import org.scalatest.matchers.should.Matchers class UnmarshallingSpec extends AnyFreeSpec with Matchers with BeforeAndAfterAll with ScalatestUtils { - implicit val system = ActorSystem(getClass.getSimpleName) - implicit val materializer = ActorMaterializer() + implicit val system: ActorSystem = ActorSystem(getClass.getSimpleName) + implicit val materializer: ActorMaterializer = ActorMaterializer() override val testConfig = ConfigFactory.load() diff --git a/build.sbt b/build.sbt index 7d5c911ff5e..6e261690753 100644 --- a/build.sbt +++ b/build.sbt @@ -280,7 +280,7 @@ lazy val httpTests = project("akka-http-tests") targetFile } ) - .enablePlugins(NoScala3) // FIXME + .settings(scala3MigrationModeOption) lazy val httpJmhBench = project("akka-http-bench-jmh") .settings(commonSettings) @@ -302,14 +302,12 @@ lazy val httpXml = .settings(AutomaticModuleName.settings("akka.http.marshallers.scalaxml")) .addAkkaModuleDependency("akka-stream", "provided") .settings(Dependencies.httpXml) - .enablePlugins(NoScala3) // FIXME lazy val httpSprayJson = httpMarshallersScalaSubproject("spray-json") .settings(AutomaticModuleName.settings("akka.http.marshallers.sprayjson")) .addAkkaModuleDependency("akka-stream", "provided") .settings(Dependencies.httpSprayJson) - .enablePlugins(NoScala3) // FIXME lazy val httpMarshallersJava = project("akka-http-marshallers-java") .settings(commonSettings) @@ -325,7 +323,6 @@ lazy val httpJackson = .dependsOn(httpTestkit % "test") .settings(Dependencies.httpJackson) .enablePlugins(ScaladocNoVerificationOfDiagrams) - .enablePlugins(NoScala3) // FIXME lazy val httpCaching = project("akka-http-caching") .settings(commonSettings) From 55859f029a0534b37fca7076a223d27c3f238cc9 Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Wed, 20 Apr 2022 11:54:56 +0200 Subject: [PATCH 36/51] http-core: Remove the 3.0-migration flag --- .../java/akka/http/javadsl/model/Query.java | 1 + .../akka/http/impl/engine/http2/Http2.scala | 2 +- .../main/scala/akka/http/javadsl/Http.scala | 2 +- .../main/scala/akka/http/scaladsl/Http.scala | 2 +- .../scaladsl/settings/ParserSettings.scala | 52 ++++++++--------- .../scaladsl/settings/ServerSettings.scala | 58 +++++++++---------- .../scaladsl/settings/WebSocketSettings.scala | 4 +- .../client/HostConnectionPoolSpec.scala | 4 +- .../engine/parsing/ResponseParserSpec.scala | 2 +- .../http/scaladsl/model/DateTimeSpec.scala | 4 +- .../http/scaladsl/model/HttpEntitySpec.scala | 2 +- build.sbt | 1 - 12 files changed, 67 insertions(+), 67 deletions(-) diff --git a/akka-http-core/src/main/java/akka/http/javadsl/model/Query.java b/akka-http-core/src/main/java/akka/http/javadsl/model/Query.java index 0a41b6e6b46..45202ee67db 100644 --- a/akka-http-core/src/main/java/akka/http/javadsl/model/Query.java +++ b/akka-http-core/src/main/java/akka/http/javadsl/model/Query.java @@ -7,6 +7,7 @@ import akka.http.impl.model.JavaQuery; import akka.http.impl.model.UriJavaAccessor; import akka.http.scaladsl.model.*; +import akka.http.javadsl.model.HttpCharset; import akka.japi.Pair; import akka.parboiled2.CharPredicate; import akka.parboiled2.ParserInput$; diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala index ea7e120d48b..08247c89f79 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/http2/Http2.scala @@ -263,7 +263,7 @@ private[http] object Http2 extends ExtensionId[Http2Ext] with ExtensionIdProvide override def get(system: ClassicActorSystemProvider): Http2Ext = super.get(system) def apply()(implicit system: ClassicActorSystemProvider): Http2Ext = super.apply(system) override def apply(system: ActorSystem): Http2Ext = super.apply(system) - def lookup(): ExtensionId[_ <: Extension] = Http2 + def lookup: ExtensionId[_ <: Extension] = Http2 def createExtension(system: ExtendedActorSystem): Http2Ext = new Http2Ext()(system) private[http] type HttpImplementation = Flow[SslTlsInbound, SslTlsOutbound, ServerTerminator] diff --git a/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala b/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala index c53d5d2dcf7..0150f379d49 100644 --- a/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/javadsl/Http.scala @@ -33,7 +33,7 @@ import akka.stream.scaladsl.Keep object Http extends ExtensionId[Http] with ExtensionIdProvider { override def get(system: ActorSystem): Http = super.get(system) override def get(system: ClassicActorSystemProvider): Http = super.get(system) - def lookup() = Http + def lookup = Http def createExtension(system: ExtendedActorSystem): Http = new Http(system) } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala index e2fbde72385..2349196add0 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/Http.scala @@ -1105,7 +1105,7 @@ object Http extends ExtensionId[HttpExt] with ExtensionIdProvider { def apply()(implicit system: ClassicActorSystemProvider): HttpExt = super.apply(system) override def apply(system: ActorSystem): HttpExt = super.apply(system) - def lookup() = Http + def lookup = Http def createExtension(system: ExtendedActorSystem): HttpExt = new HttpExt(system.settings.config getConfig "akka.http")(system) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala index c71aada3498..be970ae0abc 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ParserSettings.scala @@ -53,40 +53,40 @@ abstract class ParserSettings private[akka] () extends akka.http.javadsl.setting def modeledHeaderParsing: Boolean /* Java APIs */ - override def getCookieParsingMode: js.ParserSettings.CookieParsingMode = cookieParsingMode - override def getHeaderValueCacheLimits: util.Map[String, Int] = headerValueCacheLimits.asJava - override def getMaxChunkExtLength = maxChunkExtLength - override def getUriParsingMode: akka.http.javadsl.model.Uri.ParsingMode = uriParsingMode - override def getMaxHeaderCount = maxHeaderCount - override def getMaxContentLength = maxContentLength - override def getMaxToStrictBytes = maxToStrictBytes - override def getMaxHeaderValueLength = maxHeaderValueLength - override def getIncludeTlsSessionInfoHeader = includeTlsSessionInfoHeader - override def getIncludeSslSessionAttribute = includeSslSessionAttribute - override def getIllegalHeaderWarnings = illegalHeaderWarnings - override def getIgnoreIllegalHeaderFor = ignoreIllegalHeaderFor - override def getMaxHeaderNameLength = maxHeaderNameLength - override def getMaxChunkSize = maxChunkSize - override def getMaxResponseReasonLength = maxResponseReasonLength - override def getMaxUriLength = maxUriLength - override def getMaxMethodLength = maxMethodLength - override def getMaxCommentParsingDepth: Int = maxCommentParsingDepth - override def getErrorLoggingVerbosity: js.ParserSettings.ErrorLoggingVerbosity = errorLoggingVerbosity - override def getIllegalResponseHeaderNameProcessingMode = illegalResponseHeaderNameProcessingMode - override def getIllegalResponseHeaderValueProcessingMode = illegalResponseHeaderValueProcessingMode - override def getConflictingContentTypeHeaderProcessingMode = conflictingContentTypeHeaderProcessingMode + override def getCookieParsingMode: js.ParserSettings.CookieParsingMode = this.cookieParsingMode + override def getHeaderValueCacheLimits: util.Map[String, Int] = this.headerValueCacheLimits.asJava + override def getMaxChunkExtLength = this.maxChunkExtLength + override def getUriParsingMode: akka.http.javadsl.model.Uri.ParsingMode = this.uriParsingMode + override def getMaxHeaderCount = this.maxHeaderCount + override def getMaxContentLength = this.maxContentLength + override def getMaxToStrictBytes = this.maxToStrictBytes + override def getMaxHeaderValueLength = this.maxHeaderValueLength + override def getIncludeTlsSessionInfoHeader = this.includeTlsSessionInfoHeader + override def getIncludeSslSessionAttribute = this.includeSslSessionAttribute + override def getIllegalHeaderWarnings = this.illegalHeaderWarnings + override def getIgnoreIllegalHeaderFor = this.ignoreIllegalHeaderFor + override def getMaxHeaderNameLength = this.maxHeaderNameLength + override def getMaxChunkSize = this.maxChunkSize + override def getMaxResponseReasonLength = this.maxResponseReasonLength + override def getMaxUriLength = this.maxUriLength + override def getMaxMethodLength = this.maxMethodLength + override def getMaxCommentParsingDepth: Int = this.maxCommentParsingDepth + override def getErrorLoggingVerbosity: js.ParserSettings.ErrorLoggingVerbosity = this.errorLoggingVerbosity + override def getIllegalResponseHeaderNameProcessingMode = this.illegalResponseHeaderNameProcessingMode + override def getIllegalResponseHeaderValueProcessingMode = this.illegalResponseHeaderValueProcessingMode + override def getConflictingContentTypeHeaderProcessingMode = this.conflictingContentTypeHeaderProcessingMode override def getCustomMethods = new Function[String, Optional[akka.http.javadsl.model.HttpMethod]] { - override def apply(t: String) = OptionConverters.toJava(customMethods(t)) + override def apply(t: String) = OptionConverters.toJava(self.customMethods(t)) } override def getCustomStatusCodes = new Function[Int, Optional[akka.http.javadsl.model.StatusCode]] { - override def apply(t: Int) = OptionConverters.toJava(customStatusCodes(t)) + override def apply(t: Int) = OptionConverters.toJava(self.customStatusCodes(t)) } override def getCustomMediaTypes = new akka.japi.function.Function2[String, String, Optional[akka.http.javadsl.model.MediaType]] { override def apply(mainType: String, subType: String): Optional[model.MediaType] = - OptionConverters.toJava(customMediaTypes(mainType, subType)) + OptionConverters.toJava(self.customMediaTypes(mainType, subType)) } - def getModeledHeaderParsing: Boolean = modeledHeaderParsing + def getModeledHeaderParsing: Boolean = this.modeledHeaderParsing // override for more specific return type override def withMaxUriLength(newValue: Int): ParserSettings = self.copy(maxUriLength = newValue) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala index 15fd2ff64ae..330225e0e28 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/ServerSettings.scala @@ -59,32 +59,32 @@ abstract class ServerSettings private[akka] () extends akka.http.javadsl.setting /* Java APIs */ - override def getBacklog = backlog - override def getPreviewServerSettings: akka.http.javadsl.settings.PreviewServerSettings = previewServerSettings - override def getDefaultHostHeader = defaultHostHeader.asJava - override def getPipeliningLimit = pipeliningLimit - override def getParserSettings: js.ParserSettings = parserSettings - override def getMaxConnections = maxConnections - override def getTransparentHeadRequests = transparentHeadRequests - override def getResponseHeaderSizeHint = responseHeaderSizeHint - override def getVerboseErrorMessages = verboseErrorMessages - override def getSocketOptions = socketOptions.asJava - override def getServerHeader = OptionConverters.toJava(serverHeader.map(_.asJava)) - override def getTimeouts = timeouts - override def getRawRequestUriHeader = rawRequestUriHeader - override def getRemoteAddressHeader = remoteAddressHeader - override def getRemoteAddressAttribute: Boolean = remoteAddressAttribute - override def getLogUnencryptedNetworkBytes = OptionConverters.toJava(logUnencryptedNetworkBytes) + override def getBacklog = this.backlog + override def getPreviewServerSettings: akka.http.javadsl.settings.PreviewServerSettings = this.previewServerSettings + override def getDefaultHostHeader = this.defaultHostHeader.asJava + override def getPipeliningLimit = this.pipeliningLimit + override def getParserSettings: js.ParserSettings = this.parserSettings + override def getMaxConnections = this.maxConnections + override def getTransparentHeadRequests = this.transparentHeadRequests + override def getResponseHeaderSizeHint = this.responseHeaderSizeHint + override def getVerboseErrorMessages = this.verboseErrorMessages + override def getSocketOptions = this.socketOptions.asJava + override def getServerHeader = OptionConverters.toJava(this.serverHeader.map(_.asJava)) + override def getTimeouts = this.timeouts + override def getRawRequestUriHeader = this.rawRequestUriHeader + override def getRemoteAddressHeader = this.remoteAddressHeader + override def getRemoteAddressAttribute: Boolean = this.remoteAddressAttribute + override def getLogUnencryptedNetworkBytes = OptionConverters.toJava(this.logUnencryptedNetworkBytes) @Deprecated @deprecated("Kept for binary compatibility; Use websocketSettings.getRandomFactory instead", since = "10.2.0") override def getWebsocketRandomFactory = new Supplier[Random] { - override def get(): Random = websocketRandomFactory() + override def get(): Random = self.websocketRandomFactory() } - override def getDefaultHttpPort: Int = defaultHttpPort - override def getDefaultHttpsPort: Int = defaultHttpsPort + override def getDefaultHttpPort: Int = this.defaultHttpPort + override def getDefaultHttpsPort: Int = this.defaultHttpsPort override def getTerminationDeadlineExceededResponse: akka.http.javadsl.model.HttpResponse = - terminationDeadlineExceededResponse - override def getParsingErrorHandler: String = parsingErrorHandler - override def getStreamCancellationDelay: FiniteDuration = streamCancellationDelay + this.terminationDeadlineExceededResponse + override def getParsingErrorHandler: String = this.parsingErrorHandler + override def getStreamCancellationDelay: FiniteDuration = this.streamCancellationDelay // --- // override for more specific return type @@ -100,7 +100,7 @@ abstract class ServerSettings private[akka] () extends akka.http.javadsl.setting override def withBacklog(newValue: Int): ServerSettings = self.copy(backlog = newValue) override def withSocketOptions(newValue: java.lang.Iterable[SocketOption]): ServerSettings = self.copy(socketOptions = newValue.asScala.toList) @Deprecated @deprecated("Kept for binary compatibility; Use websocketSettings.withRandomFactoryFactory instead", since = "10.2.0") - override def withWebsocketRandomFactory(newValue: java.util.function.Supplier[Random]): ServerSettings = self.copy(websocketSettings = websocketSettings.withRandomFactoryFactory(new Supplier[Random] { + override def withWebsocketRandomFactory(newValue: java.util.function.Supplier[Random]): ServerSettings = self.copy(websocketSettings = this.websocketSettings.withRandomFactoryFactory(new Supplier[Random] { override def get(): Random = newValue.get() })) override def getWebsocketSettings: WebSocketSettings = self.websocketSettings @@ -118,7 +118,7 @@ abstract class ServerSettings private[akka] () extends akka.http.javadsl.setting def withDefaultHostHeader(newValue: Host): ServerSettings = self.copy(defaultHostHeader = newValue) def withParserSettings(newValue: ParserSettings): ServerSettings = self.copy(parserSettings = newValue) @Deprecated @deprecated("Kept for binary compatibility; Use websocketSettings.withRandomFactoryFactory instead", since = "10.2.0") - def withWebsocketRandomFactory(newValue: () => Random): ServerSettings = self.copy(websocketSettings = websocketSettings.withRandomFactoryFactory(new Supplier[Random] { + def withWebsocketRandomFactory(newValue: () => Random): ServerSettings = self.copy(websocketSettings = this.websocketSettings.withRandomFactoryFactory(new Supplier[Random] { override def get(): Random = newValue() })) def withWebsocketSettings(newValue: WebSocketSettings): ServerSettings = self.copy(websocketSettings = newValue) @@ -126,11 +126,11 @@ abstract class ServerSettings private[akka] () extends akka.http.javadsl.setting def withHttp2Settings(newValue: Http2ServerSettings): ServerSettings = copy(http2Settings = newValue) // Scala-only lenses - def mapHttp2Settings(f: Http2ServerSettings => Http2ServerSettings): ServerSettings = withHttp2Settings(f(http2Settings)) - def mapParserSettings(f: ParserSettings => ParserSettings): ServerSettings = withParserSettings(f(parserSettings)) - def mapPreviewServerSettings(f: PreviewServerSettings => PreviewServerSettings): ServerSettings = withPreviewServerSettings(f(previewServerSettings)) - def mapWebsocketSettings(f: WebSocketSettings => WebSocketSettings): ServerSettings = withWebsocketSettings(f(websocketSettings)) - def mapTimeouts(f: ServerSettings.Timeouts => ServerSettings.Timeouts): ServerSettings = withTimeouts(f(timeouts)) + def mapHttp2Settings(f: Http2ServerSettings => Http2ServerSettings): ServerSettings = withHttp2Settings(f(this.http2Settings)) + def mapParserSettings(f: ParserSettings => ParserSettings): ServerSettings = withParserSettings(f(this.parserSettings)) + def mapPreviewServerSettings(f: PreviewServerSettings => PreviewServerSettings): ServerSettings = withPreviewServerSettings(f(this.previewServerSettings)) + def mapWebsocketSettings(f: WebSocketSettings => WebSocketSettings): ServerSettings = withWebsocketSettings(f(this.websocketSettings)) + def mapTimeouts(f: ServerSettings.Timeouts => ServerSettings.Timeouts): ServerSettings = withTimeouts(f(this.timeouts)) /** * INTERNAL API diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/WebSocketSettings.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/WebSocketSettings.scala index d1578f52639..54aebb5a903 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/settings/WebSocketSettings.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/settings/WebSocketSettings.scala @@ -16,7 +16,7 @@ import scala.concurrent.duration._ abstract class WebSocketSettings extends akka.http.javadsl.settings.WebSocketSettings { self: WebSocketSettingsImpl => def randomFactory: () => Random override final val getRandomFactory: Supplier[Random] = new Supplier[Random] { - override def get(): Random = randomFactory() + override def get(): Random = self.randomFactory() } override def periodicKeepAliveMode: String override def periodicKeepAliveMaxIdle: Duration @@ -27,7 +27,7 @@ abstract class WebSocketSettings extends akka.http.javadsl.settings.WebSocketSet */ def periodicKeepAliveData: () => ByteString final def getPeriodicKeepAliveData: Supplier[ByteString] = new Supplier[ByteString] { - override def get(): ByteString = periodicKeepAliveData() + override def get(): ByteString = self.periodicKeepAliveData() } override def withRandomFactoryFactory(newValue: Supplier[Random]): WebSocketSettings = diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala index 2a1224e6355..cf1c35a3fb9 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/HostConnectionPoolSpec.scala @@ -542,7 +542,7 @@ class HostConnectionPoolSpec extends AkkaSpecWithMaterializer( lazy val requestIn = TestPublisher.probe[RequestContext]() lazy val responseOut = TestSubscriber.probe[ResponseContext]() - protected val server: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] + protected def server: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] protected def settings: ConnectionPoolSettings @@ -699,7 +699,7 @@ class HostConnectionPoolSpec extends AkkaSpecWithMaterializer( connection.acceptConnectionPromise.future } - protected override lazy val server = + protected override lazy val server: Flow[HttpRequest, HttpResponse, Future[Http.OutgoingConnection]] = Flow.fromSinkAndSourceMat( // buffer is needed because the async subscriber/publisher boundary will otherwise request > 1 Flow[HttpRequest].buffer(1, OverflowStrategy.backpressure) diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala index dd643a51480..f2138e64344 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/parsing/ResponseParserSpec.scala @@ -386,7 +386,7 @@ abstract class ResponseParserSpec(mode: String, newLine: String) extends AkkaSpe generalRawMultiParseTo(GET, expected: _*) def generalRawMultiParseTo(requestMethod: HttpMethod, expected: Either[ResponseOutput, HttpResponse]*): Matcher[Seq[String]] = equal(expected.map(strictEqualify)) - .matcher[Seq[Either[ResponseOutput, StrictEqualHttpResponse]]] compose { input: Seq[String] => + .matcher[Seq[Either[ResponseOutput, StrictEqualHttpResponse]]] compose { (input: Seq[String]) => collectBlocking { rawParse(requestMethod, input: _*) .mapAsync(1) { diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala index 24a4cee7938..8eb00aed259 100644 --- a/akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/model/DateTimeSpec.scala @@ -33,7 +33,7 @@ class DateTimeSpec extends AnyWordSpec with Matchers { fmt } def rfc1123Format(dt: DateTime) = Rfc1123Format.format(new java.util.Date(dt.clicks)) - val matchSimpleDateFormat: Matcher[DateTime] = Matcher { dt: DateTime => + val matchSimpleDateFormat: Matcher[DateTime] = Matcher { (dt: DateTime) => MatchResult( dt.toRfc1123DateTimeString == rfc1123Format(dt), dt.toRfc1123DateTimeString + " != " + rfc1123Format(dt), @@ -79,7 +79,7 @@ class DateTimeSpec extends AnyWordSpec with Matchers { "The two DateTime implementations" should { "allow for transparent round-trip conversions" in { def roundTrip(dt: DateTime) = DateTime(dt.year, dt.month, dt.day, dt.hour, dt.minute, dt.second) - val roundTripOk: Matcher[DateTime] = Matcher { dt: DateTime => + val roundTripOk: Matcher[DateTime] = Matcher { (dt: DateTime) => MatchResult( { val rt = roundTrip(dt); dt == rt && dt.weekday == rt.weekday }, dt.toRfc1123DateTimeString + " != " + roundTrip(dt).toRfc1123DateTimeString, diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala index 0fc03f6f386..b6c6bd7308c 100755 --- a/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/model/HttpEntitySpec.scala @@ -273,7 +273,7 @@ class HttpEntitySpec extends AkkaSpecWithMaterializer { } def renderStrictDataAs(dataRendering: String): Matcher[Strict] = - Matcher { strict: Strict => + Matcher { (strict: Strict) => val expectedRendering = s"${strict.productPrefix}(${strict.contentType},$dataRendering)" MatchResult( strict.toString == expectedRendering, diff --git a/build.sbt b/build.sbt index 6e261690753..8fd0ae41eef 100644 --- a/build.sbt +++ b/build.sbt @@ -164,7 +164,6 @@ lazy val httpCore = project("akka-http-core") if (System.getProperty("akka.http.test-against-akka-main", "false") == "true") AkkaDependency.masterSnapshot else AkkaDependency.default ) - .settings(scala3MigrationModeOption) .settings(Dependencies.httpCore) .settings(VersionGenerator.versionSettings) .settings(scalaMacroSupport) From ab826edb46fabd7c6e9b6af9627419d53328e939 Mon Sep 17 00:00:00 2001 From: Jan Chyb Date: Wed, 20 Apr 2022 09:44:06 +0200 Subject: [PATCH 37/51] http-tests: allow to compile tests without the 3.0-migration flag ImplicitUtils object was added, to mitigate issues with StringOps implicit conversions (and the use of * operator on Strings). --- .../main/akka/http/ccompat/ImplicitUtils.scala | 7 +++++++ .../main/akka/http/ccompat/ImplicitUtils.scala | 7 +++++++ .../main/akka/http/ccompat/ImplicitUtils.scala | 15 +++++++++++++++ .../DontLeakActorsOnFailingConnectionSpecs.scala | 2 +- .../akka/http/scaladsl/server/SizeLimitSpec.scala | 2 ++ .../directives/FileUploadDirectivesSpec.scala | 2 ++ .../server/directives/FutureDirectivesSpec.scala | 4 ++-- .../server/directives/MiscDirectivesSpec.scala | 2 ++ build.sbt | 9 --------- 9 files changed, 38 insertions(+), 12 deletions(-) create mode 100644 akka-http-tests/src/test/scala-2.13-/src/main/akka/http/ccompat/ImplicitUtils.scala create mode 100644 akka-http-tests/src/test/scala-2.13/src/main/akka/http/ccompat/ImplicitUtils.scala create mode 100644 akka-http-tests/src/test/scala-3/src/main/akka/http/ccompat/ImplicitUtils.scala diff --git a/akka-http-tests/src/test/scala-2.13-/src/main/akka/http/ccompat/ImplicitUtils.scala b/akka-http-tests/src/test/scala-2.13-/src/main/akka/http/ccompat/ImplicitUtils.scala new file mode 100644 index 00000000000..c1daf321dc8 --- /dev/null +++ b/akka-http-tests/src/test/scala-2.13-/src/main/akka/http/ccompat/ImplicitUtils.scala @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2009-2022 Lightbend Inc. + */ + +package akka.http.ccompat + +object ImplicitUtils diff --git a/akka-http-tests/src/test/scala-2.13/src/main/akka/http/ccompat/ImplicitUtils.scala b/akka-http-tests/src/test/scala-2.13/src/main/akka/http/ccompat/ImplicitUtils.scala new file mode 100644 index 00000000000..c1daf321dc8 --- /dev/null +++ b/akka-http-tests/src/test/scala-2.13/src/main/akka/http/ccompat/ImplicitUtils.scala @@ -0,0 +1,7 @@ +/* + * Copyright (C) 2009-2022 Lightbend Inc. + */ + +package akka.http.ccompat + +object ImplicitUtils diff --git a/akka-http-tests/src/test/scala-3/src/main/akka/http/ccompat/ImplicitUtils.scala b/akka-http-tests/src/test/scala-3/src/main/akka/http/ccompat/ImplicitUtils.scala new file mode 100644 index 00000000000..a8ce8d05fce --- /dev/null +++ b/akka-http-tests/src/test/scala-3/src/main/akka/http/ccompat/ImplicitUtils.scala @@ -0,0 +1,15 @@ +/* + * Copyright (C) 2009-2022 Lightbend Inc. + */ + +package akka.http.ccompat + +import scala.collection.immutable.StringOps + +object ImplicitUtils { + // Scala 3 resolves implicit conversions differently than Scala 2, + // in some instances overriding StringOps operations, like *. + implicit class Scala3StringOpsFix(string: String) { + def *(amount: Int): String = StringOps(string) * amount + } +} diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala index 72c4b965f86..cafb60783c9 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/DontLeakActorsOnFailingConnectionSpecs.scala @@ -81,7 +81,7 @@ abstract class DontLeakActorsOnFailingConnectionSpecs(poolImplementation: String } } - override def afterAll = TestKit.shutdownActorSystem(system) + override def afterAll(): Unit = TestKit.shutdownActorSystem(system) } class LegacyPoolDontLeakActorsOnFailingConnectionSpecs extends DontLeakActorsOnFailingConnectionSpecs("legacy") diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala index f5029546ea1..08a0298843e 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/SizeLimitSpec.scala @@ -30,6 +30,8 @@ import org.scalatest.wordspec.AnyWordSpec @nowarn("msg=synchronous compression with `encode` is not supported in the future any more") class SizeLimitSpec extends AnyWordSpec with Matchers with RequestBuilding with BeforeAndAfterAll with ScalaFutures { + import akka.http.ccompat.ImplicitUtils._ + val maxContentLength = 800 // Protect network more than memory: val decodeMaxSize = 1600 diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala index 7ea85e411c5..88c3821cb9a 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FileUploadDirectivesSpec.scala @@ -20,6 +20,8 @@ import scala.concurrent.duration._ class FileUploadDirectivesSpec extends RoutingSpec with Eventually { + import akka.http.ccompat.ImplicitUtils._ + // tests touches filesystem, so reqs may take longer than the default of 1.second to complete implicit val routeTimeout: RouteTestTimeout = RouteTestTimeout(6.seconds.dilated) diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FutureDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FutureDirectivesSpec.scala index 327b2bb1c8a..4e5620ae557 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FutureDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/FutureDirectivesSpec.scala @@ -123,7 +123,7 @@ class FutureDirectivesSpec extends RoutingSpec with Inside with TestKitBase { occurrences = 1, message = BasicRouteSpecs.defaultExnHandler500Error("XXX") ).intercept { - Get() ~> onSuccess(Future.failed(TestException)) { echoComplete } ~> check { + Get() ~> onSuccess(Future.failed[Int](TestException)) { echoComplete } ~> check { status shouldEqual StatusCodes.InternalServerError } } @@ -137,7 +137,7 @@ class FutureDirectivesSpec extends RoutingSpec with Inside with TestKitBase { occurrences = 1, message = BasicRouteSpecs.defaultExnHandler500Error("XXX") ).intercept { - Get() ~> onSuccess(Future.failed(TestException)) { throwTestException("EX when ") } ~> check { + Get() ~> onSuccess(Future.failed[Unit](TestException)) { throwTestException("EX when ") } ~> check { status shouldEqual StatusCodes.InternalServerError responseAs[String] shouldEqual "There was an internal server error." } diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MiscDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MiscDirectivesSpec.scala index ea8b721e8d9..04a72cccbfd 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MiscDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/MiscDirectivesSpec.scala @@ -19,6 +19,8 @@ import scala.annotation.nowarn @nowarn("msg=use remote-address-attribute instead") class MiscDirectivesSpec extends RoutingSpec { + import akka.http.ccompat.ImplicitUtils._ + "the extractClientIP directive" should { "extract from a X-Forwarded-For header" in { Get() ~> addHeaders(`X-Forwarded-For`(remoteAddress("2.3.4.5")), RawHeader("x-real-ip", "1.2.3.4")) ~> { diff --git a/build.sbt b/build.sbt index 8fd0ae41eef..fa4e4f276c9 100644 --- a/build.sbt +++ b/build.sbt @@ -130,14 +130,6 @@ val scalaMacroSupport = Seq( }), ) -val scala3MigrationModeOption = - scalacOptions ++= { - if (scalaVersion.value startsWith "3") - Seq("-source:3.0-migration") - else - Nil - } - lazy val parsing = project("akka-parsing") .settings(commonSettings) .settings(AutomaticModuleName.settings("akka.http.parsing")) @@ -279,7 +271,6 @@ lazy val httpTests = project("akka-http-tests") targetFile } ) - .settings(scala3MigrationModeOption) lazy val httpJmhBench = project("akka-http-bench-jmh") .settings(commonSettings) From 98300c3cc6fd6c9cc2ea94c261eafe8242ba0f9c Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 5 May 2022 15:51:48 +0200 Subject: [PATCH 38/51] core: slight simplification --- .../http/impl/engine/rendering/RenderSupport.scala | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala index 1e76911bcce..04b8d4d26ff 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/engine/rendering/RenderSupport.scala @@ -48,16 +48,12 @@ private[http] object RenderSupport { val defaultLastChunkBytes: ByteString = renderChunk(HttpEntity.LastChunk) - def CancelSecond[T, Mat](first: Source[T, Mat], second: Source[T, Any]): Source[T, Mat] = { - Source.fromGraph(GraphDSL.create[SourceShape[T], Mat](first) { implicit b => - { - case frst: SourceShape[T] => - import GraphDSL.Implicits._ - second ~> Sink.cancelled - SourceShape(frst.out) - } + def CancelSecond[T, Mat](first: Source[T, Mat], second: Source[T, Any]): Source[T, Mat] = + Source.fromGraph(GraphDSL.createGraph(first) { implicit b => frst => + import GraphDSL.Implicits._ + second ~> Sink.cancelled + SourceShape(frst.out) }) - } def renderEntityContentType(r: Rendering, entity: HttpEntity): r.type = { val ct = entity.contentType From 0af0c322d17b2fca6ff1841c5b75c2388228f5fd Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 5 May 2022 15:58:03 +0200 Subject: [PATCH 39/51] core: use Tcp(system) consistently --- .../scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala index c8d0b0c9b6f..7c5552cde0a 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala @@ -666,7 +666,7 @@ class NewConnectionPoolSpec extends AkkaSpecWithMaterializer(""" val sink = if (autoAccept) Sink.foreach[Http.IncomingConnection](handleConnection) else Sink.fromSubscriber(incomingConnections) val binding = - Tcp.apply + Tcp(system) .bind("localhost", 0, idleTimeout = serverSettings.timeouts.idleTimeout) .map { c => val layer = Http().serverLayer(serverSettings, log = log) From f4d6b264b69b06a82f9f1945ff1066296026c601 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 5 May 2022 16:09:47 +0200 Subject: [PATCH 40/51] http: simplify some tests --- .../scala/akka/http/scaladsl/server/BasicRouteSpecs.scala | 6 +++--- .../server/directives/ParameterDirectivesSpec.scala | 6 +++--- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala index 609a88d3b1f..b340fee1ebb 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/BasicRouteSpecs.scala @@ -149,7 +149,7 @@ class BasicRouteSpecs extends RoutingSpec { "extract one argument" in { case class MyNumber(i: Int) - val abcPath = path("abc" / IntNumber).as(ConstructFromTuple.instance1(MyNumber))(echoComplete) + val abcPath = path("abc" / IntNumber).as(MyNumber.apply _)(echoComplete) Get("/abc/5") ~> abcPath ~> check { responseAs[String] shouldEqual "MyNumber(5)" @@ -158,7 +158,7 @@ class BasicRouteSpecs extends RoutingSpec { "extract two arguments" in { case class Person(name: String, age: Int) - val personPath = path("person" / Segment / IntNumber).as(ConstructFromTuple.instance2(Person))(echoComplete) + val personPath = path("person" / Segment / IntNumber).as(Person.apply _)(echoComplete) Get("/person/john/38") ~> personPath ~> check { responseAs[String] shouldEqual "Person(john,38)" @@ -169,7 +169,7 @@ class BasicRouteSpecs extends RoutingSpec { require(i > 10) } - val abcPath = path("abc" / IntNumber).as(ConstructFromTuple.instance1(MyValidNumber))(echoComplete) + val abcPath = path("abc" / IntNumber).as(MyValidNumber.apply _)(echoComplete) Get("/abc/5") ~> abcPath ~> check { rejection shouldBe a[ValidationRejection] diff --git a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala index 7439cfc6d5c..0a997d198ba 100644 --- a/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala +++ b/akka-http-tests/src/test/scala/akka/http/scaladsl/server/directives/ParameterDirectivesSpec.scala @@ -274,7 +274,7 @@ class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with I "extract a parameter value as Case Class" in { case class Color(red: Int, green: Int, blue: Int) Get("/?red=90&green=50&blue=0") ~> { - parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(ConstructFromTuple.instance3(Color)) { color => + parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(Color.apply _) { color => complete(s"${color.red} ${color.green} ${color.blue}") } } ~> check { responseAs[String] shouldEqual "90 50 0" } @@ -286,7 +286,7 @@ class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with I require(0 <= blue && blue <= 255) } Get("/?red=500&green=0&blue=0") ~> { - parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(ConstructFromTuple.instance3(Color)) { color => + parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(Color.apply _) { color => complete(s"${color.red} ${color.green} ${color.blue}") } } ~> check { @@ -300,7 +300,7 @@ class ParameterDirectivesSpec extends AnyFreeSpec with GenericRoutingSpec with I require(0 <= blue && blue <= 255) } Get("/?red=0&green=0&blue=0") ~> { - parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(ConstructFromTuple.instance3(Color)) { _ => + parameters("red".as[Int], "green".as[Int], "blue".as[Int]).as(Color.apply _) { _ => throw new IllegalArgumentException } } ~> check { From 8d8b94a87b6baf02779f117d4e2e6480d4b40406 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 5 May 2022 16:10:54 +0200 Subject: [PATCH 41/51] scala3: use Tcp(system) consistently in more places --- .../akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala | 6 +++--- .../test/scala/akka/http/scaladsl/ClientServerSpec.scala | 4 ++-- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala index 22802754f86..5e93851217b 100644 --- a/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/impl/engine/ws/WebSocketIntegrationSpec.scala @@ -102,7 +102,7 @@ class WebSocketIntegrationSpec extends AkkaSpecWithMaterializer( Http().webSocketClientLayer(WebSocketRequest("ws://localhost:" + myPort)) .atop(TLSPlacebo()) .joinMat(completeOnlySwitch.via( - Tcp.apply.outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)))(Keep.both) + Tcp(system).outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)))(Keep.both) }(Keep.right) .toMat(TestSink.probe[Message])(Keep.both) .run() @@ -179,7 +179,7 @@ class WebSocketIntegrationSpec extends AkkaSpecWithMaterializer( .atop(TLSPlacebo()) // the resource leak of #19398 existed only for severed websocket connections .atopMat(KillSwitches.singleBidi[ByteString, ByteString])(Keep.right) - .join(Tcp.apply.outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) + .join(Tcp(system).outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) }(Keep.right) .toMat(Sink.foreach(_ => messages += 1))(Keep.both) .run() @@ -212,7 +212,7 @@ class WebSocketIntegrationSpec extends AkkaSpecWithMaterializer( Http().webSocketClientLayer(WebSocketRequest("ws://localhost:" + myPort)) .atop(TLSPlacebo()) .atopMat(KillSwitches.singleBidi[ByteString, ByteString])(Keep.right) - .join(Tcp.apply.outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) + .join(Tcp(system).outgoingConnection(new InetSocketAddress("localhost", myPort), halfClose = true)) }(Keep.right) .toMat(Sink.fromSubscriber(clientMessageIn))(Keep.left) .run() diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala index 975fb60e84b..db336338783 100644 --- a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala @@ -695,7 +695,7 @@ abstract class ClientServerSpecBase(http2: Boolean) extends AkkaSpecWithMaterial Host: example.com """)) - .via(Tcp.apply.outgoingConnection(hostname, port)) + .via(Tcp(system).outgoingConnection(hostname, port)) .runWith(Sink.reduce[ByteString](_ ++ _)) Try(Await.result(result, 2.seconds).utf8String) match { case scala.util.Success(body) => fail(body) @@ -930,7 +930,7 @@ Host: example.com "produce a useful error message when connecting to an endpoint speaking wrong protocol" in Utils.assertAllStagesStopped { val settings = ConnectionPoolSettings(system).withUpdatedConnectionSettings(_.withIdleTimeout(100.millis)) - val binding = Tcp.apply.bindAndHandle(Flow[ByteString].map(_ => ByteString("hello world!")), "127.0.0.1", 0).futureValue + val binding = Tcp(system).bindAndHandle(Flow[ByteString].map(_ => ByteString("hello world!")), "127.0.0.1", 0).futureValue val uri = "http://" + binding.localAddress.getHostString + ":" + binding.localAddress.getPort val ex = the[IllegalResponseException] thrownBy Await.result(Http().singleRequest(HttpRequest(uri = uri, method = HttpMethods.POST), settings = settings), 30.seconds) From 42bc5d96af44af395483d08d7625f72fadcf5db0 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 5 May 2022 16:13:07 +0200 Subject: [PATCH 42/51] scala3: edit sources on-the-fly in sbt to support `@pre213` methods in shared source code (#4113) --- .github/workflows/validate-and-test.yml | 2 +- .../http/scaladsl/model/HttpMessage.scala | 22 +++++----- .../model/headers/CacheDirective.scala | 8 ++-- .../model/headers/LanguageRange.scala | 4 +- .../scaladsl/model/headers/LinkValue.scala | 4 +- .../http/scaladsl/model/headers/headers.scala | 44 +++++++++---------- .../directives/FormFieldDirectives.scala | 8 ++-- .../directives/RespondWithDirectives.scala | 27 ++++++------ build.sbt | 10 +++++ project/Pre213Preprocessor.scala | 36 +++++++++++++++ 10 files changed, 105 insertions(+), 60 deletions(-) create mode 100644 project/Pre213Preprocessor.scala diff --git a/.github/workflows/validate-and-test.yml b/.github/workflows/validate-and-test.yml index 36ceccb293b..eacfab0193f 100644 --- a/.github/workflows/validate-and-test.yml +++ b/.github/workflows/validate-and-test.yml @@ -53,7 +53,7 @@ jobs: strategy: fail-fast: false matrix: - SCALA_VERSION: [2.13, 3] + SCALA_VERSION: [2.12, 2.13, 3] JABBA_JDK: [1.8] steps: - name: Checkout diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala index e0c3a9bcaf3..536f5ff73a6 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/HttpMessage.scala @@ -72,23 +72,27 @@ sealed trait HttpMessage extends jm.HttpMessage { def discardEntityBytes(system: ClassicActorSystemProvider): HttpMessage.DiscardedEntity = entity.discardBytes()(SystemMaterializer(system).materializer) /** Returns a copy of this message with the list of headers set to the given ones. */ - /*@pre213 - def withHeaders(headers: HttpHeader*): Self = withHeaders(headers.toList)*/ - - /** Returns a copy of this message with the list of headers set to the given ones. */ - def withHeaders(headers: immutable.Seq[HttpHeader]): Self + @pre213 + def withHeaders(headers: HttpHeader*): Self = withHeaders(headers.toList) /** Returns a copy of this message with the list of headers set to the given ones. */ @since213 def withHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Self = withHeaders(firstHeader +: otherHeaders.toList) + /** Returns a copy of this message with the list of headers set to the given ones. */ + def withHeaders(headers: immutable.Seq[HttpHeader]): Self + /** * Returns a new message that contains all of the given default headers which didn't already * exist (by case-insensitive header name) in this message. */ - /*@pre213 - def withDefaultHeaders(defaultHeaders: HttpHeader*): Self = withDefaultHeaders(defaultHeaders.toList)*/ + @pre213 + def withDefaultHeaders(defaultHeaders: HttpHeader*): Self = withDefaultHeaders(defaultHeaders.toList) + + @since213 + def withDefaultHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Self = + withDefaultHeaders(firstHeader +: otherHeaders.toList) /** * Returns a new message that contains all of the given default headers which didn't already @@ -100,10 +104,6 @@ sealed trait HttpMessage extends jm.HttpMessage { else defaultHeaders.foldLeft(headers) { (acc, h) => if (headers.exists(_ is h.lowercaseName)) acc else h +: acc } } - @since213 - def withDefaultHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Self = - withDefaultHeaders(firstHeader +: otherHeaders.toList) - /** Returns a copy of this message with the attributes set to the given ones. */ def withAttributes(headers: Map[AttributeKey[_], _]): Self diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala index 8b4d11b3f76..9b9fd25583d 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/CacheDirective.scala @@ -83,9 +83,9 @@ object CacheDirectives { * http://tools.ietf.org/html/rfc7234#section-5.2.1.4 */ case object `no-cache` extends SingletonValueRenderable with RequestDirective with ResponseDirective { - /*@pre213 + @pre213 def apply(fieldNames: String*): `no-cache` = - new `no-cache`(immutable.Seq(fieldNames: _*))*/ + new `no-cache`(immutable.Seq(fieldNames: _*)) @since213 def apply(firstFieldName: String, otherFieldNames: String*): `no-cache` = new `no-cache`(firstFieldName +: otherFieldNames.toList) @@ -138,8 +138,8 @@ object CacheDirectives { */ final case class `private`(fieldNames: immutable.Seq[String]) extends FieldNamesDirective with ResponseDirective object `private` { - /*@pre213 - def apply(fieldNames: String*): `private` = new `private`(immutable.Seq(fieldNames: _*))*/ + @pre213 + def apply(fieldNames: String*): `private` = new `private`(immutable.Seq(fieldNames: _*)) @since213 def apply(): `private` = new `private`(immutable.Seq.empty) @since213 diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala index a2160f7ac84..0bd4d9f28aa 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LanguageRange.scala @@ -72,9 +72,9 @@ object Language { val tags = compoundTag.split('-') new Language(tags.head, immutable.Seq(tags.tail: _*)) } else new Language(compoundTag, immutable.Seq.empty) - /*@pre213 + @pre213 def apply(primaryTag: String, subTags: String*): Language = - new Language(primaryTag, immutable.Seq(subTags: _*))*/ + new Language(primaryTag, immutable.Seq(subTags: _*)) @since213 def apply(primaryTag: String, firstSubTag: String, otherSubTags: String*): Language = new Language(primaryTag, firstSubTag +: otherSubTags) diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala index 7c0b90631f1..8a5b74ab169 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/LinkValue.scala @@ -25,8 +25,8 @@ final case class LinkValue(uri: Uri, params: immutable.Seq[LinkParam]) extends j } object LinkValue { - /*@pre213 - def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*))*/ + @pre213 + def apply(uri: Uri, params: LinkParam*): LinkValue = apply(uri, immutable.Seq(params: _*)) @since213 def apply(uri: Uri, firstParam: LinkParam, otherParams: LinkParam*): LinkValue = apply(uri, firstParam +: otherParams) } diff --git a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala index d95866858b4..e8b6fd19f03 100644 --- a/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala +++ b/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala @@ -136,9 +136,9 @@ import akka.http.impl.util.JavaMapping.Implicits._ // https://tools.ietf.org/html/rfc7231#section-5.3.2 object Accept extends ModeledCompanion[Accept] { - /*@pre213 + @pre213 def apply(mediaRanges: MediaRange*): Accept = - apply(immutable.Seq(mediaRanges: _*))*/ + apply(immutable.Seq(mediaRanges: _*)) @since213 def apply(firstMediaRange: MediaRange, otherMediaRanges: MediaRange*): Accept = apply(firstMediaRange +: otherMediaRanges) @@ -172,9 +172,9 @@ final case class `Accept-Charset`(charsetRanges: immutable.Seq[HttpCharsetRange] // https://tools.ietf.org/html/rfc7231#section-5.3.4 object `Accept-Encoding` extends ModeledCompanion[`Accept-Encoding`] { - /*@pre213 + @pre213 def apply(encodings: HttpEncodingRange*): `Accept-Encoding` = - apply(immutable.Seq(encodings: _*))*/ + apply(immutable.Seq(encodings: _*)) @since213 def apply(): `Accept-Encoding` = apply(immutable.Seq.empty) @@ -211,9 +211,9 @@ final case class `Accept-Language`(languages: immutable.Seq[LanguageRange]) exte // https://tools.ietf.org/html/rfc7233#section-2.3 object `Accept-Ranges` extends ModeledCompanion[`Accept-Ranges`] { - /*@pre213 + @pre213 def apply(rangeUnits: RangeUnit*): `Accept-Ranges` = - apply(immutable.Seq(rangeUnits: _*))*/ + apply(immutable.Seq(rangeUnits: _*)) @since213 def apply(): `Accept-Ranges` = apply(immutable.Seq.empty) @@ -242,9 +242,9 @@ final case class `Access-Control-Allow-Credentials`(allow: Boolean) // https://www.w3.org/TR/cors/#access-control-allow-headers-response-header object `Access-Control-Allow-Headers` extends ModeledCompanion[`Access-Control-Allow-Headers`] { - /*@pre213 + @pre213 def apply(headers: String*): `Access-Control-Allow-Headers` = - apply(immutable.Seq(headers: _*))*/ + apply(immutable.Seq(headers: _*)) @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Allow-Headers` = apply(firstHeader +: otherHeaders) @@ -262,9 +262,9 @@ final case class `Access-Control-Allow-Headers`(headers: immutable.Seq[String]) // https://www.w3.org/TR/cors/#access-control-allow-methods-response-header object `Access-Control-Allow-Methods` extends ModeledCompanion[`Access-Control-Allow-Methods`] { - /*@pre213 + @pre213 def apply(methods: HttpMethod*): `Access-Control-Allow-Methods` = - apply(immutable.Seq(methods: _*))*/ + apply(immutable.Seq(methods: _*)) @since213 def apply(firstMethod: HttpMethod, otherMethods: HttpMethod*): `Access-Control-Allow-Methods` = apply(firstMethod +: otherMethods) @@ -303,9 +303,9 @@ final case class `Access-Control-Allow-Origin` private (range: HttpOriginRange) // https://www.w3.org/TR/cors/#access-control-expose-headers-response-header object `Access-Control-Expose-Headers` extends ModeledCompanion[`Access-Control-Expose-Headers`] { - /*@pre213 + @pre213 def apply(headers: String*): `Access-Control-Expose-Headers` = - apply(immutable.Seq(headers: _*))*/ + apply(immutable.Seq(headers: _*)) @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Expose-Headers` = apply(firstHeader +: otherHeaders) @@ -331,9 +331,9 @@ final case class `Access-Control-Max-Age`(deltaSeconds: Long) extends jm.headers // https://www.w3.org/TR/cors/#access-control-request-headers-request-header object `Access-Control-Request-Headers` extends ModeledCompanion[`Access-Control-Request-Headers`] { - /*@pre213 + @pre213 def apply(headers: String*): `Access-Control-Request-Headers` = - apply(immutable.Seq(headers: _*))*/ + apply(immutable.Seq(headers: _*)) @since213 def apply(firstHeader: String, otherHeaders: String*): `Access-Control-Request-Headers` = apply(firstHeader +: otherHeaders) @@ -366,9 +366,9 @@ final case class Age(deltaSeconds: Long) extends jm.headers.Age with ResponseHea // https://tools.ietf.org/html/rfc7231#section-7.4.1 object Allow extends ModeledCompanion[Allow] { - /*@pre213 + @pre213 def apply(methods: HttpMethod*): Allow = - apply(immutable.Seq(methods: _*))*/ + apply(immutable.Seq(methods: _*)) @since213 def apply(): `Allow` = apply(immutable.Seq.empty) @@ -546,8 +546,8 @@ final case class `Content-Type` private[http] (contentType: ContentType) extends object Cookie extends ModeledCompanion[Cookie] { def apply(first: HttpCookiePair, more: HttpCookiePair*): Cookie = apply(immutable.Seq(first +: more: _*)) def apply(name: String, value: String): Cookie = apply(HttpCookiePair(name, value)) - /*@pre213 - def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList)*/ + @pre213 + def apply(values: (String, String)*): Cookie = apply(values.map(HttpCookiePair(_)).toList) @since213 def apply(first: (String, String), more: (String, String)*): Cookie = apply((first +: more).map(HttpCookiePair(_))) implicit val cookiePairsRenderer: Renderer[immutable.Iterable[HttpCookiePair]] = Renderer.seqRenderer[HttpCookiePair](separator = "; ") // cache @@ -695,8 +695,8 @@ final case class `Last-Modified`(date: DateTime) extends jm.headers.LastModified // https://tools.ietf.org/html/rfc5988#section-5 object Link extends ModeledCompanion[Link] { def apply(uri: Uri, first: LinkParam, more: LinkParam*): Link = apply(immutable.Seq(LinkValue(uri, first +: more.toList))) - /*@pre213 - def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*))*/ + @pre213 + def apply(values: LinkValue*): Link = apply(immutable.Seq(values: _*)) @since213 def apply(firstValue: LinkValue, otherValues: LinkValue*): Link = apply(firstValue +: otherValues) @@ -723,8 +723,8 @@ final case class Location(uri: Uri) extends jm.headers.Location with ResponseHea // https://tools.ietf.org/html/rfc6454#section-7 object Origin extends ModeledCompanion[Origin] { - /*@pre213 - def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*))*/ + @pre213 + def apply(origins: HttpOrigin*): Origin = apply(immutable.Seq(origins: _*)) @since213 def apply(firstOrigin: HttpOrigin, otherOrigins: HttpOrigin*): Origin = apply(firstOrigin +: otherOrigins) } diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala index 87f92ead0a6..9444e258e98 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/FormFieldDirectives.scala @@ -54,9 +54,9 @@ trait FormFieldDirectives extends FormFieldDirectivesInstances with ToNameRecept * * @group form */ - /*@pre213 + @pre213 @deprecated("Use new `formField` overloads with FieldSpec parameters. Kept for binary compatibility", "10.2.0") - private[http] def formField(pdm: FieldMagnet): pdm.Out = formFields(pdm)*/ + private[http] def formField(pdm: FieldMagnet): pdm.Out = formFields(pdm) /** * Extracts an HTTP form field from the request. @@ -74,10 +74,10 @@ trait FormFieldDirectives extends FormFieldDirectivesInstances with ToNameRecept * * @group form */ - /*@pre213 + @pre213 @deprecated("Use new `formField` overloads with FieldSpec parameters. Kept for binary compatibility", "10.2.0") private[http] def formFields(pdm: FieldMagnet): pdm.Out = - pdm.convert(toStrictEntity(StrictForm.toStrictTimeout).wrap { pdm() })*/ + pdm.convert(toStrictEntity(StrictForm.toStrictTimeout).wrap { pdm() }) /** * Extracts a number of HTTP form field from the request. diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala index b1a561dd62d..b718ce74e4c 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/directives/RespondWithDirectives.scala @@ -37,9 +37,13 @@ trait RespondWithDirectives { * * @group response */ - /*@pre213 + @pre213 def respondWithHeaders(responseHeaders: HttpHeader*): Directive0 = - respondWithHeaders(responseHeaders.toList)*/ + respondWithHeaders(responseHeaders.toList) + + @since213 + def respondWithHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Directive0 = + respondWithHeaders(firstHeader +: otherHeaders.toList) /** * Unconditionally adds the given response headers to all HTTP responses of its inner Route. @@ -49,19 +53,15 @@ trait RespondWithDirectives { def respondWithHeaders(responseHeaders: immutable.Seq[HttpHeader]): Directive0 = mapResponseHeaders(responseHeaders.toList ++ _) - @since213 - def respondWithHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Directive0 = - respondWithHeaders(firstHeader +: otherHeaders.toList) - /** * Adds the given response headers to all HTTP responses of its inner Route, * if a header already exists it is not added again. * * @group response */ - /*@pre213 + @pre213 def respondWithDefaultHeaders(responseHeaders: HttpHeader*): Directive0 = - respondWithDefaultHeaders(responseHeaders.toList)*/ + respondWithDefaultHeaders(responseHeaders.toList) /** * Adds the given response headers to all HTTP responses of its inner Route, @@ -69,8 +69,9 @@ trait RespondWithDirectives { * * @group response */ - def respondWithDefaultHeaders(responseHeaders: immutable.Seq[HttpHeader]): Directive0 = - mapResponse(_.withDefaultHeaders(responseHeaders)) + @since213 + def respondWithDefaultHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Directive0 = + respondWithDefaultHeaders(firstHeader +: otherHeaders.toList) /** * Adds the given response headers to all HTTP responses of its inner Route, @@ -78,10 +79,8 @@ trait RespondWithDirectives { * * @group response */ - @since213 - def respondWithDefaultHeaders(firstHeader: HttpHeader, otherHeaders: HttpHeader*): Directive0 = - respondWithDefaultHeaders(firstHeader +: otherHeaders.toList) - + def respondWithDefaultHeaders(responseHeaders: immutable.Seq[HttpHeader]): Directive0 = + mapResponse(_.withDefaultHeaders(responseHeaders)) } object RespondWithDirectives extends RespondWithDirectives diff --git a/build.sbt b/build.sbt index fa4e4f276c9..54d8736a830 100644 --- a/build.sbt +++ b/build.sbt @@ -161,6 +161,11 @@ lazy val httpCore = project("akka-http-core") .settings(scalaMacroSupport) .enablePlugins(BootstrapGenjavadoc) .enablePlugins(ReproducibleBuildsPlugin) + .enablePlugins(Pre213Preprocessor).settings( + akka.http.sbt.Pre213Preprocessor.pre213Files := Seq( + "headers.scala", "HttpMessage.scala", "LanguageRange.scala", "CacheDirective.scala", "LinkValue.scala" + ) + ) .disablePlugins(ScalafixPlugin) lazy val http = project("akka-http") @@ -173,6 +178,11 @@ lazy val http = project("akka-http") Compile / scalacOptions += "-language:_" ) .settings(scalaMacroSupport) + .enablePlugins(Pre213Preprocessor).settings( + akka.http.sbt.Pre213Preprocessor.pre213Files := Seq( + "scaladsl/server/directives/FormFieldDirectives.scala", "scaladsl/server/directives/RespondWithDirectives.scala" + ) + ) .enablePlugins(BootstrapGenjavadoc, BoilerplatePlugin) .enablePlugins(ReproducibleBuildsPlugin) diff --git a/project/Pre213Preprocessor.scala b/project/Pre213Preprocessor.scala new file mode 100644 index 00000000000..bb45998481d --- /dev/null +++ b/project/Pre213Preprocessor.scala @@ -0,0 +1,36 @@ +package akka.http.sbt + +import sbt._ +import Keys._ + +object Pre213Preprocessor extends AutoPlugin { + val pre213Files = settingKey[Seq[String]]("files that should be edited for pre213 annotation") + + val pattern = """(?s)@pre213.*?@since213""".r + + override def projectSettings: Seq[Def.Setting[_]] = { + Compile / sources := { + if (scalaVersion.value startsWith "3") { + val filter: File => Boolean = f => pre213Files.value.exists(suffix => f.getAbsolutePath.replace("\\", "//").endsWith(suffix)) + (Compile / sources).value.map { s => + if (filter(s)) { + val data = IO.read(s) + val targetFile = sourceManaged.value / s.getName + val newData = pattern.replaceAllIn(data, "@since213") + IO.write(targetFile, newData) + targetFile + } else s + } + } else (Compile / sources).value + } + } +} + +object ReplaceApp extends App { + val pattern = """(?s)@pre213.*?@since213""".r + val f = file("/home/johannes/git/opensource/akka-http/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala") + val data = IO.read(f) + val targetFile = file("/tmp/test") + val newData = pattern.replaceAllIn(data, "@since213") + IO.write(targetFile, newData) +} \ No newline at end of file From 70b6b0ee1f6d9189a18c5e8187526ad3f54720c2 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Thu, 5 May 2022 16:15:39 +0200 Subject: [PATCH 43/51] build: cleanup leftovers from testing --- project/Pre213Preprocessor.scala | 9 --------- 1 file changed, 9 deletions(-) diff --git a/project/Pre213Preprocessor.scala b/project/Pre213Preprocessor.scala index bb45998481d..c5452c15dff 100644 --- a/project/Pre213Preprocessor.scala +++ b/project/Pre213Preprocessor.scala @@ -24,13 +24,4 @@ object Pre213Preprocessor extends AutoPlugin { } else (Compile / sources).value } } -} - -object ReplaceApp extends App { - val pattern = """(?s)@pre213.*?@since213""".r - val f = file("/home/johannes/git/opensource/akka-http/akka-http-core/src/main/scala/akka/http/scaladsl/model/headers/headers.scala") - val data = IO.read(f) - val targetFile = file("/tmp/test") - val newData = pattern.replaceAllIn(data, "@since213") - IO.write(targetFile, newData) } \ No newline at end of file From a15ebade22a195c757d5bfdbbc9e695cb00dbfa5 Mon Sep 17 00:00:00 2001 From: kerr Date: Wed, 15 Jun 2022 15:05:18 +0800 Subject: [PATCH 44/51] =sbt Update Scala 3 version to 3.1.3 (#4123) --- project/Dependencies.scala | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 115e2e9da62..4f569d2ce3d 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -27,7 +27,7 @@ object Dependencies { val scala212Version = "2.12.15" val scala213Version = "2.13.8" - val scala3Version = "3.1.2" + val scala3Version = "3.1.3" val allScalaVersions = // FIXME: can be simplified when Akka 2.5 is dropped if (AkkaDependency.akkaVersion startsWith "2.6.") From 63b34370483aab3e10716e031d98c75c1bfc2e40 Mon Sep 17 00:00:00 2001 From: Arnout Engelen Date: Tue, 23 Aug 2022 14:51:10 +0200 Subject: [PATCH 45/51] scala 3: compile and test marshalling, JMH and docs subprojects (#4126) * scala 3: compile JMH and docs subprojects Three errors around parameters remaining * some more fixes * more projects now build on scala3 * Use short ask syntax --- .../src/main/scala/akka/BenchRunner.scala | 2 +- .../server/util/ConstructFromTuple.scala | 1 + build.sbt | 19 +++++----- .../docs/http/scaladsl/Http2ClientApp.scala | 5 +-- .../http/scaladsl/HttpClientExampleSpec.scala | 36 +++++++++++-------- .../http/scaladsl/HttpServerExampleSpec.scala | 25 +++++++------ .../HttpServerWithActorInteraction.scala | 7 ++-- .../scaladsl/HttpServerWithActorsSample.scala | 3 +- .../docs/http/scaladsl/SprayJsonExample.scala | 15 ++++---- .../http/scaladsl/SprayJsonExampleSpec.scala | 4 +-- .../scaladsl/SprayJsonPrettyMarshalSpec.scala | 4 +-- .../CaseClassExtractionExamplesSpec.scala | 2 +- .../server/ExceptionHandlerExamplesSpec.scala | 6 ++-- .../server/RejectionHandlerExamplesSpec.scala | 10 +++--- .../scaladsl/server/TestKitFragmentSpec.scala | 2 +- .../server/TestKitWithActorSpec.scala | 11 +++--- .../BasicDirectivesExamplesSpec.scala | 4 +-- .../CodingDirectivesExamplesSpec.scala | 6 ++-- .../FileUploadDirectivesExamplesSpec.scala | 2 +- .../FutureDirectivesExamplesSpec.scala | 4 +-- .../JsonStreamingExamplesSpec.scala | 18 ++++++---- .../JsonStreamingFullExamples.scala | 11 +++--- .../MarshallingDirectivesExamplesSpec.scala | 6 ++-- .../MiscDirectivesExamplesSpec.scala | 11 +++--- .../PathDirectivesExamplesSpec.scala | 2 +- .../RouteDirectivesExamplesSpec.scala | 10 +++--- project/Common.scala | 11 +++--- 27 files changed, 130 insertions(+), 107 deletions(-) diff --git a/akka-http-bench-jmh/src/main/scala/akka/BenchRunner.scala b/akka-http-bench-jmh/src/main/scala/akka/BenchRunner.scala index 29b6ba421bc..bfece46b1ff 100644 --- a/akka-http-bench-jmh/src/main/scala/akka/BenchRunner.scala +++ b/akka-http-bench-jmh/src/main/scala/akka/BenchRunner.scala @@ -25,7 +25,7 @@ object BenchRunner { val opts = new CommandLineOptions(args2: _*) val results = new Runner(opts).run() - val report = results.asScala.map { result: RunResult => + val report = results.asScala.map { (result: RunResult) => val bench = result.getParams.getBenchmark val params = result.getParams.getParamsKeys.asScala.map(key => s"$key=${result.getParams.getParam(key)}").mkString("_") val score = result.getAggregatedResult.getPrimaryResult.getScore.round diff --git a/akka-http/src/main/scala/akka/http/scaladsl/server/util/ConstructFromTuple.scala b/akka-http/src/main/scala/akka/http/scaladsl/server/util/ConstructFromTuple.scala index 38372113632..a178afb0f8c 100644 --- a/akka-http/src/main/scala/akka/http/scaladsl/server/util/ConstructFromTuple.scala +++ b/akka-http/src/main/scala/akka/http/scaladsl/server/util/ConstructFromTuple.scala @@ -7,6 +7,7 @@ package akka.http.scaladsl.server.util /** * Constructor for instances of type `R` which can be created from a tuple of type `T`. */ +@FunctionalInterface trait ConstructFromTuple[T, R] extends (T => R) object ConstructFromTuple extends ConstructFromTupleInstances diff --git a/build.sbt b/build.sbt index 54d8736a830..e2da72befab 100644 --- a/build.sbt +++ b/build.sbt @@ -289,11 +289,10 @@ lazy val httpJmhBench = project("akka-http-bench-jmh") .enablePlugins(JmhPlugin) .enablePlugins(NoPublish) // don't release benchs .disablePlugins(MimaPlugin) - .enablePlugins(NoScala3) // FIXME lazy val httpMarshallersScala = project("akka-http-marshallers-scala") .settings(commonSettings) - .enablePlugins(NoPublish, NoScala3 /*FIXME */ /*, AggregatePRValidation*/) + .enablePlugins(NoPublish /*, AggregatePRValidation*/) .disablePlugins(MimaPlugin) .aggregate(httpSprayJson, httpXml) @@ -311,7 +310,7 @@ lazy val httpSprayJson = lazy val httpMarshallersJava = project("akka-http-marshallers-java") .settings(commonSettings) - .enablePlugins(NoPublish, NoScala3 /*FIXME */ /*, AggregatePRValidation*/) + .enablePlugins(NoPublish /*, AggregatePRValidation*/) .disablePlugins(MimaPlugin) .aggregate(httpJackson) @@ -412,7 +411,6 @@ lazy val httpScalafixTests = lazy val docs = project("docs") .enablePlugins(AkkaParadoxPlugin, NoPublish, PublishRsyncPlugin) - .enablePlugins(NoScala3) // FIXME .disablePlugins(MimaPlugin) .addAkkaModuleDependency("akka-stream", "provided", AkkaDependency.docs) .addAkkaModuleDependency("akka-actor-typed", "provided", AkkaDependency.docs) @@ -430,12 +428,17 @@ lazy val docs = project("docs") scalacOptions ++= Seq( // Make sure we don't accidentally keep documenting deprecated calls "-Xfatal-warnings", - // In docs adding an unused variable can be helpful, for example - // to show its type - "-Xlint:-unused", // Does not appear to lead to problems "-Wconf:msg=The outer reference in this type test cannot be checked at run time:s", ), + scalacOptions ++= ( + if (scalaVersion.value.startsWith("3")) Seq.empty + else Seq( + // In docs adding an unused variable can be helpful, for example + // to show its type + "-Xlint:-unused" + ) + ), scalacOptions --= Seq( // Code after ??? can be considered 'dead', but still useful for docs "-Ywarn-dead-code", @@ -501,7 +504,7 @@ lazy val compatibilityTests = Project("akka-http-compatibility-tests", file("akk ) lazy val billOfMaterials = Project("bill-of-materials", file("akka-http-bill-of-materials")) - .enablePlugins(BillOfMaterialsPlugin, NoScala3 /* FIXME */) + .enablePlugins(BillOfMaterialsPlugin) .disablePlugins(MimaPlugin) .settings( name := "akka-http-bom", diff --git a/docs/src/test/scala/docs/http/scaladsl/Http2ClientApp.scala b/docs/src/test/scala/docs/http/scaladsl/Http2ClientApp.scala index 3191e2a8bb4..6d2fc3ec17e 100644 --- a/docs/src/test/scala/docs/http/scaladsl/Http2ClientApp.scala +++ b/docs/src/test/scala/docs/http/scaladsl/Http2ClientApp.scala @@ -19,6 +19,7 @@ import com.typesafe.config.ConfigFactory import scala.annotation.nowarn import scala.concurrent.duration._ +import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.concurrent.Promise @@ -33,8 +34,8 @@ object Http2ClientApp extends App { """ ).withFallback(ConfigFactory.defaultApplication()) - implicit val system = ActorSystem("Http2ClientApp", config) - implicit val ec = system.dispatcher + implicit val system: ActorSystem = ActorSystem("Http2ClientApp", config) + implicit val ec: ExecutionContext = system.dispatcher // #response-future-association val dispatch = singleRequest(Http().connectionTo("doc.akka.io").http2()) diff --git a/docs/src/test/scala/docs/http/scaladsl/HttpClientExampleSpec.scala b/docs/src/test/scala/docs/http/scaladsl/HttpClientExampleSpec.scala index eab588f72ca..ac6c89c33c5 100644 --- a/docs/src/test/scala/docs/http/scaladsl/HttpClientExampleSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/HttpClientExampleSpec.scala @@ -27,7 +27,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.stream.scaladsl.{ FileIO, Framing } import akka.util.ByteString - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() val response: HttpResponse = ??? @@ -43,6 +43,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp "manual-entity-consume-example-2" in compileOnlySpec { //#manual-entity-consume-example-2 + import scala.concurrent.ExecutionContext import scala.concurrent.Future import scala.concurrent.duration._ @@ -50,8 +51,8 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.http.scaladsl.model._ import akka.util.ByteString - implicit val system = ActorSystem() - implicit val dispatcher = system.dispatcher + implicit val system: ActorSystem = ActorSystem() + implicit val dispatcher: ExecutionContext = system.dispatcher case class ExamplePerson(name: String) def parse(line: ByteString): ExamplePerson = ??? @@ -78,6 +79,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp "manual-entity-consume-example-3" in compileOnlySpec { //#manual-entity-consume-example-3 + import scala.concurrent.ExecutionContext import scala.concurrent.Future import akka.NotUsed @@ -87,13 +89,13 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.util.ByteString import akka.stream.scaladsl.{ Flow, Sink, Source } - implicit val system = ActorSystem() - implicit val dispatcher = system.dispatcher + implicit val system: ActorSystem = ActorSystem() + implicit val dispatcher: ExecutionContext = system.dispatcher case class ExamplePerson(name: String) def parse(line: ByteString): Option[ExamplePerson] = - line.utf8String.split(" ").headOption.map(ExamplePerson) + line.utf8String.split(" ").headOption.map(ExamplePerson.apply) val requests: Source[HttpRequest, NotUsed] = Source .fromIterator(() => @@ -126,12 +128,14 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp "manual-entity-discard-example-1" in compileOnlySpec { //#manual-entity-discard-example-1 + import scala.concurrent.ExecutionContext + import akka.actor.ActorSystem import akka.http.scaladsl.model.HttpMessage.DiscardedEntity import akka.http.scaladsl.model._ - implicit val system = ActorSystem() - implicit val dispatcher = system.dispatcher + implicit val system: ActorSystem = ActorSystem() + implicit val dispatcher: ExecutionContext = system.dispatcher val response1: HttpResponse = ??? // obtained from an HTTP call (see examples below) @@ -141,6 +145,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp //#manual-entity-discard-example-1 } "manual-entity-discard-example-2" in compileOnlySpec { + import scala.concurrent.ExecutionContext import scala.concurrent.Future import akka.Done @@ -148,8 +153,8 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.http.scaladsl.model._ import akka.stream.scaladsl.Sink - implicit val system = ActorSystem() - implicit val dispatcher = system.dispatcher + implicit val system: ActorSystem = ActorSystem() + implicit val dispatcher: ExecutionContext = system.dispatcher //#manual-entity-discard-example-2 val response1: HttpResponse = ??? // obtained from an HTTP call (see examples below) @@ -171,7 +176,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.stream.{ OverflowStrategy, QueueOfferResult } - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() import system.dispatcher // to get an implicit ExecutionContext into scope val QueueSize = 10 @@ -218,7 +223,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.http.scaladsl.model.Multipart.FormData import akka.http.scaladsl.marshalling.Marshal - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() import system.dispatcher // to get an implicit ExecutionContext into scope case class FileToUpload(name: String, location: Path) @@ -303,9 +308,10 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.http.scaladsl.unmarshalling.Unmarshal import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import spray.json.DefaultJsonProtocol._ + import spray.json.RootJsonFormat case class Pet(name: String) - implicit val petFormat = jsonFormat1(Pet) + implicit val petFormat: RootJsonFormat[Pet] = jsonFormat1(Pet.apply) val pet: Future[Pet] = Unmarshal(response).to[Pet] //#unmarshal-response-body @@ -313,7 +319,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp "single-request-in-actor-example" in compileOnlySpec { //#single-request-in-actor-example - import akka.actor.{ Actor, ActorLogging } + import akka.actor.{ Actor, ActorLogging, ActorSystem } import akka.http.scaladsl.Http import akka.http.scaladsl.model._ import akka.util.ByteString @@ -324,7 +330,7 @@ class HttpClientExampleSpec extends AnyWordSpec with Matchers with CompileOnlySp import akka.pattern.pipe import context.dispatcher - implicit val system = context.system + implicit val system: ActorSystem = context.system val http = Http(system) override def preStart() = { diff --git a/docs/src/test/scala/docs/http/scaladsl/HttpServerExampleSpec.scala b/docs/src/test/scala/docs/http/scaladsl/HttpServerExampleSpec.scala index cb999db9ce8..2be4b7635b3 100644 --- a/docs/src/test/scala/docs/http/scaladsl/HttpServerExampleSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/HttpServerExampleSpec.scala @@ -7,8 +7,11 @@ package docs.http.scaladsl import akka.event.LoggingAdapter import akka.http.scaladsl.Http import akka.http.scaladsl.model.StatusCodes -import akka.http.scaladsl.server.Route +import akka.http.scaladsl.server.{ Directive, Route } +import akka.http.scaladsl.server.directives.FormFieldDirectives.FieldSpec +import akka.http.scaladsl.server.util.ConstructFromTuple import akka.testkit.TestActors + import scala.annotation.nowarn import docs.CompileOnlySpec @@ -262,8 +265,7 @@ class HttpServerExampleSpec extends AnyWordSpec with Matchers pathEnd { concat( put { - // form extraction from multipart or www-url-encoded forms - formFields("email", "total".as[Money]).as(Order) { order => + formFields("email", "total".as[Money]).as(Order.apply _) { (order: Order) => complete { // complete with serialized Future result (myDbActor ? Update(order)).mapTo[TransactionResult] @@ -285,7 +287,7 @@ class HttpServerExampleSpec extends AnyWordSpec with Matchers get { // parameters to case class extraction parameters("size".as[Int], "color".optional, "dangerous".withDefault("no")) - .as(OrderItem) { orderItem => + .as(OrderItem.apply _) { (orderItem: OrderItem) => // ... route using case class instance created from // required and optional query parameters complete("") // #hide @@ -309,20 +311,21 @@ class HttpServerExampleSpec extends AnyWordSpec with Matchers import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import spray.json.DefaultJsonProtocol._ + import spray.json.RootJsonFormat - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() // needed for the future flatMap/onComplete in the end - implicit val executionContext = system.dispatcher + implicit val executionContext: ExecutionContext = system.dispatcher final case class Bid(userId: String, bid: Int) // these are from spray-json - implicit val bidFormat = jsonFormat2(Bid) + implicit val bidFormat: RootJsonFormat[Bid] = jsonFormat2(Bid.apply) val route = path("bid") { put { - entity(as[Bid]) { bid => + entity(as[Bid]) { (bid: Bid) => // incoming entity is fully consumed and converted into a Bid complete("The bid was: " + bid) } @@ -371,7 +374,7 @@ class HttpServerExampleSpec extends AnyWordSpec with Matchers val route = (put & path("lines")) { withoutSizeLimit { - extractRequest { r: HttpRequest => + extractRequest { (r: HttpRequest) => val finishedWriting = r.discardEntityBytes().future // we only want to respond once the incoming data has been handled: @@ -422,11 +425,11 @@ class HttpServerExampleSpec extends AnyWordSpec with Matchers import spray.json.DefaultJsonProtocol._ import spray.json._ - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() //#dynamic-routing-example case class MockDefinition(path: String, requests: Seq[JsValue], responses: Seq[JsValue]) - implicit val format = jsonFormat3(MockDefinition) + implicit val format: RootJsonFormat[MockDefinition] = jsonFormat3(MockDefinition.apply) @volatile var state = Map.empty[String, Map[JsValue, JsValue]] diff --git a/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorInteraction.scala b/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorInteraction.scala index f0a677178ff..3b55f221fb6 100644 --- a/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorInteraction.scala +++ b/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorInteraction.scala @@ -13,6 +13,7 @@ import akka.http.scaladsl.model.StatusCodes import akka.http.scaladsl.server.Directives._ import akka.util.Timeout import spray.json.DefaultJsonProtocol._ +import spray.json.RootJsonFormat import scala.concurrent.duration._ import scala.concurrent.{ ExecutionContext, Future } @@ -44,8 +45,8 @@ object HttpServerWithActorInteraction { } // these are from spray-json - implicit val bidFormat = jsonFormat2(Auction.Bid) - implicit val bidsFormat = jsonFormat1(Auction.Bids) + implicit val bidFormat: RootJsonFormat[Auction.Bid] = jsonFormat2(Auction.Bid.apply) + implicit val bidsFormat: RootJsonFormat[Auction.Bids] = jsonFormat1(Auction.Bids.apply) def main(args: Array[String]): Unit = { implicit val system: ActorSystem[Auction.Message] = ActorSystem(Auction.apply, "auction") @@ -69,7 +70,7 @@ object HttpServerWithActorInteraction { implicit val timeout: Timeout = 5.seconds // query the actor for the current auction state - val bids: Future[Bids] = (auction ? GetBids).mapTo[Bids] + val bids: Future[Bids] = auction.ask(GetBids(_)) complete(bids) } ) diff --git a/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorsSample.scala b/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorsSample.scala index 780d1913d29..d4b8896630d 100644 --- a/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorsSample.scala +++ b/docs/src/test/scala/docs/http/scaladsl/HttpServerWithActorsSample.scala @@ -53,6 +53,7 @@ object HttpServerWithActorsSample { import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport import spray.json.DefaultJsonProtocol import spray.json.DeserializationException + import spray.json.JsonFormat import spray.json.JsString import spray.json.JsValue import spray.json.RootJsonFormat @@ -75,7 +76,7 @@ object HttpServerWithActorsSample { } } - implicit val jobFormat = jsonFormat4(Job) + implicit val jobFormat: RootJsonFormat[Job] = jsonFormat4(Job.apply) } //#akka-typed-json diff --git a/docs/src/test/scala/docs/http/scaladsl/SprayJsonExample.scala b/docs/src/test/scala/docs/http/scaladsl/SprayJsonExample.scala index 58f9ed6f65b..9872dbbcdcf 100644 --- a/docs/src/test/scala/docs/http/scaladsl/SprayJsonExample.scala +++ b/docs/src/test/scala/docs/http/scaladsl/SprayJsonExample.scala @@ -15,17 +15,19 @@ import akka.http.scaladsl.model.StatusCodes // "com.typesafe.akka" %% "akka-http-spray-json" % "10.1.7" import akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport._ import spray.json.DefaultJsonProtocol._ +import spray.json.RootJsonFormat import scala.io.StdIn +import scala.concurrent.ExecutionContext import scala.concurrent.Future object SprayJsonExample { // needed to run the route - implicit val system = ActorSystem(Behaviors.empty, "SprayExample") + implicit val system: ActorSystem[_] = ActorSystem(Behaviors.empty, "SprayExample") // needed for the future map/flatmap in the end and future in fetchItem and saveOrder - implicit val executionContext = system.executionContext + implicit val executionContext: ExecutionContext = system.executionContext var orders: List[Item] = Nil @@ -34,18 +36,15 @@ object SprayJsonExample { final case class Order(items: List[Item]) // formats for unmarshalling and marshalling - implicit val itemFormat = jsonFormat2(Item) - implicit val orderFormat = jsonFormat1(Order) + implicit val itemFormat: RootJsonFormat[Item] = jsonFormat2(Item.apply) + implicit val orderFormat: RootJsonFormat[Order] = jsonFormat1(Order.apply) // (fake) async database query api def fetchItem(itemId: Long): Future[Option[Item]] = Future { orders.find(o => o.id == itemId) } def saveOrder(order: Order): Future[Done] = { - orders = order match { - case Order(items) => items ::: orders - case _ => orders - } + orders = order.items ::: orders Future { Done } } diff --git a/docs/src/test/scala/docs/http/scaladsl/SprayJsonExampleSpec.scala b/docs/src/test/scala/docs/http/scaladsl/SprayJsonExampleSpec.scala index e9c36c83f62..e4cc43b14b7 100644 --- a/docs/src/test/scala/docs/http/scaladsl/SprayJsonExampleSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/SprayJsonExampleSpec.scala @@ -25,8 +25,8 @@ class SprayJsonExampleSpec extends AnyWordSpec with Matchers { // collect your json format instances into a support trait: trait JsonSupport extends SprayJsonSupport with DefaultJsonProtocol { - implicit val itemFormat = jsonFormat2(Item) - implicit val orderFormat = jsonFormat1(Order) // contains List[Item] + implicit val itemFormat: RootJsonFormat[Item] = jsonFormat2(Item.apply) + implicit val orderFormat: RootJsonFormat[Order] = jsonFormat1(Order.apply) // contains List[Item] } // use it wherever json (un)marshalling is needed diff --git a/docs/src/test/scala/docs/http/scaladsl/SprayJsonPrettyMarshalSpec.scala b/docs/src/test/scala/docs/http/scaladsl/SprayJsonPrettyMarshalSpec.scala index 32acfabd5d9..70bff1eb231 100644 --- a/docs/src/test/scala/docs/http/scaladsl/SprayJsonPrettyMarshalSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/SprayJsonPrettyMarshalSpec.scala @@ -20,8 +20,8 @@ class SprayJsonPrettyMarshalSpec extends RoutingSpec with CompileOnlySpec { object PrettyJsonFormatSupport { import DefaultJsonProtocol._ - implicit val printer = PrettyPrinter - implicit val prettyPrintedItemFormat = jsonFormat2(PrettyPrintedItem) + implicit val printer: JsonPrinter = PrettyPrinter + implicit val prettyPrintedItemFormat: RootJsonFormat[PrettyPrintedItem] = jsonFormat2(PrettyPrintedItem.apply) } // use it wherever json (un)marshalling is needed diff --git a/docs/src/test/scala/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala index 9261da478c6..b8bd9d82816 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/CaseClassExtractionExamplesSpec.scala @@ -68,7 +68,7 @@ class CaseClassExtractionExamplesSpec extends RoutingSpec with Inside { "example 4 test" in { val route = (path("color" / Segment) & - parameters("r".as[Int], "g".as[Int], "b".as[Int])).as(Color) { color => + parameters("r".as[Int], "g".as[Int], "b".as[Int])).as(Color.apply _) { color => // ... route working with the `color` instance doSomethingWith(color) // #hide } diff --git a/docs/src/test/scala/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala index eabdff8b6ef..20cc8ec5a19 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/ExceptionHandlerExamplesSpec.scala @@ -31,7 +31,7 @@ object MyExplicitExceptionHandler { object MyApp extends App { - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() val route: Route = handleExceptions(myExceptionHandler) { @@ -66,7 +66,7 @@ object MyImplicitExceptionHandler { object MyApp extends App { - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() val route: Route = // ... some route structure @@ -150,7 +150,7 @@ object RespondWithHeaderExceptionHandlerExample { } object MyApp extends App { - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() Http().newServerAt("localhost", 8080).bind(route) } diff --git a/docs/src/test/scala/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala index 28835b82fd1..a56ae4e9f18 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/RejectionHandlerExamplesSpec.scala @@ -41,7 +41,7 @@ object MyRejectionHandler { .handleNotFound { complete((NotFound, "Not here!")) } .result() - implicit val system = ActorSystem() + implicit val system: ActorSystem = ActorSystem() val route: Route = handleRejections(myRejectionHandler) { // ... some route structure @@ -60,7 +60,7 @@ object HandleNotFoundWithThePath { import akka.http.scaladsl.server._ import Directives._ - implicit def myRejectionHandler = + implicit def myRejectionHandler: RejectionHandler = RejectionHandler.newBuilder() .handleNotFound { extractUnmatchedPath { p => @@ -98,7 +98,7 @@ class RejectionHandlerExamplesSpec extends RoutingSpec with CompileOnlySpec { import akka.http.scaladsl.model._ import akka.http.scaladsl.server.RejectionHandler - implicit def myRejectionHandler = + implicit def myRejectionHandler: RejectionHandler = RejectionHandler.default .mapRejectionResponse { case res @ HttpResponse(_, _, ent: HttpEntity.Strict, _) => @@ -132,7 +132,7 @@ class RejectionHandlerExamplesSpec extends RoutingSpec with CompileOnlySpec { import akka.http.scaladsl.model._ import akka.http.scaladsl.server.RejectionHandler - implicit def myRejectionHandler = + implicit def myRejectionHandler: RejectionHandler = RejectionHandler.default .mapRejectionResponse { case res @ HttpResponse(_, _, ent: HttpEntity.Strict, _) => @@ -168,7 +168,7 @@ class RejectionHandlerExamplesSpec extends RoutingSpec with CompileOnlySpec { import akka.http.scaladsl.server._ import akka.http.scaladsl.model.StatusCodes.BadRequest - implicit def myRejectionHandler = RejectionHandler.newBuilder().handle { + implicit def myRejectionHandler: RejectionHandler = RejectionHandler.newBuilder().handle { case MissingCookieRejection(_) => complete(HttpResponse(BadRequest, entity = "No cookies, no service!!!")) }.result() diff --git a/docs/src/test/scala/docs/http/scaladsl/server/TestKitFragmentSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/TestKitFragmentSpec.scala index bddd3dda15a..d2e38a4329e 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/TestKitFragmentSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/TestKitFragmentSpec.scala @@ -58,6 +58,6 @@ class TestKitTimeoutSpec extends AnyWordSpec with ScalatestRouteTest { import akka.http.scaladsl.testkit.RouteTestTimeout import akka.testkit.TestDuration - implicit val timeout = RouteTestTimeout(5.seconds.dilated) + implicit val timeout: RouteTestTimeout = RouteTestTimeout(5.seconds.dilated) //#timeout-setting } diff --git a/docs/src/test/scala/docs/http/scaladsl/server/TestKitWithActorSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/TestKitWithActorSpec.scala index 70186970c25..41b2c6cca3a 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/TestKitWithActorSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/TestKitWithActorSpec.scala @@ -8,8 +8,9 @@ package docs.http.scaladsl.server import scala.concurrent.duration._ import scala.util.{ Failure, Success } +import akka.{ actor => untyped } import akka.actor.testkit.typed.scaladsl.TestProbe -import akka.actor.typed.{ ActorRef, Scheduler } +import akka.actor.typed.{ ActorRef, ActorSystem, Scheduler } import akka.actor.typed.scaladsl.AskPattern._ import akka.http.scaladsl.server.Directives._ import akka.http.scaladsl.testkit.ScalatestRouteTest @@ -24,7 +25,7 @@ object RouteUnderTest { // Your route under test, scheduler is only needed as ask is used def route(someActor: ActorRef[Ping])(implicit scheduler: Scheduler, timeout: Timeout) = get { path("ping") { - complete(someActor ? Ping) + complete(someActor ? Ping.apply) } } } @@ -35,9 +36,9 @@ class TestKitWithActorSpec extends AnyWordSpec with Matchers with ScalatestRoute // This test does not use the classic APIs, // so it needs to adapt the system: import akka.actor.typed.scaladsl.adapter._ - implicit val typedSystem = system.toTyped - implicit val timeout = Timeout(500.milliseconds) - implicit val scheduler = system.scheduler + implicit val typedSystem: ActorSystem[_] = system.toTyped + implicit val timeout: Timeout = Timeout(500.milliseconds) + implicit val scheduler: untyped.Scheduler = system.scheduler "The service" should { "return a 'PONG!' response for GET requests to /ping" in { diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala index d472270f713..2b73aeaeb5d 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/BasicDirectivesExamplesSpec.scala @@ -681,7 +681,7 @@ class BasicDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { "extractSettings-examples" in { //#extractSettings-examples val route = - extractSettings { settings: RoutingSettings => + extractSettings { (settings: RoutingSettings) => complete(s"RoutingSettings.renderVanityFooter = ${settings.renderVanityFooter}") } @@ -699,7 +699,7 @@ class BasicDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { val route = tunedSettings { - extractSettings { settings: RoutingSettings => + extractSettings { (settings: RoutingSettings) => complete(s"RoutingSettings.fileGetConditional = ${settings.fileGetConditional}") } } diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala index 06cbc480498..810bc908d6e 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/CodingDirectivesExamplesSpec.scala @@ -79,7 +79,7 @@ class CodingDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { //#decodeRequest val route = decodeRequest { - entity(as[String]) { content: String => + entity(as[String]) { (content: String) => complete(s"Request content: '$content'") } } @@ -100,7 +100,7 @@ class CodingDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { //#decodeRequestWith val route = decodeRequestWith(Coders.Gzip) { - entity(as[String]) { content: String => + entity(as[String]) { (content: String) => complete(s"Request content: '$content'") } } @@ -121,7 +121,7 @@ class CodingDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { //#decodeRequestWith val route = decodeRequestWith(Coders.Gzip, Coders.NoCoding) { - entity(as[String]) { content: String => + entity(as[String]) { (content: String) => complete(s"Request content: '$content'") } } diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala index 387a574bb30..22e47d45e0c 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/FileUploadDirectivesExamplesSpec.scala @@ -25,7 +25,7 @@ class FileUploadDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec """ // test touches disk, so give it some time - implicit val routeTimeout = RouteTestTimeout(7.seconds.dilated) + implicit val routeTimeout: RouteTestTimeout = RouteTestTimeout(7.seconds.dilated) "storeUploadedFile" in { //#storeUploadedFile diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala index 9dd19e3b7b4..0476b632f53 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/FutureDirectivesExamplesSpec.scala @@ -20,12 +20,12 @@ import docs.CompileOnlySpec class FutureDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { object TestException extends Throwable - implicit val myExceptionHandler = + implicit val myExceptionHandler: ExceptionHandler = ExceptionHandler { case TestException => complete(InternalServerError -> "Unsuccessful future!") } - implicit val responseTimeout = Timeout(2, TimeUnit.SECONDS) + implicit val responseTimeout: Timeout = Timeout(2, TimeUnit.SECONDS) "onComplete" in { //#onComplete diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingExamplesSpec.scala index fec58f8cf97..e273bcd0de5 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingExamplesSpec.scala @@ -30,11 +30,13 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { def getTweets = Source(tweets) //#tweet-format + import spray.json.RootJsonFormat + object MyTweetJsonProtocol extends akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport with spray.json.DefaultJsonProtocol { - implicit val tweetFormat = jsonFormat2(Tweet.apply) + implicit val tweetFormat: RootJsonFormat[Tweet] = jsonFormat2(Tweet.apply) } //#tweet-format @@ -86,7 +88,7 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { // {"example":1000} val newline = ByteString("\n") - implicit val jsonStreamingSupport = EntityStreamingSupport.json() + implicit val jsonStreamingSupport: EntityStreamingSupport = EntityStreamingSupport.json() .withFramingRenderer(Flow[ByteString].map(bs => bs ++ newline)) val route = @@ -120,7 +122,7 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { } // [2] enable csv streaming: - implicit val csvStreaming = EntityStreamingSupport.csv() + implicit val csvStreaming: EntityStreamingSupport = EntityStreamingSupport.csv() val route = path("tweets") { @@ -176,11 +178,13 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { //#measurement-model //#measurement-format + import spray.json.RootJsonFormat + object MyMeasurementJsonProtocol extends akka.http.scaladsl.marshallers.sprayjson.SprayJsonSupport with spray.json.DefaultJsonProtocol { - implicit val measurementFormat = jsonFormat2(Measurement.apply) + implicit val measurementFormat: RootJsonFormat[Measurement] = jsonFormat2(Measurement.apply) } //#measurement-format @@ -190,7 +194,7 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { import MyMeasurementJsonProtocol._ // [2] enable Json Streaming - implicit val jsonStreamingSupport = EntityStreamingSupport.json() + implicit val jsonStreamingSupport: EntityStreamingSupport = EntityStreamingSupport.json() // prepare your persisting logic here val persistMetrics = Flow[Measurement] @@ -207,7 +211,7 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { .runFold(0) { (cnt, _) => cnt + 1 } complete { - measurementsSubmitted.map(n => Map("msg" -> s"""Total metrics received: $n""")) + measurementsSubmitted.map(n => s"""Total metrics received: $n""") } } } @@ -224,7 +228,7 @@ class JsonStreamingExamplesSpec extends RoutingSpec with CompileOnlySpec { Post("/metrics", entity = data) ~> route ~> check { status should ===(StatusCodes.OK) - responseAs[String] should ===("""{"msg":"Total metrics received: 2"}""") + responseAs[String] should ===("Total metrics received: 2") } // the FramingWithContentType will reject any content type that it does not understand: diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingFullExamples.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingFullExamples.scala index abdd8964e35..f8d1be77636 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingFullExamples.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/JsonStreamingFullExamples.scala @@ -22,6 +22,7 @@ class JsonStreamingFullExamples extends AnyWordSpec { import akka.stream.scaladsl.Source import spray.json.DefaultJsonProtocol + import scala.concurrent.ExecutionContext import scala.io.StdIn import scala.util.Random @@ -31,21 +32,21 @@ class JsonStreamingFullExamples extends AnyWordSpec { import spray.json._ - implicit val userFormat = jsonFormat2(User) + implicit val userFormat: JsonFormat[User] = jsonFormat2(User.apply) val `vnd.example.api.v1+json` = MediaType.applicationWithFixedCharset("vnd.example.api.v1+json", HttpCharsets.`UTF-8`) val ct = ContentType.apply(`vnd.example.api.v1+json`) implicit def userMarshaller: ToEntityMarshaller[User] = Marshaller.oneOf( - Marshaller.withFixedContentType(`vnd.example.api.v1+json`) { organisation => - HttpEntity(`vnd.example.api.v1+json`, organisation.toJson.compactPrint) + Marshaller.withFixedContentType(`vnd.example.api.v1+json`) { (user: User) => + HttpEntity(`vnd.example.api.v1+json`, user.toJson.compactPrint) }) } object ApiServer extends App with UserProtocol { - implicit val system = ActorSystem("api") - implicit val executionContext = system.dispatcher + implicit val system: ActorSystem = ActorSystem("api") + implicit val executionContext: ExecutionContext = system.dispatcher implicit val jsonStreamingSupport: JsonEntityStreamingSupport = EntityStreamingSupport.json() .withContentType(ct) diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala index 58b3a8cd634..d1b35abffc2 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/MarshallingDirectivesExamplesSpec.scala @@ -9,15 +9,16 @@ import akka.http.scaladsl.model.MediaTypes.`application/json` import akka.http.scaladsl.model._ import akka.http.scaladsl.server.RoutingSpec import docs.CompileOnlySpec -import spray.json.{ DefaultJsonProtocol, JsValue } //#person-case-class case class Person(name: String, favoriteNumber: Int) //#person-case-class //#person-json-support +import spray.json.{ DefaultJsonProtocol, RootJsonFormat } + object PersonJsonSupport extends DefaultJsonProtocol with SprayJsonSupport { - implicit val PortofolioFormats = jsonFormat2(Person) + implicit val personFormat: RootJsonFormat[Person] = jsonFormat2(Person.apply) } //#person-json-support @@ -43,6 +44,7 @@ class MarshallingDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec "example-entity-with-raw-json" in { //#example-entity-with-raw-json + import spray.json.JsValue import PersonJsonSupport._ val route = post { diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala index 1a604ffada0..b5770334101 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/MiscDirectivesExamplesSpec.scala @@ -6,9 +6,10 @@ package docs.http.scaladsl.server.directives import akka.http.scaladsl.model._ import akka.http.scaladsl.server._ +import akka.util.ByteString import headers._ -import java.net.InetAddress +import java.net.InetAddress import docs.CompileOnlySpec class MiscDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { @@ -122,7 +123,7 @@ class MiscDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { // tests: def entityOfSize(size: Int) = - HttpEntity(ContentTypes.`text/plain(UTF-8)`, "0" * size) + HttpEntity(ContentTypes.`text/plain(UTF-8)`, List.fill(size)('0').mkString) Post("/abc", entityOfSize(500)) ~> route ~> check { status shouldEqual StatusCodes.OK @@ -143,7 +144,7 @@ class MiscDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { // tests: def entityOfSize(size: Int) = - HttpEntity(ContentTypes.`text/plain(UTF-8)`, "0" * size) + HttpEntity(ContentTypes.`text/plain(UTF-8)`, List.fill(size)('0').mkString) Post("/abc", entityOfSize(500)) ~> route ~> check { status shouldEqual StatusCodes.OK @@ -168,7 +169,7 @@ class MiscDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { // tests: def entityOfSize(size: Int) = - HttpEntity(ContentTypes.`text/plain(UTF-8)`, "0" * size) + HttpEntity(ContentTypes.`text/plain(UTF-8)`, List.fill(size)('0').mkString) Post("/abc", entityOfSize(800)) ~> route ~> check { status shouldEqual StatusCodes.OK } @@ -190,7 +191,7 @@ class MiscDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { // tests: def entityOfSize(size: Int) = - HttpEntity(ContentTypes.`text/plain(UTF-8)`, "0" * size) + HttpEntity(ContentTypes.`text/plain(UTF-8)`, List.fill(size)('0').mkString) // will work even if you have configured akka.http.parsing.max-content-length = 500 Post("/abc", entityOfSize(501)) ~> route ~> check { diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala index 0552770f969..faa6f9cb2a8 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/PathDirectivesExamplesSpec.scala @@ -15,7 +15,7 @@ class PathDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { "foo" / "bar" / "X" ~ IntNumber.? / ("edit" | "create") val route: Route = - path(matcher) { i: Option[Int] => + path(matcher) { (i: Option[Int]) => complete(s"Matched X${i.getOrElse("")}") } //#path-matcher diff --git a/docs/src/test/scala/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala b/docs/src/test/scala/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala index 3324e0d9176..3dd47a51734 100644 --- a/docs/src/test/scala/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala +++ b/docs/src/test/scala/docs/http/scaladsl/server/directives/RouteDirectivesExamplesSpec.scala @@ -17,7 +17,7 @@ import akka.http.scaladsl.model._ //#complete-examples import akka.http.scaladsl.model.ContentTypes._ -import akka.http.scaladsl.model.headers.`Content-Type` +import akka.http.scaladsl.model.headers.`Access-Control-Allow-Origin` //#complete-examples @@ -48,10 +48,10 @@ class RouteDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { complete(201 -> "bar") }, path("e") { - complete(StatusCodes.Created, List(`Content-Type`(`text/plain(UTF-8)`)), "bar") + complete(StatusCodes.Created, List(`Access-Control-Allow-Origin`.`*`), "bar") }, path("f") { - complete(201, List(`Content-Type`(`text/plain(UTF-8)`)), "bar") + complete(201, List(`Access-Control-Allow-Origin`.`*`), "bar") }, path("g") { complete(Future { StatusCodes.Created -> "bar" }) @@ -82,13 +82,13 @@ class RouteDirectivesExamplesSpec extends RoutingSpec with CompileOnlySpec { Get("/e") ~> route ~> check { status shouldEqual StatusCodes.Created - header[`Content-Type`] shouldEqual Some(`Content-Type`(`text/plain(UTF-8)`)) + header[`Access-Control-Allow-Origin`] shouldEqual Some(`Access-Control-Allow-Origin`.`*`) responseAs[String] shouldEqual "bar" } Get("/f") ~> route ~> check { status shouldEqual StatusCodes.Created - header[`Content-Type`] shouldEqual Some(`Content-Type`(`text/plain(UTF-8)`)) + header[`Access-Control-Allow-Origin`] shouldEqual Some(`Access-Control-Allow-Origin`.`*`) responseAs[String] shouldEqual "bar" } diff --git a/project/Common.scala b/project/Common.scala index 93cfee37937..342c7eacbb7 100644 --- a/project/Common.scala +++ b/project/Common.scala @@ -16,19 +16,15 @@ object Common extends AutoPlugin { scalacOptions ++= Seq( "-deprecation", "-encoding", "UTF-8", // yes, this is 2 args - "-target:jvm-1.8", + "-release", "8", "-unchecked", - "-Xlint", "-Ywarn-dead-code", // Silence deprecation notices for changes introduced in Scala 2.12 // Can be removed when we drop support for Scala 2.12: "-Wconf:msg=object JavaConverters in package collection is deprecated:s", "-Wconf:msg=is deprecated \\(since 2\\.13\\.:s", ), - // '-release' parameter is restricted to 'Compile, compile' scope because - // otherwise `sbt akka-http-xml/compile:doc` fails with it on Scala 2.12.9 - Compile / compile / scalacOptions ++= - onlyAfterScala212(onlyAfterJdk8("-release", "8")).value, + scalacOptions ++= onlyOnScala2(Seq("-Xlint")).value, javacOptions ++= Seq("-encoding", "UTF-8") ++ onlyOnJdk8("-source", "1.8") ++ onlyAfterJdk8("--release", "8"), // restrict to 'compile' scope because otherwise it is also passed to @@ -54,6 +50,9 @@ object Common extends AutoPlugin { def onlyAfterScala212[T](values: Seq[T]): Def.Initialize[Seq[T]] = Def.setting { if (scalaMinorVersion.value >= 12) values else Seq.empty[T] } + def onlyOnScala2[T](values: Seq[T]): Def.Initialize[Seq[T]] = Def.setting { + if (scalaVersion.value.startsWith("3")) Seq.empty[T] else values + } def scalaMinorVersion: Def.Initialize[Long] = Def.setting { CrossVersion.partialVersion(scalaVersion.value).get._2 } From 3e859b35717aad7a714bd8cf57f4bcee5f322cf9 Mon Sep 17 00:00:00 2001 From: Johannes Rudolph Date: Tue, 7 Jun 2022 14:55:37 +0200 Subject: [PATCH 46/51] core: rename to NewConnectionPoolSpec according to class name --- .../{ConnectionPoolSpec.scala => NewConnectionPoolSpec.scala} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename akka-http-core/src/test/scala/akka/http/impl/engine/client/{ConnectionPoolSpec.scala => NewConnectionPoolSpec.scala} (100%) diff --git a/akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala b/akka-http-core/src/test/scala/akka/http/impl/engine/client/NewConnectionPoolSpec.scala similarity index 100% rename from akka-http-core/src/test/scala/akka/http/impl/engine/client/ConnectionPoolSpec.scala rename to akka-http-core/src/test/scala/akka/http/impl/engine/client/NewConnectionPoolSpec.scala From 1e21e043f8cafb8c676f5d3e885453360f76cb6d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andr=C3=A9n?= Date: Thu, 29 Sep 2022 10:36:17 +0200 Subject: [PATCH 47/51] Make it build --- .github/workflows/validate-and-test.yml | 5 ++--- .../test/scala/akka/http/scaladsl/ClientServerSpec.scala | 2 +- project/Dependencies.scala | 8 +------- 3 files changed, 4 insertions(+), 11 deletions(-) diff --git a/.github/workflows/validate-and-test.yml b/.github/workflows/validate-and-test.yml index 755a3c17af5..bda373cae81 100644 --- a/.github/workflows/validate-and-test.yml +++ b/.github/workflows/validate-and-test.yml @@ -54,7 +54,7 @@ jobs: fail-fast: false matrix: SCALA_VERSION: [2.12, 2.13, 3] - JABBA_JDK: [1.8] + JABBA_JDK: [1.8, 1.11] steps: - name: Checkout uses: actions/checkout@v2 @@ -81,8 +81,7 @@ jobs: # Quick testing for PR validation - name: Validate pull request for JDK ${{ matrix.JABBA_JDK }}, Scala ${{ matrix.SCALA_VERSION }} if: ${{ github.event_name == 'pull_request' }} - # FIXME: revert back to `validatePullRequest` task, when all modules support Scala 3 - run: sbt -Dakka.http.parallelExecution=false -Dakka.test.timefactor=2 "+~ ${{ matrix.SCALA_VERSION }} executePullRequestValidation" + run: sbt -Dakka.http.parallelExecution=false -Dakka.test.timefactor=2 ++${{ matrix.SCALA_VERSION }} validatePullRequest # Full testing for pushes - name: Run all tests JDK ${{ matrix.JABBA_JDK }}, Scala ${{ matrix.SCALA_VERSION }} diff --git a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala index 493819a8e25..ff15ae856c1 100644 --- a/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala +++ b/akka-http-core/src/test/scala/akka/http/scaladsl/ClientServerSpec.scala @@ -717,7 +717,7 @@ Host: example.com // Disable hostname verification as ExampleHttpContexts.exampleClientContext sets hostname as akka.example.org val sslConfigSettings = SSLConfigSettings().withLoose(SSLLooseConfig().withDisableHostnameVerification(true)) - val sslConfig = AkkaSSLConfig.apply.withSettings(sslConfigSettings) + val sslConfig = AkkaSSLConfig.apply().withSettings(sslConfigSettings) val sslContext = { val certStore = KeyStore.getInstance(KeyStore.getDefaultType) certStore.load(null, null) diff --git a/project/Dependencies.scala b/project/Dependencies.scala index 69a5f6e4c23..e71d2d86527 100644 --- a/project/Dependencies.scala +++ b/project/Dependencies.scala @@ -28,13 +28,7 @@ object Dependencies { val scala212Version = "2.12.15" val scala213Version = "2.13.8" val scala3Version = "3.1.3" - val allScalaVersions = - // FIXME: can be simplified when Akka 2.5 is dropped - if (AkkaDependency.akkaVersion startsWith "2.6.") - // Scala 3 only for Akka 2.6 - Seq(scala213Version, scala212Version, scala3Version) - else - Seq(scala213Version, scala212Version) + val allScalaVersions = Seq(scala213Version, scala212Version, scala3Version) val Versions = Seq( crossScalaVersions := allScalaVersions, From 4daee0ae01eb5bb847667f5ab0144ae7124c23ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andr=C3=A9n?= Date: Thu, 29 Sep 2022 10:42:38 +0200 Subject: [PATCH 48/51] Minor version of Scala 3 in build matrix --- .github/workflows/validate-and-test.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/validate-and-test.yml b/.github/workflows/validate-and-test.yml index bda373cae81..5230c3c6b52 100644 --- a/.github/workflows/validate-and-test.yml +++ b/.github/workflows/validate-and-test.yml @@ -53,7 +53,7 @@ jobs: strategy: fail-fast: false matrix: - SCALA_VERSION: [2.12, 2.13, 3] + SCALA_VERSION: [2.12, 2.13, 3.1] JABBA_JDK: [1.8, 1.11] steps: - name: Checkout From 20f4cdc2080dae6da3779a0064185429a90c0955 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andr=C3=A9n?= Date: Thu, 29 Sep 2022 13:24:59 +0200 Subject: [PATCH 49/51] MiMa should pass now --- .../10.4.0.backwards.excludes/scala-3.excludes | 2 ++ project/MiMa.scala | 7 +++++-- 2 files changed, 7 insertions(+), 2 deletions(-) create mode 100644 akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/scala-3.excludes diff --git a/akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/scala-3.excludes b/akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/scala-3.excludes new file mode 100644 index 00000000000..d5c4e464e5b --- /dev/null +++ b/akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/scala-3.excludes @@ -0,0 +1,2 @@ +# MiMa doesn't get that scala.Serializable is alias for java.io.Serializable +ProblemFilters.exclude[MissingTypesProblem]("akka.http.scaladsl.model.ErrorInfo") \ No newline at end of file diff --git a/project/MiMa.scala b/project/MiMa.scala index 5e9e694418f..e759b78993e 100644 --- a/project/MiMa.scala +++ b/project/MiMa.scala @@ -23,8 +23,8 @@ object MiMa extends AutoPlugin { ) // A fork is a branch of the project where new releases are created that are not ancestors of the current release line - val forks = Seq("10.0.", "10.1.") - val currentFork = "10.2." + val forks = Seq("10.0.", "10.1.", "10.2.") + val currentFork = "10.4." // manually maintained list of previous versions to make sure all incompatibilities are found // even if so far no files have been been created in this project's mima-filters directory @@ -65,6 +65,8 @@ object MiMa extends AutoPlugin { val post213Versions = `10.1-post-2.13-versions` ++ `10.2-versions` + val post3Versions = Set.empty[String] + lazy val latestVersion = post213Versions.max(versionOrdering) lazy val latest101Version = `10.1-post-2.13-versions`.max(versionOrdering) @@ -72,6 +74,7 @@ object MiMa extends AutoPlugin { mimaPreviousArtifacts := { val versions = if (scalaBinaryVersion.value == "2.13") post213Versions + else if (scalaBinaryVersion.value == "3") post3Versions else pre213Versions ++ post213Versions versions.collect { case version if !ignoredModules.get(name.value).exists(_.contains(version)) => From 6741b16b4415b0e535c0d2f3ac67d21edcfed213 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andr=C3=A9n?= Date: Thu, 29 Sep 2022 13:59:02 +0200 Subject: [PATCH 50/51] MiMa not picking up all filters for 2.12 for some reason --- .../10.4.0.backwards.excludes/stream-utils.excludes | 2 ++ .../src/main/scala/akka/http/impl/util/StreamUtils.scala | 1 + 2 files changed, 3 insertions(+) create mode 100644 akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/stream-utils.excludes diff --git a/akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/stream-utils.excludes b/akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/stream-utils.excludes new file mode 100644 index 00000000000..c856a21f8e5 --- /dev/null +++ b/akka-http-core/src/main/mima-filters/10.4.0.backwards.excludes/stream-utils.excludes @@ -0,0 +1,2 @@ +# internal, changed earlier, not sure why not picked up from 10.1.x excludes for Scala 2.12 +ProblemFilters.exclude[ReversedMissingMethodProblem]("akka.http.impl.util.StreamUtils#ScheduleSupport.akka$http$impl$util$StreamUtils$ScheduleSupport$$super$materializer") \ No newline at end of file diff --git a/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala b/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala index 2e2d1fa0dee..8f124fef2a6 100644 --- a/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala +++ b/akka-http-core/src/main/scala/akka/http/impl/util/StreamUtils.scala @@ -198,6 +198,7 @@ private[http] object StreamUtils { * Returns a flow that is almost identity but delays propagation of cancellation from downstream to upstream. */ def delayCancellation[T](cancelAfter: Duration): Flow[T, T, NotUsed] = Flow.fromGraph(new DelayCancellationStage(cancelAfter)) + /** INTERNAL API */ final class DelayCancellationStage[T](cancelAfter: Duration) extends SimpleLinearGraphStage[T] { def createLogic(inheritedAttributes: Attributes): GraphStageLogic = new GraphStageLogic(shape) with ScheduleSupport with InHandler with OutHandler with StageLogging { setHandlers(in, out, this) From f2acbb6b46fa18f95e09ab060b27d82f2d9638ba Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Johan=20Andr=C3=A9n?= Date: Thu, 29 Sep 2022 15:54:36 +0200 Subject: [PATCH 51/51] Use crossbuild for compat module for now, so we can build it with Scala 3 --- build.sbt | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/build.sbt b/build.sbt index 21b352e0e69..ebac044f7bf 100644 --- a/build.sbt +++ b/build.sbt @@ -489,12 +489,14 @@ lazy val docs = project("docs") .settings(ParadoxSupport.paradoxWithCustomDirectives) lazy val compatibilityTests = Project("akka-http-compatibility-tests", file("akka-http-compatibility-tests")) - .enablePlugins(NoPublish, NoScala3) + .enablePlugins(NoPublish) .disablePlugins(MimaPlugin) .addAkkaModuleDependency("akka-stream", "provided") .settings( - libraryDependencies ++= Seq( - "com.typesafe.akka" %% "akka-http" % MiMa.latest101Version % "provided", + libraryDependencies +=( + // no scala 3 native artifact available yet so use 2.13 + if (scalaBinaryVersion.value == "3") ("com.typesafe.akka" %% "akka-http" % MiMa.latest101Version % "provided").cross(CrossVersion.for3Use2_13) + else "com.typesafe.akka" %% "akka-http" % MiMa.latest101Version % "provided" ), (Test / dependencyClasspath) := { // HACK: We'd like to use `dependsOn(http % "test->compile")` to upgrade the explicit dependency above to the