feat(api, lsp): Case classes exported to JS as normal JSONs (#1151)

This commit is contained in:
Dima 2024-06-07 15:38:37 +07:00 committed by GitHub
parent af741c3141
commit 037532fb85
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
5 changed files with 101 additions and 254 deletions

View File

@ -8,46 +8,38 @@ import cats.data.Validated.{invalidNec, validNec}
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
import scala.scalajs.js
import scala.scalajs.js.JSConverters.*
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.scalajs.js.annotation.{JSExport, JSExportAll, JSExportTopLevel}
import scala.scalajs.js.|
@JSExportTopLevel("Input")
@JSExportAll
class Input(
@JSExport
val input: String
)
@JSExportTopLevel("Path")
@JSExportAll
class Path(
@JSExport
val path: String
)
@JSExportTopLevel("Call")
@JSExportAll
class Call(
@JSExport
val functionCall: String,
@JSExport
val arguments: js.Dynamic,
@JSExport
val input: Path | Input
)
@JSExportTopLevel("AquaConfig")
@JSExportAll
class AquaConfig(
@JSExport
val logLevel: js.UndefOr[String],
@JSExport
val constants: js.UndefOr[js.Array[String]],
@JSExport
val noXor: js.UndefOr[Boolean],
@JSExport
val noRelay: js.UndefOr[Boolean],
@JSExport
val targetType: js.UndefOr[String],
@JSExport
val tracing: js.UndefOr[Boolean],
@JSExport
val noEmptyResponse: js.UndefOr[Boolean]
)

View File

@ -2,34 +2,24 @@ package api.types
import aqua.js.{FunctionDefJs, ServiceDefJs}
import aqua.model.transform.TransformConfig
import cats.data.Validated.{invalidNec, validNec, Invalid, Valid}
import cats.data.{Chain, NonEmptyChain, Validated, ValidatedNec}
import scala.scalajs.js
import scala.scalajs.js.JSConverters.*
import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
import scala.scalajs.js.|
@JSExportTopLevel("AquaFunction")
case class AquaFunction(
@JSExport
funcDef: FunctionDefJs,
@JSExport
script: String
)
class AquaFunction(
val funcDef: FunctionDefJs,
val script: String
) extends js.Object
@JSExportTopLevel("GeneratedSource")
case class GeneratedSource(
@JSExport
class GeneratedSource(
val name: String,
@JSExport
val tsSource: js.UndefOr[String],
@JSExport
val jsSource: js.UndefOr[String],
@JSExport
val tsTypes: js.UndefOr[String]
)
) extends js.Object
object GeneratedSource {
@ -40,21 +30,14 @@ object GeneratedSource {
new GeneratedSource(name, null, jsSource, tsTypes)
}
@JSExportTopLevel("CompilationResult")
class CompilationResult(
@JSExport
val services: js.Dictionary[ServiceDefJs],
@JSExport
val functions: js.Dictionary[AquaFunction],
@JSExport
val functionCall: js.UndefOr[AquaFunction],
@JSExport
val generatedSources: js.Array[GeneratedSource],
@JSExport
val errors: js.Array[String],
@JSExport
val warnings: js.Array[String]
)
) extends js.Object
object CompilationResult {

View File

@ -1,9 +1,9 @@
aqua StreamMapTest declares *
export testGetFunc, testGetStreamFunc, testKeysFunc, testKeysStreamFunc
export testContainsFunc, testForFunc, testParSeqMap, testForTupleFunc
export testGetFunc, Srv
import "builtin.aqua"
service Srv("baaa"):
g() -> string
func testGetFunc() -> []string, []string, []string, u32:
streamMap: %string
@ -13,116 +13,4 @@ func testGetFunc() -> []string, []string, []string, u32:
resFirst = streamMap.get(key)
streamMap <<- key, "second value"
resSecond = streamMap.get(key)
<- resEmpty, resFirst, resSecond, resSecond.length
func testGetStreamFunc() -> []string, string, string:
streamMap: %string
key = "key"
resEmptyStream = streamMap.getStream(key)
streamMap <<- key, "first value"
resFirstStream = streamMap.getStream(key)
streamMap <<- key, "second value"
resSecondStream = streamMap.getStream(key)
resFirst = resFirstStream[0]
resSecond = resSecondStream[1]
<- resEmptyStream, resFirst, resSecond
func testKeysFunc() -> []string, []string, []string:
streamMap: %string
resEmpty = streamMap.keys()
streamMap <<- "key one", ""
resFirst = streamMap.keys()
streamMap <<- "key two", ""
streamMap <<- "key one", ""
streamMap <<- "key one", "text"
resSecond = streamMap.keys()
<- resEmpty, resFirst, resSecond
func testKeysStreamFunc() -> []string, []string, []string:
streamMap: %string
resEmpty = streamMap.keysStream()
streamMap <<- "key one", ""
resFirst = streamMap.keysStream()
streamMap <<- "key one", "new"
streamMap <<- "key two", ""
resSecond = streamMap.keysStream()
<- resEmpty, resFirst, resSecond
func testContainsFunc() -> bool, bool, bool, bool, bool:
keys = ["key one", "key two"]
streamMap: %string
resFirst = streamMap.contains(keys[0])
streamMap <<- keys[0], ""
resSecond = streamMap.contains(keys[0])
resThird = streamMap.contains(keys[1])
streamMap <<- keys[0], "new"
streamMap <<- keys[1], ""
resFourth = streamMap.contains(keys[0])
resFifth = streamMap.contains(keys[1])
<- resFirst, resSecond, resThird, resFourth, resFifth
func testForFunc() -> []string, []string:
streamMap: %string
streamMap <<- "key one", "1"
streamMap <<- "key one", "2"
streamMap <<- "key two", "3"
streamMap <<- "key two", "4"
streamMap <<- "key two", "5"
streamMap <<- "key three", "6"
streamMap <<- "key four", "7"
streamKeys: *string
streamValues: *string
for kv <- streamMap:
streamKeys <<- kv.key
streamValues <<- kv.value
<- streamKeys, streamValues
func testParSeqMap(relay1: string, relay2: string, relay3: string) -> string:
relays = [relay1, relay2, relay3]
map: %u64
map2: %u64
parseq r <- relays on r:
map <<- "time", Peer.timestamp_ms()
for r <- relays par:
on r:
join map.get("time")[relays.length - 1]
map2 <<- "time", Peer.timestamp_ms()
join map2.get("time")[relays.length - 1]
<- "ok"
func testForTupleFunc() -> []string, []string, []string:
streamMap: %string
streamMap <<- "key one", "1"
streamMap <<- "key one", "2"
streamMap <<- "key two", "3"
streamMap <<- "key two", "4"
streamMap <<- "key two", "5"
streamMap <<- "key three", "6"
streamMap <<- "key four", "7"
streamFirst: *string
streamSecond: *string
streamThird: *string
for k, v <- streamMap:
streamFirst <<- k
streamSecond <<- v
for k, v <- streamMap:
streamFirst <<- v
streamSecond <<- k
for k, v <- streamMap:
streamThird <<- streamMap.get(k)!
<- streamFirst, streamSecond, streamThird
<- resEmpty, resFirst, resSecond, resSecond.length

View File

@ -5,23 +5,22 @@ import aqua.backend.*
import aqua.definitions.*
import aqua.res.FuncRes
import aqua.types.*
import io.circe.{Encoder, Json}
import scala.scalajs.js
import scala.scalajs.js.JSConverters.*
import scala.scalajs.js.annotation.{JSExportAll, JSImport}
import scala.scalajs.js.annotation.{JSExportAll, JSImport, JSName}
@JSExportAll
case class FunctionDefJs(
functionName: String,
arrow: ArrowTypeDefJs,
names: NamesConfigJs
)
class FunctionDefJs(
val functionName: String,
val arrow: ArrowTypeDefJs,
val names: NamesConfigJs
) extends js.Object
object FunctionDefJs {
def apply(fd: FunctionDef): FunctionDefJs = {
FunctionDefJs(
new FunctionDefJs(
fd.functionName,
ArrowTypeDefJs(
TypeDefinitionJs(fd.arrow.domain),
@ -33,68 +32,57 @@ object FunctionDefJs {
}
}
@JSExportAll
sealed trait TypeDefinitionJs
sealed trait TypeDefinitionJs extends js.Object
@JSExportAll
case class ArrayTypeDefJs(`type`: TypeDefinitionJs, tag: String) extends TypeDefinitionJs
class ArrayTypeDefJs(val `type`: TypeDefinitionJs, val tag: String) extends TypeDefinitionJs
@JSExportAll
case class OptionTypeDefJs(`type`: TypeDefinitionJs, tag: String) extends TypeDefinitionJs
class OptionTypeDefJs(val `type`: TypeDefinitionJs, val tag: String) extends TypeDefinitionJs
@JSExportAll
case class ScalarTypeDefJs(name: String, tag: String) extends TypeDefinitionJs
class ScalarTypeDefJs(val name: String, val tag: String) extends TypeDefinitionJs
@JSExportAll
case class StructTypeDefJs(
name: String,
fields: js.Dictionary[TypeDefinitionJs],
tag: String
class StructTypeDefJs(
val name: String,
val fields: js.Dictionary[TypeDefinitionJs],
val tag: String
) extends TypeDefinitionJs
@JSExportAll
case class LabeledTypeDefJs(fields: js.Dictionary[TypeDefinitionJs], tag: String)
class LabeledTypeDefJs(val fields: js.Dictionary[TypeDefinitionJs], val tag: String)
extends TypeDefinitionJs
object LabeledTypeDefJs {
def apply(l: LabeledProductTypeDef): LabeledTypeDefJs = {
LabeledTypeDefJs(
new LabeledTypeDefJs(
js.Dictionary[TypeDefinitionJs](l.fields.map { case (n, t) => (n, TypeDefinitionJs(t)) }: _*),
l.tag
)
}
}
@JSExportAll
case class UnlabeledTypeDefJs(items: js.Array[TypeDefinitionJs], tag: String)
class UnlabeledTypeDefJs(val items: js.Array[TypeDefinitionJs], val tag: String)
extends TypeDefinitionJs
@JSExportAll
case class TopTypeDefJs(tag: String) extends TypeDefinitionJs
class TopTypeDefJs(val tag: String) extends TypeDefinitionJs
@JSExportAll
case class BottomTypeDefJs(tag: String) extends TypeDefinitionJs
class BottomTypeDefJs(val tag: String) extends TypeDefinitionJs
@JSExportAll
case class NilTypeDefJs(tag: String) extends TypeDefinitionJs
class NilTypeDefJs(val tag: String) extends TypeDefinitionJs
@JSExportAll
case class ArrowTypeDefJs(
domain: TypeDefinitionJs,
codomain: TypeDefinitionJs,
tag: String
class ArrowTypeDefJs(
val domain: TypeDefinitionJs,
val codomain: TypeDefinitionJs,
val tag: String
) extends TypeDefinitionJs
object TypeDefinitionJs {
def apply(td: TypeDefinition): TypeDefinitionJs = td match {
case o @ OptionTypeDef(t) => OptionTypeDefJs(apply(t), o.tag)
case a @ ArrayTypeDef(t) => ArrayTypeDefJs(apply(t), a.tag)
case s @ ScalarTypeDef(n) => ScalarTypeDefJs(n, s.tag)
case o @ OptionTypeDef(t) => new OptionTypeDefJs(apply(t), o.tag)
case a @ ArrayTypeDef(t) => new ArrayTypeDefJs(apply(t), a.tag)
case s @ ScalarTypeDef(n) => new ScalarTypeDefJs(n, s.tag)
case s @ StructTypeDef(n, f) =>
StructTypeDefJs(
new StructTypeDefJs(
n,
js.Dictionary[TypeDefinitionJs](f.toList.map { case (n, t) =>
(n, TypeDefinitionJs(t))
@ -104,46 +92,44 @@ object TypeDefinitionJs {
case l: LabeledProductTypeDef =>
LabeledTypeDefJs(l)
case u @ UnlabeledProductTypeDef(items) =>
UnlabeledTypeDefJs(items.map(TypeDefinitionJs.apply).toJSArray, u.tag)
new UnlabeledTypeDefJs(items.map(TypeDefinitionJs.apply).toJSArray, u.tag)
case a @ ArrowTypeDef(domain, codomain) =>
ArrowTypeDefJs(apply(domain), apply(codomain), a.tag)
case n @ NilTypeDef => NilTypeDefJs(n.tag)
case n @ TopTypeDef => TopTypeDefJs(n.tag)
case n @ BottomTypeDef => BottomTypeDefJs(n.tag)
new ArrowTypeDefJs(apply(domain), apply(codomain), a.tag)
case n @ NilTypeDef => new NilTypeDefJs(n.tag)
case n @ TopTypeDef => new TopTypeDefJs(n.tag)
case n @ BottomTypeDef => new BottomTypeDefJs(n.tag)
}
}
@JSExportAll
case class ServiceDefJs(
defaultServiceId: js.UndefOr[String],
functions: LabeledTypeDefJs
)
class ServiceDefJs(
val defaultServiceId: js.UndefOr[String],
val functions: LabeledTypeDefJs
) extends js.Object
object ServiceDefJs {
def apply(sd: ServiceDef): ServiceDefJs = {
ServiceDefJs(
new ServiceDefJs(
sd.defaultServiceId.getOrElse(()),
LabeledTypeDefJs(sd.functions)
)
}
}
@JSExportAll
case class NamesConfigJs(
relay: String,
getDataSrv: String,
callbackSrv: String,
responseSrv: String,
responseFnName: String,
errorHandlingSrv: String,
errorFnName: String
)
class NamesConfigJs(
val relay: String,
val getDataSrv: String,
val callbackSrv: String,
val responseSrv: String,
val responseFnName: String,
val errorHandlingSrv: String,
val errorFnName: String
) extends js.Object
object NamesConfigJs {
def apply(nc: NamesConfig): NamesConfigJs = {
NamesConfigJs(
new NamesConfigJs(
nc.relay,
nc.getDataSrv,
nc.callbackSrv,
@ -157,5 +143,4 @@ object NamesConfigJs {
type LogLevel = "trace" | "debug" | "info" | "warn" | "error" | "off"
@JSExportAll
case class Debug(printParticleId: js.UndefOr[Boolean], marineLogLevel: js.UndefOr[LogLevel])
class Debug(val printParticleId: js.UndefOr[Boolean], val marineLogLevel: js.UndefOr[LogLevel]) extends js.Object

View File

@ -4,28 +4,29 @@ import aqua.parser.lift.FileSpan
import scala.scalajs.js
import scala.scalajs.js.annotation.JSExportAll
import scala.scalajs.js.{undefined, UndefOr}
import scala.scalajs.js.{UndefOr, undefined}
@JSExportAll
case class CompilationResult(
errors: js.Array[ErrorInfo],
warnings: js.Array[WarningInfo] = js.Array(),
locations: js.Array[TokenLink] = js.Array(),
importLocations: js.Array[TokenImport] = js.Array(),
tokens: js.Array[ExprInfoJs] = js.Array()
)
class CompilationResult(
val errors: js.Array[ErrorInfo],
val warnings: js.Array[WarningInfo] = js.Array(),
val locations: js.Array[TokenLink] = js.Array(),
val importLocations: js.Array[TokenImport] = js.Array(),
val tokens: js.Array[ExprInfoJs] = js.Array()
) extends js.Object
@JSExportAll
case class ExprInfoJs(location: TokenLocation, `type`: TypeJs)
class ExprInfoJs(val location: TokenLocation, val `type`: TypeJs) extends js.Object
@JSExportAll
case class TokenLocation(name: String, startLine: Int, startCol: Int, endLine: Int, endCol: Int)
class TokenLocation(
val name: String,
val startLine: Int,
val startCol: Int,
val endLine: Int,
val endCol: Int
) extends js.Object
@JSExportAll
case class TokenLink(current: TokenLocation, definition: TokenLocation)
class TokenLink(val current: TokenLocation, val definition: TokenLocation) extends js.Object
@JSExportAll
case class TokenImport(current: TokenLocation, path: String)
class TokenImport(val current: TokenLocation, val path: String) extends js.Object
object TokenLocation {
@ -36,18 +37,17 @@ object TokenLocation {
for {
startLC <- start
endLC <- end
} yield TokenLocation(span.name, startLC._1, startLC._2, endLC._1, endLC._2)
} yield new TokenLocation(span.name, startLC._1, startLC._2, endLC._1, endLC._2)
}
}
@JSExportAll
case class ErrorInfo(
start: Int,
end: Int,
message: String,
location: UndefOr[String]
) {
class ErrorInfo(
val start: Int,
val end: Int,
val message: String,
val location: UndefOr[String]
) extends js.Object {
// Used to distinguish from WarningInfo in TS
val infoType: String = "error"
}
@ -57,21 +57,20 @@ object ErrorInfo {
def apply(fileSpan: FileSpan, message: String): ErrorInfo = {
val start = fileSpan.span.startIndex
val end = fileSpan.span.endIndex
ErrorInfo(start, end, message, fileSpan.name)
new ErrorInfo(start, end, message, fileSpan.name)
}
def applyOp(start: Int, end: Int, message: String, location: Option[String]): ErrorInfo = {
ErrorInfo(start, end, message, location.getOrElse(undefined))
new ErrorInfo(start, end, message, location.getOrElse(undefined))
}
}
@JSExportAll
case class WarningInfo(
start: Int,
end: Int,
message: String,
location: UndefOr[String]
) {
class WarningInfo(
val start: Int,
val end: Int,
val message: String,
val location: UndefOr[String]
) extends js.Object {
// Used to distinguish from ErrorInfo in TS
val infoType: String = "warning"
}
@ -81,6 +80,6 @@ object WarningInfo {
def apply(fileSpan: FileSpan, message: String): WarningInfo = {
val start = fileSpan.span.startIndex
val end = fileSpan.span.endIndex
WarningInfo(start, end, message, fileSpan.name)
new WarningInfo(start, end, message, fileSpan.name)
}
}