diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index cd4ea9f..e667018 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 - if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v2 - with: - distribution: temurin - java-version: 8 - - name: Setup Java (temurin@8) + id: setup-java-temurin-8 if: matrix.java == 'temurin@8' uses: actions/setup-java@v3 with: - distribution: jdkfile + distribution: temurin java-version: 8 - jdkFile: ${{ steps.download-java-temurin-8.outputs.jdkFile }} + cache: sbt - - name: Download Java (temurin@11) - id: download-java-temurin-11 - if: matrix.java == 'temurin@11' - uses: typelevel/download-java@v2 - with: - distribution: temurin - java-version: 11 + - 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@v3 with: - distribution: jdkfile + distribution: temurin java-version: 11 - jdkFile: ${{ steps.download-java-temurin-11.outputs.jdkFile }} + cache: sbt - - 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 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 @@ -131,11 +123,11 @@ jobs: - 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 + 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 + 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') @@ -151,175 +143,222 @@ jobs: 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 - if: matrix.java == 'temurin@8' - uses: typelevel/download-java@v2 - with: - distribution: temurin - java-version: 8 - - name: Setup Java (temurin@8) + id: setup-java-temurin-8 if: matrix.java == 'temurin@8' uses: actions/setup-java@v3 with: - distribution: jdkfile + distribution: temurin java-version: 8 - jdkFile: ${{ steps.download-java-temurin-8.outputs.jdkFile }} + cache: sbt - - name: Download Java (temurin@11) - id: download-java-temurin-11 - if: matrix.java == 'temurin@11' - uses: typelevel/download-java@v2 - with: - distribution: temurin - java-version: 11 + - 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@v3 with: - distribution: jdkfile + distribution: temurin java-version: 11 - jdkFile: ${{ steps.download-java-temurin-11.outputs.jdkFile }} + cache: sbt - - 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 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: Download target directories (2.13.10, rootJS) + - name: sbt update + if: matrix.java == 'temurin@17' && steps.setup-java-temurin-17.outputs.cache-hit == 'false' + run: sbt +update + + - name: Download target directories (2.13, 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) + - name: Download target directories (2.13, rootJVM) uses: actions/download-artifact@v3 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) + - name: Download target directories (2.13, rootNative) uses: actions/download-artifact@v3 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) + - name: Download target directories (2.12, rootJS) uses: actions/download-artifact@v3 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) + - name: Download target directories (2.12, rootJVM) uses: actions/download-artifact@v3 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) + - name: Download target directories (2.12, rootNative) uses: actions/download-artifact@v3 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) + - name: Download target directories (3, rootJS) uses: actions/download-artifact@v3 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) + - name: Download target directories (3, rootJVM) uses: actions/download-artifact@v3 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) + - name: Download target directories (3, rootNative) uses: actions/download-artifact@v3 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 == '' + env: + PGP_SECRET: ${{ secrets.PGP_SECRET }} + PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }} run: echo $PGP_SECRET | base64 -di | 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_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@v3 + 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@v3 + 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@v3 + 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..229cb3c 100644 --- a/build.sbt +++ b/build.sbt @@ -2,15 +2,24 @@ 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.0" +val Java8 = JavaSpec.temurin("8") +val JavaLTS = JavaSpec.temurin("11") +val JavaLatest = JavaSpec.temurin("17") + +val mainBranch = "master" Global / onChangedBuildSource := ReloadOnSourceChanges +val releaseFlags = Seq("-Xdisable-assertions", "-opt:l:method,inline", "-opt-inline-from", "parsley.**", "-opt-warnings:at-inline-failed") +val noReleaseFlagsScala3 = true // maybe some day this can be turned off... + inThisBuild(List( - tlBaseVersion := "1.2", + tlBaseVersion := "1.3", organization := "com.github.j-mie6", + organizationName := "Parsley 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")), @@ -30,9 +39,11 @@ inThisBuild(List( ProblemFilters.exclude[MissingClassProblem]("parsley.MonoidKForParsley"), ), // CI Configuration - tlCiReleaseBranches := Seq("master"), + tlCiReleaseBranches := Seq(mainBranch), tlSonatypeUseLegacyHost := false, - githubWorkflowJavaVersions := Seq(JavaSpec.temurin("8"), JavaSpec.temurin("11"), JavaSpec.temurin("17")), + tlCiScalafmtCheck := false, + tlCiHeaderCheck := true, + githubWorkflowJavaVersions := Seq(Java8, JavaLTS, JavaLatest), )) lazy val root = tlCrossRootProject.aggregate(`parsley-cats`) @@ -43,13 +54,24 @@ lazy val `parsley-cats` = crossProject(JVMPlatform, JSPlatform, NativePlatform) .in(file("parsley-cats")) .settings( name := projectName, + + headerLicenseStyle := HeaderLicenseStyle.SpdxSyntax, + headerEmptyLine := false, + libraryDependencies ++= Seq( "org.typelevel" %%% "cats-core" % "2.8.0", "com.github.j-mie6" %%% "parsley" % "4.0.0", - "org.scalatest" %%% "scalatest" % "3.2.12" % Test, + "org.scalatest" %%% "scalatest" % "3.2.17" % Test, "org.typelevel" %%% "cats-laws" % "2.8.0" % Test, ), + + Test / testOptions += Tests.Argument(TestFrameworks.ScalaTest, "-oI"), + + scalacOptions ++= { + if (!isSnapshot.value && !(noReleaseFlagsScala3 && scalaBinaryVersion.value == "3")) releaseFlags else Seq.empty + }, ) .jsSettings( - Test / scalaJSLinkerConfig := scalaJSLinkerConfig.value.withESFeatures(_.withESVersion(ESVersion.ES2018)) + // this is required until we bump to a higher parsley major/minor (the regex is still in 4.0.0) + Test / scalaJSLinkerConfig := scalaJSLinkerConfig.value.withESFeatures(_.withESVersion(ESVersion.ES2018)) ) 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..b3ac671 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 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..d4e585d 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 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..a3d4997 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 Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats 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..fe8594c 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 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..1f87bc1 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 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..1cc8deb 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 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..4d4fd7b 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/MonadForParsley.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/MonadForParsley.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2022 Parsley Cats Contributors +/* + * Copyright 2022 Parsley Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats 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..d8be602 100644 --- a/parsley-cats/shared/src/main/scala/parsley/cats/combinator.scala +++ b/parsley-cats/shared/src/main/scala/parsley/cats/combinator.scala @@ -1,4 +1,6 @@ -/* SPDX-FileCopyrightText: © 2023 Parsley Cats Contributors +/* + * Copyright 2022 Parsley Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats @@ -127,7 +129,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..3d0e49a 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 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..11b6aff 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 Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley diff --git a/parsley-cats/shared/src/main/scala/parsley/token/cats.scala b/parsley-cats/shared/src/main/scala/parsley/token/cats.scala new file mode 100644 index 0000000..96fcf4c --- /dev/null +++ b/parsley-cats/shared/src/main/scala/parsley/token/cats.scala @@ -0,0 +1,72 @@ +/* + * Copyright 2022 Parsley Contributors + * + * SPDX-License-Identifier: BSD-3-Clause + */ +package parsley.token + +import parsley.Parsley +import parsley.cats.combinator.sepBy1 + +import _root_.cats.data.NonEmptyList + +object cats { + implicit class LexerNonEmpty(val lexer: Lexer) { + object cats { + object lexeme { + object separators { + /** This combinator parses '''one''' or more occurrences of `p`, separated by semi-colons. + * + * First parses a `p`. Then parses a semi-colon followed by `p` until there are no more semi-colons. + * The results of the `p`'s, `x,,1,,` through `x,,n,,`, are returned as `NonEmptyList(x,,1,,, .., x,,n,,)`. + * If `p` fails having consumed input, the whole parser fails. Requires at least + * one `p` to have been parsed. + * + * @example {{{ + * scala> ... + * scala> val stmts = lexer.lexeme.separators.semiSep1(int) + * scala> stmts.parse("7; 3;2") + * val res0 = Success(NonEmptyList(7; 3; 2)) + * scala> stmts.parse("") + * val res1 = Failure(..) + * scala> stmts.parse("1") + * val res2 = Success(NonEmptyList(1)) + * scala> stmts.parse("1; 2; ") + * val res3 = Failure(..) // no trailing semi-colon allowed + * }}} + * + * @param p the parser whose results are collected into a list. + * @return a parser that parses `p` delimited by semi-colons, returning the list of `p`'s results. + * @since 1.3.0 + */ + def semiSep1[A](p: Parsley[A]): Parsley[NonEmptyList[A]] = sepBy1(p, lexer.lexeme.symbol.semi) + /** This combinator parses '''one''' or more occurrences of `p`, separated by commas. + * + * First parses a `p`. Then parses a comma followed by `p` until there are no more commas. + * The results of the `p`'s, `x,,1,,` through `x,,n,,`, are returned as `NonEmptyList(x,,1,,, .., x,,n,,)`. + * If `p` fails having consumed input, the whole parser fails. Requires at least + * one `p` to have been parsed. + * + * @example {{{ + * scala> ... + * scala> val stmts = lexer.lexeme.separators.commaSep1(int) + * scala> stmts.parse("7, 3,2") + * val res0 = Success(NonEmptyList(7, 3, 2)) + * scala> stmts.parse("") + * val res1 = Failure(..) + * scala> stmts.parse("1") + * val res2 = Success(NonEmptyList(1)) + * scala> stmts.parse("1, 2, ") + * val res3 = Failure(..) // no trailing comma allowed + * }}} + * + * @param p the parser whose results are collected into a list. + * @return a parser that parses `p` delimited by commas, returning the list of `p`'s results. + * @since 1.3.0 + */ + def commaSep1[A](p: Parsley[A]): Parsley[NonEmptyList[A]] = sepBy1(p, lexer.lexeme.symbol.comma) + } + } + } + } +} diff --git a/parsley-cats/shared/src/test/scala/parsley/ParsleyTest.scala b/parsley-cats/shared/src/test/scala/parsley/ParsleyTest.scala index 6a18f97..e652e7a 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 Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley @@ -8,7 +10,6 @@ import org.scalatest.flatspec.AnyFlatSpec import org.scalatest.matchers.should.Matchers import parsley.combinator.eof -import parsley.Result 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..4d91ac3 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 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..6885ce0 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 Contributors + * * SPDX-License-Identifier: BSD-3-Clause */ package parsley.cats diff --git a/project/build.properties b/project/build.properties index 46e43a9..2743082 100644 --- a/project/build.properties +++ b/project/build.properties @@ -1 +1 @@ -sbt.version=1.8.2 +sbt.version=1.9.6 diff --git a/project/plugins.sbt b/project/plugins.sbt index 8ec63cf..0b0e38e 100644 --- a/project/plugins.sbt +++ b/project/plugins.sbt @@ -1,23 +1,18 @@ -val sbtTypelevelVersion = "0.4.19" +val sbtTypelevelVersion = "0.5.3" 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.8") addSbtPlugin("com.timushev.sbt" % "sbt-rewarn" % "0.1.3")