diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd4ea9f..8013219 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -15,23 +15,31 @@ on: tags: [v*] env: - PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} - SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} - SONATYPE_CREDENTIAL_HOST: ${{ secrets.SONATYPE_CREDENTIAL_HOST }} - SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} - PGP_SECRET: ${{ secrets.PGP_SECRET }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + +concurrency: + group: ${{ github.workflow }} @ ${{ github.ref }} + cancel-in-progress: true + jobs: build: name: Build and Test strategy: matrix: os: [ubuntu-latest] - scala: [2.13.10, 2.12.17, 3.2.1] + scala: [2.13, 2.12, 3] java: [temurin@8, temurin@11, temurin@17] project: [rootJS, rootJVM, rootNative] exclude: + - scala: 2.12 + java: temurin@11 + - scala: 2.12 + java: temurin@17 + - scala: 3 + java: temurin@11 + - scala: 3 + java: temurin@17 - project: rootJS java: temurin@11 - project: rootJS @@ -41,75 +49,59 @@ jobs: - project: rootNative java: temurin@17 runs-on: ${{ matrix.os }} + timeout-minutes: 60 steps: - name: Checkout current branch (full) - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Download Java (temurin@8) - id: download-java-temurin-8 + - name: Setup Java (temurin@8) + id: setup-java-temurin-8 if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v2 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 + cache: sbt - - name: Setup Java (temurin@8) - if: matrix.java == 'temurin@8' - uses: actions/setup-java@v3 - with: - distribution: jdkfile - java-version: 8 - jdkFile: ${{ steps.download-java-temurin-8.outputs.jdkFile }} + - name: sbt update + if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false' + run: sbt +update - - name: Download Java (temurin@11) - id: download-java-temurin-11 + - name: Setup Java (temurin@11) + id: setup-java-temurin-11 if: matrix.java == 'temurin@11' - uses: typelevel/download-java@v2 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 + cache: sbt - - name: Setup Java (temurin@11) - if: matrix.java == 'temurin@11' - uses: actions/setup-java@v3 - with: - distribution: jdkfile - java-version: 11 - jdkFile: ${{ steps.download-java-temurin-11.outputs.jdkFile }} - - - name: Download Java (temurin@17) - id: download-java-temurin-17 - if: matrix.java == 'temurin@17' - uses: typelevel/download-java@v2 - with: - distribution: temurin - java-version: 17 + - name: sbt update + if: matrix.java == 'temurin@11' && steps.setup-java-temurin-11.outputs.cache-hit == 'false' + run: sbt +update - name: Setup Java (temurin@17) + id: setup-java-temurin-17 if: matrix.java == 'temurin@17' - uses: actions/setup-java@v3 + uses: actions/setup-java@v4 with: - distribution: jdkfile + distribution: temurin java-version: 17 - jdkFile: ${{ steps.download-java-temurin-17.outputs.jdkFile }} + cache: sbt - - name: Cache sbt - uses: actions/cache@v3 - with: - path: | - ~/.sbt - ~/.ivy2/cache - ~/.coursier/cache/v1 - ~/.cache/coursier/v1 - ~/AppData/Local/Coursier/Cache/v1 - ~/Library/Caches/Coursier/v1 - key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} + - name: sbt update + if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false' + run: sbt +update - name: Check that workflows are up to date run: sbt githubWorkflowCheck + - name: Check headers + if: matrix.java == 'temurin@8' && matrix.os == 'ubuntu-latest' + run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' headerCheckAll + - name: scalaJSLink if: matrix.project == 'rootJS' run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' Test/scalaJSLinkerResult @@ -130,16 +122,16 @@ jobs: run: sbt 'project ${{ matrix.project }}' '++ ${{ matrix.scala }}' doc - name: Make target directories - if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') - run: mkdir -p target .js/target parsley-cats/js/target .jvm/target .native/target parsley-cats/jvm/target parsley-cats/native/target project/target + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/staging/1.3') + run: mkdir -p parsley-cats/js/target parsley-cats/jvm/target parsley-cats/native/target project/target - name: Compress target directories - if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') - run: tar cf targets.tar target .js/target parsley-cats/js/target .jvm/target .native/target parsley-cats/jvm/target parsley-cats/native/target project/target + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/staging/1.3') + run: tar cf targets.tar parsley-cats/js/target parsley-cats/jvm/target parsley-cats/native/target project/target - name: Upload target directories - if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') - uses: actions/upload-artifact@v3 + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/staging/1.3') + uses: actions/upload-artifact@v4 with: name: target-${{ matrix.os }}-${{ matrix.java }}-${{ matrix.scala }}-${{ matrix.project }} path: targets.tar @@ -147,179 +139,226 @@ jobs: publish: name: Publish Artifacts needs: [build] - if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/master') + if: github.event_name != 'pull_request' && (startsWith(github.ref, 'refs/tags/v') || github.ref == 'refs/heads/staging/1.3') strategy: matrix: os: [ubuntu-latest] - scala: [2.13.10] java: [temurin@8] runs-on: ${{ matrix.os }} steps: - name: Checkout current branch (full) - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - - name: Download Java (temurin@8) - id: download-java-temurin-8 + - name: Setup Java (temurin@8) + id: setup-java-temurin-8 if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v2 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 8 + cache: sbt - - name: Setup Java (temurin@8) - if: matrix.java == 'temurin@8' - uses: actions/setup-java@v3 - with: - distribution: jdkfile - java-version: 8 - jdkFile: ${{ steps.download-java-temurin-8.outputs.jdkFile }} + - name: sbt update + if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false' + run: sbt +update - - name: Download Java (temurin@11) - id: download-java-temurin-11 + - name: Setup Java (temurin@11) + id: setup-java-temurin-11 if: matrix.java == 'temurin@11' - uses: typelevel/download-java@v2 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 11 + cache: sbt - - name: Setup Java (temurin@11) - if: matrix.java == 'temurin@11' - uses: actions/setup-java@v3 - with: - distribution: jdkfile - java-version: 11 - jdkFile: ${{ steps.download-java-temurin-11.outputs.jdkFile }} + - name: sbt update + if: matrix.java == 'temurin@11' && steps.setup-java-temurin-11.outputs.cache-hit == 'false' + run: sbt +update - - name: Download Java (temurin@17) - id: download-java-temurin-17 + - name: Setup Java (temurin@17) + id: setup-java-temurin-17 if: matrix.java == 'temurin@17' - uses: typelevel/download-java@v2 + uses: actions/setup-java@v4 with: distribution: temurin java-version: 17 + cache: sbt - - name: Setup Java (temurin@17) - if: matrix.java == 'temurin@17' - uses: actions/setup-java@v3 - with: - distribution: jdkfile - java-version: 17 - jdkFile: ${{ steps.download-java-temurin-17.outputs.jdkFile }} + - name: sbt update + if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false' + run: sbt +update - - name: Cache sbt - uses: actions/cache@v3 + - name: Download target directories (2.13, rootJS) + uses: actions/download-artifact@v4 with: - path: | - ~/.sbt - ~/.ivy2/cache - ~/.coursier/cache/v1 - ~/.cache/coursier/v1 - ~/AppData/Local/Coursier/Cache/v1 - ~/Library/Caches/Coursier/v1 - key: ${{ runner.os }}-sbt-cache-v2-${{ hashFiles('**/*.sbt') }}-${{ hashFiles('project/build.properties') }} - - - name: Download target directories (2.13.10, rootJS) - uses: actions/download-artifact@v3 - with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootJS + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-rootJS - - name: Inflate target directories (2.13.10, rootJS) + - name: Inflate target directories (2.13, rootJS) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.13.10, rootJVM) - uses: actions/download-artifact@v3 + - name: Download target directories (2.13, rootJVM) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootJVM + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-rootJVM - - name: Inflate target directories (2.13.10, rootJVM) + - name: Inflate target directories (2.13, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.13.10, rootNative) - uses: actions/download-artifact@v3 + - name: Download target directories (2.13, rootNative) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.13.10-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-2.13-rootNative - - name: Inflate target directories (2.13.10, rootNative) + - name: Inflate target directories (2.13, rootNative) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.12.17, rootJS) - uses: actions/download-artifact@v3 + - name: Download target directories (2.12, rootJS) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootJS + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-rootJS - - name: Inflate target directories (2.12.17, rootJS) + - name: Inflate target directories (2.12, rootJS) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.12.17, rootJVM) - uses: actions/download-artifact@v3 + - name: Download target directories (2.12, rootJVM) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootJVM + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-rootJVM - - name: Inflate target directories (2.12.17, rootJVM) + - name: Inflate target directories (2.12, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (2.12.17, rootNative) - uses: actions/download-artifact@v3 + - name: Download target directories (2.12, rootNative) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-2.12.17-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-2.12-rootNative - - name: Inflate target directories (2.12.17, rootNative) + - name: Inflate target directories (2.12, rootNative) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.2.1, rootJS) - uses: actions/download-artifact@v3 + - name: Download target directories (3, rootJS) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.1-rootJS + name: target-${{ matrix.os }}-${{ matrix.java }}-3-rootJS - - name: Inflate target directories (3.2.1, rootJS) + - name: Inflate target directories (3, rootJS) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.2.1, rootJVM) - uses: actions/download-artifact@v3 + - name: Download target directories (3, rootJVM) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.1-rootJVM + name: target-${{ matrix.os }}-${{ matrix.java }}-3-rootJVM - - name: Inflate target directories (3.2.1, rootJVM) + - name: Inflate target directories (3, rootJVM) run: | tar xf targets.tar rm targets.tar - - name: Download target directories (3.2.1, rootNative) - uses: actions/download-artifact@v3 + - name: Download target directories (3, rootNative) + uses: actions/download-artifact@v4 with: - name: target-${{ matrix.os }}-${{ matrix.java }}-3.2.1-rootNative + name: target-${{ matrix.os }}-${{ matrix.java }}-3-rootNative - - name: Inflate target directories (3.2.1, rootNative) + - name: Inflate target directories (3, rootNative) run: | tar xf targets.tar rm targets.tar - name: Import signing key if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE == '' - run: echo $PGP_SECRET | base64 -di | gpg --import + env: + PGP_SECRET: ${{ secrets.PGP_SECRET }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} + run: echo $PGP_SECRET | base64 -d -i - | gpg --import - name: Import signing key and strip passphrase if: env.PGP_SECRET != '' && env.PGP_PASSPHRASE != '' + env: + PGP_SECRET: ${{ secrets.PGP_SECRET }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: | - echo "$PGP_SECRET" | base64 -di > /tmp/signing-key.gpg + echo "$PGP_SECRET" | base64 -d -i - > /tmp/signing-key.gpg echo "$PGP_PASSPHRASE" | gpg --pinentry-mode loopback --passphrase-fd 0 --import /tmp/signing-key.gpg (echo "$PGP_PASSPHRASE"; echo; echo) | gpg --command-fd 0 --pinentry-mode loopback --change-passphrase $(gpg --list-secret-keys --with-colons 2> /dev/null | grep '^sec:' | cut --delimiter ':' --fields 5 | tail -n 1) - name: Publish - run: sbt '++ ${{ matrix.scala }}' tlCiRelease + env: + SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }} + SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }} + SONATYPE_CREDENTIAL_HOST: ${{ secrets.SONATYPE_CREDENTIAL_HOST }} + run: sbt tlCiRelease + + dependency-submission: + name: Submit Dependencies + if: github.event_name != 'pull_request' + strategy: + matrix: + os: [ubuntu-latest] + java: [temurin@8] + runs-on: ${{ matrix.os }} + steps: + - name: Checkout current branch (full) + uses: actions/checkout@v4 + with: + fetch-depth: 0 + + - name: Setup Java (temurin@8) + id: setup-java-temurin-8 + if: matrix.java == 'temurin@8' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 8 + cache: sbt + + - name: sbt update + if: matrix.java == 'temurin@8' && steps.setup-java-temurin-8.outputs.cache-hit == 'false' + run: sbt +update + + - name: Setup Java (temurin@11) + id: setup-java-temurin-11 + if: matrix.java == 'temurin@11' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 11 + cache: sbt + + - name: sbt update + if: matrix.java == 'temurin@11' && steps.setup-java-temurin-11.outputs.cache-hit == 'false' + run: sbt +update + + - name: Setup Java (temurin@17) + id: setup-java-temurin-17 + if: matrix.java == 'temurin@17' + uses: actions/setup-java@v4 + with: + distribution: temurin + java-version: 17 + cache: sbt + + - name: sbt update + if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false' + run: sbt +update + + - name: Submit Dependencies + uses: scalacenter/sbt-dependency-submission@v2 + with: + modules-ignore: rootjs_2.13 rootjs_2.12 rootjs_3 rootjvm_2.13 rootjvm_2.12 rootjvm_3 rootnative_2.13 rootnative_2.12 rootnative_3 + configs-ignore: test scala-tool scala-doc-tool test-internal diff --git a/build.sbt b/build.sbt index a68be88..c955ec8 100644 --- a/build.sbt +++ b/build.sbt @@ -2,21 +2,19 @@ import org.scalajs.linker.interface.ESVersion import com.typesafe.tools.mima.core._ val projectName = "parsley-cats" -val Scala213 = "2.13.10" -val Scala212 = "2.12.17" -val Scala3 = "3.2.1" +val Scala213 = "2.13.12" +val Scala212 = "2.12.18" +val Scala3 = "3.3.1" Global / onChangedBuildSource := ReloadOnSourceChanges inThisBuild(List( - tlBaseVersion := "1.2", + tlBaseVersion := "1.3", organization := "com.github.j-mie6", + organizationName := "Parsley-Cats Contributors ", startYear := Some(2022), homepage := Some(url("https://github.com/j-mie6/parsley-cats")), licenses := List("BSD-3-Clause" -> url("https://opensource.org/licenses/BSD-3-Clause")), - developers := List( - tlGitHubDev("j-mie6", "Jamie Willis") - ), versionScheme := Some("early-semver"), crossScalaVersions := Seq(Scala213, Scala212, Scala3), scalaVersion := Scala213, @@ -30,8 +28,9 @@ inThisBuild(List( ProblemFilters.exclude[MissingClassProblem]("parsley.MonoidKForParsley"), ), // CI Configuration - tlCiReleaseBranches := Seq("master"), - tlSonatypeUseLegacyHost := false, + tlCiReleaseBranches := Seq("staging/1.3"), + tlCiScalafmtCheck := false, + tlCiHeaderCheck := true, githubWorkflowJavaVersions := Seq(JavaSpec.temurin("8"), JavaSpec.temurin("11"), JavaSpec.temurin("17")), )) @@ -43,13 +42,16 @@ lazy val `parsley-cats` = crossProject(JVMPlatform, JSPlatform, NativePlatform) .in(file("parsley-cats")) .settings( name := projectName, + headerLicenseStyle := HeaderLicenseStyle.SpdxSyntax, + headerEmptyLine := false, + + resolvers ++= Opts.resolver.sonatypeOssReleases, // Will speed up MiMA during fast back-to-back releases libraryDependencies ++= Seq( "org.typelevel" %%% "cats-core" % "2.8.0", - "com.github.j-mie6" %%% "parsley" % "4.0.0", - "org.scalatest" %%% "scalatest" % "3.2.12" % Test, + "com.github.j-mie6" %%% "parsley" % "4.5.0", + "org.scalatest" %%% "scalatest" % "3.2.17" % Test, "org.typelevel" %%% "cats-laws" % "2.8.0" % Test, ), - ) - .jsSettings( - Test / scalaJSLinkerConfig := scalaJSLinkerConfig.value.withESFeatures(_.withESVersion(ESVersion.ES2018)) + + Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-oI"), ) diff --git a/parsley-cats/shared/src/main/scala-2.12/parsley/cats/MonoidKForParsley.scala b/parsley-cats/shared/src/main/scala-2.12/parsley/cats/MonoidKForParsley.scala index 43c306d..df6876d 100644 --- a/parsley-cats/shared/src/main/scala-2.12/parsley/cats/MonoidKForParsley.scala +++ b/parsley-cats/shared/src/main/scala-2.12/parsley/cats/MonoidKForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/parsley-cats/shared/src/main/scala-2.13+/parsley/cats/MonoidKForParsley.scala b/parsley-cats/shared/src/main/scala-2.13+/parsley/cats/MonoidKForParsley.scala index ebac5f0..2dbf508 100644 --- a/parsley-cats/shared/src/main/scala-2.13+/parsley/cats/MonoidKForParsley.scala +++ b/parsley-cats/shared/src/main/scala-2.13+/parsley/cats/MonoidKForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/ApplicativeForParsley.scala b/parsley-cats/shared/src/main/scala/parsley/cats/ApplicativeForParsley.scala index 3b37021..f352017 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/ApplicativeForParsley.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/ApplicativeForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats @@ -20,7 +22,7 @@ private [parsley] trait ApplicativeForParsley extends Applicative[Parsley] { override def ap[A, B](mf: Parsley[A => B])(mx: Parsley[A]): Parsley[B] = mf <*> mx override def replicateA[A](n: Int, mx: Parsley[A]): Parsley[List[A]] = parsley.combinator.exactly(n, mx) - override def replicateA_[A](n: Int, mx: Parsley[A]): Parsley[Unit] = parsley.combinator.skip(mx, (1 until n).map(_ => mx): _*) + override def replicateA_[A](n: Int, mx: Parsley[A]): Parsley[Unit] = replicateA(n, mx).void // Maps and Tuples override def map2[A, B, Z](mx: Parsley[A], my: Parsley[B])(f: (A, B) => Z): Parsley[Z] = lift2(f, mx, my) diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/DeferForParsley.scala b/parsley-cats/shared/src/main/scala/parsley/cats/DeferForParsley.scala index 0fedcd5..a55908a 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/DeferForParsley.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/DeferForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/FunctorFilterForParsley.scala b/parsley-cats/shared/src/main/scala/parsley/cats/FunctorFilterForParsley.scala index 2ebf022..0314b05 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/FunctorFilterForParsley.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/FunctorFilterForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/FunctorForParsley.scala b/parsley-cats/shared/src/main/scala/parsley/cats/FunctorForParsley.scala index 8170a4a..4364320 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/FunctorForParsley.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/FunctorForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/MonadForParsley.scala b/parsley-cats/shared/src/main/scala/parsley/cats/MonadForParsley.scala index 0520617..3c4e8fc 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/MonadForParsley.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/MonadForParsley.scala @@ -1,10 +1,12 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats import parsley.Parsley -import parsley.registers.{RegisterMaker, RegisterMethods} +import parsley.state.{RefMaker, StateCombinators} import cats.{Alternative, Monad} @@ -17,17 +19,17 @@ private [parsley] trait MonadForParsley extends Monad[Parsley] { } // Monad Overrides - override def ifM[B](mx: Parsley[Boolean])(ifTrue: => Parsley[B], ifFalse: => Parsley[B]): Parsley[B] = parsley.combinator.ifP(mx, ifTrue, ifFalse) + override def ifM[B](mx: Parsley[Boolean])(ifTrue: => Parsley[B], ifFalse: => Parsley[B]): Parsley[B] = parsley.combinator.ifS(mx, ifTrue, ifFalse) override def whileM_[A](p: Parsley[Boolean])(body: =>Parsley[A]): Parsley[Unit] = { - parsley.combinator.when(p, parsley.combinator.whileP(body ~> p)) + parsley.combinator.whenS(p, parsley.combinator.whileS(body ~> p)) } - override def untilM_[A](body: Parsley[A])(p: => Parsley[Boolean]): Parsley[Unit] = parsley.combinator.whileP(body *> p.map(!_)) + override def untilM_[A](body: Parsley[A])(p: => Parsley[Boolean]): Parsley[Unit] = parsley.combinator.whileS(body *> p.map(!_)) override def whileM[G[_]: Alternative, A](p: Parsley[Boolean])(body: => Parsley[A]): Parsley[G[A]] = { val G = implicitly[Alternative[G]] - G.empty[A].makeReg { acc => + G.empty[A].makeRef { acc => whileM_(p) { - acc.modify(body.map(x => (xs: G[A]) => G.appendK(xs, x))) + acc.update(body.map(x => (xs: G[A]) => G.appendK(xs, x))) } *> acc.get } } @@ -44,19 +46,19 @@ private [parsley] trait MonadForParsley extends Monad[Parsley] { override def iterateUntil[A](mx: Parsley[A])(p: A => Boolean): Parsley[A] = { lazy val loop: Parsley[A] = mx.persist { mx => - parsley.combinator.ifP(mx.map(p), mx, loop) + parsley.combinator.ifS(mx.map(p), mx, loop) } loop } override def iterateWhile[A](mx: Parsley[A])(p: A => Boolean): Parsley[A] = { lazy val loop: Parsley[A] = mx.persist { mx => - parsley.combinator.ifP(mx.map(p), loop, mx) + parsley.combinator.ifS(mx.map(p), loop, mx) } loop } override def ifElseM[A](branches: (Parsley[Boolean], Parsley[A])*)(els: Parsley[A]): Parsley[A] = { branches.foldRight(els) { - case ((cond, t), e) => parsley.combinator.ifP(cond, t, e) + case ((cond, t), e) => parsley.combinator.ifS(cond, t, e) } } } diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/combinator.scala b/parsley-cats/shared/src/main/scala/parsley/cats/combinator.scala index b804753..72262a8 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/combinator.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/combinator.scala @@ -1,12 +1,14 @@ -/* SPDX-FileCopyrightText: © 2023 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats import cats.data.NonEmptyList -import parsley.Parsley, Parsley.notFollowedBy -import parsley.combinator.{many, manyUntil} +import parsley.Parsley, Parsley.{notFollowedBy, many} +import parsley.combinator.{manyTill} import parsley.lift.lift2 /** This module contains pre-made combinators that are very useful for a variety of purposes, specialised to `cats`. @@ -46,6 +48,34 @@ object combinator { */ def some[A](p: Parsley[A]): Parsley[NonEmptyList[A]] = nonEmptyList(p, many(p)) + /** This combinator repeatedly parses a given parser '''one''' or more times, until the `end` parser succeeds, collecting the results into a list. + * + * First ensures that trying to parse `end` fails, then tries to parse `p`. If it succeed then it will repeatedly: try to parse `end`, if it fails + * '''without consuming input''', then parses `p`, which must succeed. When `end` does succeed, this combinator will return all of the results + * generated by `p`, `x,,1,,` through `x,,n,,` (with `n >= 1`), in a non-empty list: `NonEmptyList.of(x,,1,,, .., x,,n,,)`. The parser `p` must succeed + * at least once before `end` succeeds. + * + * @example This can be useful for scanning comments: {{{ + * scala> import parsley.character.{string, item, endOfLine} + * scala> import parsley.cats.combinator.someTill + * scala> val comment = string("//") *> someTill(item, endOfLine) + * scala> p.parse("//hello world") + * val res0 = Failure(..) + * scala> p.parse("//hello world\n") + * val res1 = Success(NonEmptyList.of('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd')) + * scala> p.parse("//\n") + * val res2 = Failure(..) + * scala> p.parse("//a\n") + * val res3 = Success(NonEmptyList.of('a')) + * }}} + * + * @param p the parser to execute multiple times. + * @param end the parser that stops the parsing of `p`. + * @return a parser that parses `p` until `end` succeeds, returning the non-empty list of all the successful results. + * @since 1.3.0 + */ + def someTill[A](p: Parsley[A], end: Parsley[_]): Parsley[NonEmptyList[A]] = notFollowedBy(end) *> (nonEmptyList(p, manyTill(p, end))) + /** This combinator repeatedly parses a given parser '''one''' or more times, until the `end` parser succeeds, collecting the results into a list. * * First ensures that trying to parse `end` fails, then tries to parse `p`. If it succeed then it will repeatedly: try to parse `end`, if it fails @@ -72,7 +102,8 @@ object combinator { * @return a parser that parses `p` until `end` succeeds, returning the non-empty list of all the successful results. * @since 1.2.0 */ - def someUntil[A](p: Parsley[A], end: Parsley[_]): Parsley[NonEmptyList[A]] = notFollowedBy(end) *> (nonEmptyList(p, manyUntil(p, end))) + @deprecated("This combinator will be removed in 2.0.0, use someTill instead", "1.3.0") + def someUntil[A](p: Parsley[A], end: Parsley[_]): Parsley[NonEmptyList[A]] = notFollowedBy(end) *> (nonEmptyList(p, manyTill(p, end))) /** This combinator parses '''one''' or more occurrences of `p`, separated by `sep`. * @@ -127,7 +158,7 @@ object combinator { * @since 1.2.0 */ def sepEndBy1[A](p: Parsley[A], sep: =>Parsley[_]): Parsley[NonEmptyList[A]] = parsley.combinator.sepEndBy1(p, sep).map { xxs => - val (x::xs) = xxs + val (x::xs) = xxs: @unchecked NonEmptyList(x, xs) } diff --git a/parsley-cats/shared/src/main/scala/parsley/cats/instances.scala b/parsley-cats/shared/src/main/scala/parsley/cats/instances.scala index 48038d5..28e5cf6 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/instances.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/instances.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2023 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/parsley-cats/shared/src/main/scala/parsley/catsinstances.scala b/parsley-cats/shared/src/main/scala/parsley/catsinstances.scala index 95dca29..3127809 100644 --- a/parsley-cats/shared/src/main/scala/parsley/catsinstances.scala +++ b/parsley-cats/shared/src/main/scala/parsley/catsinstances.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley diff --git a/parsley-cats/shared/src/test/scala/parsley/ParsleyTest.scala b/parsley-cats/shared/src/test/scala/parsley/ParsleyTest.scala index 6a18f97..a6426cc 100644 --- a/parsley-cats/shared/src/test/scala/parsley/ParsleyTest.scala +++ b/parsley-cats/shared/src/test/scala/parsley/ParsleyTest.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2023 Parsley Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley @@ -7,8 +9,7 @@ import org.scalatest.Assertions import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers -import parsley.combinator.eof -import parsley.Result +import parsley.Parsley.eof import parsley.errors.{ErrorBuilder, tokenextractors} import org.scalatest.Inside import org.scalactic.source.Position diff --git a/parsley-cats/shared/src/test/scala/parsley/cats/CatsSuite.scala b/parsley-cats/shared/src/test/scala/parsley/cats/CatsSuite.scala index 17d2702..7efd77c 100644 --- a/parsley-cats/shared/src/test/scala/parsley/cats/CatsSuite.scala +++ b/parsley-cats/shared/src/test/scala/parsley/cats/CatsSuite.scala @@ -1,3 +1,8 @@ +/* + * Copyright 2022 Parsley-Cats Contributors + * + * SPDX-License-Identifier: BSD-3-Clause + */ package parsley.cats import org.scalatest.flatspec.AnyFlatSpec diff --git a/parsley-cats/shared/src/test/scala/parsley/cats/CombinatorTests.scala b/parsley-cats/shared/src/test/scala/parsley/cats/CombinatorTests.scala index d2a3995..ebff00b 100644 --- a/parsley-cats/shared/src/test/scala/parsley/cats/CombinatorTests.scala +++ b/parsley-cats/shared/src/test/scala/parsley/cats/CombinatorTests.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2023 Parsley Contributors +/* + * Copyright 2022 Parsley-Cats Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats @@ -6,7 +8,7 @@ package parsley.cats import Predef.{ArrowAssoc => _} import parsley.{ParsleyTest, Success, Failure} -import parsley.implicits.character.{charLift, stringLift} +import parsley.syntax.character.{charLift, stringLift} import parsley.cats.combinator._ import cats.data.NonEmptyList diff --git a/project/build.properties b/project/build.properties index 46e43a9..abbbce5 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.8.2 +sbt.version=1.9.8 diff --git a/project/plugins.sbt b/project/plugins.sbt index 8ec63cf..1d89b12 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,23 +1,16 @@ -val sbtTypelevelVersion = "0.4.19" +val sbtTypelevelVersion = "0.6.5" libraryDependencySchemes ++= Seq( "org.scala-native" % "sbt-scala-native" % VersionScheme.Always, "org.scala-lang.modules" %% "scala-xml" % VersionScheme.Always, ) -//addSbtPlugin("org.typelevel" % "sbt-typelevel" % sbtTypelevelVersion) // disabled because I don't want headers and formatting checks -addSbtPlugin("org.typelevel" % "sbt-typelevel-settings" % sbtTypelevelVersion) -addSbtPlugin("org.typelevel" % "sbt-typelevel-ci-release" % sbtTypelevelVersion) +addSbtPlugin("org.typelevel" % "sbt-typelevel" % sbtTypelevelVersion) -// Cross Project Setup -addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.2.0") -addSbtPlugin("org.portable-scala" % "sbt-scala-native-crossproject" % "1.2.0") -addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.11.0") -addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.8") +addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.13.2") +addSbtPlugin("org.scala-native" % "sbt-scala-native" % "0.4.15") -// Other -// This is here purely to enable the niceness settings -addSbtPlugin("ch.epfl.scala" % "sbt-bloop" % "1.4.8") addSbtPlugin("com.beautiful-scala" % "sbt-scalastyle" % "1.5.1") -addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.5") +addSbtPlugin("org.jmotor.sbt" % "sbt-dependency-updates" % "1.2.7") +addSbtPlugin("org.scoverage" % "sbt-scoverage" % "2.0.9") addSbtPlugin("com.timushev.sbt" % "sbt-rewarn" % "0.1.3") diff --git a/scalastyle-config.xml b/scalastyle-config.xml index c7d339d..45aed07 100644 --- a/scalastyle-config.xml +++ b/scalastyle-config.xml @@ -12,15 +12,6 @@ - - - true - - \* SPDX-License-Identifier: BSD-3-Clause - \*/]]> - - Each file must have a copyright notice that references the date of the file's creation, acknowledges the contributors, and declares the license. - @@ -101,7 +92,6 @@ java,scala,cats,parsley,parsley.internal,others javax?\..+ scala\..+ - cats\..+ parsley\.(?!internal).+ parsley\.internal\..+ .+