Skip to content

Commit

Permalink
Migrate to Scala 3 (#349)
Browse files Browse the repository at this point in the history
* WIP: scala 3

* Pass tests

* disable mima

* Fix extension

* fix tests

* scalafmt and so on

* unused

* Use LTS in plugin module

* lint

* simplify

* recover uuid, fix imports

* oops

* magic trick

* just binary is fine

* lol
  • Loading branch information
kubukoz authored Oct 29, 2024
1 parent 6775bea commit b98ad60
Show file tree
Hide file tree
Showing 58 changed files with 553 additions and 305 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ jobs:
build:
name: "Build"
runs-on: ubuntu-20.04
timeout-minutes: 30
timeout-minutes: 10
steps:

- uses: actions/checkout@v4.1.1
Expand Down
12 changes: 10 additions & 2 deletions .scalafmt.conf
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
runner.dialect=scala213source3
version = 3.7.2
version = 3.8.3

runner.dialect=scala3
runner.dialectOverride.allowSignificantIndentation = false
runner.dialectOverride.allowQuietSyntax = true

maxColumn = 100
align.preset = some

Expand All @@ -17,6 +21,10 @@ assumeStandardLibraryStripMargin = true

trailingCommas = "multiple"

project {
git = true
}

rewrite.rules = [
RedundantBraces,
RedundantParens,
Expand Down
45 changes: 33 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,12 @@ inThisBuild(
)
)

val ScalaLTS = "3.3.4"
val ScalaNext = "3.5.2"

ThisBuild / scalaVersion := ScalaNext
ThisBuild / versionScheme := Some("early-semver")

import scala.sys.process.*

def crossPlugin(
Expand All @@ -30,13 +36,6 @@ val compilerPlugins =
crossPlugin("org.typelevel" % "kind-projector" % "0.13.3")
))

ThisBuild / versionScheme := Some("early-semver")

Global / onChangedBuildSource := ReloadOnSourceChanges

ThisBuild / scalaVersion := "2.13.15"
ThisBuild / crossScalaVersions := Seq("2.13.15")

// For coursier's "latest.integration"
ThisBuild / dynverSeparator := "-"

Expand All @@ -54,8 +53,25 @@ val commonSettings = Seq(
compilerPlugins,
scalacOptions -= "-Xfatal-warnings",
scalacOptions -= "-Vtype-diffs",
scalacOptions += "-Wnonunit-statement",
scalacOptions ++= Seq("-Xsource:3.0"),
scalacOptions -= "-language:existentials",
// https://github.com/lampepfl/dotty/issues/18674
Test / scalacOptions -= "-Wunused:implicits",
Test / scalacOptions -= "-Wunused:explicits",
Test / scalacOptions -= "-Wunused:imports",
Test / scalacOptions -= "-Wunused:locals",
Test / scalacOptions -= "-Wunused:params",
Test / scalacOptions -= "-Wunused:privates",
//
scalacOptions += "-no-indent",
scalacOptions ++= {
if (scalaVersion.value.startsWith("3.5"))
Seq(
// for cats-tagless macros
"-experimental"
)
else
Nil
},
Test / scalacOptions += "-Wconf:cat=deprecation:silent,msg=Specify both message and version:silent",
scalacOptions ++= Seq("-release", "11"),
mimaFailOnNoPrevious := false,
Expand All @@ -73,8 +89,9 @@ lazy val pluginCore = module("plugin-core").settings(
libraryDependencies ++= Seq(
"com.disneystreaming.smithy4s" %% "smithy4s-http4s" % smithy4sVersion.value
),
// mimaPreviousArtifacts := Set(organization.value %% name.value % "0.3.0"),
// mimaPreviousArtifacts := Set(organization.value %% name.value % "0.7.0"),
mimaPreviousArtifacts := Set.empty,
scalaVersion := ScalaLTS,
)

lazy val pluginSample = module("plugin-sample")
Expand Down Expand Up @@ -133,6 +150,7 @@ lazy val core = module("core")
"com.disneystreaming.alloy" % "alloy-core" % "0.3.14" % Test,
"software.amazon.smithy" % "smithy-aws-traits" % "1.52.1" % Test,
),
// todo: move this to a separate module like "examples"
Smithy4sCodegenPlugin.defaultSettings(Test),
)
.enablePlugins(Smithy4sCodegenPlugin)
Expand All @@ -156,8 +174,11 @@ lazy val lsp = module("lsp")
"io.circe" %% "circe-core" % "0.14.10",
"org.http4s" %% "http4s-ember-client" % "0.23.29",
"org.http4s" %% "http4s-ember-server" % "0.23.29" % Test,
"io.get-coursier" %% "coursier" % "2.1.14",
"org.typelevel" %% "cats-tagless-macros" % "0.16.2",
("io.get-coursier" % "coursier" % "2.1.14")
.cross(CrossVersion.for3Use2_13)
.exclude("org.scala-lang.modules", "scala-collection-compat_2.13")
.exclude("com.github.plokhotnyuk.jsoniter-scala", "jsoniter-scala-core_2.13"),
"org.typelevel" %% "cats-tagless-core" % "0.16.2",
),
buildInfoPackage := "playground.lsp.buildinfo",
buildInfoKeys ++= Seq(version, scalaBinaryVersion),
Expand Down
5 changes: 2 additions & 3 deletions modules/ast/src/main/scala/playground/smithyql/AST.scala
Original file line number Diff line number Diff line change
Expand Up @@ -166,8 +166,7 @@ object QualifiedIdentifier {

implicit val show: Show[QualifiedIdentifier] = Show.fromToString

implicit val ord: Order[QualifiedIdentifier] = Order.by(unapply(_).get)

implicit val ord: Order[QualifiedIdentifier] = Order.by(Tuple.fromProductTyped)
}

// the keywords of the clause are captured in the Prelude's useClauses list.
Expand Down Expand Up @@ -240,7 +239,7 @@ final case class Binding[F[_]](

final case class Identifier(
text: String
) extends AnyVal
)

object Struct {

Expand Down
4 changes: 2 additions & 2 deletions modules/ast/src/main/scala/playground/smithyql/DSL.scala
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ import cats.syntax.all.*
object DSL {

implicit class StringDSLOps(
val s: String
private val s: String
) extends AnyVal {

def call(
Expand All @@ -16,7 +16,7 @@ object DSL {
)*
): Query[Id] = Query[Id](
operationName = QueryOperationName[Id](None, OperationName(s)),
input = struct(args: _*),
input = struct(args*),
)

}
Expand Down
4 changes: 2 additions & 2 deletions modules/core/src/main/scala/playground/CompilationError.scala
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ sealed trait CompilationErrorDetails extends Product with Serializable {
s"""Matching enums by value is deprecated and may be removed in the future. Use $enumName instead.""".stripMargin
case DuplicateItem => "Duplicate item - some entries will be dropped to fit in a set shape."
case AmbiguousService(workspaceServices) =>
s"""Couldn't determine service for this operation. Add a use clause, or use an explicit reference to specify the service you want to use.
|Available services:""".stripMargin + workspaceServices
"""Couldn't determine service for this operation. Add a use clause, or use an explicit reference to specify the service you want to use.
|Available services:""".stripMargin + workspaceServices
.sorted
.map(UseClause[Id](_).mapK(WithSource.liftId))
.map(Formatter.useClauseFormatter.format(_, Int.MaxValue))
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,6 @@ class DynamicServiceProxy[Alg[_[_, _, _, _, _]], Op[_, _, _, _, _]](
): FunctorInterpreter[Op, F] = {
val grp = serviceStatic.endpoints.groupBy(_.id).fmap(_.head)

type Proxy[I, E, O, SE, EO] = I => F[O]

def makeProxy[A, B](
schemaIn: Schema[A],
schemaOut: Schema[B],
Expand All @@ -39,7 +37,7 @@ class DynamicServiceProxy[Alg[_[_, _, _, _, _]], Op[_, _, _, _, _]](
}

val endpointMapping =
new smithy4s.kinds.PolyFunction5[Endpoint[Op, *, *, *, *, *], Proxy] {
new service.FunctorEndpointCompiler[F] {
private val trans = serviceStatic.toPolyFunction(interp)

private def applyWithStatic[I, E, O, SI, SO, STI, STE, STO, STSI, STSO](
Expand Down
1 change: 0 additions & 1 deletion modules/core/src/main/scala/playground/FileCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ package playground
import cats.Parallel
import cats.syntax.all.*
import cats.~>
import playground.*
import playground.smithyql.SourceFile
import playground.smithyql.WithSource

Expand Down
1 change: 0 additions & 1 deletion modules/core/src/main/scala/playground/FileRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package playground

import cats.data.NonEmptyList
import cats.syntax.all.*
import playground.*
import playground.smithyql.SourceFile
import playground.smithyql.SourceRange
import playground.smithyql.WithSource
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ object NodeEncoderVisitor extends SchemaVisitor[NodeEncoder] { self =>
def struct[S](
shapeId: ShapeId,
hints: Hints,
fieldsRaw: Vector[Field[S, _]],
fieldsRaw: Vector[Field[S, ?]],
make: IndexedSeq[Any] => S,
): NodeEncoder[S] = {

Expand All @@ -192,7 +192,7 @@ object NodeEncoderVisitor extends SchemaVisitor[NodeEncoder] { self =>
def union[U](
shapeId: ShapeId,
hints: Hints,
alternatives: Vector[Alt[U, _]],
alternatives: Vector[Alt[U, ?]],
dispatcher: Alt.Dispatcher[U],
): NodeEncoder[U] = dispatcher.compile(new Alt.Precompiler[NodeEncoder] {

Expand Down
24 changes: 15 additions & 9 deletions modules/core/src/main/scala/playground/OperationCompiler.scala
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,7 @@ import playground.smithyql.Query
import playground.smithyql.WithSource
import smithy.api
import smithy4s.Endpoint
import smithy4s.Hints
import smithy4s.Service
import smithy4s.dynamic.DynamicSchemaIndex
import smithyql.syntax.*
Expand All @@ -22,12 +23,15 @@ import util.chaining.*

trait CompiledInput {
type _Op[_, _, _, _, _]
type I
type E
type O
type SI
type SO
def catchError: Throwable => Option[E]
def writeError: Option[NodeEncoder[E]]
def writeOutput: NodeEncoder[O]
def op: _Op[_, E, O, _, _]
def op: _Op[I, E, O, SI, SO]
}

object CompiledInput {
Expand Down Expand Up @@ -149,8 +153,8 @@ private class ServiceCompiler[Alg[_[_, _, _, _, _]]](
service: Service[Alg]
) extends OperationCompiler[IorNel[CompilationError, *]] {

private def compileEndpoint[In, Err, Out](
e: Endpoint[service.Operation, In, Err, Out, _, _]
private def compileEndpoint[In, Err, Out, SIn, SOut](
e: Endpoint[service.Operation, In, Err, Out, SIn, SOut]
): QueryCompiler[CompiledInput] = {
val inputCompiler = e.input.compile(QueryCompilerVisitor.full)
val outputEncoder = NodeEncoder.derive(e.output)
Expand All @@ -162,10 +166,13 @@ private class ServiceCompiler[Alg[_[_, _, _, _, _]]](
.map { compiled =>
new CompiledInput {
type _Op[_I, _E, _O, _SE, _SO] = service.Operation[_I, _E, _O, _SE, _SO]
type I = In
type E = Err
type O = Out
type SI = SIn
type SO = SOut

val op: _Op[_, Err, Out, _, _] = e.wrap(compiled)
val op: _Op[I, E, O, SI, SO] = e.wrap(compiled)
val writeOutput: NodeEncoder[Out] = outputEncoder
val writeError: Option[NodeEncoder[Err]] = errorEncoder
val catchError: Throwable => Option[Err] = e.Error.unapply(_).map(_._2)
Expand All @@ -174,12 +181,12 @@ private class ServiceCompiler[Alg[_[_, _, _, _, _]]](
}

// https://github.com/kubukoz/smithy-playground/issues/154
// map of endpoint names to (endpoint, input compiler)
// map of endpoint names to (endpoint hints, input compiler)
private val endpoints = service
.endpoints
.toList
.groupByNel(_.name)
.map(_.map(_.head).map(e => (e, compileEndpoint(e))))
.map(_.map(_.head).map(e => (e.hints, compileEndpoint(e))))

// Checks the explicit service reference (if any).
// Note that the reference should be valid thanks to MultiServiceResolver's checks.
Expand All @@ -201,10 +208,9 @@ private class ServiceCompiler[Alg[_[_, _, _, _, _]]](

private def deprecatedOperationCheck(
q: Query[WithSource],
endpoint: Endpoint[service.Operation, _, _, _, _, _],
endpointHints: Hints,
): IorNel[CompilationError, Unit] =
endpoint
.hints
endpointHints
.get(api.Deprecated)
.map { info =>
CompilationError.deprecation(
Expand Down
5 changes: 2 additions & 3 deletions modules/core/src/main/scala/playground/OperationRunner.scala
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,6 @@ import cats.syntax.all.*
import fs2.compression.Compression
import org.http4s.Uri
import org.http4s.client.Client
import playground.*
import playground.plugins.PlaygroundPlugin
import playground.plugins.SimpleHttpBuilder
import playground.smithyql.InputNode
Expand Down Expand Up @@ -157,7 +156,7 @@ object OperationRunner {

def forServices[F[_]: StdlibRuntime: Async: Compression: std.Console](
services: List[DynamicSchemaIndex.ServiceWrapper],
getSchema: ShapeId => Option[Schema[_]],
getSchema: ShapeId => Option[Schema[?]],
client: Client[F],
baseUri: F[Uri],
awsEnv: Resource[F, AwsEnvironment[F]],
Expand Down Expand Up @@ -204,7 +203,7 @@ object OperationRunner {
client: Client[F],
baseUri: F[Uri],
awsEnv: Resource[F, AwsEnvironment[F]],
schemaIndex: ShapeId => Option[Schema[_]],
schemaIndex: ShapeId => Option[Schema[?]],
plugins: List[PlaygroundPlugin],
): Resolver[F] =
new Resolver[F] {
Expand Down
5 changes: 3 additions & 2 deletions modules/core/src/main/scala/playground/PlaygroundConfig.scala
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ package playground

import cats.kernel.Eq
import cats.syntax.all.*
import com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec
import com.github.plokhotnyuk.jsoniter_scala.macros.JsonCodecMaker

final case class PlaygroundConfig(
Expand Down Expand Up @@ -47,7 +46,9 @@ object PlaygroundConfig {
}

object BuildConfig {
implicit val c: JsonValueCodec[BuildConfig] = JsonCodecMaker.make
// note: this is flagged as an unused import if imported
implicit val c: com.github.plokhotnyuk.jsoniter_scala.core.JsonValueCodec[BuildConfig] =
JsonCodecMaker.make

def fromPlaygroundConfig(
c: PlaygroundConfig
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -219,7 +219,7 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
private object FieldCompiler {

def compile[A](
field: Field[_, A]
field: Field[?, A]
): FieldCompiler[A] =
new FieldCompiler[A] {
override val compiler: QueryCompiler[A] = field.schema.compile(QueryCompilerVisitorInternal)
Expand All @@ -233,7 +233,7 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
def struct[S](
shapeId: ShapeId,
hints: Hints,
fieldsRaw: Vector[Field[S, _]],
fieldsRaw: Vector[Field[S, ?]],
make: IndexedSeq[Any] => S,
): QueryCompiler[S] = {
val fields = fieldsRaw
Expand Down Expand Up @@ -318,7 +318,7 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
def union[U](
shapeId: ShapeId,
hints: Hints,
alternatives: Vector[Alt[U, _]],
alternatives: Vector[Alt[U, ?]],
dispatcher: Alt.Dispatcher[U],
): QueryCompiler[U] = {
def handleAlt[A](
Expand Down Expand Up @@ -445,7 +445,7 @@ object QueryCompilerVisitorInternal extends SchemaVisitor[QueryCompiler] {
.parTraverse { binding =>
document.compile(binding.value).tupleLeft(binding.identifier.value.text)
}
.map(Document.obj(_: _*))
.map(Document.obj(_*))
case NullLiteral() => Document.nullDoc.rightIor
}

Expand Down
Loading

0 comments on commit b98ad60

Please sign in to comment.