Port Navigator to Scala 2.13 (#8847)

changelog_begin
changelog_end
This commit is contained in:
Moritz Kiefer 2021-02-15 15:55:36 +01:00 committed by GitHub
parent 9cd3909c31
commit 91b185dcc3
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
24 changed files with 200 additions and 151 deletions

View File

@ -184,6 +184,7 @@ jobs:
//ledger-service/... \ //ledger-service/... \
//triggers/... \ //triggers/... \
//daml-script/... \ //daml-script/... \
//navigator/... \
-//ledger/ledger-api-test-tool/... \ -//ledger/ledger-api-test-tool/... \
-//ledger/ledger-api-test-tool-on-canton/... -//ledger/ledger-api-test-tool-on-canton/...
# gatling-utils tests fail with a ClassNotFoundException for scala.collection.SeqLike # gatling-utils tests fail with a ClassNotFoundException for scala.collection.SeqLike
@ -196,6 +197,7 @@ jobs:
//ledger-service/... \ //ledger-service/... \
//daml-script/... \ //daml-script/... \
//triggers/... \ //triggers/... \
//navigator/... \
-//libs-scala/gatling-utils/... \ -//libs-scala/gatling-utils/... \
-//ledger/ledger-api-test-tool/... \ -//ledger/ledger-api-test-tool/... \
-//ledger/ledger-api-test-tool-on-canton/... -//ledger/ledger-api-test-tool-on-canton/...

View File

@ -37,12 +37,37 @@ da_scala_library(
srcs = glob([ srcs = glob([
"src/main/scala/**/*.scala", "src/main/scala/**/*.scala",
]), ]),
scala_deps = [
"@maven//:com_chuusai_shapeless",
"@maven//:com_github_pureconfig_pureconfig_core",
"@maven//:com_github_pureconfig_pureconfig_generic",
"@maven//:com_github_scopt_scopt",
"@maven//:com_lihaoyi_sourcecode",
"@maven//:com_typesafe_akka_akka_actor",
"@maven//:com_typesafe_akka_akka_http",
"@maven//:com_typesafe_akka_akka_http_core",
"@maven//:com_typesafe_akka_akka_http_spray_json",
"@maven//:com_typesafe_akka_akka_stream",
"@maven//:com_typesafe_scala_logging_scala_logging",
"@maven//:io_spray_spray_json",
"@maven//:org_sangria_graphql_sangria",
"@maven//:org_sangria_graphql_sangria_marshalling_api",
"@maven//:org_scalaz_scalaz_core",
"@maven//:org_tpolecat_doobie_core",
"@maven//:org_tpolecat_doobie_free",
"@maven//:org_typelevel_cats_core",
"@maven//:org_typelevel_cats_effect",
"@maven//:org_typelevel_cats_free",
"@maven//:org_typelevel_cats_kernel",
],
scala_runtime_deps = [
"@maven//:com_typesafe_akka_akka_slf4j",
],
scalacopts = navigator_scalacopts, scalacopts = navigator_scalacopts,
silent_annotations = True, silent_annotations = True,
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
runtime_deps = [ runtime_deps = [
"@maven//:ch_qos_logback_logback_classic", "@maven//:ch_qos_logback_logback_classic",
"@maven//:com_typesafe_akka_akka_slf4j_2_12",
"@maven//:org_xerial_sqlite_jdbc", "@maven//:org_xerial_sqlite_jdbc",
], ],
deps = [ deps = [
@ -63,31 +88,10 @@ da_scala_library(
"//libs-scala/build-info", "//libs-scala/build-info",
"//libs-scala/grpc-utils", "//libs-scala/grpc-utils",
"//libs-scala/scala-utils", "//libs-scala/scala-utils",
"@maven//:com_chuusai_shapeless_2_12",
"@maven//:com_github_pureconfig_pureconfig_core_2_12",
"@maven//:com_github_pureconfig_pureconfig_generic_2_12",
"@maven//:com_github_scopt_scopt_2_12",
"@maven//:com_lihaoyi_sourcecode_2_12",
"@maven//:com_typesafe_akka_akka_actor_2_12",
"@maven//:com_typesafe_akka_akka_http_2_12",
"@maven//:com_typesafe_akka_akka_http_core_2_12",
"@maven//:com_typesafe_akka_akka_http_spray_json_2_12",
"@maven//:com_typesafe_akka_akka_stream_2_12",
"@maven//:com_typesafe_config", "@maven//:com_typesafe_config",
"@maven//:com_typesafe_scala_logging_scala_logging_2_12",
"@maven//:io_grpc_grpc_netty", "@maven//:io_grpc_grpc_netty",
"@maven//:io_netty_netty_handler", "@maven//:io_netty_netty_handler",
"@maven//:io_spray_spray_json_2_12",
"@maven//:org_sangria_graphql_sangria_2_12",
"@maven//:org_sangria_graphql_sangria_marshalling_api_2_12",
"@maven//:org_scalaz_scalaz_core_2_12",
"@maven//:org_slf4j_slf4j_api", "@maven//:org_slf4j_slf4j_api",
"@maven//:org_tpolecat_doobie_core_2_12",
"@maven//:org_tpolecat_doobie_free_2_12",
"@maven//:org_typelevel_cats_core_2_12",
"@maven//:org_typelevel_cats_effect_2_12",
"@maven//:org_typelevel_cats_free_2_12",
"@maven//:org_typelevel_cats_kernel_2_12",
], ],
) )
@ -100,10 +104,15 @@ da_scala_library(
"src/test/**/*Test.scala", "src/test/**/*Test.scala",
], ],
), ),
scala_deps = [
"@maven//:org_scalaz_scalaz_core",
],
scala_runtime_deps = [
"@maven//:com_typesafe_akka_akka_stream_testkit",
],
scalacopts = navigator_scalacopts, scalacopts = navigator_scalacopts,
runtime_deps = [ runtime_deps = [
"@maven//:ch_qos_logback_logback_classic", "@maven//:ch_qos_logback_logback_classic",
"@maven//:com_typesafe_akka_akka_stream_testkit_2_12",
"@maven//:io_grpc_grpc_netty", "@maven//:io_grpc_grpc_netty",
"@maven//:org_xerial_sqlite_jdbc", "@maven//:org_xerial_sqlite_jdbc",
], ],
@ -115,7 +124,6 @@ da_scala_library(
"//language-support/scala/bindings", "//language-support/scala/bindings",
"//ledger-service/lf-value-json", "//ledger-service/lf-value-json",
"//ledger/ledger-api-common", "//ledger/ledger-api-common",
"@maven//:org_scalaz_scalaz_core_2_12",
], ],
) )
@ -150,6 +158,22 @@ da_scala_test_suite(
"src/test/**/*Test.scala", "src/test/**/*Test.scala",
]), ]),
data = ["//ledger/test-common:dar-files"], data = ["//ledger/test-common:dar-files"],
scala_deps = [
"@maven//:com_typesafe_akka_akka_actor",
"@maven//:com_typesafe_akka_akka_http",
"@maven//:com_typesafe_akka_akka_http_core",
"@maven//:com_typesafe_akka_akka_http_spray_json",
"@maven//:com_typesafe_akka_akka_http_testkit",
"@maven//:com_typesafe_akka_akka_stream",
"@maven//:com_typesafe_scala_logging_scala_logging",
"@maven//:io_spray_spray_json",
"@maven//:org_sangria_graphql_sangria",
"@maven//:org_sangria_graphql_sangria_marshalling_api",
"@maven//:org_scalacheck_scalacheck",
"@maven//:org_scalatest_scalatest",
"@maven//:org_scalatestplus_scalacheck_1_14",
"@maven//:org_scalaz_scalaz_core",
],
scalacopts = navigator_scalacopts, scalacopts = navigator_scalacopts,
deps = [ deps = [
":navigator-library", ":navigator-library",
@ -175,21 +199,7 @@ da_scala_test_suite(
"//libs-scala/ports", "//libs-scala/ports",
"//libs-scala/resources", "//libs-scala/resources",
"//libs-scala/timer-utils", "//libs-scala/timer-utils",
"@maven//:com_typesafe_akka_akka_actor_2_12",
"@maven//:com_typesafe_akka_akka_http_2_12",
"@maven//:com_typesafe_akka_akka_http_core_2_12",
"@maven//:com_typesafe_akka_akka_http_spray_json_2_12",
"@maven//:com_typesafe_akka_akka_http_testkit_2_12",
"@maven//:com_typesafe_akka_akka_stream_2_12",
"@maven//:com_typesafe_config", "@maven//:com_typesafe_config",
"@maven//:com_typesafe_scala_logging_scala_logging_2_12",
"@maven//:io_spray_spray_json_2_12",
"@maven//:org_sangria_graphql_sangria_2_12",
"@maven//:org_sangria_graphql_sangria_marshalling_api_2_12",
"@maven//:org_scalacheck_scalacheck_2_12",
"@maven//:org_scalatest_scalatest_2_12",
"@maven//:org_scalatestplus_scalacheck_1_14_2_12",
"@maven//:org_scalaz_scalaz_core_2_12",
], ],
) )

View File

@ -305,7 +305,7 @@ abstract class UIBackend extends LazyLogging with ApplicationInfoJsonSupport {
sys.addShutdownHook { sys.addShutdownHook {
// Stop the web server, then the Akka system consuming the ledger API // Stop the web server, then the Akka system consuming the ledger API
stopServer() stopServer()
partyRefresh.foreach(_.cancel) partyRefresh.foreach(_.cancel())
stopAkka() stopAkka()
() ()
} }

View File

@ -27,7 +27,7 @@ final case class Config(users: Map[String, UserConfig] = Map.empty[String, UserC
def userIds: Set[String] = users.keySet def userIds: Set[String] = users.keySet
def roles: Set[String] = users.values.flatMap(_.role.toList)(collection.breakOut) def roles: Set[String] = users.values.view.flatMap(_.role.toList).toSet
} }
sealed abstract class ConfigReadError extends Product with Serializable { sealed abstract class ConfigReadError extends Product with Serializable {

View File

@ -64,7 +64,7 @@ class DatabaseActions extends LazyLogging {
Queries.createCommandTable.update.run *> Queries.createCommandTable.update.run *>
Queries.commandIdIndex.update.run) Queries.commandIdIndex.update.run)
.transact(xa) .transact(xa)
.unsafeRunSync .unsafeRunSync()
def schema(): Try[String] = { def schema(): Try[String] = {
Try( Try(

View File

@ -114,7 +114,7 @@ package dotnot {
* @param delegate the dotnot handler for `e` * @param delegate the dotnot handler for `e`
*/ */
def onElements[E](getName: E => String, delegate: OnTreeReady[E, R, C])(implicit def onElements[E](getName: E => String, delegate: OnTreeReady[E, R, C])(implicit
ev: T <:< Traversable[E] ev: T <:< Iterable[E]
): OnTreeReady[T, R, C] = { ): OnTreeReady[T, R, C] = {
val action: (T, PropertyCursor, String, C) => Either[DotNotFailure, R] = val action: (T, PropertyCursor, String, C) => Either[DotNotFailure, R] =
(t: T, cursor: PropertyCursor, value: String, context: C) => { (t: T, cursor: PropertyCursor, value: String, context: C) => {
@ -222,7 +222,7 @@ package dotnot {
def perform[K](f: (T, K) => R)(implicit readK: Read[K]): OnLeafReady[T, R, C] = { def perform[K](f: (T, K) => R)(implicit readK: Read[K]): OnLeafReady[T, R, C] = {
val action: Action[T, R, C] = (t: T, cursor: PropertyCursor, value: String, _: C) => { val action: Action[T, R, C] = (t: T, cursor: PropertyCursor, value: String, _: C) => {
if (cursor.isLast) { if (cursor.isLast) {
Right(f(t, readK.from(value).right.get)) Right(f(t, readK.from(value).toOption.get))
} else { } else {
Left(MustBeLastPart(onLeaf.onTreeOld.target, cursor, value)) Left(MustBeLastPart(onLeaf.onTreeOld.target, cursor, value))
} }

View File

@ -40,10 +40,27 @@ case class UserFacingError(message: String)
override def getMessage: String = message override def getMessage: String = message
} }
private object Implicits {
implicit final class `ExtendedInterfaceType Ops`[Ctx, Val](
private val self: InterfaceType[Ctx, Val]
) extends AnyVal {
// Hack around https://github.com/scala/bug/issues/11662 which
// otherwise results in the implicit PossibleObject constructor
// being ambiguous due to the also implicit apply method.
def withPossibleObjectTypes(possible: () => List[ObjectType[Ctx, _]]) =
self.withPossibleTypes(() => possible().map(new PossibleObject[Ctx, Val](_)))
}
}
/** Schema definition for the UI backend GraphQL API. */ /** Schema definition for the UI backend GraphQL API. */
@SuppressWarnings(Array("org.wartremover.warts.JavaSerializable")) @SuppressWarnings(
Array("org.wartremover.warts.JavaSerializable", "org.wartremover.warts.Serializable")
)
final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) { final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
import Implicits._
implicit private val actorTimeout: Timeout = Timeout(60, TimeUnit.SECONDS) implicit private val actorTimeout: Timeout = Timeout(60, TimeUnit.SECONDS)
implicit private val executionContext: ExecutionContext = ExecutionContext.global implicit private val executionContext: ExecutionContext = ExecutionContext.global
@ -105,12 +122,12 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
) )
//noinspection ForwardReference //noinspection ForwardReference
val NodeType: InterfaceType[GraphQLContext, Node[_]] = InterfaceType( val NodeType: InterfaceType[GraphQLContext, Node[_]] = InterfaceType[GraphQLContext, Node[_]](
"Node", "Node",
fields[GraphQLContext, Node[_]]( fields[GraphQLContext, Node[_]](
Field("id", IDType, resolve = _.value.idString) Field("id", IDType, resolve = _.value.idString)
), ),
).withPossibleTypes(() => ).withPossibleObjectTypes(() =>
List( List(
TransactionType, TransactionType,
TemplateType, TemplateType,
@ -132,7 +149,7 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
Field("module", StringType, resolve = _.value.id.qualifiedName.module.toString()), Field("module", StringType, resolve = _.value.id.qualifiedName.module.toString()),
Field("name", StringType, resolve = _.value.id.qualifiedName.name.toString()), Field("name", StringType, resolve = _.value.id.qualifiedName.name.toString()),
), ),
).withPossibleTypes(() => ).withPossibleObjectTypes(() =>
List( List(
DamlLfDefDataTypeType, DamlLfDefDataTypeType,
TemplateType, TemplateType,
@ -231,7 +248,7 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
resolve = context => Tag.unwrap[String, ApiTypes.WorkflowIdTag](context.value.workflowId), resolve = context => Tag.unwrap[String, ApiTypes.WorkflowIdTag](context.value.workflowId),
), ),
), ),
).withPossibleTypes(() => List(CreatedEventType, ExercisedEventType)) ).withPossibleObjectTypes(() => List(CreatedEventType, ExercisedEventType))
//noinspection ForwardReference //noinspection ForwardReference
val CreatedEventType: ObjectType[GraphQLContext, ContractCreated] = ObjectType( val CreatedEventType: ObjectType[GraphQLContext, ContractCreated] = ObjectType(
@ -294,7 +311,7 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
), ),
) )
val TransactionType = ObjectType( val TransactionType: ObjectType[GraphQLContext, Transaction] = ObjectType(
"Transaction", "Transaction",
interfaces[GraphQLContext, Transaction](NodeType), interfaces[GraphQLContext, Transaction](NodeType),
() => () =>
@ -382,7 +399,7 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
fields[GraphQLContext, CommandStatus]( fields[GraphQLContext, CommandStatus](
Field("completed", BooleanType, resolve = _.value.isCompleted) Field("completed", BooleanType, resolve = _.value.isCompleted)
), ),
).withPossibleTypes(() => ).withPossibleObjectTypes(() =>
List( List(
CommandStatusErrorType, CommandStatusErrorType,
CommandStatusWaitingType, CommandStatusWaitingType,
@ -448,7 +465,7 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
.getOrElse(CommandStatusUnknown()), .getOrElse(CommandStatusUnknown()),
), ),
), ),
).withPossibleTypes(() => List(CreateCommandType, ExerciseCommandType)) ).withPossibleObjectTypes(() => List(CreateCommandType, ExerciseCommandType))
val CreateCommandType: ObjectType[GraphQLContext, CreateCommand] = ObjectType( val CreateCommandType: ObjectType[GraphQLContext, CreateCommand] = ObjectType(
"CreateCommand", "CreateCommand",
@ -844,12 +861,14 @@ final class GraphQLSchema(customEndpoints: Set[CustomEndpoint[_]]) {
def filterCriteria(arg: Seq[DefaultInput]): AndFilterCriterion = def filterCriteria(arg: Seq[DefaultInput]): AndFilterCriterion =
AndFilterCriterion( AndFilterCriterion(
arg.map(input => arg.view
FilterCriterion( .map(input =>
input("field").toString, FilterCriterion(
input("value").toString, input("field").toString,
input("value").toString,
)
) )
)(collection.breakOut) .toList
) )
private def parseInstant(s: String): Either[Violation, Instant] = Try(Instant.parse(s)) match { private def parseInstant(s: String): Either[Violation, Instant] = Try(Instant.parse(s)) match {

View File

@ -69,22 +69,22 @@ object JsonType {
ScalarType[JsValue]( ScalarType[JsValue](
name, name,
description = description, description = description,
coerceOutput = (value, _) value, coerceOutput = (value, _) => value,
coerceUserInput = { coerceUserInput = {
case v: String Right(JsString(v)) case v: String => Right(JsString(v): JsValue)
case v: Boolean Right(JsBoolean(v)) case v: Boolean => Right(JsBoolean(v))
case v: Int Right(JsNumber(v)) case v: Int => Right(JsNumber(v))
case v: Long Right(JsNumber(v)) case v: Long => Right(JsNumber(v))
case v: Float Right(JsNumber(v.toDouble)) case v: Float => Right(JsNumber(v.toDouble): JsValue)
case v: Double Right(JsNumber(v)) case v: Double => Right(JsNumber(v): JsValue)
case v: BigInt Right(JsNumber(v)) case v: BigInt => Right(JsNumber(v))
case v: BigDecimal Right(JsNumber(v)) case v: BigDecimal => Right(JsNumber(v))
case v: JsValue Right(v) case v: JsValue => Right(v)
}, },
coerceInput = { coerceInput = {
case ast.StringValue(jsonStr, _, _, _, _) case ast.StringValue(jsonStr, _, _, _, _) =>
Right(jsonStr.parseJson) Right(jsonStr.parseJson)
case _ case _ =>
Left(JsonCoercionViolation) Left(JsonCoercionViolation)
}, },
) )

View File

@ -36,22 +36,22 @@ object SprayMarshallers {
def arrayNode(values: Vector[JsValue]) = JsArray(values) def arrayNode(values: Vector[JsValue]) = JsArray(values)
def optionalArrayNodeValue(value: Option[JsValue]): JsValue = value match { def optionalArrayNodeValue(value: Option[JsValue]): JsValue = value match {
case Some(v) v case Some(v) => v
case None nullNode case None => nullNode
} }
def scalarNode(value: Any, typeName: String, info: Set[ScalarValueInfo]): JsValue = def scalarNode(value: Any, typeName: String, info: Set[ScalarValueInfo]): JsValue =
value match { value match {
case v: String JsString(v) case v: String => JsString(v)
case v: Boolean JsBoolean(v) case v: Boolean => JsBoolean(v)
case v: Int JsNumber(v) case v: Int => JsNumber(v)
case v: Long JsNumber(v) case v: Long => JsNumber(v)
case v: Float JsNumber(v.toDouble) case v: Float => JsNumber(v.toDouble)
case v: Double JsNumber(v) case v: Double => JsNumber(v)
case v: BigInt JsNumber(v) case v: BigInt => JsNumber(v)
case v: BigDecimal JsNumber(v) case v: BigDecimal => JsNumber(v)
case v: JsValue v case v: JsValue => v
case v throw new IllegalArgumentException("Unsupported scalar value: " + v.toString) case v => throw new IllegalArgumentException("Unsupported scalar value: " + v.toString)
} }
def enumNode(value: String, typeName: String) = JsString(value) def enumNode(value: String, typeName: String) = JsString(value)
@ -80,10 +80,10 @@ object SprayMarshallers {
def isDefined(node: JsValue): Boolean = node != JsNull def isDefined(node: JsValue): Boolean = node != JsNull
def getScalarValue(node: JsValue): Any = node match { def getScalarValue(node: JsValue): Any = node match {
case JsBoolean(b) b case JsBoolean(b) => b
case JsNumber(d) d.toBigIntExact getOrElse d case JsNumber(d) => d.toBigIntExact getOrElse d
case JsString(s) s case JsString(s) => s
case n n case n => n
} }
def getScalaScalarValue(node: JsValue): Any = getScalarValue(node) def getScalaScalarValue(node: JsValue): Any = getScalarValue(node)
@ -118,7 +118,7 @@ object SprayMarshallers {
implicit def sprayJsonWriterToInput[T: JsonWriter]: ToInput[T, JsValue] = implicit def sprayJsonWriterToInput[T: JsonWriter]: ToInput[T, JsValue] =
new ToInput[T, JsValue] { new ToInput[T, JsValue] {
def toInput(value: T): (JsValue, CustomSprayJsonInputUnmarshaller.type) = def toInput(value: T): (JsValue, CustomSprayJsonInputUnmarshaller.type) =
implicitly[JsonWriter[T]].write(value) CustomSprayJsonInputUnmarshaller implicitly[JsonWriter[T]].write(value) -> CustomSprayJsonInputUnmarshaller
} }
implicit def sprayJsonReaderFromInput[T: JsonReader]: FromInput[T] = implicit def sprayJsonReaderFromInput[T: JsonReader]: FromInput[T] =
@ -127,7 +127,7 @@ object SprayMarshallers {
def fromResult(node: marshaller.Node): T = def fromResult(node: marshaller.Node): T =
try implicitly[JsonReader[T]].read(node) try implicitly[JsonReader[T]].read(node)
catch { catch {
case e: DeserializationException throw InputParsingError(Vector(e.msg)) case e: DeserializationException => throw InputParsingError(Vector(e.msg))
} }
} }

View File

@ -19,11 +19,11 @@ object StringAliasType {
coerceOutput = sangria.schema.valueOutput, coerceOutput = sangria.schema.valueOutput,
coerceUserInput = { coerceUserInput = {
case s: String => Right(s) case s: String => Right(s)
case _ Left(StringCoercionViolation) case _ => Left(StringCoercionViolation)
}, },
coerceInput = { coerceInput = {
case StringValue(s, _, _, _, _) => Right(s) case StringValue(s, _, _, _, _) => Right(s)
case _ Left(StringCoercionViolation) case _ => Left(StringCoercionViolation)
}, },
) )
@ -34,11 +34,11 @@ object StringAliasType {
coerceOutput = (value, _) => Tag.unwrap(value), coerceOutput = (value, _) => Tag.unwrap(value),
coerceUserInput = { coerceUserInput = {
case s: String => Right(Tag.of[T](s)) case s: String => Right(Tag.of[T](s))
case _ Left(StringCoercionViolation) case _ => Left(StringCoercionViolation)
}, },
coerceInput = { coerceInput = {
case StringValue(s, _, _, _, _) => Right(Tag.of[T](s)) case StringValue(s, _, _, _, _) => Right(Tag.of[T](s))
case _ Left(StringCoercionViolation) case _ => Left(StringCoercionViolation)
}, },
) )
} }

View File

@ -139,7 +139,7 @@ object ApiCodecVerbose {
case `tagVariant` => jsValueToApiVariant(value) case `tagVariant` => jsValueToApiVariant(value)
case `tagEnum` => jsValueToApiEnum(value) case `tagEnum` => jsValueToApiEnum(value)
case `tagList` => case `tagList` =>
V.ValueList(arrayField(value, propValue, "ApiList").map(jsValueToApiValue).to[FrontStack]) V.ValueList(arrayField(value, propValue, "ApiList").map(jsValueToApiValue).to(FrontStack))
case `tagText` => V.ValueText(strField(value, propValue, "ApiText")) case `tagText` => V.ValueText(strField(value, propValue, "ApiText"))
case `tagInt64` => V.ValueInt64(strField(value, propValue, "ApiInt64").toLong) case `tagInt64` => V.ValueInt64(strField(value, propValue, "ApiInt64").toLong)
case `tagNumeric` => case `tagNumeric` =>
@ -179,7 +179,7 @@ object ApiCodecVerbose {
asObject(value, "ApiRecord").fields asObject(value, "ApiRecord").fields
.get(propId) .get(propId)
.flatMap(_.convertTo[Option[DamlLfIdentifier]]), .flatMap(_.convertTo[Option[DamlLfIdentifier]]),
arrayField(value, propFields, "ApiRecord").map(jsValueToApiRecordField).to[ImmArray], arrayField(value, propFields, "ApiRecord").map(jsValueToApiRecordField).to(ImmArray),
) )
case t => case t =>
deserializationError( deserializationError(
@ -265,5 +265,5 @@ object ApiCodecVerbose {
} }
private[this] def assertDE[A](ea: Either[String, A]): A = private[this] def assertDE[A](ea: Either[String, A]): A =
ea fold (deserializationError(_), identity) ea.fold(deserializationError(_), identity)
} }

View File

@ -7,6 +7,7 @@ import com.daml.ledger.api.refinements.ApiTypes
import com.daml.navigator.data.DatabaseActions import com.daml.navigator.data.DatabaseActions
import com.typesafe.scalalogging.LazyLogging import com.typesafe.scalalogging.LazyLogging
import scala.collection.compat.immutable.LazyList
import scala.util.{Failure, Success, Try} import scala.util.{Failure, Success, Try}
/** In-memory projection of ledger events. */ /** In-memory projection of ledger events. */
@ -274,28 +275,28 @@ case class Ledger(
} }
} }
def allContracts(types: PackageRegistry): Stream[Contract] = { def allContracts(types: PackageRegistry): LazyList[Contract] = {
if (useDatabase) { if (useDatabase) {
logErrorAndDefaultTo(db.contracts(types), List.empty[Contract]).toStream logErrorAndDefaultTo(db.contracts(types), List.empty[Contract]).to(LazyList)
} else { } else {
contractById.values.toStream contractById.values.to(LazyList)
} }
} }
def activeContracts(types: PackageRegistry): Stream[Contract] = { def activeContracts(types: PackageRegistry): LazyList[Contract] = {
if (useDatabase) { if (useDatabase) {
logErrorAndDefaultTo(db.activeContracts(types), List.empty[Contract]).toStream logErrorAndDefaultTo(db.activeContracts(types), List.empty[Contract]).to(LazyList)
} else { } else {
activeContractById.values.toStream activeContractById.values.to(LazyList)
} }
} }
def activeTemplateContractsOf(template: Template, types: PackageRegistry): Stream[Contract] = { def activeTemplateContractsOf(template: Template, types: PackageRegistry): LazyList[Contract] = {
if (useDatabase) { if (useDatabase) {
logErrorAndDefaultTo( logErrorAndDefaultTo(
db.activeContractsForTemplate(template.id, types), db.activeContractsForTemplate(template.id, types),
List.empty[Contract], List.empty[Contract],
).toStream ).to(LazyList)
} else { } else {
templateContractsOf(template, types).filter(contract => templateContractsOf(template, types).filter(contract =>
activeContractById.contains(contract.id) activeContractById.contains(contract.id)
@ -303,22 +304,22 @@ case class Ledger(
} }
} }
def templateContractsOf(template: Template, types: PackageRegistry): Stream[Contract] = { def templateContractsOf(template: Template, types: PackageRegistry): LazyList[Contract] = {
if (useDatabase) { if (useDatabase) {
logErrorAndDefaultTo( logErrorAndDefaultTo(
db.contractsForTemplate(template.id, types), db.contractsForTemplate(template.id, types),
List.empty[Contract], List.empty[Contract],
).toStream ).to(LazyList)
} else { } else {
contractsByTemplateId.getOrElse(template.id, Set.empty).toStream contractsByTemplateId.getOrElse(template.id, Set.empty).to(LazyList)
} }
} }
def allCommands(types: PackageRegistry): Stream[Command] = { def allCommands(types: PackageRegistry): LazyList[Command] = {
if (useDatabase) { if (useDatabase) {
logErrorAndDefaultTo(db.allCommands(types), List.empty[Command]).toStream logErrorAndDefaultTo(db.allCommands(types), List.empty[Command]).to(LazyList)
} else { } else {
commandById.values.toStream commandById.values.to(LazyList)
} }
} }

View File

@ -7,6 +7,7 @@ import com.daml.navigator.{model => Model}
import com.daml.ledger.api.refinements.ApiTypes import com.daml.ledger.api.refinements.ApiTypes
import com.daml.lf.{iface => DamlLfIface} import com.daml.lf.{iface => DamlLfIface}
import com.daml.lf.data.{Ref => DamlLfRef} import com.daml.lf.data.{Ref => DamlLfRef}
import scala.collection.compat.immutable.LazyList
/** Manages a set of known DAML-LF packages. */ /** Manages a set of known DAML-LF packages. */
case class PackageRegistry( case class PackageRegistry(
@ -74,8 +75,8 @@ case class PackageRegistry(
def pack(id: DamlLfRef.PackageId): Option[DamlLfPackage] = def pack(id: DamlLfRef.PackageId): Option[DamlLfPackage] =
packages.get(id) packages.get(id)
def allPackages(): Stream[DamlLfPackage] = def allPackages(): LazyList[DamlLfPackage] =
packages.values.toStream packages.values.to(LazyList)
// ------------------------------------------------------------------------------------------------------------------ // ------------------------------------------------------------------------------------------------------------------
// Templates // Templates
@ -96,8 +97,8 @@ case class PackageRegistry(
def templateCount: Int = def templateCount: Int =
templates.size templates.size
def allTemplates(): Stream[Template] = def allTemplates(): LazyList[Template] =
templates.values.toStream templates.values.to(LazyList)
def templatesByName(topLevelDecl: String): Seq[Template] = def templatesByName(topLevelDecl: String): Seq[Template] =
templates.toList templates.toList

View File

@ -8,6 +8,7 @@ import java.util.concurrent.atomic.AtomicReference
import com.daml.lf.{iface => DamlLfIface} import com.daml.lf.{iface => DamlLfIface}
import com.daml.ledger.api.refinements.ApiTypes import com.daml.ledger.api.refinements.ApiTypes
import com.daml.navigator.config.UserConfig import com.daml.navigator.config.UserConfig
import scala.collection.compat.immutable.LazyList
import scalaz.Tag import scalaz.Tag
case class State(ledger: Ledger, packageRegistry: PackageRegistry) case class State(ledger: Ledger, packageRegistry: PackageRegistry)
@ -56,5 +57,5 @@ class PartyState(val config: UserConfig) {
override def toString: String = "Party(" + name.toString + ")" override def toString: String = "Party(" + name.toString + ")"
def contracts(): Stream[Contract] = this.ledger.allContracts(this.packageRegistry) def contracts(): LazyList[Contract] = this.ledger.allContracts(this.packageRegistry)
} }

View File

@ -8,7 +8,7 @@ case object Converter {
/** Returns the sequence of values, or the last error encountered */ /** Returns the sequence of values, or the last error encountered */
def sequence[E, T](xs: Seq[Either[E, T]]): Either[E, List[T]] = def sequence[E, T](xs: Seq[Either[E, T]]): Either[E, List[T]] =
xs.foldRight(Right(Nil): Either[E, List[T]]) { (e, acc) => xs.foldRight(Right(Nil): Either[E, List[T]]) { (e, acc) =>
for (xs <- acc.right; x <- e.right) yield x :: xs for (xs <- acc; x <- e) yield x :: xs
} }
/** Returns the value of a required protobuf3 field, or RequiredFieldDoesNotExistError if it doesn't exist. */ /** Returns the value of a required protobuf3 field, or RequiredFieldDoesNotExistError if it doesn't exist. */

View File

@ -465,10 +465,12 @@ case object LedgerApiV1 {
final class NotACoid(message: String) extends RuntimeException(message) with NoStackTrace final class NotACoid(message: String) extends RuntimeException(message) with NoStackTrace
// this is 100% cheating as Value should have Traverse instead // this is 100% cheating as Value should have Traverse instead
try Right(value mapContractId { coid => try Right(value mapContractId { coid =>
ContractId fromString coid fold ( ContractId
e => throw new NotACoid(e), .fromString(coid)
identity .fold(
) e => throw new NotACoid(e),
identity,
)
}) })
catch { case e: NotACoid => Left(GenericConversionError(e.getMessage)) } catch { case e: NotACoid => Left(GenericConversionError(e.getMessage)) }
} }

View File

@ -136,7 +136,7 @@ class PlatformStore(
context.become( context.become(
connected(StateConnected(value.ledgerClient, state.parties, value.staticTime, value.time)) connected(StateConnected(value.ledgerClient, state.parties, value.staticTime, value.time))
) )
unstashAll unstashAll()
case Connected(Failure(e)) => case Connected(Failure(e)) =>
// Connection failed even after several retries - not sure how to recover from this // Connection failed even after several retries - not sure how to recover from this
@ -147,7 +147,7 @@ class PlatformStore(
context.become(failed(StateFailed(e))) context.become(failed(StateFailed(e)))
case GetApplicationStateInfo => case GetApplicationStateInfo =>
sender ! ApplicationStateConnecting( sender() ! ApplicationStateConnecting(
platformHost, platformHost,
platformPort, platformPort,
tlsConfig.exists(_.enabled), tlsConfig.exists(_.enabled),
@ -155,7 +155,7 @@ class PlatformStore(
) )
case _ => case _ =>
stash stash()
} }
def connected(state: StateConnected): Receive = { def connected(state: StateConnected): Receive = {
@ -192,16 +192,16 @@ class PlatformStore(
} }
case CreateContract(party, templateId, value) => case CreateContract(party, templateId, value) =>
createContract(state.time.time.getCurrentTime, party, templateId, value, sender) createContract(state.time.time.getCurrentTime, party, templateId, value, sender())
case ExerciseChoice(party, contractId, choiceId, value) => case ExerciseChoice(party, contractId, choiceId, value) =>
exerciseChoice(state.time.time.getCurrentTime, party, contractId, choiceId, value, sender) exerciseChoice(state.time.time.getCurrentTime, party, contractId, choiceId, value, sender())
case ReportCurrentTime => case ReportCurrentTime =>
sender ! Success(state.time) sender() ! Success(state.time)
case AdvanceTime(to) => case AdvanceTime(to) =>
advanceTime(state.staticTime, to, sender) advanceTime(state.staticTime, to, sender())
case ResetConnection => case ResetConnection =>
// Wait for all children to stop, then initiate new connection // Wait for all children to stop, then initiate new connection
@ -214,7 +214,7 @@ class PlatformStore(
implicit val actorTimeout: Timeout = Timeout(5, TimeUnit.SECONDS) implicit val actorTimeout: Timeout = Timeout(5, TimeUnit.SECONDS)
// Store the original sender (sender is mutable) // Store the original sender (sender is mutable)
val snd = sender val snd = sender()
Future Future
.traverse(state.parties.toList) { .traverse(state.parties.toList) {
@ -262,7 +262,7 @@ class PlatformStore(
// Permanently failed state // Permanently failed state
def failed(state: StateFailed): Receive = { def failed(state: StateFailed): Receive = {
case GetApplicationStateInfo => case GetApplicationStateInfo =>
sender ! ApplicationStateFailed( sender() ! ApplicationStateFailed(
platformHost, platformHost,
platformPort, platformPort,
tlsConfig.exists(_.enabled), tlsConfig.exists(_.enabled),

View File

@ -111,10 +111,10 @@ class PlatformSubscriber(
unstashAll() unstashAll()
case GetPartyActorInfo => case GetPartyActorInfo =>
sender ! PartyActorStarting(party) sender() ! PartyActorStarting(party)
case _ => case _ =>
stash stash()
} }
def running(state: StateRunning): Receive = { def running(state: StateRunning): Receive = {
@ -122,20 +122,20 @@ class PlatformSubscriber(
log.debug("Resetting connection for '{}'", party.name) log.debug("Resetting connection for '{}'", party.name)
killSwitch.shutdown() killSwitch.shutdown()
context.stop(self) context.stop(self)
sender ! ConnectionReset sender() ! ConnectionReset
case SubmitCommand(command, commandSender) => case SubmitCommand(command, commandSender) =>
// Submit command and reply to // Submit command and reply to
submitCommand(ledgerClient, state.commandTracker, party, command, commandSender) submitCommand(ledgerClient, state.commandTracker, party, command, commandSender)
case GetPartyActorInfo => case GetPartyActorInfo =>
sender ! PartyActorStarted(party) sender() ! PartyActorStarted(party)
} }
// Permanently failed state // Permanently failed state
def failed(error: Throwable): Receive = { def failed(error: Throwable): Receive = {
case GetApplicationStateInfo => case GetApplicationStateInfo =>
sender ! PartyActorFailed(party, error) sender() ! PartyActorFailed(party, error)
case _ => () case _ => ()
} }

View File

@ -350,7 +350,7 @@ case object DamlConstants {
private[navigator] def record(fields: (String, ApiValue)*): ApiRecord = private[navigator] def record(fields: (String, ApiValue)*): ApiRecord =
V.ValueRecord( V.ValueRecord(
None, None,
fields.iterator.map { case (label, value) => Some(name(label)) -> value }.to[ImmArray], fields.iterator.map { case (label, value) => Some(name(label)) -> value }.to(ImmArray),
) )
} }

View File

@ -104,13 +104,16 @@ class LedgerSpec extends AnyWordSpec with Matchers {
} }
"return the created contracts when traversing all contracts" in { "return the created contracts when traversing all contracts" in {
result.allContracts(templateRegistry) should contain allOf (contract("C1"), contract("C2")) result.allContracts(templateRegistry) should contain.allOf(contract("C1"), contract("C2"))
} }
"consider the created contracts to be active" in { "consider the created contracts to be active" in {
result.activeContracts(templateRegistry) should contain allOf (contract("C1"), contract( result.activeContracts(templateRegistry) should contain.allOf(
"C2" contract("C1"),
)) contract(
"C2"
),
)
} }
"return the events by id" in { "return the events by id" in {
@ -247,7 +250,7 @@ class LedgerSpec extends AnyWordSpec with Matchers {
actingParties = List(party), actingParties = List(party),
consuming = true, consuming = true,
) )
val latest = transaction("Tx1").copy(events = List(exercisedEvent, createdEvent)) val latest = transaction("Tx1").copy(events = List[Event](exercisedEvent, createdEvent))
val result = subject.withTransaction(latest, templateRegistry) val result = subject.withTransaction(latest, templateRegistry)

View File

@ -121,7 +121,8 @@ class ContractFilterSpec extends AnyFlatSpec with Matchers {
def test(filters: List[(String, String)], expected: List[Contract], isAnd: Boolean): Unit = { def test(filters: List[(String, String)], expected: List[Contract], isAnd: Boolean): Unit = {
it should s"return $expected on filter (${filters.map { case (k, v) => s"$k contains $v" }.mkString(" and ")})" in { it should s"return $expected on filter (${filters.map { case (k, v) => s"$k contains $v" }.mkString(" and ")})" in {
val criteria = filters.map { case (k, v) => new FilterCriterion(k, v) } val criteria = filters.map { case (k, v) => new FilterCriterion(k, v) }
val criterion = if (isAnd) AndFilterCriterion(criteria) else OrFilterCriterion(criteria) val criterion: FilterCriterionBase =
if (isAnd) AndFilterCriterion(criteria) else OrFilterCriterion(criteria)
val filter = new ContractFilter(criterion, damlLfDefDataTypes.get, AllContractsPager) val filter = new ContractFilter(criterion, damlLfDefDataTypes.get, AllContractsPager)
contracts.filter(filter.isIncluded) should contain theSameElementsAs expected contracts.filter(filter.isIncluded) should contain theSameElementsAs expected
} }

View File

@ -15,25 +15,31 @@ da_scala_binary(
main_class = "com.daml.navigator.test.Main", main_class = "com.daml.navigator.test.Main",
resource_strip_prefix = "navigator/integration-test/src/main/resources/", resource_strip_prefix = "navigator/integration-test/src/main/resources/",
resources = ["src/main/resources/Main.daml"], resources = ["src/main/resources/Main.daml"],
scala_deps = [
"@maven//:com_chuusai_shapeless",
"@maven//:com_github_scopt_scopt",
"@maven//:com_typesafe_scala_logging_scala_logging",
"@maven//:io_circe_circe_core",
"@maven//:io_circe_circe_generic",
"@maven//:io_circe_circe_parser",
"@maven//:org_scalactic_scalactic",
"@maven//:org_scalatest_scalatest",
"@maven//:org_scalatestplus_selenium_3_141",
"@maven//:org_typelevel_cats_core",
"@maven//:org_typelevel_cats_kernel",
],
versioned_scala_deps = {
"2.12": ["@maven//:org_scala_lang_modules_scala_collection_compat"],
},
visibility = ["//visibility:public"], visibility = ["//visibility:public"],
runtime_deps = [ runtime_deps = [
"//ledger/sandbox-classic", "//ledger/sandbox-classic",
"@maven//:ch_qos_logback_logback_classic", "@maven//:ch_qos_logback_logback_classic",
], ],
deps = [ deps = [
"@maven//:com_chuusai_shapeless_2_12",
"@maven//:com_github_scopt_scopt_2_12",
"@maven//:com_typesafe_scala_logging_scala_logging_2_12",
"@maven//:commons_codec_commons_codec", "@maven//:commons_codec_commons_codec",
"@maven//:io_circe_circe_core_2_12",
"@maven//:io_circe_circe_generic_2_12",
"@maven//:io_circe_circe_parser_2_12",
"@maven//:org_scalactic_scalactic_2_12",
"@maven//:org_scalatest_scalatest_2_12",
"@maven//:org_scalatestplus_selenium_3_141_2_12",
"@maven//:org_seleniumhq_selenium_selenium_api", "@maven//:org_seleniumhq_selenium_selenium_api",
"@maven//:org_seleniumhq_selenium_selenium_remote_driver", "@maven//:org_seleniumhq_selenium_selenium_remote_driver",
"@maven//:org_slf4j_slf4j_api", "@maven//:org_slf4j_slf4j_api",
"@maven//:org_typelevel_cats_core_2_12",
], ],
) )

View File

@ -65,7 +65,7 @@ class BrowserTest(args: Arguments)
// Don't log the actual command, it contains credentials // Don't log the actual command, it contains credentials
logger.info("Running BrowserStackLocal...") logger.info("Running BrowserStackLocal...")
Process(commands).run Process(commands).run()
} }
implicit private val webDriver: WebDriver = getBrowserStackDriver() match { implicit private val webDriver: WebDriver = getBrowserStackDriver() match {

View File

@ -4,7 +4,7 @@
package com.daml.navigator.test package com.daml.navigator.test
import scala.collection._ import scala.collection._
import scala.collection.JavaConverters._ import scala.jdk.CollectionConverters._
import java.util.concurrent.ConcurrentHashMap import java.util.concurrent.ConcurrentHashMap
import com.daml.navigator.test.config.Arguments import com.daml.navigator.test.config.Arguments
@ -22,7 +22,10 @@ object Main extends LazyLogging {
case Some(arguments) => case Some(arguments) =>
val reporter = new LoggerReporter() val reporter = new LoggerReporter()
val status = new BrowserTest(arguments) val status = new BrowserTest(arguments)
.run(None, Args(reporter = reporter, configMap = new ConfigMap(Map.empty[String, Any]))) .run(
None,
Args(reporter = reporter, configMap = new ConfigMap(immutable.Map.empty[String, Any])),
)
val success = Try(status.succeeds()).getOrElse(false) val success = Try(status.succeeds()).getOrElse(false)
val exitCode = if (success) 0 else 1 val exitCode = if (success) 0 else 1
val header = val header =