Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

surface (breaking): Fixes #3462 Deprecate unstable Reflect/TastySurfaceFactory for Scala 3 #3464

Merged
merged 2 commits into from
Mar 21, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -12,11 +12,10 @@
* limitations under the License.
*/
package wvlet.airframe.codec
import wvlet.airframe.surface.Surface
import wvlet.airframe.surface.reflect.ReflectSurfaceFactory
import wvlet.airframe.surface.{AnyRefSurface, Surface}

trait CompatBase:
inline def codecOf[A]: MessageCodec[A] =
MessageCodecFactory.defaultFactory.of[A]
// TODO Remove this method usage as runtime-reflection in Scala 3 is unstable and slow
def surfaceOfClass(cl: Class[?]): Surface = ReflectSurfaceFactory.ofClass(cl)

def surfaceOfClass(cl: Class[?]): Surface = AnyRefSurface
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ object HttpCodeGenerator extends LogSupport {
}

def generate(config: HttpClientGeneratorConfig, cl: ClassLoader): String = {
val router = RouteScanner.buildRouter(Seq(config.apiPackageName), cl)
val router = RouteScanner.buildRxRouter(Seq(config.apiPackageName), cl)
val code = generate(router, config)
code
}
Expand Down Expand Up @@ -201,11 +201,9 @@ class HttpCodeGenerator(
debug(s"Target API packages: ${apiPackageNames.mkString(", ")}")
val rxRouter = RouteScanner.buildRxRouter(apiPackageNames, classLoader)
if (rxRouter.routes.isEmpty) {
warn(s"Scanning classes implementing @RPC or @Endpoint from the classpath...")
RouteScanner.buildRouter(apiPackageNames, classLoader)
} else {
Router.fromRxRouter(rxRouter)
warn(s"No router definition is found. Forgot to implement RxRouterProvider interface?")
}
Router.fromRxRouter(rxRouter)
}

@command(description = "Generate HTTP client code using a JSON configuration file")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,9 @@
* limitations under the License.
*/
package wvlet.airframe.http.codegen
import wvlet.airframe.http.{Endpoint, RPC, Router, RxRouter, RxRouterProvider}
import wvlet.airframe.surface.{Surface, TypeName}
import wvlet.airframe.http.*
import wvlet.airframe.surface.reflect.ReflectTypeUtil
import wvlet.airframe.surface.{Surface, TypeName}
import wvlet.log.LogSupport

import scala.util.{Success, Try}
Expand Down Expand Up @@ -84,48 +84,12 @@ object RouteScanner extends LogSupport {
*/
@deprecated("Use buildRxRouter instead", since = "23.5.0")
def buildRouter(targetPackages: Seq[String], classLoader: ClassLoader): Router = {
trace(s"buildRouter: ${targetPackages}")

// We need to use our own class loader as sbt's layered classloader cannot find application classes
withClassLoader(classLoader) {
val lst = ClassScanner.scanClasses(classLoader, targetPackages)
trace(s"classes: ${lst.mkString(", ")}")
val classes = Seq.newBuilder[Class[_]]
lst.foreach { x =>
Try(classLoader.loadClass(x)) match {
case Success(cl) => classes += cl
case _ =>
}
}
buildRouter(classes.result())
}
throw new UnsupportedOperationException("Use buildRxRouter instead")
}

@deprecated("Use buildRxRouter instead", since = "23.5.0")
private[codegen] def buildRouter(classes: Seq[Class[_]]): Router = {
var router = Router.empty
// Find classes with @RPC or @Endpoint annotations.
//
// Note: We need to remove object classes ending with $, because Surface.fullTypeNameOf(...)
// will not distinguish regular classes and their corresponding objects.
// This is because we generally cannot call classOf[MyObj$] in Scala other than scanning classes directly from class loaders.
for (cl <- classes if !cl.getName.endsWith("$")) {
trace(f"Searching ${cl} for HTTP endpoints")
import wvlet.airframe.surface.reflect.*
lazy val s = ReflectSurfaceFactory.ofClass(cl)
lazy val methods = ReflectSurfaceFactory.methodsOfClass(cl)
val hasRPC = findDeclaredAnnotation[RPC](cl).isDefined
if (hasRPC) {
debug(s"Found an Airframe RPC interface: ${s.fullName}")
router = router.addInternal(s, methods)
} else if (methods.exists(m => m.findAnnotationOf[Endpoint].isDefined)) {
debug(s"Found an Airframe HTTP interface: ${s.fullName}")
router = router.addInternal(s, methods)
}
}
// Check whether the route is valid or not
router.verifyRoutes
router
throw new UnsupportedOperationException("Use buildRxRouter instead")
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,6 @@ package wvlet.airframe.launcher

import wvlet.airframe.control.CommandLineTokenizer
import wvlet.airframe.launcher.Launcher.newCommandLauncher
import wvlet.airframe.surface.reflect.ReflectSurfaceFactory
import wvlet.airframe.surface.Surface

trait LauncherCompat:
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@ import wvlet.airframe.codec.{MessageCodecFactory, MessageContext, ParamListCodec
import wvlet.airframe.control.CommandLineTokenizer
import wvlet.airframe.launcher.OptionParser.CLOption
import wvlet.airframe.msgpack.spi.MessagePack
import wvlet.airframe.surface.reflect.ReflectSurfaceFactory
import wvlet.airframe.surface.{CName, MethodSurface, Surface}
import wvlet.log.LogSupport

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ package wvlet.airframe.launcher
import wvlet.airframe.control.CommandLineTokenizer
import wvlet.airframe.launcher.StringTree.{Leaf, SeqLeaf}
import wvlet.airframe.surface.*
import wvlet.airframe.surface.reflect.{GenericBuilder, ObjectBuilder, Path, ReflectSurfaceFactory}
import wvlet.airframe.surface.reflect.{GenericBuilder, ObjectBuilder, Path}
import wvlet.log.{LogSupport, Logger}

import scala.collection.mutable.ArrayBuffer
Expand Down

This file was deleted.

This file was deleted.

This file was deleted.

13 changes: 2 additions & 11 deletions airspec/build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -130,7 +130,8 @@ def excludePomDependency(excludes: Seq[String]) = { node: XmlNode =>
}).transform(node).head
}

/** AirSpec build definitions.
/**
* AirSpec build definitions.
*
* To make AirSpec a standalone library without any cyclic project references, AirSpec embeds the source code of
* airframe-log, di, surface, etc.
Expand Down Expand Up @@ -249,16 +250,6 @@ lazy val airspecCore =
)
.jvmSettings(
airspecJVMBuildSettings,
libraryDependencies ++= {
scalaVersion.value match {
case s if s.startsWith("3.") =>
Seq(
"org.scala-lang" %% "scala3-tasty-inspector" % s,
"org.scala-lang" %% "scala3-staging" % s
)
case _ => Seq.empty
}
},
Compile / packageBin / mappings ++= (airspecLog.jvm / Compile / packageBin / mappings).value,
Compile / packageSrc / mappings ++= (airspecLog.js / Compile / packageSrc / mappings).value
)
Expand Down
12 changes: 0 additions & 12 deletions build.sbt
Original file line number Diff line number Diff line change
Expand Up @@ -451,17 +451,6 @@ val surfaceDependencies = { scalaVersion: String =>
}
}

val surfaceJVMDependencies = { scalaVersion: String =>
scalaVersion match {
case s if s.startsWith("3.") =>
Seq(
"org.scala-lang" %% "scala3-tasty-inspector" % s,
"org.scala-lang" %% "scala3-staging" % s
)
case _ => Seq.empty
}
}

lazy val surface =
crossProject(JVMPlatform, JSPlatform)
.crossType(CrossType.Pure)
Expand All @@ -476,7 +465,6 @@ lazy val surface =
)
.jvmSettings(
// For adding PreDestroy, PostConstruct annotations to Java9
libraryDependencies ++= surfaceJVMDependencies(scalaVersion.value),
libraryDependencies += "javax.annotation" % "javax.annotation-api" % JAVAX_ANNOTATION_API_VERSION % Test
)
.jsSettings(jsBuildSettings)
Expand Down
Loading