├── .github
└── workflows
│ └── release.yml
├── .gitignore
├── .scalafmt.conf
├── annotations
└── src
│ └── main
│ └── scala
│ └── eu
│ └── swdev
│ └── scala
│ └── ts
│ └── annotation
│ └── adapt-annotations.scala
├── build.sbt
├── example
└── angular
│ ├── build.sbt
│ ├── client
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── CounterClient.scala
│ ├── project
│ ├── build.properties
│ └── plugins.sbt
│ ├── readme.md
│ ├── server
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── CounterServer.scala
│ ├── shared
│ └── src
│ │ └── main
│ │ └── scala
│ │ └── CounterEndpoints.scala
│ └── webapp
│ ├── README.md
│ ├── angular.json
│ ├── browserslist
│ ├── karma.conf.js
│ ├── package-lock.json
│ ├── package.json
│ ├── proxy.conf.json
│ ├── src
│ ├── app
│ │ ├── app.component.css
│ │ ├── app.component.html
│ │ ├── app.component.spec.ts
│ │ ├── app.component.ts
│ │ └── app.module.ts
│ ├── environments
│ │ ├── environment.prod.ts
│ │ └── environment.ts
│ ├── favicon.ico
│ ├── index.html
│ ├── main.ts
│ ├── polyfills.ts
│ ├── styles.css
│ └── test.ts
│ ├── tsconfig.app.json
│ ├── tsconfig.json
│ ├── tsconfig.spec.json
│ └── tslint.json
├── explore
├── jest.config.mjs
├── module
│ ├── index.d.ts
│ ├── index.js
│ ├── index.js.map
│ └── package.json
├── package-lock.json
├── package.json
├── readme.md
├── src
│ ├── app.ts
│ ├── main
│ │ ├── module
│ │ │ ├── index.d.ts
│ │ │ └── package.json
│ │ └── scala
│ │ │ ├── AdapterV1.scala
│ │ │ └── scalajs.scala
│ └── test
│ │ └── ts
│ │ ├── adapter.spec.ts
│ │ ├── adt.spec.ts
│ │ ├── array.spec.ts
│ │ ├── class-with-inner-obj.spec.ts
│ │ ├── iterator.spec.ts
│ │ ├── non-exported-js-object.spec.ts
│ │ ├── property.spec.ts
│ │ ├── trait-methods.spec.ts
│ │ └── util.ts
├── tsconfig.json
└── tslint.json
├── generator
└── src
│ ├── main
│ └── scala
│ │ └── eu
│ │ └── swdev
│ │ └── scala
│ │ └── ts
│ │ ├── Adapter.scala
│ │ ├── AdapterGenerator.scala
│ │ ├── AdapterGeneratorMain.scala
│ │ ├── AdapterTypeFormatter.scala
│ │ ├── Adaption.scala
│ │ ├── Analyzer.scala
│ │ ├── DtsGeneratorMain.scala
│ │ ├── Generator.scala
│ │ ├── GeneratorMain.scala
│ │ ├── Input.scala
│ │ ├── Namespace.scala
│ │ ├── NativeSymbolAnalyzer.scala
│ │ ├── Output.scala
│ │ ├── ReferencedSymbolsAnalyzer.scala
│ │ ├── Result.scala
│ │ ├── SealedTraitSubtypeAnalyzer.scala
│ │ ├── SemSource.scala
│ │ ├── TypeFormatter.scala
│ │ ├── ValidationInfo.scala
│ │ └── package.scala
│ └── test
│ ├── scala-2.13
│ └── eu
│ │ └── swdev
│ │ └── scala
│ │ └── ts
│ │ └── dts
│ │ └── LiteralTypeTest.scala
│ └── scala
│ ├── eu
│ └── swdev
│ │ └── scala
│ │ └── ts
│ │ ├── AbstractAutoDetectingTest.scala
│ │ ├── AdapterFunSuite.scala
│ │ ├── DtsFunSuite.scala
│ │ ├── FullNameTest.scala
│ │ ├── GeneratorTest.scala
│ │ ├── NativeSymbolAnalyzerTest.scala
│ │ ├── ScalaMetaHelper.scala
│ │ ├── adapter
│ │ ├── ArrayTest.scala
│ │ ├── ClassTest.scala
│ │ ├── ListTest.scala
│ │ ├── NestedClassTest.scala
│ │ └── ObjectDefValVarTest.scala
│ │ ├── auto
│ │ ├── AutoDetectingTest.scala
│ │ ├── PrimitiveTypes.scala
│ │ ├── group-1-file-1.scala
│ │ └── group-1-file-2.scala
│ │ ├── dts
│ │ ├── AbstractClassTest1.scala
│ │ ├── AbstractClassTest2.scala
│ │ ├── AccessorPairTest.scala
│ │ ├── AccessorTest.scala
│ │ ├── AdapterClassTest.scala
│ │ ├── AdapterNestedClassTest.scala
│ │ ├── AdapterV1.scala
│ │ ├── Adt1Test.scala
│ │ ├── Adt2Test.scala
│ │ ├── Adt3Test.scala
│ │ ├── AliasTest.scala
│ │ ├── ApiReferenceTest.scala
│ │ ├── ArrayTest.scala
│ │ ├── ArrayTypeAliasTest.scala
│ │ ├── BoundsTest.scala
│ │ ├── BracketNotationTest.scala
│ │ ├── ClassInheritanceTest.scala
│ │ ├── ClassTest.scala
│ │ ├── ClassWithInnerObjPropertyTest.scala
│ │ ├── CtorParamExportTest.scala
│ │ ├── DateTest.scala
│ │ ├── DictionaryTest.scala
│ │ ├── FunctionTest.scala
│ │ ├── GenericClassTest.scala
│ │ ├── GenericFunctionTest.scala
│ │ ├── GenericUnionTest.scala
│ │ ├── GlobalTest.scala
│ │ ├── ImportNamespaceTest.scala
│ │ ├── ImportTest.scala
│ │ ├── InnerClassTest.scala
│ │ ├── IteratorTest.scala
│ │ ├── JSExportTest.scala
│ │ ├── JsClassTest.scala
│ │ ├── NativeSymbolTest.scala
│ │ ├── NoneTest.scala
│ │ ├── ObjectTest.scala
│ │ ├── OuterTest.scala
│ │ ├── PromiseLikeTest.scala
│ │ ├── PromiseTest.scala
│ │ ├── ReadOnlyArrayTest.scala
│ │ ├── RegExpTest.scala
│ │ ├── RootPackageClassTest.scala
│ │ ├── RootPackageObjectTest.scala
│ │ ├── SealedTraitAllMembersExportedTest.scala
│ │ ├── SealedTraitHierarchyTest.scala
│ │ ├── SealedTraitNoMembersExportedTest.scala
│ │ ├── SealedTraitSomeMembersExportedTest.scala
│ │ ├── SealedTraitUnexportedMembersTest.scala
│ │ ├── SealedTraitWithoutMembersExportedTest.scala
│ │ ├── StaticTest.scala
│ │ ├── SymbolTest.scala
│ │ ├── ThisFunctionTest.scala
│ │ ├── TopLevelDefValVarTest.scala
│ │ ├── TraitInheritanceTest1.scala
│ │ ├── TraitInheritanceTest2.scala
│ │ ├── TupleTest.scala
│ │ ├── TypeAliasTest.scala
│ │ ├── UndefOrTest.scala
│ │ ├── UnionTest.scala
│ │ └── VarArgsTest.scala
│ │ └── tpe
│ │ └── package.scala
│ └── scala
│ └── scalajs
│ └── js
│ ├── annotation
│ └── stubs.scala
│ ├── package.scala
│ └── stubs.scala
├── project
├── build.properties
└── plugins.sbt
├── readme.md
├── runtime
└── src
│ ├── main
│ └── scala
│ │ └── eu
│ │ └── swdev
│ │ └── scala
│ │ └── ts
│ │ ├── adapter
│ │ ├── InteropConverter.scala
│ │ ├── InteropIterable.scala
│ │ └── package.scala
│ │ └── tpe
│ │ └── package.scala
│ └── test
│ └── scala
│ └── eu
│ └── swdev
│ └── scala
│ └── ts
│ └── adapter
│ ├── AsyncConverterTest.scala
│ └── ConverterTest.scala
└── sbt-scala-ts
└── src
├── main
└── scala
│ ├── BuildInfo.scala
│ └── ScalaTsPlugin.scala
└── sbt-test
├── readme.md
└── scala-ts
├── adapter
├── build.sbt
├── client
│ ├── package-lock.json
│ ├── package.json
│ ├── src
│ │ └── test
│ │ │ └── ts
│ │ │ ├── spec
│ │ │ ├── date-adaption.spec.ts
│ │ │ ├── nested-class.spec.ts
│ │ │ ├── package-object.spec.ts
│ │ │ ├── simple-class.spec.ts
│ │ │ ├── util.spec.ts
│ │ │ └── util.ts
│ │ │ ├── tsconfig.json
│ │ │ ├── ws-scala-2.12
│ │ │ ├── jest.config.mjs
│ │ │ ├── mod
│ │ │ │ └── scala-ts-mod.ts
│ │ │ ├── package.json
│ │ │ ├── spec
│ │ │ └── tsconfig.json
│ │ │ └── ws-scala-2.13
│ │ │ ├── jest.config.mjs
│ │ │ ├── mod
│ │ │ └── scala-ts-mod.ts
│ │ │ ├── package.json
│ │ │ ├── spec
│ │ │ └── tsconfig.json
│ └── tsconfig.json
├── project
│ ├── build.properties
│ ├── plugins.sbt
│ └── project
│ │ └── plugins.sbt
├── readme.md
├── shared
│ └── src
│ │ └── main
│ │ └── scala
│ │ ├── DateAdaption.scala
│ │ ├── OuterClass.scala
│ │ ├── SimpleClass.scala
│ │ ├── Util.scala
│ │ └── eu
│ │ └── swdev
│ │ └── scala
│ │ └── ts
│ │ └── adapter
│ │ └── test
│ │ └── package.scala
└── test
├── dts
├── build.sbt
├── package-lock.json
├── package.json
├── project
│ ├── build.properties
│ ├── plugins.sbt
│ └── project
│ │ └── plugins.sbt
├── readme.md
├── src
│ ├── main
│ │ ├── scala-2.13
│ │ │ └── e2e
│ │ │ │ ├── AdtTest.scala
│ │ │ │ └── FunctionTest.scala
│ │ └── scala
│ │ │ └── e2e
│ │ │ ├── Abstract.scala
│ │ │ ├── Adapter1.scala
│ │ │ ├── AdapterWithInnerClass.scala
│ │ │ ├── BigIntInterop.scala
│ │ │ ├── BracketNotation.scala
│ │ │ ├── ClassWithStatics.scala
│ │ │ ├── FromToRange.scala
│ │ │ ├── Outer.scala
│ │ │ ├── TraitInheritance1.scala
│ │ │ ├── TraitInheritance2.scala
│ │ │ ├── file1.scala
│ │ │ └── root-package.scala
│ └── test
│ │ └── ts
│ │ ├── spec
│ │ ├── abstract.spec.ts
│ │ ├── api-reference.spec.ts
│ │ ├── bigint.spec.ts
│ │ ├── bracket-notation.spec.ts
│ │ ├── ctor-param-export.spec.ts
│ │ ├── date.spec.ts
│ │ ├── dictionary.spec.ts
│ │ ├── global.spec.ts
│ │ ├── import.spec.ts
│ │ ├── iterable.spec.ts
│ │ ├── iterator.spec.ts
│ │ ├── js-class.spec.ts
│ │ ├── nested-objects.spec.ts
│ │ ├── promise.spec.ts
│ │ ├── regexp.spec.ts
│ │ ├── root-package.spec.ts
│ │ ├── static.spec.ts
│ │ ├── this-function.spec.ts
│ │ ├── top-level-def-val-var.spec.ts
│ │ ├── trait-inheritance.spec.ts
│ │ ├── tuple.spec.ts
│ │ ├── type-conversions.spec.ts
│ │ ├── union.spec.ts
│ │ └── varargs.spec.ts
│ │ ├── tsconfig.json
│ │ ├── ws-scala-2.12
│ │ ├── jest.config.mjs
│ │ ├── mod
│ │ │ └── scala-ts-mod.ts
│ │ ├── package.json
│ │ ├── spec
│ │ └── tsconfig.json
│ │ └── ws-scala-2.13
│ │ ├── jest.config.mjs
│ │ ├── mod
│ │ └── scala-ts-mod.ts
│ │ ├── package.json
│ │ ├── spec
│ │ ├── spec-2.13
│ │ ├── function.spec.ts
│ │ ├── object-adt.spec.ts
│ │ ├── simple-adt.spec.ts
│ │ └── util.ts
│ │ └── tsconfig.json
└── test
├── readme.md
└── simple
├── build.sbt
├── project
├── build.properties
├── plugins.sbt
└── project
│ └── plugins.sbt
├── src
└── main
│ └── scala
│ └── simple
│ └── file1.scala
└── test
/.github/workflows/release.yml:
--------------------------------------------------------------------------------
1 | name: Release
2 | on:
3 | push:
4 | branches: [master, main, 'feature/**']
5 | tags: ["*"]
6 | jobs:
7 | publish:
8 | runs-on: ubuntu-20.04
9 | steps:
10 | - uses: actions/checkout@v3
11 | with:
12 | fetch-depth: 0
13 | - uses: actions/setup-java@v3
14 | with:
15 | distribution: temurin
16 | java-version: 8
17 | cache: sbt
18 | - run: sbt ci-release
19 | env:
20 | PGP_PASSPHRASE: ${{ secrets.PGP_PASSPHRASE }}
21 | PGP_SECRET: ${{ secrets.PGP_SECRET }}
22 | SONATYPE_PASSWORD: ${{ secrets.SONATYPE_PASSWORD }}
23 | SONATYPE_USERNAME: ${{ secrets.SONATYPE_USERNAME }}
24 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | .*
2 | !.github
3 | target
4 | dist
5 | node_modules
6 |
--------------------------------------------------------------------------------
/.scalafmt.conf:
--------------------------------------------------------------------------------
1 | maxColumn = 140
2 | align = most
3 |
--------------------------------------------------------------------------------
/annotations/src/main/scala/eu/swdev/scala/ts/annotation/adapt-annotations.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.annotation
2 |
3 | import scala.annotation.Annotation
4 |
5 | /**
6 | * Indicates that adapter code should be generated and allows to override the default interoperation type.
7 | *
8 | * The interop type is the type that is exposed to the JavaScript side. It is either the type of parameters
9 | * or of returned values. ScalaTs chooses a default interop type if no interop type is specified.
10 | *
11 | * - When applied to a def, val, var then adapter code for accessing the definition is created; the interop
12 | * specifies the type of the returned value.
13 | * - When applied to a parameter of an adapted 'def' or constructor then the interop type specifies the type
14 | * of the exposed parameter.
15 | *
16 | * This annotation has no effect when applied on classes, objects, or traits.
17 | */
18 | class Adapt extends Annotation {
19 | def this(interopType: String) = this()
20 | }
21 |
22 | /**
23 | * Indicates that adapter code for all members should be generated.
24 | *
25 | * Can be applied to classes, objects, and traits.
26 | */
27 | class AdaptMembers extends Annotation
28 |
29 | /**
30 | * Indicates that adapter code for a constructor should be generated.
31 | *
32 | * Can be applied to classes.
33 | */
34 | class AdaptConstructor extends Annotation
35 |
36 | /**
37 | * Implies [[AdaptMembers]] and [[AdaptConstructor]].
38 | *
39 | * Can be applied to classes, objects, and traits.
40 | */
41 | class AdaptAll extends Annotation
42 |
43 |
--------------------------------------------------------------------------------
/example/angular/build.sbt:
--------------------------------------------------------------------------------
1 | ThisBuild / scalaVersion := "2.13.11"
2 |
3 | val shared =
4 | crossProject(JSPlatform, JVMPlatform)
5 | .crossType(CrossType.Pure)
6 | .settings(
7 | libraryDependencies ++= Seq(
8 | "org.endpoints4s" %%% "algebra" % "1.0.0",
9 | "org.endpoints4s" %%% "json-schema-generic" % "1.0.0",
10 | )
11 | )
12 | .jvmSettings(
13 | libraryDependencies += "org.scala-js" %% "scalajs-stubs" % "1.0.0" % "provided",
14 | )
15 | .jsSettings(
16 | // the shared project contains classes (i.e. Counter and Increment) that are referenced in the exported API of the client project
17 | // -> semantic db information is required for these classes
18 | // -> configure the semanticdb compiler plugin
19 | ScalaTsPlugin.crossProject.jsSettings
20 | )
21 |
22 | val sharedJS = shared.js
23 | val sharedJVM = shared.jvm
24 |
25 | val client =
26 | project
27 | .enablePlugins(ScalaTsPlugin)
28 | .settings(
29 | scalaTsModuleName := "scala-client",
30 | scalaTsConsiderFullCompileClassPath := true,
31 | libraryDependencies += "org.endpoints4s" %%% "xhr-client" % "1.0.0+sjs1",
32 | )
33 | .dependsOn(sharedJS)
34 |
35 | val server =
36 | project
37 | .settings(
38 | libraryDependencies ++= Seq(
39 | "org.endpoints4s" %% "akka-http-server" % "1.0.0",
40 | )
41 | )
42 | .dependsOn(sharedJVM)
43 |
44 | lazy val root = project
45 | .in(file("."))
46 | .aggregate(client, server, sharedJS, sharedJVM)
47 | .settings(
48 | name := "scala-ts-angular",
49 | publish := {},
50 | publishLocal := {},
51 | )
52 |
--------------------------------------------------------------------------------
/example/angular/client/src/main/scala/CounterClient.scala:
--------------------------------------------------------------------------------
1 | package org.test.client
2 |
3 | import endpoints4s.xhr
4 | import org.test.shared.{Counter, CounterEndpoints, Increment}
5 |
6 | import scala.scalajs.js
7 | import scala.scalajs.js.annotation.JSExportTopLevel
8 |
9 | /**
10 | * Defines an HTTP client for the endpoints described in the `CounterEndpoints` trait.
11 | * The derived HTTP client uses XMLHttpRequest to perform requests and returns
12 | * results in a `js.Thenable`.
13 | */
14 | @JSExportTopLevel("CounterClient")
15 | object CounterClient extends js.Object {
16 |
17 | private object client
18 | extends CounterEndpoints
19 | with xhr.thenable.Endpoints
20 | with xhr.JsonEntitiesFromSchemas
21 |
22 | /**
23 | * Performs an XMLHttpRequest on the `currentValue` endpoint, and then
24 | * deserializes the JSON response as a `Counter`.
25 | */
26 | def currentValue(): js.Thenable[Counter] = client.currentValue(())
27 |
28 | /**
29 | * Serializes the `Increment` value into JSON and performs an XMLHttpRequest
30 | * on the `increment` endpoint.
31 | */
32 | def increment(value: Int): js.Thenable[Unit] = client.increment(Increment(value))
33 | }
34 |
--------------------------------------------------------------------------------
/example/angular/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.9.3
--------------------------------------------------------------------------------
/example/angular/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("io.github.swachter" % "sbt-scala-ts" % "0.12.0")
2 |
3 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.1.1")
4 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0")
5 |
--------------------------------------------------------------------------------
/example/angular/readme.md:
--------------------------------------------------------------------------------
1 | ### Example Project: Angular with [endpoint4s](https://endpoints4s.github.io/)
2 |
3 | - A simple counter service is defined using endpoint4s. The example was copied from endpoint4s.
4 | - The definition is shared by the server and the client.
5 | - A Node module is generated that allows the Angular applicatioin to communicate with the server in a type safe manner.
6 |
7 | Generate the Node module that is used in the Angular application to access the server:
8 |
9 | ```
10 | > sbt client/scalaTsFastOpt
11 | ```
12 |
13 | Start the server via SBT:
14 |
15 | ```
16 | > sbt server/run
17 | ```
18 |
19 | In the webapp folder run:
20 |
21 | ```
22 | > npm i
23 | > npm start
24 | ```
--------------------------------------------------------------------------------
/example/angular/server/src/main/scala/CounterServer.scala:
--------------------------------------------------------------------------------
1 | package org.test.server
2 |
3 | import java.util.concurrent.atomic.AtomicInteger
4 |
5 | import akka.http.scaladsl.server.Directives._
6 | import akka.http.scaladsl.server.{HttpApp, Route}
7 | import endpoints4s.akkahttp.server
8 | import org.test.shared.{Counter, CounterEndpoints}
9 |
10 | /**
11 | * Defines Akka HTTP routes for the endpoints described in the `CounterEndpoints` trait.
12 | */
13 | object CounterServer
14 | extends CounterEndpoints
15 | with server.Endpoints
16 | with server.JsonEntitiesFromSchemas {
17 |
18 | /** Simple implementation of an in-memory counter */
19 | val counter = new AtomicInteger()
20 |
21 | // Implements the `currentValue` endpoint
22 | val currentValueRoute = currentValue.implementedBy(_ => Counter(counter.get))
23 |
24 | // Implements the `increment` endpoint
25 | val incrementRoute = increment.implementedBy(inc => counter.addAndGet(inc.step))
26 |
27 | val routes: Route = currentValueRoute ~ incrementRoute
28 |
29 | }
30 |
31 | object WebServer extends HttpApp {
32 | override protected def routes: Route = CounterServer.routes
33 |
34 | def main(args: Array[String]): Unit = startServer("localhost", 8000)
35 | }
--------------------------------------------------------------------------------
/example/angular/shared/src/main/scala/CounterEndpoints.scala:
--------------------------------------------------------------------------------
1 | package org.test.shared
2 |
3 | import endpoints4s.{algebra, generic}
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | /**
8 | * Defines the HTTP endpoints description of a web service implementing a counter.
9 | * This web service has two endpoints: one for getting the current value of the counter,
10 | * and one for incrementing it.
11 | */
12 | trait CounterEndpoints extends algebra.Endpoints with algebra.JsonEntitiesFromSchemas with generic.JsonSchemas {
13 |
14 | /**
15 | * Get the counter current value.
16 | * Uses the HTTP verb “GET” and URL path “/current-value”.
17 | * The response entity is a JSON document representing the counter value.
18 | */
19 | val currentValue: Endpoint[Unit, Counter] = endpoint(get(path / "current-value"), ok(jsonResponse[Counter]))
20 |
21 | /**
22 | * Increments the counter value.
23 | * Uses the HTTP verb “POST” and URL path “/increment”.
24 | * The request entity is a JSON document representing the increment to apply to the counter.
25 | * The response entity is empty.
26 | */
27 | val increment: Endpoint[Increment, Unit] = endpoint(post(path / "increment", jsonRequest[Increment]), ok(emptyResponse))
28 |
29 | // Generically derive the JSON schema of our `Counter`
30 | // and `Increment` case classes defined thereafter
31 | implicit lazy val counterSchema: JsonSchema[Counter] = genericJsonSchema
32 | implicit lazy val incrementSchema: JsonSchema[Increment] = genericJsonSchema
33 |
34 | }
35 |
36 | @JSExportTopLevel("Counter")
37 | @JSExportAll
38 | case class Counter(value: Int)
39 | @JSExportTopLevel("Increment")
40 | @JSExportAll
41 | case class Increment(step: Int)
42 |
--------------------------------------------------------------------------------
/example/angular/webapp/README.md:
--------------------------------------------------------------------------------
1 | # Webapp
2 |
3 | This project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 9.1.11.
4 |
5 | ## Development server
6 |
7 | Run `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.
8 |
9 | ## Code scaffolding
10 |
11 | Run `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.
12 |
13 | ## Build
14 |
15 | Run `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `--prod` flag for a production build.
16 |
17 | ## Running unit tests
18 |
19 | Run `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).
20 |
21 | ## Running end-to-end tests
22 |
23 | Run `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).
24 |
25 | ## Further help
26 |
27 | To get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).
28 |
--------------------------------------------------------------------------------
/example/angular/webapp/browserslist:
--------------------------------------------------------------------------------
1 | # This file is used by the build system to adjust CSS and JS output to support the specified browsers below.
2 | # For additional information regarding the format and rule options, please see:
3 | # https://github.com/browserslist/browserslist#queries
4 |
5 | # You can see what browsers were selected by your queries by running:
6 | # npx browserslist
7 |
8 | > 0.5%
9 | last 2 versions
10 | Firefox ESR
11 | not dead
12 | not IE 9-11 # For IE 9-11 support, remove 'not'.
--------------------------------------------------------------------------------
/example/angular/webapp/karma.conf.js:
--------------------------------------------------------------------------------
1 | // Karma configuration file, see link for more information
2 | // https://karma-runner.github.io/1.0/config/configuration-file.html
3 |
4 | module.exports = function (config) {
5 | config.set({
6 | basePath: '',
7 | frameworks: ['jasmine', '@angular-devkit/build-angular'],
8 | plugins: [
9 | require('karma-jasmine'),
10 | require('karma-chrome-launcher'),
11 | require('karma-jasmine-html-reporter'),
12 | require('karma-coverage-istanbul-reporter'),
13 | require('@angular-devkit/build-angular/plugins/karma')
14 | ],
15 | client: {
16 | clearContext: false // leave Jasmine Spec Runner output visible in browser
17 | },
18 | coverageIstanbulReporter: {
19 | dir: require('path').join(__dirname, './coverage/webapp'),
20 | reports: ['html', 'lcovonly', 'text-summary'],
21 | fixWebpackSourcePaths: true
22 | },
23 | reporters: ['progress', 'kjhtml'],
24 | port: 9876,
25 | colors: true,
26 | logLevel: config.LOG_INFO,
27 | autoWatch: true,
28 | browsers: ['Chrome'],
29 | singleRun: false,
30 | restartOnFileChange: true
31 | });
32 | };
33 |
--------------------------------------------------------------------------------
/example/angular/webapp/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "webapp",
3 | "version": "0.0.0",
4 | "scripts": {
5 | "ng": "ng",
6 | "start": "ng serve --proxy-config proxy.conf.json --open",
7 | "build": "ng build",
8 | "test": "ng test",
9 | "lint": "ng lint",
10 | "e2e": "ng e2e"
11 | },
12 | "type": "module",
13 | "private": true,
14 | "dependencies": {
15 | "@angular/animations": "~9.1.12",
16 | "@angular/common": "~9.1.12",
17 | "@angular/compiler": "~9.1.12",
18 | "@angular/core": "~9.1.12",
19 | "@angular/forms": "~9.1.12",
20 | "@angular/platform-browser": "~9.1.12",
21 | "@angular/platform-browser-dynamic": "~9.1.12",
22 | "@angular/router": "~9.1.12",
23 | "rxjs": "~6.5.4",
24 | "scala-client": "file:../client/target/scala-2.13",
25 | "tslib": "^1.10.0",
26 | "zone.js": "~0.10.2"
27 | },
28 | "devDependencies": {
29 | "@angular-devkit/build-angular": "~0.901.11",
30 | "@angular/cli": "~9.1.11",
31 | "@angular/compiler-cli": "~9.1.12",
32 | "@types/node": "^12.11.1",
33 | "@types/jasmine": "~3.5.0",
34 | "@types/jasminewd2": "~2.0.3",
35 | "codelyzer": "^5.1.2",
36 | "jasmine-core": "~3.5.0",
37 | "jasmine-spec-reporter": "~4.2.1",
38 | "karma": "~5.0.0",
39 | "karma-chrome-launcher": "~3.1.0",
40 | "karma-coverage-istanbul-reporter": "~2.1.0",
41 | "karma-jasmine": "~3.0.1",
42 | "karma-jasmine-html-reporter": "^1.4.2",
43 | "protractor": "~7.0.0",
44 | "ts-node": "~8.3.0",
45 | "tslint": "~6.1.0",
46 | "typescript": "~3.8.3"
47 | }
48 | }
49 |
--------------------------------------------------------------------------------
/example/angular/webapp/proxy.conf.json:
--------------------------------------------------------------------------------
1 | {
2 | "*": {
3 | "target": "http://localhost:8000",
4 | "secure": false,
5 | "pathRewrite": {
6 | "^/posts": ""
7 | },
8 | "changeOrigin": true
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/app/app.component.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swachter/scala-ts/5ae7cf3d79213686157e2a38d0afcace7037335d/example/angular/webapp/src/app/app.component.css
--------------------------------------------------------------------------------
/example/angular/webapp/src/app/app.component.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
current counter value: {{counterValue}}
4 |
5 |
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/app/app.component.spec.ts:
--------------------------------------------------------------------------------
1 | import { TestBed, async } from '@angular/core/testing';
2 | import { AppComponent } from './app.component';
3 |
4 | describe('AppComponent', () => {
5 | beforeEach(async(() => {
6 | TestBed.configureTestingModule({
7 | declarations: [
8 | AppComponent
9 | ],
10 | }).compileComponents();
11 | }));
12 |
13 | it('should create the app', () => {
14 | const fixture = TestBed.createComponent(AppComponent);
15 | const app = fixture.componentInstance;
16 | expect(app).toBeTruthy();
17 | });
18 |
19 | it(`should have as title 'webapp'`, () => {
20 | const fixture = TestBed.createComponent(AppComponent);
21 | const app = fixture.componentInstance;
22 | expect(app.title).toEqual('webapp');
23 | });
24 |
25 | it('should render title', () => {
26 | const fixture = TestBed.createComponent(AppComponent);
27 | fixture.detectChanges();
28 | const compiled = fixture.nativeElement;
29 | expect(compiled.querySelector('.content span').textContent).toContain('webapp app is running!');
30 | });
31 | });
32 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/app/app.component.ts:
--------------------------------------------------------------------------------
1 | import { Component } from '@angular/core'
2 | import { CounterClient } from 'scala-client'
3 |
4 | @Component({
5 | selector: 'app-root',
6 | templateUrl: './app.component.html',
7 | styleUrls: ['./app.component.css']
8 | })
9 | export class AppComponent {
10 | title = 'webapp'
11 | counterValue: number
12 |
13 | constructor() {
14 | this.updateCurrentValue()
15 | }
16 |
17 | private updateCurrentValue(): void {
18 | CounterClient.currentValue().then(counter => this.counterValue = counter.value)
19 | }
20 |
21 | increment(): void {
22 | CounterClient.increment(1).then(_ => this.updateCurrentValue());
23 | }
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/app/app.module.ts:
--------------------------------------------------------------------------------
1 | import { BrowserModule } from '@angular/platform-browser';
2 | import { NgModule } from '@angular/core';
3 |
4 | import { AppComponent } from './app.component';
5 |
6 | @NgModule({
7 | declarations: [
8 | AppComponent
9 | ],
10 | imports: [
11 | BrowserModule
12 | ],
13 | providers: [],
14 | bootstrap: [AppComponent]
15 | })
16 | export class AppModule { }
17 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/environments/environment.prod.ts:
--------------------------------------------------------------------------------
1 | export const environment = {
2 | production: true
3 | };
4 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/environments/environment.ts:
--------------------------------------------------------------------------------
1 | // This file can be replaced during build by using the `fileReplacements` array.
2 | // `ng build --prod` replaces `environment.ts` with `environment.prod.ts`.
3 | // The list of file replacements can be found in `angular.json`.
4 |
5 | export const environment = {
6 | production: false
7 | };
8 |
9 | /*
10 | * For easier debugging in development mode, you can import the following file
11 | * to ignore zone related error stack frames such as `zone.run`, `zoneDelegate.invokeTask`.
12 | *
13 | * This import should be commented out in production mode because it will have a negative impact
14 | * on performance if an error is thrown.
15 | */
16 | // import 'zone.js/dist/zone-error'; // Included with Angular CLI.
17 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/favicon.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/swachter/scala-ts/5ae7cf3d79213686157e2a38d0afcace7037335d/example/angular/webapp/src/favicon.ico
--------------------------------------------------------------------------------
/example/angular/webapp/src/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | Webapp
6 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/main.ts:
--------------------------------------------------------------------------------
1 | import { enableProdMode } from '@angular/core';
2 | import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
3 |
4 | import { AppModule } from './app/app.module';
5 | import { environment } from './environments/environment';
6 |
7 | if (environment.production) {
8 | enableProdMode();
9 | }
10 |
11 | platformBrowserDynamic().bootstrapModule(AppModule)
12 | .catch(err => console.error(err));
13 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/polyfills.ts:
--------------------------------------------------------------------------------
1 | /**
2 | * This file includes polyfills needed by Angular and is loaded before the app.
3 | * You can add your own extra polyfills to this file.
4 | *
5 | * This file is divided into 2 sections:
6 | * 1. Browser polyfills. These are applied before loading ZoneJS and are sorted by browsers.
7 | * 2. Application imports. Files imported after ZoneJS that should be loaded before your main
8 | * file.
9 | *
10 | * The current setup is for so-called "evergreen" browsers; the last versions of browsers that
11 | * automatically update themselves. This includes Safari >= 10, Chrome >= 55 (including Opera),
12 | * Edge >= 13 on the desktop, and iOS 10 and Chrome on mobile.
13 | *
14 | * Learn more in https://angular.io/guide/browser-support
15 | */
16 |
17 | /***************************************************************************************************
18 | * BROWSER POLYFILLS
19 | */
20 |
21 | /** IE10 and IE11 requires the following for NgClass support on SVG elements */
22 | // import 'classlist.js'; // Run `npm install --save classlist.js`.
23 |
24 | /**
25 | * Web Animations `@angular/platform-browser/animations`
26 | * Only required if AnimationBuilder is used within the application and using IE/Edge or Safari.
27 | * Standard animation support in Angular DOES NOT require any polyfills (as of Angular 6.0).
28 | */
29 | // import 'web-animations-js'; // Run `npm install --save web-animations-js`.
30 |
31 | /**
32 | * By default, zone.js will patch all possible macroTask and DomEvents
33 | * user can disable parts of macroTask/DomEvents patch by setting following flags
34 | * because those flags need to be set before `zone.js` being loaded, and webpack
35 | * will put import in the top of bundle, so user need to create a separate file
36 | * in this directory (for example: zone-flags.ts), and put the following flags
37 | * into that file, and then add the following code before importing zone.js.
38 | * import './zone-flags';
39 | *
40 | * The flags allowed in zone-flags.ts are listed here.
41 | *
42 | * The following flags will work for all browsers.
43 | *
44 | * (window as any).__Zone_disable_requestAnimationFrame = true; // disable patch requestAnimationFrame
45 | * (window as any).__Zone_disable_on_property = true; // disable patch onProperty such as onclick
46 | * (window as any).__zone_symbol__UNPATCHED_EVENTS = ['scroll', 'mousemove']; // disable patch specified eventNames
47 | *
48 | * in IE/Edge developer tools, the addEventListener will also be wrapped by zone.js
49 | * with the following flag, it will bypass `zone.js` patch for IE/Edge
50 | *
51 | * (window as any).__Zone_enable_cross_context_check = true;
52 | *
53 | */
54 |
55 | /***************************************************************************************************
56 | * Zone JS is required by default for Angular itself.
57 | */
58 | import 'zone.js/dist/zone'; // Included with Angular CLI.
59 |
60 |
61 | /***************************************************************************************************
62 | * APPLICATION IMPORTS
63 | */
64 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/styles.css:
--------------------------------------------------------------------------------
1 | /* You can add global styles to this file, and also import other style files */
2 |
--------------------------------------------------------------------------------
/example/angular/webapp/src/test.ts:
--------------------------------------------------------------------------------
1 | // This file is required by karma.conf.js and loads recursively all the .spec and framework files
2 |
3 | import 'zone.js/dist/zone-testing';
4 | import { getTestBed } from '@angular/core/testing';
5 | import {
6 | BrowserDynamicTestingModule,
7 | platformBrowserDynamicTesting
8 | } from '@angular/platform-browser-dynamic/testing';
9 |
10 | declare const require: {
11 | context(path: string, deep?: boolean, filter?: RegExp): {
12 | keys(): string[];
13 | (id: string): T;
14 | };
15 | };
16 |
17 | // First, initialize the Angular testing environment.
18 | getTestBed().initTestEnvironment(
19 | BrowserDynamicTestingModule,
20 | platformBrowserDynamicTesting()
21 | );
22 | // Then we find all the tests.
23 | const context = require.context('./', true, /\.spec\.ts$/);
24 | // And load the modules.
25 | context.keys().map(context);
26 |
--------------------------------------------------------------------------------
/example/angular/webapp/tsconfig.app.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/app",
5 | "types": []
6 | },
7 | "files": [
8 | "src/main.ts",
9 | "src/polyfills.ts"
10 | ],
11 | "include": [
12 | "src/**/*.d.ts"
13 | ]
14 | }
15 |
--------------------------------------------------------------------------------
/example/angular/webapp/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compileOnSave": false,
3 | "compilerOptions": {
4 | "baseUrl": "./",
5 | "outDir": "./dist/out-tsc",
6 | "sourceMap": true,
7 | "declaration": false,
8 | "downlevelIteration": true,
9 | "experimentalDecorators": true,
10 | "module": "es2015",
11 | "moduleResolution": "node",
12 | "importHelpers": true,
13 | "target": "es2015",
14 | "lib": [
15 | "es2018",
16 | "dom"
17 | ]
18 | },
19 | "angularCompilerOptions": {
20 | "fullTemplateTypeCheck": true,
21 | "strictInjectionParameters": true
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/example/angular/webapp/tsconfig.spec.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "./tsconfig.json",
3 | "compilerOptions": {
4 | "outDir": "./out-tsc/spec",
5 | "types": [
6 | "jasmine",
7 | "node"
8 | ]
9 | },
10 | "files": [
11 | "src/test.ts",
12 | "src/polyfills.ts"
13 | ],
14 | "include": [
15 | "src/**/*.spec.ts",
16 | "src/**/*.d.ts"
17 | ]
18 | }
19 |
--------------------------------------------------------------------------------
/example/angular/webapp/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "tslint:recommended",
3 | "rules": {
4 | "align": {
5 | "options": [
6 | "parameters",
7 | "statements"
8 | ]
9 | },
10 | "array-type": false,
11 | "arrow-return-shorthand": true,
12 | "curly": true,
13 | "deprecation": {
14 | "severity": "warning"
15 | },
16 | "component-class-suffix": true,
17 | "contextual-lifecycle": true,
18 | "directive-class-suffix": true,
19 | "directive-selector": [
20 | true,
21 | "attribute",
22 | "app",
23 | "camelCase"
24 | ],
25 | "component-selector": [
26 | true,
27 | "element",
28 | "app",
29 | "kebab-case"
30 | ],
31 | "eofline": true,
32 | "import-blacklist": [
33 | true,
34 | "rxjs/Rx"
35 | ],
36 | "import-spacing": true,
37 | "indent": {
38 | "options": [
39 | "spaces"
40 | ]
41 | },
42 | "max-classes-per-file": false,
43 | "max-line-length": [
44 | true,
45 | 140
46 | ],
47 | "member-ordering": [
48 | true,
49 | {
50 | "order": [
51 | "static-field",
52 | "instance-field",
53 | "static-method",
54 | "instance-method"
55 | ]
56 | }
57 | ],
58 | "no-console": [
59 | true,
60 | "debug",
61 | "info",
62 | "time",
63 | "timeEnd",
64 | "trace"
65 | ],
66 | "no-empty": false,
67 | "no-inferrable-types": [
68 | true,
69 | "ignore-params"
70 | ],
71 | "no-non-null-assertion": true,
72 | "no-redundant-jsdoc": true,
73 | "no-switch-case-fall-through": true,
74 | "no-var-requires": false,
75 | "object-literal-key-quotes": [
76 | true,
77 | "as-needed"
78 | ],
79 | "quotemark": [
80 | true,
81 | "single"
82 | ],
83 | "semicolon": {
84 | "options": [
85 | "always"
86 | ]
87 | },
88 | "space-before-function-paren": {
89 | "options": {
90 | "anonymous": "never",
91 | "asyncArrow": "always",
92 | "constructor": "never",
93 | "method": "never",
94 | "named": "never"
95 | }
96 | },
97 | "typedef-whitespace": {
98 | "options": [
99 | {
100 | "call-signature": "nospace",
101 | "index-signature": "nospace",
102 | "parameter": "nospace",
103 | "property-declaration": "nospace",
104 | "variable-declaration": "nospace"
105 | },
106 | {
107 | "call-signature": "onespace",
108 | "index-signature": "onespace",
109 | "parameter": "onespace",
110 | "property-declaration": "onespace",
111 | "variable-declaration": "onespace"
112 | }
113 | ]
114 | },
115 | "variable-name": {
116 | "options": [
117 | "ban-keywords",
118 | "check-format",
119 | "allow-pascal-case"
120 | ]
121 | },
122 | "whitespace": {
123 | "options": [
124 | "check-branch",
125 | "check-decl",
126 | "check-operator",
127 | "check-separator",
128 | "check-type",
129 | "check-typecast"
130 | ]
131 | },
132 | "no-conflicting-lifecycle": true,
133 | "no-host-metadata-property": true,
134 | "no-input-rename": true,
135 | "no-inputs-metadata-property": true,
136 | "no-output-native": true,
137 | "no-output-on-prefix": true,
138 | "no-output-rename": true,
139 | "no-outputs-metadata-property": true,
140 | "template-banana-in-box": true,
141 | "template-no-negated-async": true,
142 | "use-lifecycle-interface": true,
143 | "use-pipe-transform-interface": true
144 | },
145 | "rulesDirectory": [
146 | "codelyzer"
147 | ]
148 | }
--------------------------------------------------------------------------------
/explore/module/index.d.ts:
--------------------------------------------------------------------------------
1 | ../src/main/module/index.d.ts
--------------------------------------------------------------------------------
/explore/module/index.js:
--------------------------------------------------------------------------------
1 | ../target/scala-2.13/explore-fastopt.js
--------------------------------------------------------------------------------
/explore/module/index.js.map:
--------------------------------------------------------------------------------
1 | ../target/scala-2.13/explore-fastopt.js.map
--------------------------------------------------------------------------------
/explore/module/package.json:
--------------------------------------------------------------------------------
1 | ../src/main/module/package.json
--------------------------------------------------------------------------------
/explore/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "manual-dts",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "tsc && node dist/app.js",
8 | "test": "tsc && node --experimental-vm-modules node_modules/jest/bin/jest"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "devDependencies": {
13 | "@types/jest": "^25.2.3",
14 | "jest": "^26.0.1",
15 | "tslint": "^6.1.2",
16 | "typescript": "^3.8.3"
17 | },
18 | "dependencies": {
19 | "@types/node": "^13.13.4",
20 | "from-scala": "file:module"
21 | },
22 | "type": "module"
23 | }
24 |
--------------------------------------------------------------------------------
/explore/readme.md:
--------------------------------------------------------------------------------
1 | Manual experiments for TypeScript <-> Scala interop
2 | ===
3 |
4 | Scala sources are compiled into JavaScript containing an EcmaScript module. ScalaJS is configured to output an EcmaScript module by setting the corresponding `ModuleKind` in `build.sbt`:
5 |
6 | ```
7 | scalaJSLinkerConfig ~= { _.withModuleKind(ModuleKind.ESModule) }
8 | ```
9 |
10 | The EcmaScript module in turn is augmented by a `package.json` and a hand crafted [TypeScript Declaration File](https://www.typescriptlang.org/docs/handbook/declaration-files/introduction.html). The module is used by the TypeScript compiler and Node to compile and run the TypeScript application `app.ts`.
11 |
12 | Commands and Setup:
13 | ---
14 |
15 | Scala sources are compiled into JavaScript by:
16 |
17 | ```
18 | > sbt explore/fastOptJS
19 | ```
20 |
21 | The top-level `module` folder contains a couple of symbolic links:
22 |
23 | ```
24 | index.d.ts -> ../src/main/module/index.d.ts
25 | index.js -> ../target/scala-2.13/explore-dts-fastopt.js
26 | index.js.map -> ../target/scala-2.13/explore-dts-fastopt.js.map
27 | package.json -> ../src/main/module/package.json
28 | ```
29 |
30 | This folder represents a node module that contains the transpiled ScalaJS code and its meta data. In particular, the `package.json` file specifies that the module is an EcmaScript module named 'from-scala'. The 'from-scala' module has to be installed once as a local module by:
31 |
32 | ```
33 | npm i ./module
34 | ```
35 |
36 | Before running the test application or unit tests the necessary node modules have to be installed:
37 |
38 | ```
39 | > npm i
40 | ```
41 |
42 | Finally the TypeScript application `app.ts` can be compiled and run by:
43 |
44 | ```
45 | > npm run start
46 | ```
47 |
48 | Unit tests are run by:
49 |
50 | ```
51 | npm t
52 | ```
53 |
--------------------------------------------------------------------------------
/explore/src/main/module/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "from-scala",
3 | "main": "index.js",
4 | "version": "0.0.1",
5 | "type": "module"
6 | }
7 |
--------------------------------------------------------------------------------
/explore/src/main/scala/AdapterV1.scala:
--------------------------------------------------------------------------------
1 | import scala.scalajs.js
2 | import scala.scalajs.js.annotation.{JSExport, JSExportAll, JSExportTopLevel}
3 |
4 | @JSExportTopLevel("AdapterV1")
5 | object AdapterV1 extends js.Object {
6 |
7 | @JSExportAll
8 | trait InstanceAdapter[D] {
9 | val $delegate: D
10 | }
11 |
12 | object x extends js.Object {
13 |
14 | @JSExportAll
15 | trait OuterV1 extends InstanceAdapter[_root_.x.OuterV1] {
16 |
17 | def x: Int = $delegate.x
18 |
19 | @JSExportAll
20 | trait MiddleV1 extends InstanceAdapter[_root_.x.OuterV1#MiddleV1] {
21 |
22 | def y: String = $delegate.y
23 |
24 | @JSExportAll
25 | trait InnerV1 extends InstanceAdapter[_root_.x.OuterV1#MiddleV1#InnerV1] {
26 | def z = $delegate.z
27 | }
28 |
29 | object InnerV1 extends js.Object {
30 | def newInstance(z: Boolean): _root_.x.OuterV1#MiddleV1#InnerV1 = new $delegate.InnerV1(z)
31 | def newAdapter(d: _root_.x.OuterV1#MiddleV1#InnerV1): InnerV1 = new InnerV1 {
32 | override val $delegate = d
33 | }
34 | }
35 |
36 | val innerV1 = InnerV1
37 |
38 | }
39 |
40 | object MiddleV1 extends js.Object {
41 | def newInstance(y: String): _root_.x.OuterV1#MiddleV1 = new $delegate.MiddleV1(y)
42 | def newAdapter(d: _root_.x.OuterV1#MiddleV1): MiddleV1 = new MiddleV1 {
43 | override val $delegate = d
44 | override def y = $delegate.y
45 | }
46 | }
47 |
48 | val middleV1 = MiddleV1
49 |
50 | }
51 |
52 | object OuterV1 extends js.Object {
53 | def newInstance(x: Int) = new _root_.x.OuterV1(x)
54 | def newAdapter(d: _root_.x.OuterV1): OuterV1 = new OuterV1 {
55 | override val $delegate = d
56 | override def x = $delegate.x
57 | }
58 | }
59 |
60 | val outerV1 = OuterV1
61 |
62 | }
63 | }
64 |
65 | package x {
66 |
67 | class OuterV1(val x: Int) {
68 | class MiddleV1(val y: String) {
69 | class InnerV1(val z: Boolean) {
70 |
71 | }
72 | }
73 | }
74 | }
--------------------------------------------------------------------------------
/explore/src/test/ts/adapter.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 | import { assertNever } from './util'
3 |
4 | describe('adapter', function() {
5 |
6 | it('instantiate inner classes', function() {
7 | const outer = m.AdapterV1.x.OuterV1.newInstance(5)
8 | const outerAdapter = m.AdapterV1.x.OuterV1.newAdapter(outer)
9 | expect(outerAdapter.x).toBe(5)
10 |
11 | const middle = outerAdapter.middleV1.newInstance('abc')
12 | const middleAdapter = outerAdapter.middleV1.newAdapter(middle)
13 | expect(middleAdapter.y).toBe('abc')
14 |
15 | const inner = middleAdapter.innerV1.newInstance(true)
16 | const innerAdapter = middleAdapter.innerV1.newAdapter(inner)
17 | expect(innerAdapter.z).toBe(true)
18 |
19 | });
20 |
21 |
22 | });
--------------------------------------------------------------------------------
/explore/src/test/ts/adt.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 | import { assertNever } from './util'
3 |
4 | describe('adt', function() {
5 |
6 | function checkByLiteralInt(adt: m.ADT, caseId: number): void {
7 | if (adt.literalTypedInt === 1) {
8 | expect(adt.caseId).toBe(1)
9 | } else if (adt.literalTypedInt === 2) {
10 | expect(adt.caseId).toBe(2)
11 | } else {
12 | assertNever(adt)
13 | }
14 | }
15 |
16 | function checkByLiteralString(adt: m.ADT, caseId: number): void {
17 | if (adt.literalTypedString === 'a') {
18 | expect(adt.caseId).toBe(1)
19 | } else if (adt.literalTypedString === 'b') {
20 | expect(adt.caseId).toBe(2)
21 | } else {
22 | assertNever(adt)
23 | }
24 | }
25 |
26 | function checkByLiteralBoolean(adt: m.ADT, caseId: number): void {
27 | if (adt.literalTypedBoolean === false) {
28 | expect(adt.caseId).toBe(1)
29 | } else if (adt.literalTypedBoolean === true) {
30 | expect(adt.caseId).toBe(2)
31 | } else {
32 | assertNever(adt)
33 | }
34 | }
35 |
36 | it('discriminate based on number', function() {
37 | checkByLiteralInt(new m.Case1(''), 1)
38 | checkByLiteralInt(new m.Case2(''), 2)
39 | });
40 |
41 | it('discriminate based on string', function() {
42 | checkByLiteralString(new m.Case1(''), 1)
43 | checkByLiteralString(new m.Case2(''), 2)
44 | });
45 |
46 | it('discriminate based on boolean', function() {
47 | checkByLiteralBoolean(new m.Case1(''), 1)
48 | checkByLiteralBoolean(new m.Case2(''), 2)
49 | });
50 |
51 |
52 | });
--------------------------------------------------------------------------------
/explore/src/test/ts/array.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 |
3 | describe('array', function() {
4 |
5 | it('set / get vector', function() {
6 | const vec = [1, 2, 3]
7 | const mat = [[1, 2, 3], [4, 5, 6], [7, 8, 9]]
8 | const c = new m.ArrayAccess(vec, mat)
9 |
10 | expect(c.vector.length).toBe(vec.length)
11 | expect(c.matrix.length).toBe(mat.length)
12 | expect(c.matrix[0].length).toBe(mat[0].length)
13 |
14 | expect(c.vector).toStrictEqual(vec)
15 | expect(c.matrix).toStrictEqual(mat)
16 |
17 | const vec2 = [4]
18 | const mat2 = [[1]]
19 | c.vector = vec2
20 | c.matrix = mat2
21 | expect(c.vector).toStrictEqual(vec2)
22 | expect(c.matrix).toStrictEqual(mat2)
23 | });
24 |
25 | });
--------------------------------------------------------------------------------
/explore/src/test/ts/class-with-inner-obj.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 |
3 | describe('class with inner obj', () => {
4 |
5 | it('inner object can be accessed', () => {
6 | const c = new m.ClassWithInnerObj()
7 | expect(c.x).toBe(1)
8 | // TODO uncomment after issue is fixed
9 | // cf. https://github.com/scala-js/scala-js/issues/4142
10 | //expect(c.innerObj.y).toBe(2)
11 | expect(c.innerObj).toBeUndefined
12 | })
13 |
14 | })
--------------------------------------------------------------------------------
/explore/src/test/ts/iterator.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 | import { assertNever } from './util'
3 |
4 | describe('iterator', function() {
5 |
6 | it('discriminate based on number', function() {
7 | const range = new m.ToRange(0, 5)
8 | let sum = 0
9 | for (let n of range) {
10 | sum += n
11 | }
12 | expect(sum).toBe(15)
13 | })
14 |
15 | })
16 |
17 |
--------------------------------------------------------------------------------
/explore/src/test/ts/non-exported-js-object.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 |
3 | describe('non-exported js.Object', function() {
4 |
5 | it('access js.Object member', function() {
6 | expect(m.nonExportedJsObject.name).toBe('nonExportedJsObject')
7 | });
8 |
9 | it('access class derived from js.Object member', function() {
10 | expect(m.nonExportedJsClass().name).toBe('nonExportedJsClass')
11 | });
12 |
13 | });
--------------------------------------------------------------------------------
/explore/src/test/ts/property.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 |
3 | describe('property', function() {
4 |
5 | it('access value via accessors and via property', function() {
6 | const i = new m.StdClass2()
7 | expect(i.value).toBe(5)
8 | i.value = 6
9 | expect(i.value).toBe(6)
10 | expect(i.valueProperty).toBe(6)
11 | i.valueProperty = 7
12 | expect(i.value).toBe(7)
13 | expect(i.valueProperty).toBe(7)
14 | });
15 |
16 | it('array', () => {
17 | const i = new m.StdClass2()
18 | expect(i.numbers.length).toBe(5)
19 | i.numbers = [66, 67, 68]
20 | expect(i.numbers.length).toBe(3)
21 | expect(i.numbers[0]).toBe(66)
22 | expect(i.numbers[1]).toBe(67)
23 | expect(i.numbers[2]).toBe(68)
24 | })
25 |
26 | it('option', () => {
27 | const i = new m.StdClass2()
28 | expect(i.option).toBe(5)
29 | i.option = undefined
30 | expect(i.option).toBeUndefined()
31 | i.option = 68
32 | expect(i.option).toBe(68)
33 | })
34 |
35 | it('tuple', () => {
36 | const i = new m.StdClass2()
37 | expect(i.tuple).toStrictEqual(['abc', 1])
38 | i.tuple = ['uvw', 2]
39 | expect(i.tuple).toStrictEqual(['uvw', 2])
40 | })
41 |
42 | })
--------------------------------------------------------------------------------
/explore/src/test/ts/trait-methods.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from 'from-scala'
2 |
3 | describe('trait methods', function() {
4 |
5 | it('simple', function() {
6 | const c = new m.ClassWithMethodsFromTraits()
7 | expect(c.base(2)).toBe(4)
8 | expect(c.middle(2)).toBe(6)
9 | });
10 |
11 | });
--------------------------------------------------------------------------------
/explore/src/test/ts/util.ts:
--------------------------------------------------------------------------------
1 | export function assertNever(n: never): never {
2 | throw new Error('never case reached')
3 | }
4 |
--------------------------------------------------------------------------------
/explore/tslint.json:
--------------------------------------------------------------------------------
1 | {
2 | "defaultSeverity": "error",
3 | "extends": [
4 | "tslint:recommended"
5 | ],
6 | "jsRules": {
7 | },
8 | "rules": {
9 | "no-console": false,
10 | "semicolon": false,
11 | },
12 | "rulesDirectory": []
13 | }
14 |
--------------------------------------------------------------------------------
/generator/src/main/scala/eu/swdev/scala/ts/AdapterGeneratorMain.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import java.io.File
4 | import java.nio.charset.StandardCharsets
5 | import java.nio.file.{Files, Paths}
6 | import java.util.regex.Pattern
7 |
8 | import eu.swdev.scala.ts
9 |
10 | import scala.meta.{Dialect, dialects}
11 | import scala.meta.internal.symtab.GlobalSymbolTable
12 | import scala.meta.io.{AbsolutePath, Classpath}
13 | import scala.util.control.NonFatal
14 |
15 | // this class is referenced in the ScalaTsPlugin when the generator is forked
16 | class AdapterGeneratorMain extends GeneratorMain
17 |
18 | /**
19 | * Main class that is started when the TypeScript declaration file generator is forked by the ScalaTsPlugin
20 | */
21 | object AdapterGeneratorMain extends AdapterGeneratorMain {
22 |
23 | case class Config(
24 | adapterFile: File,
25 | adapterName: String,
26 | include: Pattern,
27 | exclude: Pattern,
28 | compileFullClasspath: List[File],
29 | validate: Boolean,
30 | ) {
31 | import Config._
32 |
33 | def asEnvVars = Map(
34 | kAdapterFile -> adapterFile.toString,
35 | kAdapterName -> adapterName,
36 | kInclude -> include.pattern(),
37 | kExclude -> exclude.pattern(),
38 | kCompileFullClassPath -> compileFullClasspath.mkString(File.pathSeparator),
39 | kValidate -> String.valueOf(validate),
40 | )
41 | }
42 |
43 | object Config {
44 |
45 | val kAdapterFile = "ADAPTER_FILE"
46 | val kAdapterName = "ADAPTER_NAME"
47 | val kInclude = "INCLUDE"
48 | val kExclude = "EXCLUDE"
49 | val kCompileFullClassPath = "COMPILE_FULL_CLASS_PATH"
50 | val kValidate = "VALIDATE"
51 |
52 | def fromEnvVars = Config(
53 | adapterFile = new File(System.getenv(kAdapterFile)),
54 | adapterName = System.getenv(kAdapterName),
55 | include = Pattern.compile(System.getenv(kInclude)),
56 | exclude = Pattern.compile(System.getenv(kExclude)),
57 | compileFullClasspath = System.getenv(kCompileFullClassPath).split(File.pathSeparatorChar).map(new File(_)).toList,
58 | validate = System.getenv(kValidate).toBoolean,
59 | )
60 |
61 | }
62 |
63 | def main(args: Array[String]): Unit = {
64 | try {
65 | val config = Config.fromEnvVars
66 | val adapterPath = config.adapterFile.toPath
67 |
68 | val cp = config.compileFullClasspath.map(AbsolutePath(_))
69 | val symTab = GlobalSymbolTable(Classpath(cp), true)
70 |
71 | val semSrcs =
72 | config.compileFullClasspath
73 | .filter(f => config.include.matcher(f.toString).find())
74 | .filter(f => !config.exclude.matcher(f.toString).find())
75 | .flatMap(SemSource.locate(_, dialect))
76 |
77 | val inputs = Analyzer.analyze(semSrcs, symTab)
78 |
79 | def inputInfo =
80 | inputs.flattened
81 | .groupBy(_.getClass.getSimpleName)
82 | .toList
83 | .sortBy(_._1)
84 | .map {
85 | case (cn, lst) => s"$cn: ${lst.length}"
86 | }
87 | .mkString("{", ", ", "}")
88 |
89 | System.out.println(s"ScalaTs input : $inputInfo")
90 |
91 | val output = AdapterGenerator.generate(inputs, symTab, config.adapterName)
92 |
93 | System.out.println(s"ScalaTs output: $adapterPath")
94 |
95 | Files.createDirectories(adapterPath.getParent)
96 | Files.write(adapterPath, output.getBytes(StandardCharsets.UTF_8))
97 |
98 | if (config.validate) {
99 | validate(semSrcs, symTab, inputs => AdapterGenerator.generate(inputs, symTab, config.adapterName))
100 | }
101 |
102 | } catch {
103 | case NonFatal(e) =>
104 | System.err.println("adapter creation failed")
105 | e.printStackTrace()
106 | System.exit(1)
107 | }
108 |
109 | }
110 |
111 | }
112 |
--------------------------------------------------------------------------------
/generator/src/main/scala/eu/swdev/scala/ts/Adaption.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | sealed trait Adaption {
4 | def fullName: FullName
5 | def simpleName: String = fullName.last
6 | def input: Input
7 | }
8 |
9 | object Adaption {
10 |
11 | sealed trait Method extends Adaption
12 | sealed trait DefValVar extends Method {
13 | def fullName: FullName = FullName(input.si)
14 | }
15 |
16 | case class Def(input: Input.Def) extends DefValVar
17 | case class Val(input: Input.Val) extends DefValVar
18 | case class Var(input: Input.Var) extends DefValVar
19 |
20 | // the newDelegate and newAdapter methods must be part of the adapter object of the class
21 | // -> construct the full name by adding "newDelegate" or "newAdapter" to the full name of the class
22 |
23 | case class NewDelegate(input: Input.Cls) extends Method {
24 | def fullName = FullName(input.si).member("newDelegate")
25 | }
26 | case class NewAdapter(input: Input.Cls) extends Method {
27 | def fullName = FullName(input.si).member("newAdapter")
28 | }
29 |
30 | case class Trait(input: Input.Cls) extends Adaption {
31 | def fullName: FullName = FullName(input.si)
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/generator/src/main/scala/eu/swdev/scala/ts/GeneratorMain.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import scala.meta.{Dialect, dialects}
4 | import scala.meta.internal.symtab.SymbolTable
5 |
6 | class GeneratorMain {
7 |
8 | protected def dialect: Dialect = scala.util.Properties.versionNumberString match {
9 | case s if s.startsWith("2.12.") => dialects.Scala212
10 | case s if s.startsWith("2.13.") => dialects.Scala213
11 | case _ => dialects.Scala
12 | }
13 |
14 | protected def validate(semSrcs: List[SemSource], symTab: SymbolTable, generate: Inputs => String): Unit = {
15 | val infos = semSrcs.map(s => s -> ValidationInfo.dts(s)).collect { case (semSource, Some(dtsInfo)) => semSource -> dtsInfo }
16 | var failed = false
17 | def check(name: String, inputs: Inputs, expected: String): Unit = {
18 | val actual = generate(inputs).trim
19 | if (actual != expected) {
20 | System.err.println(s"$name: failed\n====== expected:\n$expected\n==== actual:\n$actual\n====")
21 | failed = true
22 | } else {
23 | System.out.println(s"$name: passed")
24 | }
25 | }
26 | infos.foreach {
27 | case (semSrc, ValidationInfo.Expected(expectedDts)) =>
28 | val inputs = Analyzer.analyze(List(semSrc), symTab)
29 | check(s"file: ${semSrc.td.uri}", inputs, expectedDts)
30 |
31 | case (_, ValidationInfo.ExpectedAndGroup(expectedDts, group)) =>
32 | val semSrcs = infos
33 | .collect {
34 | case (semSrc, ValidationInfo.Group(`group`)) => semSrc
35 | case (semSrc, ValidationInfo.ExpectedAndGroup(_, `group`)) => semSrc
36 | }
37 | val inputs = Analyzer.analyze(semSrcs, symTab)
38 | check(s"group: $group", inputs, expectedDts)
39 |
40 | case _ =>
41 | }
42 |
43 | if (failed) {
44 | System.exit(1)
45 | }
46 |
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/generator/src/main/scala/eu/swdev/scala/ts/Result.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | trait Result {
4 |
5 | def openBlock(line: String): Unit
6 |
7 | def closeBlock(): Unit
8 |
9 | def addLine(line: String): Unit
10 | }
11 |
12 | object Result {
13 |
14 | class StringBuilderResult extends Result {
15 | var indent = 0
16 | def space = " " * indent
17 |
18 | val sb = new StringBuilder
19 |
20 | override def openBlock(line: String): Unit = {
21 | sb.append(s"$space$line {\n")
22 | indent += 1
23 | }
24 |
25 | override def closeBlock(): Unit = {
26 | indent -= 1
27 | sb.append(s"$space}\n")
28 | }
29 |
30 | override def addLine(line: String): Unit = sb.append(s"$space$line\n")
31 | }
32 | }
33 |
--------------------------------------------------------------------------------
/generator/src/main/scala/eu/swdev/scala/ts/SemSource.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import java.io.File
4 | import java.nio.file.Path
5 | import scala.meta.common.Convert
6 | import scala.meta.inputs.Position
7 | import scala.meta.internal.semanticdb.SymbolInformation.Kind
8 | import scala.meta.internal.semanticdb.SymbolOccurrence.Role
9 | import scala.meta.{Dialect, Source}
10 | import scala.meta.internal.semanticdb.{Locator, SymbolInformation, SymbolOccurrence, TextDocument}
11 | import scala.meta.parsers.Parse
12 | import scala.meta.tokens.Tokens
13 |
14 | case class SemSource(td: TextDocument, source: Source, dialect: Dialect) {
15 |
16 | def symbolInfo(symbol: String): SymbolInformation = td.symbols.find(_.symbol == symbol).get
17 |
18 | def symbolInfo(pos: Position, kind: Kind): Option[SymbolInformation] = symbolInfos(pos, kind).headOption
19 |
20 | /**
21 | * Returns SymbolInformation instances that lie in the given range and or of the given kind.
22 | *
23 | * The returned sequence is ordered by start positions.
24 | */
25 | def symbolInfos(pos: Position, kind: Kind): Seq[SymbolInformation] = {
26 | val symbolOccurrencesInRange = symbolOccurrences(pos, Role.DEFINITION)
27 | val matchingSymbolInformationsOfKind = symbolOccurrencesInRange
28 | .flatMap {
29 | case so => td.symbols.collect {
30 | case si if si.kind == kind && si.symbol == so.symbol => (si, so.range.get)
31 | }
32 | }
33 | val sortedByStartPosition = matchingSymbolInformationsOfKind
34 | .sortWith {
35 | case ((_, r1), (_, r2)) => r1.startLine < r2.startLine || r1.startLine == r2.startLine && r1.startCharacter < r2.startCharacter
36 | }
37 | sortedByStartPosition.map(_._1)
38 | }
39 |
40 | def symbolOccurrences(pos: Position, role: Role): Seq[SymbolOccurrence] = {
41 | td.occurrences.filter(so => so.range.map(pos.includes(_)).getOrElse(false) && so.role == role)
42 | }
43 |
44 | def tokens: Tokens = source.tokens(dialect)
45 |
46 | }
47 |
48 | object SemSource {
49 |
50 | def apply(td: TextDocument, dialect: Dialect): SemSource = {
51 | val parseSource = implicitly[Parse[Source]]
52 | val stringToInput = implicitly[Convert[String, scala.meta.inputs.Input]]
53 | val input = stringToInput.apply(td.text)
54 | val source = parseSource.apply(input, dialect).get
55 | SemSource(td, source, dialect)
56 | }
57 |
58 | /**
59 | * Locates SemSources in the given directory.
60 | *
61 | * The returned SemSources are sorted by the uri of their contained text document.
62 | */
63 | def locate(dir: File, dialect: Dialect): List[SemSource] = locate(dir.toPath, dialect)
64 |
65 | /**
66 | * Locates SemSources in the given directory.
67 | *
68 | * The returned SemSources are sorted by the uri of their contained text document.
69 | */
70 | def locate(dir: Path, dialect: Dialect): List[SemSource] = {
71 | val builder = List.newBuilder[SemSource]
72 | Locator(dir) { (_, tds) =>
73 | tds.documents.foreach { td =>
74 | val semSource = SemSource(td, dialect)
75 | builder += semSource
76 | }
77 | }
78 | builder.result().sortBy(_.td.uri)
79 | }
80 | }
81 |
--------------------------------------------------------------------------------
/generator/src/main/scala/eu/swdev/scala/ts/ValidationInfo.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import scala.meta.tokens.Token
4 |
5 | /**
6 | * Represents information that can be used to validate the TypeScript declaration file generation.
7 | *
8 | * The information is given in comments: A block comment that starts with ".d.ts:" or "adapter:" contains a
9 | * declaration file fragment or an adapter file fragment.
10 | * That fragment is either the result of processing the ScalaJS file that contains that comment or a group of ScalaJS files.
11 | * Groups of ScalaJS files can be formed by using an end of line comment that starts with "group:".
12 | *
13 | * Although being a test support type, the ValidationInfo type is defined in the main classes of the generator because
14 | * the ScalaTsPlugin depends on it to validate its generation result.
15 | *
16 | * In case that multiple ".d.ts:", "adapter:", or "group:" comments are given only the first is considered.
17 | */
18 | sealed trait ValidationInfo
19 |
20 | object ValidationInfo {
21 |
22 | case class Expected(string: String) extends ValidationInfo
23 | case class Group(group: String) extends ValidationInfo
24 | case class ExpectedAndGroup(expected: String, group: String) extends ValidationInfo
25 |
26 | val groupMarker = "group:"
27 | val dtsMarker = ".d.ts:"
28 | val adapterMarker = "adapter:"
29 |
30 | def apply(semSrc: SemSource, expectedMarker: String): Option[ValidationInfo] = {
31 | val optFragment = semSrc.tokens.collectFirst {
32 | case t: Token.Comment if t.value.trim.startsWith(expectedMarker) => t.value.trim.substring(expectedMarker.length).trim
33 | }
34 | val optGroup = semSrc.tokens.collectFirst {
35 | case t: Token.Comment if t.value.trim.startsWith(groupMarker) => t.value.trim.substring(groupMarker.length).trim
36 | }
37 | (optFragment, optGroup) match {
38 | case (Some(fragment), Some(group)) => Some(ExpectedAndGroup(fragment, group))
39 | case (Some(fragment), _) => Some(Expected(fragment))
40 | case (_, Some(group)) => Some(Group(group))
41 | case _ => None
42 | }
43 | }
44 |
45 | def dts(semSrc: SemSource) = apply(semSrc, dtsMarker)
46 | def adapter(semSrc: SemSource) = apply(semSrc, adapterMarker)
47 | }
48 |
--------------------------------------------------------------------------------
/generator/src/test/scala-2.13/eu/swdev/scala/ts/dts/LiteralTypeTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class LiteralTypeTest extends DtsFunSuite {
8 |
9 | """
10 | |export const litString: 'a'
11 | |export const litNumber: 1
12 | |export const litBoolean: true
13 | |""".check()
14 |
15 | }
16 |
17 | object LiteralTypeTest {
18 |
19 | @JSExportTopLevel("litString")
20 | val litString: "a" = "a"
21 | @JSExportTopLevel("litNumber")
22 | val litNumber: 1 = 1
23 | @JSExportTopLevel("litBoolean")
24 | val litBoolean: true = true
25 |
26 | }
27 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/AbstractAutoDetectingTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import org.scalatest.funsuite.AnyFunSuite
4 | import org.scalatest.matchers.must.Matchers
5 |
6 | /**
7 | * Base class for tests that scan semantic db files and check for comments that start with a ".d.ts:" or "group:" mark.
8 | *
9 | * The package where the test class is located is the package where semantic db files are looked for. Subpackages
10 | * are also considered. If a semantic db file has a comment starting with ".d.ts:" then that comment specifies the
11 | * expected generated declaration file.
12 | *
13 | * Multiple files can be grouped and processed together resulting in a single declaration file. All files belonging
14 | * to the same group contain a comment that starts with "group:" followed by the same identifier.
15 | */
16 | abstract class AbstractAutoDetectingTest extends AnyFunSuite with ScalaMetaHelper with Matchers {
17 |
18 | def dtsInfos(): List[(SemSource, ValidationInfo)] = {
19 | val relativeTestDir = basePath.relativize(testDirPath).toString
20 | locateSemSources(metaInfPath, dialect)
21 | .filter(_.td.uri.contains(relativeTestDir))
22 | .map(s => s -> ValidationInfo.dts(s))
23 | .collect {
24 | case (semSource, Some(dtsInfo)) => semSource -> dtsInfo
25 | }
26 | }
27 |
28 | val infos = dtsInfos()
29 |
30 | private def check(inputs: Inputs, expectedDts: String): Unit = {
31 | val generatedDts = Generator.generate(inputs, false, symTab, getClass.getClassLoader).trim
32 | generatedDts mustBe expectedDts
33 | }
34 |
35 | infos.foreach {
36 |
37 | case (semSrc, ValidationInfo.Expected(expectedDts)) =>
38 | test(s"file: ${semSrc.td.uri}") {
39 | val inputs = Analyzer.analyze(List(semSrc), symTab)
40 | check(inputs, expectedDts)
41 | }
42 |
43 | case (_, ValidationInfo.ExpectedAndGroup(expectedDts, group)) =>
44 | test(s"group: $group") {
45 | val semSrcs = infos
46 | .collect {
47 | case (semSrc, ValidationInfo.Group(`group`)) => semSrc
48 | case (semSrc, ValidationInfo.ExpectedAndGroup(_, `group`)) => semSrc
49 | }
50 | val inputs = Analyzer.analyze(semSrcs, symTab)
51 | check(inputs, expectedDts)
52 | }
53 |
54 | case _ =>
55 | }
56 |
57 | }
58 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/AdapterFunSuite.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import eu.swdev.scala.ts
4 | import org.scalatest.funsuite.AnyFunSuite
5 | import org.scalatest.matchers.must.Matchers
6 |
7 | trait AdapterFunSuite extends AnyFunSuite with ScalaMetaHelper with Matchers { self =>
8 |
9 | implicit def strOps(str: String): StrOps = StrOps(str)
10 |
11 | case class StrOps(expectedAdapter: String) {
12 |
13 | /**
14 | * Creates a test that generates the adapter code for the given classes and checks if it matches the expected value.
15 | *
16 | * If no classes are given then the test class itself is used.
17 | *
18 | * Note that not only the given classes are considered when generating the adapter code but all
19 | * symbols that are defined in the corresponding files.
20 | */
21 | def check(classes: Class[_]*): Unit = {
22 | test("adapter") {
23 | val is = inputs(classes: _*)
24 | val generatedAdapter = AdapterGenerator.generate(is, symTab, "Adapter").trim
25 | generatedAdapter mustBe expectedAdapter.stripMargin.trim
26 | }
27 | }
28 | }
29 | }
30 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/DtsFunSuite.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import org.scalatest.funsuite.AnyFunSuite
4 | import org.scalatest.matchers.must.Matchers
5 |
6 | trait DtsFunSuite extends AnyFunSuite with ScalaMetaHelper with Matchers { self =>
7 |
8 | implicit def strOps(str: String): StrOps = StrOps(str)
9 |
10 | case class StrOps(expectedDts: String) {
11 |
12 | /**
13 | * Creates a test that generates the type declaration file for this test class and checks if it matches the expected value.
14 | */
15 | def check(addRootNamespace: Boolean = false): Unit = {
16 | test("dts") {
17 | val is = inputs()
18 | val generatedDts = Generator.generate(is, addRootNamespace, symTab, getClass.getClassLoader).trim
19 | generatedDts mustBe expectedDts.stripMargin.trim
20 | }
21 | }
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/FullNameTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import org.scalatest.funsuite.AnyFunSuite
4 | import org.scalatest.matchers.must.Matchers
5 |
6 | class FullNameTest extends AnyFunSuite with Matchers {
7 |
8 | test("tail") {
9 | FullName.fromSymbol("dts/AccessorTest.").tail.map(_.str) mustBe Some("AccessorTest$")
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/GeneratorTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import org.scalatest.funsuite.AnyFunSuite
4 | import org.scalatest.matchers.must.Matchers
5 |
6 | class GeneratorTest extends AnyFunSuite with Matchers {
7 |
8 | test("string escape") {
9 | TypeFormatter.escapeTypeScriptString("abc") mustBe "abc"
10 | TypeFormatter.escapeTypeScriptString("'") mustBe "\\'"
11 | TypeFormatter.escapeTypeScriptString("\"") mustBe "\\\""
12 | TypeFormatter.escapeTypeScriptString("\n") mustBe "\\n"
13 | TypeFormatter.escapeTypeScriptString("\u00e4\u00f6\u00fc") mustBe "\\u00e4\\u00f6\\u00fc"
14 | }
15 |
16 | }
17 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/NativeSymbolAnalyzerTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import org.scalatest.funsuite.AnyFunSuite
4 | import org.scalatest.matchers.must.Matchers
5 |
6 | import scala.scalajs.js
7 | import scala.scalajs.js.annotation.{JSGlobal, JSImport, JSName}
8 |
9 | class NativeSymbolAnalyzerTest extends AnyFunSuite with Matchers with ScalaMetaHelper {
10 |
11 | val na = new NativeSymbolAnalyzer(Map.empty, getClass.getClassLoader, symTab)
12 |
13 | def nativeSymbol(cls: Class[_]): Option[NativeSymbol] = {
14 | val sym = cls.getName.replace('.', '/').replace('$', '.') + "#"
15 | na.nativeSymbol(sym)
16 | }
17 |
18 | import NativeSymbolAnalyzerTest._
19 |
20 | test("global without name") {
21 | nativeSymbol(classOf[GlobalWithoutName]) mustBe Some(NativeSymbol.Global("GlobalWithoutName", true))
22 | }
23 |
24 | test("global with name") {
25 | nativeSymbol(classOf[GlobalWithName]) mustBe Some(NativeSymbol.Global("SomeName", false))
26 | }
27 |
28 | test("import with name") {
29 | nativeSymbol(classOf[ImportWithName]) mustBe Some(NativeSymbol.ImportedName("SomeModule", "SomeName", false))
30 | }
31 |
32 | test("import with default") {
33 | nativeSymbol(classOf[ImportWithDefault]) mustBe Some(NativeSymbol.ImportedName("SomeModule", "default", false))
34 | }
35 |
36 | test("import with namespace") {
37 | nativeSymbol(classOf[ImportWithNamespace]) mustBe Some(NativeSymbol.ImportedNamespace("SomeModule", false))
38 | }
39 |
40 | test("import with namespace / nested") {
41 | nativeSymbol(classOf[SomeModule.Nested]) mustBe Some(
42 | NativeSymbol.Inner("Nested", NativeSymbol.ImportedNamespace("SomeModule", true), true))
43 | }
44 |
45 | test("import with namespace / nested2 / nested3") {
46 | nativeSymbol(classOf[SomeModule2.Nested2.Nested3]) mustBe Some(
47 | NativeSymbol.Inner(
48 | "Nested3",
49 | NativeSymbol.Inner(
50 | "Nested2",
51 | NativeSymbol.ImportedNamespace(
52 | "SomeModule2",
53 | true
54 | ),
55 | true
56 | ),
57 | false
58 | )
59 | )
60 | }
61 |
62 | }
63 |
64 | object NativeSymbolAnalyzerTest {
65 |
66 | @JSGlobal
67 | @js.native
68 | class GlobalWithoutName extends js.Object
69 |
70 | @JSGlobal("SomeName")
71 | @js.native
72 | class GlobalWithName
73 |
74 | @JSImport("SomeModule", "SomeName")
75 | @js.native
76 | class ImportWithName
77 |
78 | @JSImport("SomeModule", JSImport.Default)
79 | @js.native
80 | class ImportWithDefault
81 |
82 | @JSImport("SomeModule", JSImport.Namespace)
83 | @js.native
84 | class ImportWithNamespace
85 |
86 | @JSImport("SomeModule", JSImport.Namespace)
87 | object SomeModule extends js.Object {
88 | class Nested extends js.Object
89 | }
90 |
91 | @JSImport("SomeModule2", JSImport.Namespace)
92 | object SomeModule2 extends js.Object {
93 | object Nested2 extends js.Object {
94 | @JSName(js.Symbol.iterator)
95 | class Nested3
96 | }
97 | }
98 | }
99 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/ScalaMetaHelper.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import java.net.URLClassLoader
4 | import java.nio.file.{Path, Paths}
5 |
6 | import scala.collection.mutable
7 | import scala.meta.{Dialect, dialects}
8 | import scala.meta.internal.symtab.GlobalSymbolTable
9 | import scala.meta.io.{AbsolutePath, Classpath}
10 |
11 | trait ScalaMetaHelper { self =>
12 |
13 | def dialect: Dialect = dialects.Scala
14 |
15 | val symTab = {
16 | def classLoaders(cl: ClassLoader): List[ClassLoader] =
17 | Option(cl).fold[List[ClassLoader]](Nil)(cl => cl :: classLoaders(cl.getParent))
18 | val urls = classLoaders(getClass.getClassLoader).collect {
19 | case ucl: URLClassLoader => ucl.getURLs
20 | }.flatten
21 |
22 | val paths = urls.map(url => Paths.get(url.toURI).toAbsolutePath.toFile).map(AbsolutePath(_))
23 | val cp = Classpath(paths)
24 | GlobalSymbolTable(cp, true)
25 | }
26 |
27 | val testDirPath: Path = {
28 | val clazz = getClass
29 | val url = clazz.getResource(s"${getClass.getSimpleName}.class")
30 | val uri = url.toURI
31 | Paths.get(uri).getParent
32 | }
33 |
34 | val basePath: Path = {
35 | val clazz = getClass
36 | var res = testDirPath
37 | var s = clazz.getName
38 | while (s.indexOf('.') > 0) {
39 | s = s.substring(s.indexOf('.') + 1)
40 | res = res.getParent
41 | }
42 | res
43 | }
44 |
45 | val metaInfPath: Path = basePath.resolve("META-INF")
46 |
47 | def locateSemSources(dir: Path, dialect: Dialect) = ScalaMetaHelper.locateSemSources(dir, dialect)
48 |
49 | /**
50 | * Analyzes semantic db files that contain symbols for the given classes.
51 | *
52 | * If no classes are given then the test class itself is used.
53 | *
54 | * @param classes
55 | * @return
56 | */
57 | def inputs(classes: Class[_]*): Inputs = {
58 | val clss = if (classes.isEmpty) Seq(self.getClass) else classes
59 | val classSymbols = clss
60 | .map(_.getName.replace('.', '/'))
61 | .map { n =>
62 | if (n.endsWith("$")) {
63 | // symbol of a Scala object class -> replace trailing '$' by a '.'
64 | s"${n.dropRight(1)}."
65 | } else {
66 | // symbol of a standard class -> append a '#'
67 | s"$n#"
68 | }
69 | }
70 | .toSet
71 |
72 | val semSources = locateSemSources(metaInfPath, dialect)
73 | .filter(_.td.symbols.map(_.symbol).exists(s => classSymbols.exists(cs => s.endsWith(cs))))
74 | .sortBy(_.td.uri)
75 |
76 | Analyzer.analyze(semSources, symTab)
77 | }
78 | }
79 |
80 | object ScalaMetaHelper {
81 |
82 | def locateSemSources(dir: Path, dialect: Dialect): List[SemSource] = synchronized {
83 | map.getOrElseUpdate((dir, dialect), SemSource.locate(dir, dialect))
84 | }
85 |
86 | // caches located SemSources during test runs
87 | private val map = mutable.Map.empty[(Path, Dialect), List[SemSource]]
88 | }
89 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/adapter/ArrayTest.scala:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import eu.swdev.scala.ts.AdapterFunSuite
4 | import eu.swdev.scala.ts.annotation.AdaptAll
5 |
6 | class ArrayTest extends AdapterFunSuite {
7 |
8 | """
9 | |import scala.scalajs.js
10 | |import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
11 | |import eu.swdev.scala.ts.adapter._
12 | |@JSExportTopLevel("Adapter")
13 | |object Adapter extends js.Object {
14 | | object adapter extends js.Object {
15 | | object ArrayTest extends js.Object {
16 | | def x = _root_.adapter.ArrayTest.x.$cnv[_root_.eu.swdev.scala.ts.tpe.ReadOnlyArray[Int]]
17 | | def x_=(value: _root_.eu.swdev.scala.ts.tpe.ReadOnlyArray[Int]) = _root_.adapter.ArrayTest.x = value.$cnv[_root_.scala.Array[Int]]
18 | | }
19 | | }
20 | |}
21 | |""".check()
22 |
23 | }
24 |
25 | @AdaptAll
26 | object ArrayTest {
27 |
28 | var x: Array[Int] = ???
29 | }
30 |
31 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/adapter/ClassTest.scala:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import eu.swdev.scala.ts.AdapterFunSuite
4 | import eu.swdev.scala.ts.annotation.AdaptAll
5 |
6 | class ClassTest extends AdapterFunSuite {
7 | """
8 | |import scala.scalajs.js
9 | |import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
10 | |import eu.swdev.scala.ts.adapter._
11 | |@JSExportTopLevel("Adapter")
12 | |object Adapter extends js.Object {
13 | | @JSExportAll
14 | | trait InstanceAdapter[D] {
15 | | val $delegate: D
16 | | }
17 | | object test extends js.Object {
18 | | @JSExportAll
19 | | trait AdaptedClass extends InstanceAdapter[_root_.test.AdaptedClass] {
20 | | def sum = $delegate.sum.$cnv[Int]
21 | | def x = $delegate.x.$cnv[Int]
22 | | }
23 | | object AdaptedClass extends js.Object {
24 | | def newAdapter(delegate: _root_.test.AdaptedClass): AdaptedClass = new AdaptedClass {
25 | | override val $delegate = delegate
26 | | }
27 | | def newDelegate(x: Int, y: Int): _root_.test.AdaptedClass = new _root_.test.AdaptedClass(x.$cnv[Int], y.$cnv[Int])
28 | | }
29 | | }
30 | |}
31 | |""".check()
32 | }
33 |
34 | @AdaptAll
35 | class AdaptedClass(val x: Int, y: Int) {
36 |
37 | def sum = x + y
38 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/adapter/ListTest.scala:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import eu.swdev.scala.ts.AdapterFunSuite
4 | import eu.swdev.scala.ts.annotation.AdaptAll
5 |
6 | class ListTest extends AdapterFunSuite {
7 |
8 | """
9 | |import scala.scalajs.js
10 | |import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
11 | |import eu.swdev.scala.ts.adapter._
12 | |@JSExportTopLevel("Adapter")
13 | |object Adapter extends js.Object {
14 | | object adapter extends js.Object {
15 | | object ListTest extends js.Object {
16 | | def traverse[X](ol: _root_.scala.scalajs.js.Iterable[_root_.scala.scalajs.js.UndefOr[X]]) = _root_.adapter.ListTest.traverse(ol.$cnv[_root_.scala.List[_root_.scala.Option[X]]]).$cnv[_root_.scala.scalajs.js.UndefOr[_root_.scala.scalajs.js.Iterable[X]]]
17 | | }
18 | | }
19 | |}
20 | |""".check()
21 |
22 | }
23 |
24 | @AdaptAll
25 | object ListTest {
26 |
27 | def traverse[X](ol: List[Option[X]]): Option[List[X]] = ???
28 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/adapter/NestedClassTest.scala:
--------------------------------------------------------------------------------
1 | package adapter
2 |
3 | import eu.swdev.scala.ts.AdapterFunSuite
4 | import eu.swdev.scala.ts.annotation.AdaptAll
5 |
6 | class NestedClassTest extends AdapterFunSuite {
7 |
8 | """
9 | |import scala.scalajs.js
10 | |import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
11 | |import eu.swdev.scala.ts.adapter._
12 | |@JSExportTopLevel("Adapter")
13 | |object Adapter extends js.Object {
14 | | @JSExportAll
15 | | trait InstanceAdapter[D] {
16 | | val $delegate: D
17 | | }
18 | | object adapter extends js.Object {
19 | | @JSExportAll
20 | | trait OuterClass extends InstanceAdapter[_root_.adapter.OuterClass] {
21 | | def x = $delegate.x.$cnv[Int]
22 | | @JSExportAll
23 | | trait Inner extends InstanceAdapter[_root_.adapter.OuterClass#Inner] {
24 | | def y = $delegate.y.$cnv[String]
25 | | }
26 | | object Inner extends js.Object {
27 | | def newAdapter(delegate: _root_.adapter.OuterClass#Inner): Inner = new Inner {
28 | | override val $delegate = delegate
29 | | }
30 | | def newDelegate(y: String): _root_.adapter.OuterClass#Inner = new $delegate.Inner(y.$cnv[String])
31 | | }
32 | | }
33 | | object OuterClass extends js.Object {
34 | | def newAdapter(delegate: _root_.adapter.OuterClass): OuterClass = new OuterClass {
35 | | override val $delegate = delegate
36 | | }
37 | | def newDelegate(x: Int): _root_.adapter.OuterClass = new _root_.adapter.OuterClass(x.$cnv[Int])
38 | | }
39 | | }
40 | |}
41 | |""".check()
42 |
43 | }
44 |
45 | @AdaptAll
46 | class OuterClass(val x: Int) {
47 | @AdaptAll
48 | class Inner(val y: String)
49 | }
50 |
51 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/adapter/ObjectDefValVarTest.scala:
--------------------------------------------------------------------------------
1 | package test
2 |
3 | import eu.swdev.scala.ts.AdapterFunSuite
4 | import eu.swdev.scala.ts.annotation.AdaptAll
5 |
6 | class ObjectDefValVarTest extends AdapterFunSuite {
7 | """
8 | |import scala.scalajs.js
9 | |import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
10 | |import eu.swdev.scala.ts.adapter._
11 | |@JSExportTopLevel("Adapter")
12 | |object Adapter extends js.Object {
13 | | object test extends js.Object {
14 | | object ObjectDefValVarTest extends js.Object {
15 | | def method(x: Int) = _root_.test.ObjectDefValVarTest.method(x).$cnv[Boolean]
16 | | def value = _root_.test.ObjectDefValVarTest.value.$cnv[String]
17 | | def variable = _root_.test.ObjectDefValVarTest.variable.$cnv[Boolean]
18 | | def variable_=(value: Boolean) = _root_.test.ObjectDefValVarTest.variable = value.$cnv[Boolean]
19 | | }
20 | | }
21 | |}
22 | |""".check()
23 | }
24 |
25 | @AdaptAll
26 | object ObjectDefValVarTest {
27 |
28 | def method(x: Int): Boolean = ???
29 | val value: String = ???
30 | var variable: Boolean = ???
31 |
32 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/auto/AutoDetectingTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.auto
2 |
3 | import eu.swdev.scala.ts.AbstractAutoDetectingTest
4 |
5 | class AutoDetectingTest extends AbstractAutoDetectingTest
6 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/auto/PrimitiveTypes.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.auto
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
5 |
6 | /* .d.ts:
7 |
8 | export interface PrimitiveTypes$ {
9 | readonly string: string
10 | readonly int: number
11 | readonly double: number
12 | readonly byte: number
13 | readonly short: number
14 | readonly float: number
15 | readonly char: scala.Char
16 | readonly long: scala.Long
17 | readonly bigInt: bigint
18 | 'PrimitiveTypes$': never
19 | }
20 | export const PrimitiveTypes: PrimitiveTypes$
21 | export namespace scala {
22 | interface Char {
23 | 'scala.Char': never
24 | }
25 | interface Long {
26 | 'scala.Long': never
27 | }
28 | }
29 | */
30 |
31 | @JSExportTopLevel("PrimitiveTypes")
32 | @JSExportAll
33 | object PrimitiveTypes {
34 |
35 | val string: String = ???
36 | val int: Int = ???
37 | val double: Double = ???
38 | val byte: Byte = ???
39 | val short: Short = ???
40 | val float: Float = ???
41 | val char: Char = ???
42 | val long: Long = ???
43 | val bigInt: js.BigInt = ???
44 |
45 | }
46 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/auto/group-1-file-1.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.auto
2 |
3 | import scala.scalajs.js.annotation.JSExportTopLevel
4 |
5 | /* .d.ts:
6 |
7 | export const fromFile1: string
8 | export const fromFile2: string
9 |
10 | */
11 |
12 | // group: group-1
13 |
14 | object Grouped1 {
15 |
16 | @JSExportTopLevel("fromFile1")
17 | val x: String= ???
18 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/auto/group-1-file-2.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.auto
2 |
3 | import scala.scalajs.js.annotation.JSExportTopLevel
4 |
5 | // group: group-1
6 |
7 | object Grouped2 {
8 |
9 | @JSExportTopLevel("fromFile2")
10 | val x: String= ???
11 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AbstractClassTest1.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class AbstractClassTest1 extends DtsFunSuite {
8 |
9 | """
10 | |export interface Case1 extends dts.AbstractClassTest1.Base {
11 | | 'Case1': never
12 | |}
13 | |export class Case1 {
14 | | constructor(s: string)
15 | |}
16 | |export interface Case2 extends dts.AbstractClassTest1.Base {
17 | | 'Case2': never
18 | |}
19 | |export class Case2 {
20 | | constructor(i: number)
21 | |}
22 | |export namespace dts {
23 | | namespace AbstractClassTest1 {
24 | | interface Base {
25 | | readonly x: X
26 | | 'dts.AbstractClassTest1.Base': never
27 | | }
28 | | }
29 | |}
30 | |""".check()
31 |
32 | }
33 |
34 | object AbstractClassTest1 {
35 |
36 | @JSExportAll
37 | abstract class Base[X](val x: X)
38 |
39 | @JSExportTopLevel("Case1")
40 | class Case1(s: String) extends Base(s)
41 | @JSExportTopLevel("Case2")
42 | class Case2(i: Int) extends Base(i)
43 | }
44 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AbstractClassTest2.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
7 |
8 | class AbstractClassTest2 extends DtsFunSuite {
9 |
10 | """
11 | |export abstract class Base {
12 | | constructor(x: X)
13 | | readonly x: X
14 | | abstract size(): number
15 | |}
16 | |export class Case1 extends Base {
17 | | constructor(s: string)
18 | | size(): number
19 | |}
20 | |export class Case2 extends Base {
21 | | constructor(i: number)
22 | | size(): number
23 | |}
24 | |""".check()
25 |
26 | }
27 |
28 | object AbstractClassTest2 {
29 |
30 | @JSExportTopLevel("Base")
31 | abstract class Base[X](val x: X) extends js.Object {
32 | def size(): Int
33 | }
34 |
35 | @JSExportTopLevel("Case1")
36 | class Case1(s: String) extends Base(s) {
37 | override def size(): Int = s.length
38 | }
39 | @JSExportTopLevel("Case2")
40 | class Case2(i: Int) extends Base(i) {
41 | override def size(): Int = i
42 | }
43 | }
44 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AccessorPairTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class AccessorPairTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface AccessorPairTest$ {
11 | | prop: string
12 | | 'AccessorPairTest$': never
13 | |}
14 | |export const AccessorPairTest: AccessorPairTest$
15 | |""".check()
16 |
17 | }
18 |
19 |
20 | @JSExportTopLevel("AccessorPairTest")
21 | @JSExportAll
22 | object AccessorPairTest {
23 | def prop = Holder.x
24 | def prop_=(v: String) = Holder.x = v
25 |
26 | private object Holder {
27 | var x = "abc"
28 | }
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AccessorTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class AccessorTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface AccessorTest$ {
11 | | property: number
12 | | 'AccessorTest$': never
13 | |}
14 | |export const AccessorTest: AccessorTest$
15 | |""".check()
16 |
17 | }
18 |
19 | @JSExportTopLevel("AccessorTest")
20 | @JSExportAll
21 | object AccessorTest {
22 |
23 | private var x = 1
24 |
25 | def property = x
26 | def property_=(v: Int): Unit = x = v
27 |
28 | }
29 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AdapterClassTest.scala:
--------------------------------------------------------------------------------
1 | import eu.swdev.scala.ts.DtsFunSuite
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
5 |
6 | class AdapterClassTest extends DtsFunSuite {
7 | """
8 | |export interface AdapterClassTest$ {
9 | | readonly x: _root_AdapterClassTest.x$
10 | | 'AdapterClassTest$': never
11 | |}
12 | |export const AdapterClassTest: AdapterClassTest$
13 | |export namespace AdapterClassTest {
14 | | interface InstanceAdapter {
15 | | readonly $delegate: D
16 | | 'AdapterClassTest.InstanceAdapter': never
17 | | }
18 | | interface x$ {
19 | | readonly SomeClass: _root_AdapterClassTest.x.SomeClass$
20 | | 'AdapterClassTest.x$': never
21 | | }
22 | | namespace x {
23 | | interface SomeClass extends AdapterClassTest.InstanceAdapter<_root_x.SomeClass> {
24 | | readonly array: (number)[]
25 | | readonly sum: number
26 | | 'AdapterClassTest.x.SomeClass': never
27 | | }
28 | | interface SomeClass$ {
29 | | newInstance(array: (number)[]): _root_x.SomeClass
30 | | newAdapter(d: _root_x.SomeClass): AdapterClassTest.x.SomeClass
31 | | 'AdapterClassTest.x.SomeClass$': never
32 | | }
33 | | }
34 | |}
35 | |export namespace x {
36 | | interface SomeClass {
37 | | 'x.SomeClass': never
38 | | }
39 | |}
40 | |import _root_AdapterClassTest = AdapterClassTest
41 | |import _root_x = x
42 | |""".check(addRootNamespace = true)
43 | }
44 |
45 | package x {
46 | class SomeClass(val array: Array[Int]) {
47 | def sum: Int = ???
48 | }
49 | }
50 |
51 | @JSExportTopLevel("AdapterClassTest")
52 | object AdapterClassTest extends js.Object {
53 |
54 | @JSExportAll
55 | trait InstanceAdapter[D] {
56 | val $delegate: D
57 | }
58 |
59 | object x extends js.Object {
60 | @JSExportAll
61 | trait SomeClass extends InstanceAdapter[_root_.x.SomeClass] {
62 | def array: js.Array[Int] = ???
63 | def sum: Int = ???
64 | }
65 | object SomeClass extends js.Object {
66 | def newInstance(array: js.Array[Int]): _root_.x.SomeClass = ???
67 | def newAdapter(d: _root_.x.SomeClass): SomeClass = new SomeClass {
68 | override val $delegate = d
69 | }
70 | }
71 | }
72 |
73 | }
74 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AdapterNestedClassTest.scala:
--------------------------------------------------------------------------------
1 | import eu.swdev.scala.ts.DtsFunSuite
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
5 |
6 | class AdapterNestedClassTest extends DtsFunSuite {
7 |
8 | """
9 | |export interface AdapterNestedClassTest$ {
10 | | readonly x: AdapterNestedClassTest.x$
11 | | 'AdapterNestedClassTest$': never
12 | |}
13 | |export const AdapterNestedClassTest: AdapterNestedClassTest$
14 | |export namespace AdapterNestedClassTest {
15 | | interface InstanceAdapter {
16 | | readonly $delegate: D
17 | | 'AdapterNestedClassTest.InstanceAdapter': never
18 | | }
19 | | interface x$ {
20 | | readonly Outer: AdapterNestedClassTest.x.Outer$
21 | | 'AdapterNestedClassTest.x$': never
22 | | }
23 | | namespace x {
24 | | interface Outer extends AdapterNestedClassTest.InstanceAdapter {
25 | | outerMethod(): number
26 | | readonly Inner: AdapterNestedClassTest.x.Outer.Inner$
27 | | 'AdapterNestedClassTest.x.Outer': never
28 | | }
29 | | interface Outer$ {
30 | | newInstance(x: number): x.Outer
31 | | newAdapter(d: x.Outer): AdapterNestedClassTest.x.Outer
32 | | 'AdapterNestedClassTest.x.Outer$': never
33 | | }
34 | | namespace Outer {
35 | | interface Inner extends AdapterNestedClassTest.InstanceAdapter {
36 | | innerMethod(): string
37 | | 'AdapterNestedClassTest.x.Outer.Inner': never
38 | | }
39 | | interface Inner$ {
40 | | newInstance(y: string): x.Outer.Inner
41 | | newAdapter(d: x.Outer.Inner): AdapterNestedClassTest.x.Outer.Inner
42 | | 'AdapterNestedClassTest.x.Outer.Inner$': never
43 | | }
44 | | }
45 | | }
46 | |}
47 | |export namespace x {
48 | | interface Outer {
49 | | 'x.Outer': never
50 | | }
51 | | namespace Outer {
52 | | interface Inner {
53 | | 'x.Outer.Inner': never
54 | | }
55 | | }
56 | |}
57 | |""".check()
58 |
59 | }
60 |
61 | package x {
62 | case class Outer(val x: Int) {
63 | def outerMethod() = 2 * x
64 | case class Inner(val y: String) {
65 | def innerMethod() = y.reverse
66 | }
67 | }
68 | }
69 |
70 | @JSExportTopLevel("AdapterNestedClassTest")
71 | object AdapterNestedClassTest extends js.Object {
72 | @JSExportAll
73 | trait InstanceAdapter[D] {
74 | val $delegate: D
75 | }
76 |
77 | object x extends js.Object {
78 |
79 | object Outer extends js.Object {
80 | def newInstance(x: Int) = new _root_.x.Outer(x)
81 | def newAdapter(d: _root_.x.Outer): Outer = new Outer {
82 | override val $delegate = d
83 | }
84 | }
85 | @JSExportAll
86 | trait Outer extends InstanceAdapter[_root_.x.Outer] {
87 | def outerMethod() = $delegate.outerMethod()
88 | object Inner extends js.Object {
89 | def newInstance(y: String): _root_.x.Outer#Inner = new $delegate.Inner(y)
90 | def newAdapter(d: _root_.x.Outer#Inner): Inner = new Inner {
91 | override val $delegate = d
92 | }
93 |
94 | }
95 | @JSExportAll
96 | trait Inner extends InstanceAdapter[_root_.x.Outer#Inner] {
97 | def innerMethod() = $delegate.innerMethod()
98 | }
99 | }
100 |
101 | }
102 |
103 | }
104 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/Adt1Test.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class Adt1Test extends DtsFunSuite {
8 |
9 | """
10 | |export interface Adt1Case1 extends eu.swdev.scala.ts.dts.Adt1Test.Base {
11 | | 'Adt1Case1': never
12 | |}
13 | |export class Adt1Case1 {
14 | | constructor()
15 | |}
16 | |export interface Adt1Case2 extends eu.swdev.scala.ts.dts.Adt1Test.Base {
17 | | 'Adt1Case2': never
18 | |}
19 | |export class Adt1Case2 {
20 | | constructor()
21 | |}
22 | |export namespace eu {
23 | | namespace swdev {
24 | | namespace scala {
25 | | namespace ts {
26 | | namespace dts {
27 | | namespace Adt1Test {
28 | | interface Base {
29 | | 'eu.swdev.scala.ts.dts.Adt1Test.Base': never
30 | | }
31 | | type Base$u = Adt1Case1 | Adt1Case2
32 | | }
33 | | }
34 | | }
35 | | }
36 | | }
37 | |}
38 | |""".check()
39 | }
40 |
41 | object Adt1Test {
42 |
43 | sealed trait Base
44 |
45 | @JSExportTopLevel("Adt1Case1")
46 | class Case1 extends Base
47 |
48 | @JSExportTopLevel("Adt1Case2")
49 | class Case2 extends Base
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/Adt2Test.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class Adt2Test extends DtsFunSuite {
8 |
9 | """
10 | |export interface Adt2Case1 extends eu.swdev.scala.ts.dts.Adt2Test.Base {
11 | | 'Adt2Case1': never
12 | |}
13 | |export class Adt2Case1 {
14 | | constructor()
15 | |}
16 | |export interface Adt2Case2 extends eu.swdev.scala.ts.dts.Adt2Test.Base {
17 | | 'Adt2Case2': never
18 | |}
19 | |export class Adt2Case2 {
20 | | constructor()
21 | |}
22 | |export namespace eu {
23 | | namespace swdev {
24 | | namespace scala {
25 | | namespace ts {
26 | | namespace dts {
27 | | namespace Adt2Test {
28 | | interface Base {
29 | | 'eu.swdev.scala.ts.dts.Adt2Test.Base': never
30 | | }
31 | | type Base$u = Adt2Case1 | Adt2Case2
32 | | }
33 | | }
34 | | }
35 | | }
36 | | }
37 | |}
38 | |""".check()
39 | }
40 |
41 | object Adt2Test {
42 |
43 | sealed trait Base[X]
44 |
45 | @JSExportTopLevel("Adt2Case1")
46 | class Case1[Y] extends Base[Y]
47 |
48 | @JSExportTopLevel("Adt2Case2")
49 | class Case2 extends Base[Nothing]
50 |
51 | }
52 |
53 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/Adt3Test.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class Adt3Test extends DtsFunSuite {
8 |
9 | """
10 | |export interface Adt3TestCase1$ extends eu.swdev.scala.ts.dts.Adt3Test.T {
11 | | readonly str: string
12 | | 'Adt3TestCase1$': never
13 | |}
14 | |export const Adt3TestCase1: Adt3TestCase1$
15 | |export interface Adt3TestCase2$ extends eu.swdev.scala.ts.dts.Adt3Test.T {
16 | | readonly num: number
17 | | 'Adt3TestCase2$': never
18 | |}
19 | |export const Adt3TestCase2: Adt3TestCase2$
20 | |export namespace eu {
21 | | namespace swdev {
22 | | namespace scala {
23 | | namespace ts {
24 | | namespace dts {
25 | | namespace Adt3Test {
26 | | interface T {
27 | | 'eu.swdev.scala.ts.dts.Adt3Test.T': never
28 | | }
29 | | type T$u = Adt3TestCase1$ | Adt3TestCase2$
30 | | }
31 | | }
32 | | }
33 | | }
34 | | }
35 | |}
36 | |""".check()
37 | }
38 |
39 | object Adt3Test {
40 |
41 | sealed trait T
42 |
43 | @JSExportTopLevel("Adt3TestCase1")
44 | @JSExportAll
45 | object Case1 extends T {
46 | val str = "abc"
47 | }
48 | @JSExportTopLevel("Adt3TestCase2")
49 | @JSExportAll
50 | object Case2 extends T {
51 | val num = 555
52 | }
53 |
54 | }
55 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/AliasTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 | import scala.scalajs.js.|
7 |
8 | class AliasTest extends DtsFunSuite {
9 |
10 | """
11 | |export function invert(v: dts.AliasTest.U): dts.AliasTest.U
12 | |export namespace dts {
13 | | namespace AliasTest {
14 | | type U = number | string | boolean
15 | | }
16 | |}
17 | |""".check()
18 |
19 | }
20 |
21 | object AliasTest {
22 |
23 | type U = Int | String | Boolean
24 |
25 | @JSExportTopLevel("invert")
26 | def invert(v: U): U = ???
27 | }
28 |
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ApiReferenceTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 | import scala.scalajs.js.|
8 |
9 | class ApiReferenceTest extends DtsFunSuite {
10 |
11 | """
12 | |export function someExportedMethod(in: dts.ApiReferenceTest.Input): dts.ApiReferenceTest.Output
13 | |export namespace dts {
14 | | namespace ApiReferenceTest {
15 | | interface In1 {
16 | | readonly i: number
17 | | 'dts.ApiReferenceTest.In1': never
18 | | }
19 | | type In2 = dts.ApiReferenceTest.In2$
20 | | interface In2$ {
21 | | readonly s: string
22 | | 'dts.ApiReferenceTest.In2$': never
23 | | }
24 | | type Input = dts.ApiReferenceTest.In1 | dts.ApiReferenceTest.In2
25 | | interface Out1 {
26 | | readonly i: number
27 | | 'dts.ApiReferenceTest.Out1': never
28 | | }
29 | | interface Out2$ {
30 | | readonly s: string
31 | | 'dts.ApiReferenceTest.Out2$': never
32 | | }
33 | | type Output = dts.ApiReferenceTest.Out1 | dts.ApiReferenceTest.Out2$
34 | | }
35 | |}
36 | |""".check()
37 |
38 | }
39 |
40 | object ApiReferenceTest {
41 |
42 | // types Input, Output, In1, In2, In2$, Out1, and Out2$ are exported
43 | // -> they are reference in the exported method
44 |
45 | type In2 = In2.type
46 | type Out2 = Out2.type // the Out2 type alias is not exported because it is not referenced
47 |
48 | type Input = In1 | In2
49 | type Output = Out1 | Out2.type
50 |
51 | @JSExportTopLevel("someExportedMethod")
52 | def someExportedMethod(in: Input): Output = ???
53 |
54 | class Out1(val i: Int) extends js.Object
55 |
56 | object Out2 extends js.Object {
57 | val s = "abc"
58 | }
59 |
60 | class In1(val i: Int) extends js.Object
61 |
62 | object In2 extends js.Object {
63 | val s = "abc"
64 | }
65 |
66 | }
67 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ArrayTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class ArrayTest extends DtsFunSuite {
9 |
10 | """
11 | |export function vector(v: (number)[]): (number)[]
12 | |export function vectorGen(v: (X)[]): (X)[]
13 | |export function matrix(v: ((number)[])[]): ((number)[])[]
14 | |export function matrixGen(v: ((X)[])[]): ((X)[])[]
15 | |""".check()
16 |
17 | }
18 |
19 | object ArrayTest {
20 |
21 | @JSExportTopLevel("vector")
22 | def vector(v: js.Array[Int]) = v
23 | @JSExportTopLevel("vectorGen")
24 | def vectorGen[X](v: js.Array[X]) = v
25 | @JSExportTopLevel("matrix")
26 | def matrix(v: js.Array[js.Array[Int]]) = v
27 | @JSExportTopLevel("matrixGen")
28 | def matrixGen[X](v: js.Array[js.Array[X]]) = v
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ArrayTypeAliasTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 | import eu.swdev.scala.ts.tpe.ReadOnlyArray
5 |
6 | import scala.scalajs.js
7 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
8 |
9 | class ArrayTypeAliasTest extends DtsFunSuite {
10 |
11 | """
12 | |export class Example {
13 | | constructor()
14 | | foo(a: dts.Example.Elems): dts.Example.Elems
15 | |}
16 | |export namespace dts {
17 | | namespace Example {
18 | | type Elem = [string, any]
19 | | type Elems = (dts.Example.Elem)[]
20 | | }
21 | |}
22 | |""".check()
23 |
24 | }
25 |
26 | object Example {
27 | type Elem = js.Tuple2[String, js.Any]
28 | type Elems = js.Array[Elem]
29 | }
30 |
31 | @JSExportTopLevel("Example")
32 | @JSExportAll
33 | class Example() {
34 |
35 | import Example._
36 |
37 | def foo(a: Elems) = a
38 |
39 | }
40 |
41 |
42 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/BoundsTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class BoundsTest extends DtsFunSuite {
9 |
10 | """
11 | |export function upperBound(t: T): void
12 | |export class UpperBound {
13 | | constructor()
14 | |}
15 | |""".check()
16 |
17 | }
18 |
19 | object BoundsTest {
20 |
21 | @JSExportTopLevel("upperBound")
22 | def upperBound[T <: js.Object](t: T): Unit = ???
23 |
24 | @JSExportTopLevel("UpperBound")
25 | class UpperBound[T <: js.Object]
26 | }
27 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/BracketNotationTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportTopLevel, JSName}
7 |
8 | class BracketNotationTest extends DtsFunSuite {
9 |
10 | """
11 | |export interface BracketNotation$ {
12 | | readonly ['!x']: number
13 | | ['!y']: number
14 | | ['!z'](): number
15 | | 'BracketNotation$': never
16 | |}
17 | |export const BracketNotation: BracketNotation$
18 | |""".check()
19 |
20 | }
21 |
22 | @JSExportTopLevel("BracketNotation")
23 | object BracketNotationTest extends js.Object {
24 |
25 | @JSName("!x")
26 | val x = 1
27 |
28 | @JSName("!y")
29 | var y = 1
30 |
31 | @JSName("!z")
32 | def z() = 1
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ClassInheritanceTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class ClassInheritanceTest extends DtsFunSuite {
8 |
9 | """
10 | |export class A {
11 | | constructor(n: number)
12 | | readonly n: number
13 | |}
14 | |export class B extends A {
15 | | constructor(n: number, s: string)
16 | | readonly s: string
17 | |}
18 | |""".check()
19 |
20 | }
21 |
22 | object ClassInheritanceTest {
23 |
24 | @JSExportTopLevel("A")
25 | @JSExportAll
26 | class A(val n: Int)
27 |
28 | @JSExportTopLevel("B")
29 | @JSExportAll
30 | class B(n: Int, val s: String) extends A(n)
31 |
32 | }
33 |
34 |
35 |
36 |
37 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ClassTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class ClassTest extends DtsFunSuite {
8 |
9 | """
10 | |export class SomeClass {
11 | | constructor(s: string, i: number, b: boolean)
12 | | readonly s: string
13 | | i: number
14 | | doIt(): void
15 | |}
16 | |""".check()
17 |
18 | }
19 |
20 | @JSExportTopLevel("SomeClass")
21 | @JSExportAll
22 | case class SomeClass(s: String, var i: Int, private val b: Boolean) {
23 |
24 | def doIt() = ()
25 |
26 | private def privateDef() = ()
27 | private val privateVal = 1
28 | private var privateVar = 2
29 |
30 | }
31 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ClassWithInnerObjPropertyTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
7 |
8 | class ClassWithInnerObjPropertyTest extends DtsFunSuite {
9 |
10 | """
11 | |export interface AObj$ {
12 | | readonly outerV1: AObj.OuterV1
13 | | 'AObj$': never
14 | |}
15 | |export const AObj: AObj$
16 | |export namespace eu {
17 | | namespace swdev {
18 | | namespace scala {
19 | | namespace ts {
20 | | namespace dts {
21 | | namespace AObj {
22 | | interface OuterV1 {
23 | | readonly Middle: eu.swdev.scala.ts.dts.AObj.OuterV1.Middle$
24 | | 'eu.swdev.scala.ts.dts.AObj.OuterV1': never
25 | | }
26 | | namespace OuterV1 {
27 | | interface Middle$ {
28 | | readonly newAdapter: eu.swdev.scala.ts.dts.AObj.OuterV1.MiddleV1
29 | | 'eu.swdev.scala.ts.dts.AObj.OuterV1.Middle$': never
30 | | }
31 | | interface MiddleV1 {
32 | | 'eu.swdev.scala.ts.dts.AObj.OuterV1.MiddleV1': never
33 | | }
34 | | }
35 | | }
36 | | }
37 | | }
38 | | }
39 | | }
40 | |}
41 | |""".check()
42 | }
43 |
44 | @JSExportTopLevel("AObj")
45 | object AObj extends js.Object {
46 |
47 | @JSExportAll
48 | trait OuterV1 {
49 |
50 | @JSExportAll
51 | trait MiddleV1
52 |
53 | object Middle extends js.Object {
54 | def newAdapter: MiddleV1 = ???
55 | }
56 |
57 | // val middle = Middle
58 | }
59 |
60 | val outerV1: OuterV1 = ???
61 | // object OuterV1 extends js.Object {
62 | // def newAdapter: OuterV1 = ???
63 | // }
64 |
65 | }
66 |
67 | //@JSExportTopLevel("OuterClass")
68 | //@JSExportAll
69 | //class OuterClassWithInheritedObject extends OuterTrait
70 |
71 | //@JSExportTopLevel("ClassWithInnerObjProperty")
72 | //@JSExportAll
73 | //class ClassWithInnerObjProperty {
74 | //
75 | // trait InnerObj
76 | //
77 | // object InnerObj extends js.Object {
78 | // val x = 1
79 | // }
80 | //
81 | // val innnerObj = InnerObj
82 | //}
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/CtorParamExportTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
6 |
7 | class CtorParamExportTest extends DtsFunSuite {
8 |
9 | """
10 | |export class CtorParamClass {
11 | | constructor(x: number, z: number)
12 | | readonly x: number
13 | | y: number
14 | |}
15 | |""".check()
16 |
17 | }
18 |
19 | object CtorParamExportTest {
20 |
21 | @JSExportTopLevel("CtorParamClass")
22 | class C(@JSExport val x: Int, @JSExport("y") var z: Int)
23 |
24 | }
25 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/DateTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class DateTest extends DtsFunSuite {
9 |
10 | """
11 | |export const date: Date
12 | |""".check()
13 |
14 | }
15 |
16 | object DateTest {
17 | @JSExportTopLevel("date")
18 | val date: js.Date = ???
19 | }
20 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/DictionaryTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 | import scala.scalajs.js.|
8 |
9 | class DictionaryTest extends DtsFunSuite {
10 |
11 | """
12 | |export const dict1: { [key: string]: number }
13 | |export const dict2: { [key: string]: number | string }
14 | |""".check()
15 |
16 | }
17 |
18 | object DictionaryTest {
19 | @JSExportTopLevel("dict1")
20 | val dict1: js.Dictionary[Int] = ???
21 | @JSExportTopLevel("dict2")
22 | val dict2: js.Dictionary[Int | String] = ???
23 | }
24 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/FunctionTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class FunctionTest extends DtsFunSuite {
9 |
10 | """
11 | |export function fun0(f: () => R): void
12 | |export function fun1(f: (p1: T1) => R): void
13 | |export function fun2(f: (p1: T1, p2: T2) => R): void
14 | |export function fun3(f: (p1: () => R, p2: (p1: T1) => R) => R): void
15 | |""".check()
16 | }
17 |
18 | object FunctionTest {
19 | @JSExportTopLevel("fun0")
20 | def fun0[R](f: js.Function0[R]) = ()
21 | @JSExportTopLevel("fun1")
22 | def fun1[T1, R](f: js.Function1[T1, R]) = ()
23 | @JSExportTopLevel("fun2")
24 | def fun2[T1, T2, R](f: js.Function2[T1, T2, R]) = ()
25 | @JSExportTopLevel("fun3")
26 | def fun3[T1, R](f: js.Function2[js.Function0[R], js.Function1[T1, R], R]) = ()
27 | }
28 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/GenericClassTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class GenericClassTest extends DtsFunSuite {
8 |
9 | """
10 | |export class Box {
11 | | constructor(value: T)
12 | | readonly value: T
13 | | map(f: scala.Function1): Box
14 | |}
15 | |export function box(value: T): Box
16 | |export function unbox(b: Box): T
17 | |export namespace scala {
18 | | interface Function1 {
19 | | 'scala.Function1': never
20 | | }
21 | |}
22 | |""".check()
23 |
24 | }
25 |
26 | object GenericClassTest {
27 |
28 | @JSExportTopLevel("Box")
29 | @JSExportAll
30 | case class Box[T](value: T) {
31 |
32 | def map[X](f: T => X) = Box(f(value))
33 | }
34 |
35 | @JSExportTopLevel("box")
36 | def box[T](value: T) = Box(value)
37 |
38 | @JSExportTopLevel("unbox")
39 | def unbox[T](b: Box[T]): T = b.value
40 | }
41 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/GenericFunctionTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class GenericFunctionTest extends DtsFunSuite {
8 |
9 | """
10 | |export function some(t: T): scala.Some
11 | |export function option(t: T): scala.Option
12 | |export const none: scala.None$
13 | |export namespace scala {
14 | | interface None$ extends scala.Option {
15 | | 'scala.None$': never
16 | | }
17 | | interface Option {
18 | | 'scala.Option': never
19 | | }
20 | | interface Some extends scala.Option {
21 | | 'scala.Some': never
22 | | }
23 | |}
24 | |""".check()
25 |
26 | }
27 |
28 | object GenericFunctionTest {
29 |
30 | @JSExportTopLevel("some")
31 | def some[T](t: T): Some[T] = Some(t)
32 |
33 | @JSExportTopLevel("option")
34 | def option[T](t: T): Option[T] = Some(t)
35 |
36 | @JSExportTopLevel("none")
37 | val none = None
38 |
39 | }
40 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/GenericUnionTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class GenericUnionTest extends DtsFunSuite {
9 |
10 | """
11 | |export interface GenUnionCase1 extends eu.swdev.scala.ts.dts.GenericUnionTest.Base {
12 | | 'GenUnionCase1': never
13 | |}
14 | |export class GenUnionCase1 {
15 | | constructor()
16 | |}
17 | |export interface GenUnionCase2 extends eu.swdev.scala.ts.dts.GenericUnionTest.Base {
18 | | 'GenUnionCase2': never
19 | |}
20 | |export class GenUnionCase2 {
21 | | constructor()
22 | |}
23 | |export interface GenUnionCase3 extends eu.swdev.scala.ts.dts.GenericUnionTest.Base {
24 | | 'GenUnionCase3': never
25 | |}
26 | |export class GenUnionCase3 {
27 | | constructor()
28 | |}
29 | |export namespace eu {
30 | | namespace swdev {
31 | | namespace scala {
32 | | namespace ts {
33 | | namespace dts {
34 | | namespace GenericUnionTest {
35 | | interface Base {
36 | | 'eu.swdev.scala.ts.dts.GenericUnionTest.Base': never
37 | | }
38 | | type Base$u = GenUnionCase1 | GenUnionCase2 | GenUnionCase3<$M2_Y,T>
39 | | }
40 | | }
41 | | }
42 | | }
43 | | }
44 | |}
45 | |""".check()
46 |
47 | }
48 |
49 | object GenericUnionTest {
50 |
51 | sealed trait Base[T <: js.Object]
52 |
53 | @JSExportTopLevel("GenUnionCase1")
54 | class Case1[T <: js.Object] extends Base[T]
55 | @JSExportTopLevel("GenUnionCase2")
56 | class Case2[T <: js.Object, X] extends Base[T]
57 | @JSExportTopLevel("GenUnionCase3")
58 | class Case3[Y, T <: js.Object] extends Base[T]
59 | }
60 |
61 |
62 |
63 |
64 |
65 |
66 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/GlobalTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportTopLevel, JSGlobal}
7 |
8 | class GlobalTest extends DtsFunSuite {
9 |
10 | """
11 | |export const weakMap: WeakMap
12 | |export const weakSet: WeakSet
13 | |""".check()
14 |
15 | }
16 |
17 | object GlobalTest {
18 |
19 | @JSGlobal
20 | @js.native
21 | class WeakMap[K, V]
22 |
23 | @JSGlobal("WeakSet")
24 | @js.native
25 | class WeakSetRenamed[T]
26 |
27 | @JSExportTopLevel("weakMap")
28 | val map: WeakMap[String, String] = ???
29 |
30 | @JSExportTopLevel("weakSet")
31 | val set: WeakSetRenamed[String] = ???
32 | }
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ImportNamespaceTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportTopLevel, JSImport, JSName}
7 |
8 | class ImportNamespaceTest extends DtsFunSuite {
9 |
10 | """
11 | |import * as $module from 'module'
12 | |export const namespaceImported: $module.ImportedClass
13 | |export const renamedNamespaceImported: $module.Renamed
14 | |""".check()
15 |
16 | }
17 |
18 |
19 | object ImportNamespaceTest extends js.Object {
20 |
21 | @JSImport("module", JSImport.Namespace)
22 | object ImportedNamespace extends js.Object {
23 |
24 | class ImportedClass
25 |
26 | @JSName("Renamed")
27 | class RenamedImportedClass
28 |
29 | }
30 |
31 | @JSExportTopLevel("namespaceImported")
32 | val namespaceImported: ImportedNamespace.ImportedClass = ???
33 |
34 | @JSExportTopLevel("renamedNamespaceImported")
35 | val renamedNamespaceImported: ImportedNamespace.RenamedImportedClass = ???
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ImportTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportTopLevel, JSGlobal, JSImport}
7 |
8 | class ImportTest extends DtsFunSuite {
9 |
10 | """
11 | |import $random_ from 'random'
12 | |import * as $rxjs from 'rxjs'
13 | |export const observable: $rxjs.Observable
14 | |export const random: $random_
15 | |""".check()
16 |
17 | }
18 |
19 | object ImportTest {
20 |
21 | @JSImport("rxjs", "Observable")
22 | @js.native
23 | class Observable[T]
24 |
25 | @JSImport("random", JSImport.Default)
26 | @js.native
27 | object Random
28 |
29 | @JSExportTopLevel("observable")
30 | val observable: Observable[String] = ???
31 |
32 | @JSExportTopLevel("random")
33 | val random: Random.type = ???
34 | }
35 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/InnerClassTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class InnerClassTest extends DtsFunSuite {
8 |
9 | """
10 | |export const test: eu.swdev.scala.ts.dts.InnerClassTest.Outer.Inner
11 | |export namespace eu {
12 | | namespace swdev {
13 | | namespace scala {
14 | | namespace ts {
15 | | namespace dts {
16 | | namespace InnerClassTest {
17 | | namespace Outer {
18 | | interface Inner {
19 | | 'eu.swdev.scala.ts.dts.InnerClassTest.Outer.Inner': never
20 | | }
21 | | }
22 | | }
23 | | }
24 | | }
25 | | }
26 | | }
27 | |}
28 | |""".check()
29 | }
30 |
31 | object InnerClassTest {
32 |
33 | @JSExportTopLevel("test")
34 | val test: Outer#Inner = ???
35 |
36 | class Outer {
37 | class Inner
38 | }
39 |
40 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/IteratorTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class IteratorTest extends DtsFunSuite {
9 |
10 | """
11 | |export const iterator: Iterator
12 | |export const iterable: Iterable
13 | |""".check()
14 |
15 | }
16 |
17 | object IteratorTest {
18 | @JSExportTopLevel("iterator")
19 | val x: js.Iterator[String] = ???
20 | @JSExportTopLevel("iterable")
21 | val y: js.Iterable[Int] = ???
22 | }
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/JSExportTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExport, JSExportTopLevel}
6 |
7 | class JSExportTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface jsExportTest$ {
11 | | readonly x: number
12 | | readonly y: number
13 | | 'jsExportTest$': never
14 | |}
15 | |export const jsExportTest: jsExportTest$
16 | |""".check()
17 |
18 | }
19 |
20 | @JSExportTopLevel("jsExportTest")
21 | object JSExportTest {
22 |
23 | @JSExport
24 | val x = 0
25 | @JSExport("y")
26 | val z = 0
27 |
28 | }
29 |
30 |
31 |
32 |
33 |
34 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/JsClassTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class JsClassTest extends DtsFunSuite {
9 |
10 | """
11 | |export class JsClass {
12 | | constructor(str: string, num: number)
13 | | readonly str: string
14 | | num: number
15 | | setNum(n: number): void
16 | |}
17 | |""".check()
18 |
19 | }
20 |
21 | object JsClassTest {
22 |
23 | @JSExportTopLevel("JsClass")
24 | class JsClass(val str: String, var num: Int) extends js.Object {
25 | def setNum(n: Int): Unit = num = n
26 | }
27 | }
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/NativeSymbolTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel, JSName}
7 |
8 | class NativeSymbolTest extends DtsFunSuite {
9 |
10 | """
11 | |export interface NativeSymbol$ {
12 | | readonly someSymbol: symbol
13 | | [Symbol.iterator](): Iterator
14 | | [NativeSymbol.someSymbol](x: number): number
15 | | 'NativeSymbol$': never
16 | |}
17 | |export const NativeSymbol: NativeSymbol$
18 | |""".check()
19 |
20 | }
21 |
22 | @JSExportTopLevel("NativeSymbol")
23 | object NativeSymbolTest extends js.Object {
24 |
25 | val someSymbol: js.Symbol = ???
26 |
27 | @JSName(js.Symbol.iterator)
28 | def iterator(): js.Iterator[Int] = ???
29 |
30 | @JSName(someSymbol)
31 | def someMethod(x: Int): Int = x
32 | }
33 |
34 |
35 |
36 |
37 |
38 |
39 |
40 |
41 |
42 |
43 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/NoneTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class NoneTest extends DtsFunSuite {
8 |
9 | """
10 | |export const none: scala.None$
11 | |export namespace scala {
12 | | interface None$ {
13 | | 'scala.None$': never
14 | | }
15 | |}
16 | |""".check()
17 |
18 | }
19 |
20 | object NoneTest {
21 |
22 | @JSExportTopLevel("none")
23 | val none = None
24 |
25 | }
26 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ObjectTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
7 |
8 | class ObjectTest extends DtsFunSuite {
9 |
10 | """
11 | |export interface SomeObject$ {
12 | | doIt(): void
13 | | readonly x: number
14 | | y: number
15 | | readonly o: eu.swdev.scala.ts.dts.ObjectTest.o$
16 | | 'SomeObject$': never
17 | |}
18 | |export const SomeObject: SomeObject$
19 | |export namespace eu {
20 | | namespace swdev {
21 | | namespace scala {
22 | | namespace ts {
23 | | namespace dts {
24 | | namespace ObjectTest {
25 | | interface o$ {
26 | | readonly a: string
27 | | 'eu.swdev.scala.ts.dts.ObjectTest.o$': never
28 | | }
29 | | }
30 | | }
31 | | }
32 | | }
33 | | }
34 | |}
35 | |""".check()
36 |
37 | }
38 |
39 | @JSExportTopLevel("SomeObject")
40 | @JSExportAll
41 | object ObjectTest {
42 |
43 | def doIt() = ()
44 |
45 | val x = 1
46 | var y = 2
47 |
48 | @JSExportAll
49 | object o {
50 | val a = "abc"
51 | }
52 |
53 | private val a = 0
54 | private var b = 1
55 | private def m = ()
56 |
57 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/OuterTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class OuterTest extends DtsFunSuite {
9 |
10 | """
11 | |export class OuterClass {
12 | | constructor()
13 | | readonly midd: eu.swdev.scala.ts.dts.Outer.midd$
14 | |}
15 | |export interface OuterObject$ {
16 | | readonly middle: eu.swdev.scala.ts.dts.Outer.middle$
17 | | 'OuterObject$': never
18 | |}
19 | |export const OuterObject: OuterObject$
20 | |export namespace eu {
21 | | namespace swdev {
22 | | namespace scala {
23 | | namespace ts {
24 | | namespace dts {
25 | | namespace Outer {
26 | | interface midd$ {
27 | | x: number
28 | | 'eu.swdev.scala.ts.dts.Outer.midd$': never
29 | | }
30 | | interface middle$ {
31 | | readonly innerMost: eu.swdev.scala.ts.dts.Outer.middle.innerMost$
32 | | 'eu.swdev.scala.ts.dts.Outer.middle$': never
33 | | }
34 | | namespace middle {
35 | | interface innerMost$ {
36 | | x: number
37 | | 'eu.swdev.scala.ts.dts.Outer.middle.innerMost$': never
38 | | }
39 | | }
40 | | }
41 | | }
42 | | }
43 | | }
44 | | }
45 | |}
46 | |""".check()
47 |
48 | }
49 |
50 |
51 | @JSExportTopLevel("OuterClass")
52 | class Outer extends js.Object {
53 | object midd extends js.Object {
54 | // object innerMost extends js.Object {
55 | var x = 1
56 | // }
57 | }
58 | }
59 |
60 | @JSExportTopLevel("OuterObject")
61 | object Outer extends js.Object {
62 | object middle extends js.Object {
63 | object innerMost extends js.Object {
64 | var x = 1
65 | }
66 | }
67 | }
68 |
69 |
70 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/PromiseLikeTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class PromiseLikeTest extends DtsFunSuite {
9 |
10 | """
11 | |export const promiseLike: PromiseLike
12 | |""".check()
13 |
14 | }
15 |
16 | object PromiseLikeTest {
17 |
18 | @JSExportTopLevel("promiseLike")
19 | val pl: js.Thenable[Int] = ???
20 | }
21 |
22 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/PromiseTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class PromiseTest extends DtsFunSuite {
9 |
10 | """
11 | |export const promise: Promise
12 | |""".check()
13 |
14 | }
15 |
16 | object PromiseTest {
17 |
18 | @JSExportTopLevel("promise")
19 | val promise: js.Promise[String] = ???
20 | }
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ReadOnlyArrayTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 | import eu.swdev.scala.ts.tpe.ReadOnlyArray
5 |
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class ReadOnlyArrayTest extends DtsFunSuite {
9 |
10 | """
11 | |export const readOnlyArray: ReadonlyArray
12 | |""".check()
13 |
14 | }
15 |
16 | object ReadOnlyArrayTest {
17 |
18 | @JSExportTopLevel("readOnlyArray")
19 | val readOnlyArray: ReadOnlyArray[Int] = ???
20 | }
21 |
22 |
23 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/RegExpTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class RegExpTest extends DtsFunSuite {
9 |
10 | """
11 | |export const regExp: RegExp
12 | |""".check()
13 |
14 | }
15 |
16 | object RegExpTest {
17 | @JSExportTopLevel("regExp")
18 | val regExp: js.RegExp = ???
19 | }
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/RootPackageClassTest.scala:
--------------------------------------------------------------------------------
1 | import eu.swdev.scala.ts.DtsFunSuite
2 |
3 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
4 |
5 | class RootPackageClassTest extends DtsFunSuite {
6 |
7 | """
8 | |export class RootPackageClass {
9 | | constructor()
10 | | readonly i: number
11 | |}
12 | |""".check()
13 |
14 | }
15 |
16 | @JSExportTopLevel("RootPackageClass")
17 | @JSExportAll
18 | class RootPackageClass {
19 | val i = 1
20 | }
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/RootPackageObjectTest.scala:
--------------------------------------------------------------------------------
1 |
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class RootPackageObjectTest extends DtsFunSuite {
9 |
10 | """
11 | |export interface rootPackageObject$ {
12 | | readonly x: RootPackageObjectTest.x$
13 | | 'rootPackageObject$': never
14 | |}
15 | |export const rootPackageObject: rootPackageObject$
16 | |export namespace RootPackageObjectTest {
17 | | interface x$ {
18 | | readonly x: number
19 | | 'RootPackageObjectTest.x$': never
20 | | }
21 | |}
22 | |""".check()
23 |
24 | }
25 |
26 | @JSExportTopLevel("rootPackageObject")
27 | object RootPackageObjectTest extends js.Object {
28 | object x extends js.Object {
29 | val x = 1
30 | }
31 | }
32 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SealedTraitAllMembersExportedTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class SealedTraitAllMembersExportedTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface Case1 extends dts.SealedTraitAllMembersExportedTest.Base {
11 | | 'Case1': never
12 | |}
13 | |export class Case1 {
14 | | constructor()
15 | |}
16 | |export interface Case2 extends dts.SealedTraitAllMembersExportedTest.Sub {
17 | | 'Case2': never
18 | |}
19 | |export class Case2 {
20 | | constructor()
21 | |}
22 | |export namespace dts {
23 | | namespace SealedTraitAllMembersExportedTest {
24 | | interface Base {
25 | | 'dts.SealedTraitAllMembersExportedTest.Base': never
26 | | }
27 | | type Base$u = Case1 | dts.SealedTraitAllMembersExportedTest.Sub$u
28 | | interface Sub extends dts.SealedTraitAllMembersExportedTest.Base {
29 | | 'dts.SealedTraitAllMembersExportedTest.Sub': never
30 | | }
31 | | type Sub$u = Case2
32 | | }
33 | |}
34 | |""".check()
35 |
36 | }
37 |
38 | object SealedTraitAllMembersExportedTest {
39 |
40 | sealed trait Base
41 | sealed trait Sub extends Base
42 |
43 | @JSExportTopLevel("Case1")
44 | class Case1 extends Base
45 |
46 | @JSExportTopLevel("Case2")
47 | class Case2 extends Sub
48 | }
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SealedTraitHierarchyTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class SealedTraitHierarchyTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface Case1 extends dts.SealedTraitHierarchyTest.Base {
11 | | 'Case1': never
12 | |}
13 | |export class Case1 {
14 | | constructor()
15 | |}
16 | |export interface Case2 extends dts.SealedTraitHierarchyTest.Base {
17 | | 'Case2': never
18 | |}
19 | |export class Case2 {
20 | | constructor()
21 | |}
22 | |export interface Case3 extends dts.SealedTraitHierarchyTest.Middle {
23 | | 'Case3': never
24 | |}
25 | |export class Case3 {
26 | | constructor()
27 | |}
28 | |export interface Case4 extends dts.SealedTraitHierarchyTest.Middle {
29 | | 'Case4': never
30 | |}
31 | |export class Case4 {
32 | | constructor()
33 | |}
34 | |export interface Case5 extends dts.SealedTraitHierarchyTest.Middle {
35 | | 'Case5': never
36 | |}
37 | |export class Case5 {
38 | | constructor()
39 | |}
40 | |export namespace dts {
41 | | namespace SealedTraitHierarchyTest {
42 | | interface Base {
43 | | 'dts.SealedTraitHierarchyTest.Base': never
44 | | }
45 | | type Base$u = Case1 | Case2 | dts.SealedTraitHierarchyTest.Middle$u
46 | | interface Middle extends dts.SealedTraitHierarchyTest.Base {
47 | | 'dts.SealedTraitHierarchyTest.Middle': never
48 | | }
49 | | type Middle$u = Case3 | Case4 | Case5
50 | | }
51 | |}
52 | |""".check()
53 |
54 | }
55 |
56 | object SealedTraitHierarchyTest {
57 |
58 | sealed trait Base[X]
59 |
60 | sealed trait Middle[X, Y] extends Base[X]
61 |
62 | @JSExportTopLevel("Case1")
63 | class Case1[X] extends Base[X]
64 |
65 | @JSExportTopLevel("Case2")
66 | class Case2[X, Y] extends Base[X]
67 |
68 | @JSExportTopLevel("Case3")
69 | class Case3[X, Y] extends Middle[X, Y]
70 |
71 | @JSExportTopLevel("Case4")
72 | class Case4[X, Y, Z] extends Middle[X, Y]
73 |
74 | @JSExportTopLevel("Case5")
75 | class Case5[X, Y, Z] extends Middle[X, Y]
76 |
77 | }
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 |
87 |
88 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SealedTraitNoMembersExportedTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | class SealedTraitNoMembersExportedTest extends DtsFunSuite {
6 |
7 | """
8 | |""".check()
9 |
10 | }
11 |
12 | object SealedTraitNoMembersExportedTest {
13 | sealed trait Base
14 | sealed trait Sub extends Base
15 |
16 | class Case1 extends Base
17 |
18 | class Case2 extends Sub
19 |
20 | class Case3 extends Sub
21 |
22 | }
23 |
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SealedTraitSomeMembersExportedTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class SealedTraitSomeMembersExportedTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface Case1 extends dts.SealedTraitSomeMembersExportedTest.Base {
11 | | 'Case1': never
12 | |}
13 | |export class Case1 {
14 | | constructor()
15 | |}
16 | |export interface Case2 extends dts.SealedTraitSomeMembersExportedTest.Sub {
17 | | 'Case2': never
18 | |}
19 | |export class Case2 {
20 | | constructor()
21 | |}
22 | |export namespace dts {
23 | | namespace SealedTraitSomeMembersExportedTest {
24 | | interface Base {
25 | | 'dts.SealedTraitSomeMembersExportedTest.Base': never
26 | | }
27 | | type Base$u = Case1 | dts.SealedTraitSomeMembersExportedTest.Sub$u
28 | | interface Case3 extends dts.SealedTraitSomeMembersExportedTest.Sub {
29 | | 'dts.SealedTraitSomeMembersExportedTest.Case3': never
30 | | }
31 | | interface Sub extends dts.SealedTraitSomeMembersExportedTest.Base {
32 | | 'dts.SealedTraitSomeMembersExportedTest.Sub': never
33 | | }
34 | | type Sub$u = Case2 | dts.SealedTraitSomeMembersExportedTest.Case3
35 | | }
36 | |}
37 | |""".check()
38 |
39 | }
40 |
41 | object SealedTraitSomeMembersExportedTest {
42 | sealed trait Base
43 | sealed trait Sub extends Base
44 |
45 | @JSExportTopLevel("Case1")
46 | class Case1 extends Base
47 |
48 | @JSExportTopLevel("Case2")
49 | class Case2 extends Sub
50 |
51 | class Case3 extends Sub
52 |
53 | }
54 |
55 |
56 |
57 |
58 |
59 |
60 |
61 |
62 |
63 |
64 |
65 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SealedTraitUnexportedMembersTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class SealedTraitUnexportedMembersTest extends DtsFunSuite {
8 |
9 | """
10 | |export interface Case1 extends dts.SealedTraitUnexportedMembersTest.Base {
11 | | 'Case1': never
12 | |}
13 | |export class Case1 {
14 | | constructor()
15 | |}
16 | |export namespace dts {
17 | | namespace SealedTraitUnexportedMembersTest {
18 | | interface Base {
19 | | 'dts.SealedTraitUnexportedMembersTest.Base': never
20 | | }
21 | | type Base$u = Case1 | dts.SealedTraitUnexportedMembersTest.Case2 | dts.SealedTraitUnexportedMembersTest.Case3$
22 | | interface Case2 extends dts.SealedTraitUnexportedMembersTest.Base {
23 | | 'dts.SealedTraitUnexportedMembersTest.Case2': never
24 | | }
25 | | interface Case3$ extends dts.SealedTraitUnexportedMembersTest.Base {
26 | | 'dts.SealedTraitUnexportedMembersTest.Case3$': never
27 | | }
28 | | }
29 | |}
30 | |""".check()
31 |
32 | }
33 |
34 | object SealedTraitUnexportedMembersTest {
35 |
36 | sealed trait Base
37 |
38 | @JSExportTopLevel("Case1")
39 | class Case1 extends Base
40 |
41 | class Case2 extends Base
42 |
43 | object Case3 extends Base
44 | }
45 |
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
55 |
56 |
57 |
58 |
59 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SealedTraitWithoutMembersExportedTest.scala:
--------------------------------------------------------------------------------
1 | package dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | class SealedTraitWithoutMembersExportedTest extends DtsFunSuite {
6 |
7 | """
8 | |""".check()
9 |
10 | }
11 |
12 | object SealedTraitWithoutMembersExportedTest {
13 |
14 | sealed trait Base
15 | sealed trait Sub
16 |
17 | }
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/StaticTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.{JSExportStatic, JSExportTopLevel}
7 |
8 | class StaticTest extends DtsFunSuite {
9 |
10 | """
11 | |export class ClassWitStatics {
12 | | static twice(x: number): number
13 | | static readonly str: string
14 | | static numero: number
15 | | static get x(): number
16 | | static set x(i: number)
17 | | constructor()
18 | |}
19 | |""".check()
20 |
21 | }
22 |
23 | object StaticTest {
24 |
25 | @JSExportTopLevel("ClassWitStatics")
26 | class ClassWitStatics extends js.Object
27 |
28 | object ClassWitStatics {
29 |
30 | @JSExportStatic
31 | def twice(x: Int) = 2 * x
32 | @JSExportStatic
33 | val str = "abc"
34 | @JSExportStatic("numero")
35 | var num = 55
36 | @JSExportStatic
37 | def x: Int = ???
38 | @JSExportStatic
39 | def x_=(i: Int): Unit = ???
40 |
41 | }
42 |
43 | }
44 |
45 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/SymbolTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class SymbolTest extends DtsFunSuite {
9 |
10 | """
11 | |export const sym: symbol
12 | |""".check()
13 |
14 | }
15 |
16 | object SymbolTest {
17 |
18 | @JSExportTopLevel("sym")
19 | val sym: js.Symbol = ???
20 | }
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 |
29 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/ThisFunctionTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.{ThisFunction1, ThisFunction2}
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class ThisFunctionTest extends DtsFunSuite {
9 |
10 | """
11 | |export const thisFunction1: (this: void, p1: string) => number
12 | |export const thisFunction2: (this: void, p1: string, p2: boolean) => number
13 | |export function thisMethod(this: void, i: number): number
14 | |""".check()
15 |
16 | }
17 |
18 | object ThisFunctionTest {
19 | @JSExportTopLevel("thisFunction1")
20 | val f1: ThisFunction1[Unit, String, Int] = ???
21 | @JSExportTopLevel("thisFunction2")
22 | val f2: ThisFunction2[Unit, String, Boolean, Int] = ???
23 | @JSExportTopLevel("thisMethod")
24 | def f3(`this`: Unit, i: Int): Int = i
25 | }
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/TopLevelDefValVarTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class TopLevelDefValVarTest extends DtsFunSuite {
8 |
9 | """
10 | |export const topLevelDefValVar_valString: string
11 | |export const topLevelDefValVar_valBoolean: boolean
12 | |export const topLevelDefValVar_valInt: number
13 | |export const topLevelDefValVar_valDouble: number
14 | |export let topLevelDefValVar_varString: string
15 | |export let topLevelDefValVar_varBoolean: boolean
16 | |export let topLevelDefValVar_varInt: number
17 | |export let topLevelDefValVar_varDouble: number
18 | |export function topLevelDefValVar_defUnit(): void
19 | |export function topLevelDefValVar_defNothing(): never
20 | |export function topLevelDefValVar_defDouble(n: number): number
21 | |""".check()
22 |
23 | }
24 |
25 | object TopLevelDefValVarTest {
26 |
27 | @JSExportTopLevel("topLevelDefValVar_valString")
28 | val valString = "abc";
29 | @JSExportTopLevel("topLevelDefValVar_valBoolean")
30 | val valBoolean = true
31 | @JSExportTopLevel("topLevelDefValVar_valInt")
32 | val valInt = 1
33 | @JSExportTopLevel("topLevelDefValVar_valDouble")
34 | val valDouble = 1.0
35 |
36 | @JSExportTopLevel("topLevelDefValVar_varString")
37 | var varString = "abc";
38 | @JSExportTopLevel("topLevelDefValVar_varBoolean")
39 | var varBoolean = true
40 | @JSExportTopLevel("topLevelDefValVar_varInt")
41 | var varInt = 1
42 | @JSExportTopLevel("topLevelDefValVar_varDouble")
43 | var varDouble = 1.0
44 |
45 | @JSExportTopLevel("topLevelDefValVar_defUnit")
46 | def unit() = ()
47 | @JSExportTopLevel("topLevelDefValVar_defNothing")
48 | def nothing(): Nothing = throw new RuntimeException()
49 | @JSExportTopLevel("topLevelDefValVar_defDouble")
50 | def double(n: Double) = 2 * n
51 |
52 | }
53 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/TraitInheritanceTest1.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
6 |
7 | class TraitInheritanceTest1 extends DtsFunSuite {
8 |
9 | """
10 | |export interface ClassWithInheritedMethods1 extends eu.swdev.scala.ts.dts.TraitInheritanceTest1.Middle {
11 | | 'ClassWithInheritedMethods1': never
12 | |}
13 | |export class ClassWithInheritedMethods1 {
14 | | constructor()
15 | |}
16 | |export namespace eu {
17 | | namespace swdev {
18 | | namespace scala {
19 | | namespace ts {
20 | | namespace dts {
21 | | namespace TraitInheritanceTest1 {
22 | | interface Base {
23 | | base(n: number): number
24 | | 'eu.swdev.scala.ts.dts.TraitInheritanceTest1.Base': never
25 | | }
26 | | interface Middle extends eu.swdev.scala.ts.dts.TraitInheritanceTest1.Base {
27 | | middle(n: number): number
28 | | 'eu.swdev.scala.ts.dts.TraitInheritanceTest1.Middle': never
29 | | }
30 | | }
31 | | }
32 | | }
33 | | }
34 | | }
35 | |}
36 | |""".check()
37 |
38 | }
39 |
40 | object TraitInheritanceTest1 {
41 | @JSExportAll
42 | trait Base {
43 | def base(n: Int) = 2*n
44 | }
45 |
46 | @JSExportAll
47 | trait Middle extends Base {
48 | def middle(n: Int) = 3*n
49 | }
50 |
51 | @JSExportTopLevel("ClassWithInheritedMethods1")
52 | class Cls extends Middle
53 | }
54 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/TraitInheritanceTest2.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class TraitInheritanceTest2 extends DtsFunSuite {
9 |
10 | """
11 | |export interface ClassWithInheritedMethods2 extends eu.swdev.scala.ts.dts.TraitInheritanceTest2.Middle {
12 | | 'ClassWithInheritedMethods2': never
13 | |}
14 | |export class ClassWithInheritedMethods2 {
15 | | constructor()
16 | | middle(n: number): number
17 | | base(n: number): number
18 | |}
19 | |export namespace eu {
20 | | namespace swdev {
21 | | namespace scala {
22 | | namespace ts {
23 | | namespace dts {
24 | | namespace TraitInheritanceTest2 {
25 | | interface Base {
26 | | base(n: number): number
27 | | 'eu.swdev.scala.ts.dts.TraitInheritanceTest2.Base': never
28 | | }
29 | | interface Middle extends eu.swdev.scala.ts.dts.TraitInheritanceTest2.Base {
30 | | middle(n: number): number
31 | | 'eu.swdev.scala.ts.dts.TraitInheritanceTest2.Middle': never
32 | | }
33 | | }
34 | | }
35 | | }
36 | | }
37 | | }
38 | |}
39 | |""".check()
40 |
41 | }
42 |
43 | object TraitInheritanceTest2 {
44 | trait Base extends js.Object {
45 | def base(n: Int): Int
46 | }
47 |
48 | trait Middle extends Base {
49 | def middle(n: Int): Int
50 | }
51 |
52 | @JSExportTopLevel("ClassWithInheritedMethods2")
53 | class Cls extends Middle {
54 | override def middle(n: Int): Int = 3*n
55 |
56 | override def base(n: Int): Int = 2*n
57 | }
58 | }
59 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/TupleTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js
6 | import scala.scalajs.js.annotation.JSExportTopLevel
7 |
8 | class TupleTest extends DtsFunSuite {
9 |
10 | """
11 | |export const tuple2: [string, number]
12 | |export const tuple3: [string, number, boolean]
13 | |""".check()
14 | }
15 |
16 | object TupleTest {
17 | @JSExportTopLevel("tuple2")
18 | val tuple2: js.Tuple2[String, Int] = ???
19 | @JSExportTopLevel("tuple3")
20 | val tuple3: js.Tuple3[String, Int, Boolean] = ???
21 | }
22 |
23 |
24 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/TypeAliasTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 | import scala.scalajs.js.|
7 |
8 | class TypeAliasTest extends DtsFunSuite {
9 |
10 | """
11 | |export const valWithTypeAlias: eu.swdev.scala.ts.dts.TypeAliasTest.X
12 | |export namespace eu {
13 | | namespace swdev {
14 | | namespace scala {
15 | | namespace ts {
16 | | namespace dts {
17 | | namespace TypeAliasTest {
18 | | type X = string | number
19 | | }
20 | | }
21 | | }
22 | | }
23 | | }
24 | |}
25 | |""".check()
26 |
27 | }
28 |
29 | object TypeAliasTest {
30 |
31 | type X = String | Int
32 |
33 | @JSExportTopLevel("valWithTypeAlias")
34 | val alias: X = ???
35 | }
36 |
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/UndefOrTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.UndefOr
6 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
7 |
8 | class UndefOrTest extends DtsFunSuite {
9 |
10 | """
11 | |export function undefOrInt(u?: number): number | undefined
12 | |export function undefOrGeneric(u?: X): X | undefined
13 | |export class UndefOrClass {
14 | | constructor(x?: X, y?: X)
15 | | readonly x?: X
16 | | y?: X
17 | | method(p?: X): X | undefined
18 | |}
19 | |""".check()
20 |
21 | }
22 |
23 | object UndefOrTest {
24 |
25 | @JSExportTopLevel("undefOrInt")
26 | def undefOrInt(u: UndefOr[Int]) = u
27 | @JSExportTopLevel("undefOrGeneric")
28 | def undefOrGeneric[X](u: UndefOr[X]) = u
29 |
30 | @JSExportTopLevel("UndefOrClass")
31 | @JSExportAll
32 | case class UndefOrClass[X](x: UndefOr[X], var y: UndefOr[X]) {
33 | def method(p: UndefOr[X]) = p
34 | }
35 |
36 | }
37 |
38 |
39 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/UnionTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 | import scala.scalajs.js.|
7 |
8 | class UnionTest extends DtsFunSuite {
9 |
10 | """
11 | |export const stringOrBooleanOrInt: string | boolean | number
12 | |""".check()
13 |
14 | }
15 |
16 | object UnionTest {
17 |
18 | @JSExportTopLevel("stringOrBooleanOrInt")
19 | val x: String | Boolean | Int = ???
20 |
21 | }
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/dts/VarArgsTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.dts
2 |
3 | import eu.swdev.scala.ts.DtsFunSuite
4 |
5 | import scala.scalajs.js.annotation.JSExportTopLevel
6 |
7 | class VarArgsTest extends DtsFunSuite {
8 |
9 | """
10 | |export function sumVarArgs(...is: number[]): number
11 | |""".check()
12 |
13 | }
14 |
15 | object VarArgsTest {
16 |
17 | @JSExportTopLevel("sumVarArgs")
18 | def sum(is: Int*): Int = is.sum
19 | }
20 |
21 |
22 |
23 |
24 |
25 |
--------------------------------------------------------------------------------
/generator/src/test/scala/eu/swdev/scala/ts/tpe/package.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | package object tpe {
4 |
5 | type ReadOnlyArray[T] = scala.scalajs.js.Array[T]
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/generator/src/test/scala/scala/scalajs/js/annotation/stubs.scala:
--------------------------------------------------------------------------------
1 | /*
2 | * Scala.js (https://www.scala-js.org/)
3 | *
4 | * Copyright EPFL.
5 | *
6 | * Licensed under Apache License 2.0
7 | * (https://www.apache.org/licenses/LICENSE-2.0).
8 | *
9 | * See the NOTICE file distributed with this work for
10 | * additional information regarding copyright ownership.
11 | */
12 |
13 | package scala.scalajs.js.annotation
14 |
15 | /** Marks the annotated class or object as imported from another JS module.
16 | *
17 | * Intuitively, this corresponds to ECMAScript import directives. See the
18 | * documentation of the various constructors.
19 | *
20 | * `@JSImport` is not compatible with the `jsDependencies` mechanism offered
21 | * by the Scala.js sbt plugin. You are responsible for resolving and/or
22 | * bundling the JavaScript modules that you are importing using other
23 | * mechanisms.
24 | */
25 | class JSImport private () extends scala.annotation.StaticAnnotation {
26 |
27 | /** Named import of a member of the module.
28 | *
29 | * Intuitively, this corresponds to the following ECMAScript import
30 | * directive:
31 | * {{{
32 | * import { as AnnotatedClassOrObject } from
33 | * }}}
34 | *
35 | * To import the default export of a module, use `JSImport.Default` as
36 | * `name`.
37 | */
38 | def this(module: String, name: String) = this()
39 |
40 | /** Namespace import (import the module itself).
41 | *
42 | * The second parameter should be the singleton `JSImport.Namespace`.
43 | *
44 | * Intuitively, this corresponds to
45 | * {{{
46 | * import * as AnnotatedObject from
47 | * }}}
48 | */
49 | def this(module: String, name: JSImport.Namespace.type) = this()
50 |
51 | /** Named import of a member of the module, with a fallback on a global
52 | * variable.
53 | *
54 | * When linking with module support, this is equivalent to
55 | * `@JSImport(module, name)`.
56 | *
57 | * When linking without module support, this is equivalent to
58 | * `@JSGlobal(globalFallback)`.
59 | */
60 | def this(module: String, name: String, globalFallback: String) = this()
61 |
62 | /** Namespace import (import the module itself), with a fallback on a global
63 | * variable.
64 | *
65 | * When linking with module support, this is equivalent to
66 | * `@JSImport(module, name)`.
67 | *
68 | * When linking without module support, this is equivalent to
69 | * `@JSGlobal(globalFallback)`.
70 | */
71 | def this(module: String, name: JSImport.Namespace.type,
72 | globalFallback: String) = this()
73 | }
74 |
75 | object JSImport {
76 | /** Use as the `name` of a `JSImport` to use the default import.
77 | *
78 | * The actual value of this constant, the string `"default"`, is not
79 | * arbitrary. It is the name under which a default export is registered in
80 | * the ECMAScript 2015 specification.
81 | */
82 | final val Default = "default"
83 |
84 | /** Use as the `name` of a `JSImport` to use a namespace import.
85 | *
86 | * Intuitively, it corresponds to `*` in an ECMAScript import:
87 | * {{{
88 | * import * as AnnotatedObject from
89 | * }}}
90 | */
91 | object Namespace
92 | }
93 |
94 | class JSGlobal extends scala.annotation.StaticAnnotation {
95 | def this(name: String) = this()
96 | }
97 |
98 | class JSName private () extends scala.annotation.StaticAnnotation {
99 | def this(name: String) = this()
100 | def this(symbol: scala.scalajs.js.Symbol) = this()
101 | }
102 |
103 | class JSExportStatic extends scala.annotation.StaticAnnotation {
104 | def this(name: String) = this()
105 | }
106 |
--------------------------------------------------------------------------------
/generator/src/test/scala/scala/scalajs/js/package.scala:
--------------------------------------------------------------------------------
1 | package scala.scalajs
2 |
3 | import scala.annotation.unchecked.uncheckedVariance
4 |
5 | package object js {
6 |
7 | type UndefOr[+A] = (A @uncheckedVariance) | Unit
8 |
9 | class native extends scala.annotation.StaticAnnotation
10 | }
11 |
--------------------------------------------------------------------------------
/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version = 1.9.3
2 |
--------------------------------------------------------------------------------
/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | libraryDependencies += "org.scala-sbt" %% "scripted-plugin" % sbtVersion.value
2 |
3 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.13.2")
4 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0")
5 | addSbtPlugin("com.github.sbt" % "sbt-ci-release" % "1.5.12")
6 |
--------------------------------------------------------------------------------
/runtime/src/main/scala/eu/swdev/scala/ts/adapter/InteropIterable.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.adapter
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.JSConverters._
5 | import scala.scalajs.js.annotation.JSName
6 |
7 | class InteropIterable[A, B](iter: Iterable[A], f: A => B) extends js.Iterable[B] {
8 | @JSName(js.Symbol.iterator)
9 | override def jsIterator(): js.Iterator[B] = iter.map(f).iterator.toJSIterator
10 | }
11 |
--------------------------------------------------------------------------------
/runtime/src/main/scala/eu/swdev/scala/ts/adapter/package.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | package object adapter {
4 |
5 | /**
6 | * Captures the the type of the value that is converted.
7 | */
8 | implicit class InteropFrom[F](val f: F) extends AnyVal {
9 | def $cnv[T](implicit ev: InteropConverter[F, T]): T = ev(f)
10 | }
11 |
12 | }
13 |
--------------------------------------------------------------------------------
/runtime/src/main/scala/eu/swdev/scala/ts/tpe/package.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | package object tpe {
4 |
5 | type ReadOnlyArray[T] = scala.scalajs.js.Array[T]
6 |
7 | }
8 |
--------------------------------------------------------------------------------
/runtime/src/test/scala/eu/swdev/scala/ts/adapter/AsyncConverterTest.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.adapter
2 |
3 | import org.scalatest.funsuite.AsyncFunSuite
4 | import org.scalatest.matchers.must.Matchers
5 |
6 | import scala.concurrent.Future
7 | import scala.scalajs.js
8 |
9 | class AsyncConverterTest extends AsyncFunSuite with Matchers {
10 |
11 | implicit override def executionContext = scala.scalajs.concurrent.JSExecutionContext.queue
12 |
13 | test("Promise<->Future") {
14 | def method[X](a: Future[X]) = a
15 | val r: js.Promise[Int] = method(js.Promise.resolve[Int](1).$cnv/*.[Future[Int]]*/).$cnv
16 | r.toFuture.map(_ mustBe 1)
17 | }
18 |
19 | }
20 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/main/scala/BuildInfo.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts
2 |
3 | import java.util.Properties
4 |
5 | import sbt.internal.util.MessageOnlyException
6 |
7 | object BuildInfo {
8 | def version: String = props.getProperty("version")
9 |
10 | private lazy val props: Properties = {
11 | val props = new Properties()
12 | val path = "scala-ts.properties"
13 | val classloader = this.getClass.getClassLoader
14 | Option(classloader.getResourceAsStream(path)) match {
15 | case Some(stream) => props.load(stream)
16 | case None => throw new MessageOnlyException(s"can not determine ScalaTsPlugin version; missing resource: $path")
17 | }
18 | props
19 | }
20 | }
21 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/readme.md:
--------------------------------------------------------------------------------
1 | ### Test projects that use the ScalaTsPlugin
2 |
3 | Note: Node must be installed in order to test these projects.
4 |
5 | These projects are stand-alone projects that can be opened in an IDE and worked upon. In addition, each project contains a top-level `test` script file that configures a sequence of steps that is executed by the `scripted` task of the main build (cf. [Testing-sbt-plugins](https://www.scala-sbt.org/1.x/docs/Testing-sbt-plugins.html)).
6 |
7 | The plugin configuration of the `ScalaTsPlugin` in these projects is slightly complicated. The version number of the `ScalaTsPlugin` to use should match the version number of the current source state. The plugin configuration of the `ScalaTsPlugin` in `project/plugins.sbt` must distinguish two cases:
8 | * The project is tested by the `scripted` task: In this case, project files are copied into a temporary folder and no version can be derived from the current source state. The version number to use is specified by the `plugin.version` system property that is specified when running the `scripted` task.
9 | * The project is worked upon manually: In this case, the plugin version number is derived from the current source state. The derivation is done with the help of the [dynver](https://github.com/sbt/sbt-dynver) plugin. This plugin must be activated in `project/project/plugin.sbt` files in order to have the git version information available when configuring the `ScalaTsPlugin`.
10 |
11 | Projects that are cross built for different Scala versions output their generated node module in the cross target folders. Tests written in TypeScript use [NPM workspaces](https://docs.npmjs.com/cli/v7/using-npm/workspaces) corresponding to these Scala versions. Test specification code is shared between workspaces (using symlinks) and access to corresponding generated node module is given by a relative import of the `../mod/scala-ts-mod`.
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/build.sbt:
--------------------------------------------------------------------------------
1 | import scala.sys.process.Process
2 |
3 | val scala212 = "2.12.18"
4 | val scala213 = "2.13.11"
5 | val scala3 = "3.4.0-RC1-bin-SNAPSHOT" // "3.3.0"
6 | //val scala3 = "3.3.0"
7 |
8 | val scalaVersions = List(scala213, scala212) // TODO: Scala 3 not (yet) working
9 |
10 | ThisBuild / scalaVersion := scala213
11 |
12 | val npmInstall = taskKey[Unit]("Execute the 'npm install' command")
13 |
14 | lazy val shared =
15 | crossProject(JSPlatform, JVMPlatform)
16 | .crossType(CrossType.Pure)
17 | .settings(
18 | crossScalaVersions := scalaVersions,
19 | // add annotations dependency
20 | ScalaTsPlugin.crossProject.settings
21 | )
22 | .jvmSettings(
23 | libraryDependencies += "org.scala-js" %% "scalajs-stubs" % "1.0.0" % "provided",
24 | )
25 | .jsSettings(
26 | // adds semantic db settings
27 | ScalaTsPlugin.crossProject.jsSettings
28 | )
29 |
30 | lazy val client =
31 | project
32 | .enablePlugins(ScalaTsPlugin)
33 | .dependsOn(shared.js)
34 | .settings(
35 | crossScalaVersions := scalaVersions,
36 | name := "adapter-cross",
37 | organization := "eu.swdev",
38 | scalaTsModuleName := {
39 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
40 | s"scala-$scalaMajorMinor-ts-mod"
41 | },
42 | scalaTsValidate := true,
43 | scalaTsAdapterEnabled := true,
44 | (fastOptJS / crossTarget) := (Compile / crossTarget).value / "node_module",
45 | (fullOptJS / crossTarget) := (Compile / crossTarget).value / "node_module",
46 | //scalaTsChangeForkOptions := withDebugForkOptions(5005),
47 | npmInstall := Def
48 | .task {
49 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
50 | val cmd = Seq("npm", "i", "-w", s"ws-scala-$scalaMajorMinor")
51 | val r = (
52 | Process(cmd, baseDirectory.value) !
53 | )
54 | val log = streams.value.log
55 | if (r != 0) {
56 | log.warn(s"Exit code of command '${cmd.mkString(" ")}' was non zero; maybe the error can be ignored - exitCode: $r")
57 | }
58 | baseDirectory.value
59 | }
60 | .dependsOn(scalaTsFastOpt)
61 | .value,
62 | test := Def
63 | .task {
64 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
65 | val r = (
66 | Process(Seq("npm", "t", "-w", s"ws-scala-$scalaMajorMinor"), baseDirectory.value) !
67 | )
68 | if (r != 0) {
69 | throw new MessageOnlyException("e2e tests failed")
70 | }
71 | }
72 | .dependsOn(npmInstall)
73 | .value,
74 | cleanFiles += baseDirectory.value / "node_modules",
75 | cleanFiles ++= {
76 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
77 | val workspaceDir = baseDirectory.value / "src" / "test" / "ts" / s"ws-scala-$scalaMajorMinor"
78 | Seq(workspaceDir / "node_modules", workspaceDir / "dist")
79 | }
80 | )
81 |
82 | lazy val root = project
83 | .in(file("."))
84 | .aggregate(client, shared.js, shared.jvm)
85 | .settings(
86 | name := "adapter-cross",
87 | crossScalaVersions := Nil,
88 | // crossScalaVersions := scalaVersions,
89 | publish := {},
90 | publishLocal := {},
91 | )
92 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "workspaces": [ "src/test/ts/ws-*" ],
7 | "scripts": {
8 | "clean": "rm -rf node_modules"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "type": "module"
13 | }
14 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/spec/date-adaption.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('date access', function () {
4 |
5 | // class adapter
6 | const da = m.Adapter.t.DateAdaption
7 |
8 | it('as JavaScript date', function () {
9 | const d = new Date()
10 | da.date = d
11 | expect(da.date).toStrictEqual(d)
12 | })
13 |
14 | it('as number', function () {
15 | const d = new Date().getTime()
16 | da.doubleDate = d
17 | expect(da.doubleDate).toBe(d)
18 | })
19 |
20 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/spec/nested-class.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 | import { newAdapter } from './util'
3 |
4 | describe('nested class', function () {
5 |
6 | // class adapter
7 | const ca = m.Adapter.o.OuterClass
8 |
9 | it('two step construction', function () {
10 | const dOuter = ca.newDelegate(5)
11 | const aOuter = ca.newAdapter(dOuter)
12 | expect(aOuter.x).toBe(5)
13 | const dInner = aOuter.Inner.newDelegate('abc')
14 | const aInner = aOuter.Inner.newAdapter(dInner)
15 | expect(aInner.y).toBe('abc')
16 | })
17 |
18 | it('combined construction', () => {
19 | const outer = newAdapter(ca, 1)
20 | expect(outer.x).toBe(1)
21 | const inner = newAdapter(outer.Inner, 'uvw')
22 | expect(inner.y).toBe('uvw')
23 | })
24 |
25 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/spec/package-object.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 | import { newAdapter } from './util'
3 |
4 | describe('package object', function () {
5 |
6 | it('access method from package object', function () {
7 | expect(m.Adapter.eu.swdev.scala.ts.adapter.test.min([7, 6, 8])).toBe(6)
8 | })
9 |
10 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/spec/simple-class.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 | import { newAdapter } from './util'
3 |
4 | describe('simple class', function () {
5 |
6 | // class adapter
7 | const sca = m.Adapter.x.y.SimpleClass
8 |
9 | it('access constructor var', function () {
10 | const d = sca.newDelegate([1, 2, 3])
11 | const a = sca.newAdapter(d)
12 | expect(a.x).toStrictEqual([1, 2, 3])
13 | expect(a.sum).toBe(6)
14 | a.x = [4, 5, 6]
15 | expect(a.x).toStrictEqual([4, 5, 6])
16 | expect(a.sum).toBe(15)
17 | a.filter(n => n % 2 === 0)
18 | expect(a.sum).toBe(10)
19 | })
20 |
21 | it('combine instance creation and adaption', () => {
22 | const c = newAdapter(sca, [1, 2, 3, 4, 5])
23 | expect(c.sum).toBe(15)
24 | })
25 |
26 | it('acceess method in companion object', () => {
27 | const d = sca.fromInt(7)
28 | const a = sca.newAdapter(d)
29 | expect(a.sum).toBe(7)
30 | })
31 |
32 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/spec/util.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('util', function() {
4 |
5 | it('sequence list of options', function() {
6 | expect(m.Adapter.x.Util.sequence([1, 2])).toStrictEqual([1, 2])
7 | expect(m.Adapter.x.Util.sequence([1, undefined])).toBeUndefined
8 | expect(m.Adapter.x.Util.sequence([undefined, 2])).toBeUndefined
9 | expect(m.Adapter.x.Util.sequence([undefined, undefined])).toBeUndefined
10 | })
11 |
12 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/spec/util.ts:
--------------------------------------------------------------------------------
1 | // combine delegate and adapter creation
2 | export function newAdapter(
3 | a: { newDelegate: (...args: ARGS) => DELEGATE, newAdapter: (d: DELEGATE) => ADAPTER },
4 | ...args: ARGS
5 | ): ADAPTER {
6 | return a.newAdapter(a.newDelegate(...args))
7 | }
8 |
9 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.12/mod/scala-ts-mod.ts:
--------------------------------------------------------------------------------
1 | export * from 'scala-2.12-ts-mod'
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.12/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ws-scala-2.12",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "tsc && node --experimental-vm-modules ../../../../node_modules/jest/bin/jest"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "js-joda": "^1.11.0"
13 | },
14 | "comment": "scala-ts-mod is configured as a devDependecy -> cf. comment of externalNpm in build.sbt",
15 | "devDependencies": {
16 | "@types/jest": "^29.5.3",
17 | "@types/node": "^16.11.7",
18 | "jest": "^29.6.2",
19 | "jest-environment-node": "^29.6.2",
20 | "scala-2.12-ts-mod": "file:./../../../../target/scala-2.12/node_module",
21 | "typescript": "^5.1.6"
22 | },
23 | "type": "module"
24 | }
25 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.12/spec:
--------------------------------------------------------------------------------
1 | ../spec
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.12/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "include": [
4 | "spec/*",
5 | "mod/*"
6 | ],
7 | "compilerOptions": {
8 | "outDir": "./dist"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.13/mod/scala-ts-mod.ts:
--------------------------------------------------------------------------------
1 | export * from 'scala-2.13-ts-mod'
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.13/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "ws-scala-2.13",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "tsc && node --experimental-vm-modules ../../../../node_modules/jest/bin/jest"
8 | },
9 | "author": "",
10 | "license": "ISC",
11 | "dependencies": {
12 | "js-joda": "^1.11.0"
13 | },
14 | "comment": "scala-ts-mod is configured as a devDependecy -> cf. comment of externalNpm in build.sbt",
15 | "devDependencies": {
16 | "@types/jest": "^29.5.3",
17 | "@types/node": "^16.11.7",
18 | "jest": "^29.6.2",
19 | "jest-environment-node": "^29.6.2",
20 | "scala-2.13-ts-mod": "file:../../../../target/scala-2.13/node_module",
21 | "typescript": "^5.1.6"
22 | },
23 | "type": "module"
24 | }
25 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.13/spec:
--------------------------------------------------------------------------------
1 | ../spec
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/client/src/test/ts/ws-scala-2.13/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "extends": "../tsconfig.json",
3 | "include": [
4 | "spec/*",
5 | "mod/*"
6 | ],
7 | "compilerOptions": {
8 | "outDir": "./dist"
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.9.3
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | import sbt.Defaults.sbtPluginExtra
2 |
3 | // complicated way of adding the scala-ts plugin
4 | // -> the pluginVersion is derived from the git based version using the dynver plugin
5 | // -> the logic corresponds to: addSbtPlugin("io.github.swachter" % "sbt-scala-ts" % pluginVersion)
6 | libraryDependencies += {
7 | val sbtV = (pluginCrossBuild / sbtBinaryVersion).value
8 | val scalaV = (update / scalaBinaryVersion).value
9 | val Version = """(\d+(?:\.\d+)*).*""".r
10 | val pluginVersion = sys.props.get("plugin.version").getOrElse(version.value) match {
11 | case Version(v) if isSnapshot.value => s"$v-SNAPSHOT"
12 | case v => v
13 | }
14 | val dependency = "io.github.swachter" % "sbt-scala-ts" % pluginVersion
15 | sbtPluginExtra(dependency, sbtV, scalaV)
16 | }
17 |
18 | addSbtPlugin("org.portable-scala" % "sbt-scalajs-crossproject" % "1.0.0")
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/project/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1")
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/readme.md:
--------------------------------------------------------------------------------
1 | ### End-2-End of Adapter Generation
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/shared/src/main/scala/DateAdaption.scala:
--------------------------------------------------------------------------------
1 | package t
2 |
3 | import java.util.Date
4 |
5 | import eu.swdev.scala.ts.annotation.Adapt
6 |
7 | object DateAdaption {
8 |
9 | @Adapt
10 | var date: Date = new Date()
11 |
12 | @Adapt("Double")
13 | var doubleDate: Date = new Date()
14 |
15 | }
16 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/shared/src/main/scala/OuterClass.scala:
--------------------------------------------------------------------------------
1 | package o
2 |
3 | import eu.swdev.scala.ts.annotation.AdaptAll
4 |
5 | /* adapter:
6 |
7 | import scala.scalajs.js
8 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
9 | import eu.swdev.scala.ts.adapter._
10 | @JSExportAll
11 | trait InstanceAdapter[D] {
12 | val $delegate: D
13 | }
14 | @JSExportTopLevel("Adapter")
15 | object Adapter extends js.Object {
16 | object o extends js.Object {
17 | @JSExportAll
18 | trait OuterClass extends InstanceAdapter[_root_.o.OuterClass] {
19 | def x = $delegate.x.$res
20 | @JSExportAll
21 | trait Inner extends InstanceAdapter[_root_.o.OuterClass#Inner] {
22 | def y = $delegate.y.$res
23 | }
24 | object nner extends js.Object {
25 | def newAdapter(delegate: $delegate.Inner): Inner = new Inner {
26 | override val $delegate = delegate
27 | }
28 | def newDelegate(y: String) = new $delegate.Inner(y.$cnv[String])
29 | }
30 | }
31 | object OuterClass extends js.Object {
32 | def newAdapter(delegate: _root_.o.OuterClass): OuterClass = new OuterClass {
33 | override val $delegate = delegate
34 | }
35 | def newDelegate(x: Int) = new _root_.o.OuterClass(x.$cnv[Int])
36 | }
37 | }
38 | }
39 |
40 | */
41 | @AdaptAll
42 | class OuterClass(val x: Int) {
43 | @AdaptAll
44 | class Inner(val y: String)
45 | }
46 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/shared/src/main/scala/SimpleClass.scala:
--------------------------------------------------------------------------------
1 | package x.y
2 |
3 | import eu.swdev.scala.ts.annotation.{Adapt, AdaptAll}
4 |
5 | @AdaptAll
6 | class SimpleClass(var x: Array[Int]) {
7 |
8 | def sum = x.sum
9 |
10 | def filter(p: Int => Boolean) = x = x.filter(p)
11 |
12 | }
13 |
14 | object SimpleClass {
15 |
16 | @Adapt
17 | def fromInt(int: Int) = new SimpleClass(Array(int))
18 | }
19 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/shared/src/main/scala/Util.scala:
--------------------------------------------------------------------------------
1 | package x
2 |
3 | import eu.swdev.scala.ts.annotation._
4 |
5 | object Util {
6 |
7 | @Adapt("js.UndefOr[js.Array[X]]")
8 | def sequence[X](ol: List[Option[X]]): Option[List[X]] = ol.foldRight(Option(List.empty[X]))((o, a) => a.flatMap(l => o.map(_ :: l)))
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/shared/src/main/scala/eu/swdev/scala/ts/adapter/test/package.scala:
--------------------------------------------------------------------------------
1 | package eu.swdev.scala.ts.adapter
2 |
3 | import eu.swdev.scala.ts.annotation.Adapt
4 |
5 | package object test {
6 |
7 | @Adapt
8 | def min(list: List[Double]): Double = list.min
9 |
10 | }
11 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/adapter/test:
--------------------------------------------------------------------------------
1 | > +test
2 | # $ pause
3 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/build.sbt:
--------------------------------------------------------------------------------
1 | import sbt.KeyRanks.APlusTask
2 | import scala.jdk.CollectionConverters._
3 | import scala.sys.process.Process
4 |
5 | val scala212 = "2.12.18"
6 | val scala213 = "2.13.11"
7 | val scala3 = "3.4.0-RC1-bin-SNAPSHOT" // "3.3.0"
8 | //val scala3 = "3.3.0"
9 |
10 | val scalaVersions = List(scala213, scala212) // TODO: Scala 3 not (yet) working
11 |
12 | val npmInstall = taskKey[Unit]("Install npm packages.")
13 |
14 | ThisBuild / scalaVersion := scala213
15 |
16 | scalaTsFastOpt / logLevel := Level.Info
17 |
18 | lazy val root = (project in file("."))
19 | .enablePlugins(ScalaTsPlugin, ScalablyTypedConverterExternalNpmPlugin)
20 | .settings(
21 | crossScalaVersions := scalaVersions,
22 | version := "0.0.1-SNAPSHOT",
23 | name := "dts-cross",
24 | organization := "eu.swdev",
25 | scalaTsModuleName := {
26 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
27 | s"scala-$scalaMajorMinor-ts-mod"
28 | },
29 | scalaTsValidate := true,
30 | // enable adapter in order to include scala-ts-runtime library
31 | scalaTsAdapterEnabled := true,
32 | (fastOptJS / crossTarget) := (Compile / crossTarget).value / "node_module",
33 | (fullOptJS / crossTarget) := (Compile / crossTarget).value / "node_module",
34 | // scalaTsChangeForkOptions := withDebugForkOptions(5005),
35 | // the externalNpm task is executed by the ScalablyTypedConverterExternalNpmPlugin before the scala-ts module is generated
36 | // -> install dependencies; cf. https://scalablytyped.org/docs/plugin-no-bundler
37 | externalNpm := {
38 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
39 | val r = (
40 | Process("npm" :: "i" :: "-w" :: s"ws-scala-$scalaMajorMinor" :: "--omit=dev" :: Nil,
41 | baseDirectory.value,
42 | /* "PATH" -> System.getenv("PATH") */ ) !
43 | )
44 | if (r != 0) {
45 | throw new MessageOnlyException("Could not install nondev dependencies")
46 | }
47 | baseDirectory.value
48 | },
49 | npmInstall := Def
50 | .task {
51 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
52 | val cmd = Seq("npm", "i", "-w", s"ws-scala-$scalaMajorMinor")
53 | val r = (
54 | Process(cmd, baseDirectory.value) !
55 | )
56 | val log = streams.value.log
57 | if (r != 0) {
58 | log.warn(s"Exit code of command '${cmd.mkString(" ")}' was non zero; maybe the error can be ignored - exitCode: $r")
59 | }
60 | baseDirectory.value
61 | }
62 | .dependsOn(scalaTsFastOpt)
63 | .value,
64 | test := Def
65 | .task {
66 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
67 | val r = (
68 | Process(Seq("npm", "t", "-w", s"ws-scala-$scalaMajorMinor"), baseDirectory.value) !
69 | )
70 | if (r != 0) {
71 | throw new MessageOnlyException("e2e tests failed")
72 | }
73 | }
74 | .dependsOn(npmInstall)
75 | .value,
76 | cleanFiles += baseDirectory.value / "node_modules",
77 | cleanFiles ++= {
78 | val scalaMajorMinor = CrossVersion.partialVersion(scalaVersion.value).map(t => s"${t._1}.${t._2}").get
79 | val workspaceDir = baseDirectory.value / "src" / "test" / "ts" / s"ws-scala-$scalaMajorMinor"
80 | Seq(workspaceDir / "node_modules", workspaceDir / "dist")
81 | }
82 | // scalaTsChangeForkOptions := withDebugForkOptions(5005)
83 | )
84 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "test-app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "workspaces": [ "src/test/ts/ws-*" ],
7 | "scripts": {
8 | "clean": "rm -rf node_modules"
9 | },
10 | "author": "",
11 | "license": "ISC",
12 | "---": "the js-joda dependency is added here because the scalablytyped plugin process package.json and adds a js-joda dependency to the ScalaJS project",
13 | "dependencies": {
14 | "js-joda": "^1.11.0"
15 | },
16 | "type": "module"
17 | }
18 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/project/build.properties:
--------------------------------------------------------------------------------
1 | sbt.version=1.9.3
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | import sbt.Defaults.sbtPluginExtra
2 |
3 | // the ScalaTs plugin and the ScalablyTyped plugin both transitively depend on the ScalaJS plugin
4 | // -> set the necessary version here to overrule their version (TODO: validate that this is the correct way)
5 | addSbtPlugin("org.scala-js" % "sbt-scalajs" % "1.1.1")
6 |
7 | // complicated way of adding the scala-ts plugin
8 | // -> the pluginVersion is derived from the git based version using the dynver plugin
9 | // -> the logic corresponds to: addSbtPlugin("io.github.swachter" % "sbt-scala-ts" % pluginVersion)
10 | libraryDependencies += {
11 | val sbtV = (pluginCrossBuild / sbtBinaryVersion).value
12 | val scalaV = (update / scalaBinaryVersion).value
13 | val Version = """(\d+(?:\.\d+)*).*""".r
14 | val pluginVersion = sys.props.get("plugin.version").getOrElse(version.value) match {
15 | case Version(v) if isSnapshot.value => s"$v-SNAPSHOT"
16 | case v => v
17 | }
18 | val dependency = "io.github.swachter" % "sbt-scala-ts" % pluginVersion
19 | sbtPluginExtra(dependency, sbtV, scalaV)
20 | }
21 |
22 | addSbtPlugin("org.scalablytyped.converter" % "sbt-converter" % "1.0.0-beta42")
23 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/project/project/plugins.sbt:
--------------------------------------------------------------------------------
1 | addSbtPlugin("com.github.sbt" % "sbt-dynver" % "5.0.1")
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/readme.md:
--------------------------------------------------------------------------------
1 | ### End-2-End of TypeScript Declaration File Generation
2 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala-2.13/e2e/AdtTest.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
4 |
5 | object SimpleAdt {
6 |
7 | sealed trait Adt
8 |
9 | @JSExportTopLevel("SimpleAdtCase1")
10 | @JSExportAll
11 | case class Case1(int: Int) extends Adt {
12 | val tpe: "i" = "i"
13 | }
14 | @JSExportTopLevel("SimpleAdtCase2")
15 | @JSExportAll
16 | case class Case2(str: String) extends Adt {
17 | val tpe: "s" = "s"
18 | }
19 | }
20 |
21 | object ObjectAdt {
22 |
23 | sealed trait Adt
24 |
25 | @JSExportTopLevel("ObjectAdtCase1")
26 | @JSExportAll
27 | object Case1 extends Adt {
28 | val tpe: 1 = 1
29 | val str = "abc"
30 | }
31 |
32 | @JSExportTopLevel("ObjectAdtCase2")
33 | @JSExportAll
34 | object Case2 extends Adt {
35 | val tpe: 2 = 2
36 | val num = 555
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala-2.13/e2e/FunctionTest.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.JSExportTopLevel
5 |
6 | object FunctionTest {
7 | @JSExportTopLevel("fun0")
8 | def fun0[R](f: js.Function0[R]): R = f()
9 | @JSExportTopLevel("fun1")
10 | def fun1[T1, R](a: js.Array[T1], f: js.Function1[T1, js.Array[R]]): js.Array[R] = a.flatMap(f)
11 | @JSExportTopLevel("fun2")
12 | def fun2[T1, T2, R](a1: js.Array[T1], a2: js.Array[T2], f: js.Function2[T1, T2, R]): js.Array[R] = a1.zip(a2).map(f.tupled)
13 | }
14 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/Abstract.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
5 |
6 | /* .d.ts:
7 |
8 |
9 | */
10 |
11 | object Abstract {
12 |
13 | // abstract classes can not be exported at the moment: https://github.com/scala-js/scala-js/issues/4117
14 |
15 | /*
16 | @JSExportTopLevel("AbstractBase")
17 | abstract class Base(val length: Int) extends js.Object {
18 | def area(): Double
19 | def color: String
20 | val dimensions: Int
21 | var name: String
22 | }
23 |
24 | @JSExportTopLevel("Square")
25 | class Square(length: Int) extends Base(length) {
26 | override def area(): Double = length * length
27 | override def color: String = "red"
28 | override val dimensions: Int = 2
29 | override var name: String = "square"
30 | }
31 | */
32 |
33 | }
34 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/Adapter1.scala:
--------------------------------------------------------------------------------
1 | import scala.scalajs.js
2 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
3 | import eu.swdev.scala.ts.adapter._
4 |
5 | package x {
6 | package y {
7 | class SomeClass(val array: Array[Int]) {
8 | def sum: Int = array.sum
9 | }
10 | object SomeClass {
11 | def upper(s: String) = s.toUpperCase
12 | val x = 5
13 | var y = "abc"
14 | }
15 | }
16 | }
17 |
18 | @JSExportTopLevel("Adapter1")
19 | object Adapter1 extends js.Object {
20 |
21 | @JSExportAll
22 | trait InstanceAdapter[D] {
23 | val $delegate: D
24 | }
25 |
26 | object x extends js.Object {
27 | object y extends js.Object {
28 | @JSExportAll
29 | trait SomeClass extends InstanceAdapter[_root_.x.y.SomeClass] {
30 | def array = $delegate.array.$cnv[js.Array[Int]]
31 | def sum = $delegate.sum.$cnv[Int]
32 | }
33 | object SomeClass extends js.Object {
34 | def newInstance(array: js.Array[Int]) = new _root_.x.y.SomeClass(array.$cnv[Array[Int]])
35 | def newAdapter(delegate: _root_.x.y.SomeClass) = new SomeClass {
36 | override val $delegate = delegate
37 | }
38 | // access object def
39 | def upper(s: String): String = _root_.x.y.SomeClass.upper(s).$cnv[String]
40 | // access object val
41 | def x = _root_.x.y.SomeClass.x.$cnv[Int]
42 | // access object var
43 | def y = _root_.x.y.SomeClass.y.$cnv[String]
44 | def y_=(v: String) = _root_.x.y.SomeClass.y = v.$cnv[String]
45 | }
46 | }
47 | }
48 |
49 | }
50 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/AdapterWithInnerClass.scala:
--------------------------------------------------------------------------------
1 | import scala.scalajs.js
2 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
3 | import eu.swdev.scala.ts.adapter._
4 |
5 | package x {
6 | package y {
7 | case class Outer(val x: Int) {
8 | def outerMethod() = 2 * x
9 | case class Inner(val y: String) {
10 | def innerMethod() = y.reverse
11 | }
12 | }
13 | }
14 | }
15 |
16 | @JSExportTopLevel("AdapterWithInnerClass")
17 | object AdapterWithInnerClass extends js.Object {
18 | @JSExportAll
19 | trait InstanceAdapter[D] {
20 | val $delegate: D
21 | }
22 |
23 | object x extends js.Object {
24 |
25 | object y extends js.Object {
26 | object Outer extends js.Object {
27 | def newInstance(x: Int) = new _root_.x.y.Outer(x)
28 | def newAdapter(d: _root_.x.y.Outer) = new Outer {
29 | override val $delegate = d
30 | }
31 | }
32 | @JSExportAll
33 | trait Outer extends InstanceAdapter[_root_.x.y.Outer] {
34 | def outerMethod() = $delegate.outerMethod()
35 | object Inner {
36 | def newInstance(y: String) = new $delegate.Inner(y)
37 | def newAdapter(d: $delegate.Inner) = new Inner {
38 | override val $delegate = d
39 | }
40 |
41 | }
42 | @JSExportAll
43 | trait Inner extends InstanceAdapter[$delegate.Inner] {
44 | def innerMethod() = $delegate.innerMethod()
45 | }
46 | }
47 | }
48 |
49 | }
50 |
51 | }
52 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/BigIntInterop.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.JSExportTopLevel
5 |
6 | @JSExportTopLevel("BigIntInterop")
7 | object BigIntInterop extends js.Object {
8 |
9 | def string2BigInt(str: String): js.BigInt = js.BigInt(str)
10 |
11 | def bigInt2String(bigInt: js.BigInt): String = bigInt.toString()
12 |
13 | }
14 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/BracketNotation.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportTopLevel, JSName}
5 |
6 | @JSExportTopLevel("BracketNotation")
7 | object BracketNotation extends js.Object {
8 |
9 | @JSName("!a")
10 | val a = 1
11 |
12 | @JSName("!b")
13 | var b = 1
14 |
15 | @JSName("!c")
16 | def c() = 1
17 |
18 | @JSName("!d")
19 | def d(n: Int) = n
20 |
21 | @JSName("!e")
22 | object o extends js.Object {
23 | @JSName("!f")
24 | val x = 1
25 | }
26 |
27 | }
28 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/ClassWithStatics.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportStatic, JSExportTopLevel}
5 |
6 | /* .d.ts:
7 |
8 | export class ClassWitStatics {
9 | static twice(x: number): number
10 | static readonly str: string
11 | static numero: number
12 | static get x(): number
13 | static set x(i: number)
14 | constructor()
15 | }
16 |
17 | */
18 |
19 | @JSExportTopLevel("ClassWitStatics")
20 | class ClassWitStatics extends js.Object
21 |
22 | object ClassWitStatics {
23 |
24 | @JSExportStatic
25 | def twice(x: Int) = 2 * x
26 | @JSExportStatic
27 | val str = "abc"
28 | @JSExportStatic("numero")
29 | var num = 55
30 | @JSExportStatic
31 | def x = _x
32 | @JSExportStatic
33 | def x_=(i: Int) = _x = i
34 |
35 | var _x = 0
36 |
37 | }
38 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/FromToRange.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.{JSExportTopLevel, JSName}
5 | import scala.scalajs.js.JSConverters._
6 |
7 | @JSExportTopLevel("FromToRange")
8 | class FromToRange(from: Int, to: Int) extends js.Object {
9 |
10 | @JSName(js.Symbol.iterator)
11 | def iterator(): js.Iterator[Int] = (from to to).iterator.toJSIterator
12 | }
13 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/Outer.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.JSExportTopLevel
5 |
6 | @JSExportTopLevel("OuterClass")
7 | class Outer extends js.Object {
8 | object mid extends js.Object {
9 | // object innerMost1 extends js.Object {
10 | var x = 1
11 | // }
12 | }
13 | }
14 |
15 | @JSExportTopLevel("OuterObject")
16 | object Outer extends js.Object {
17 | object middle extends js.Object {
18 | object innerMost extends js.Object {
19 | var x = 1
20 | }
21 | }
22 | }
23 |
24 |
25 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/TraitInheritance1.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js.annotation.{JSExportAll, JSExportTopLevel}
4 |
5 | /* .d.ts:
6 |
7 | export interface ClassWithInheritedMethods1 extends e2e.TraitInheritance1.Middle {
8 | 'ClassWithInheritedMethods1': never
9 | }
10 | export class ClassWithInheritedMethods1 {
11 | constructor()
12 | }
13 | export namespace e2e {
14 | namespace TraitInheritance1 {
15 | interface Base {
16 | base(n: number): number
17 | 'e2e.TraitInheritance1.Base': never
18 | }
19 | interface Middle extends e2e.TraitInheritance1.Base {
20 | middle(n: number): number
21 | 'e2e.TraitInheritance1.Middle': never
22 | }
23 | }
24 | }
25 | import _root_e2e = e2e
26 |
27 | */
28 |
29 | object TraitInheritance1 {
30 | @JSExportAll
31 | trait Base {
32 | def base(n: Int) = 2*n
33 | }
34 |
35 | @JSExportAll
36 | trait Middle extends Base {
37 | def middle(n: Int) = 3*n
38 | }
39 |
40 | @JSExportTopLevel("ClassWithInheritedMethods1")
41 | class Cls extends Middle
42 |
43 | }
44 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/TraitInheritance2.scala:
--------------------------------------------------------------------------------
1 | package e2e
2 |
3 | import scala.scalajs.js
4 | import scala.scalajs.js.annotation.JSExportTopLevel
5 |
6 | /* .d.ts:
7 |
8 | export interface ClassWithInheritedMethods2 extends e2e.TraitInheritance2.Middle {
9 | 'ClassWithInheritedMethods2': never
10 | }
11 | export class ClassWithInheritedMethods2 {
12 | constructor()
13 | middle(n: number): number
14 | base(n: number): number
15 | }
16 | export namespace e2e {
17 | namespace TraitInheritance2 {
18 | interface Base {
19 | base(n: number): number
20 | 'e2e.TraitInheritance2.Base': never
21 | }
22 | interface Middle extends e2e.TraitInheritance2.Base {
23 | middle(n: number): number
24 | 'e2e.TraitInheritance2.Middle': never
25 | }
26 | }
27 | }
28 | import _root_e2e = e2e
29 |
30 | */
31 |
32 | object TraitInheritance2 {
33 |
34 | trait Base extends js.Object {
35 | def base(n: Int): Int
36 | }
37 |
38 | trait Middle extends Base {
39 | def middle(n: Int): Int
40 | }
41 |
42 | @JSExportTopLevel("ClassWithInheritedMethods2")
43 | class Cls extends Middle {
44 | override def middle(n: Int): Int = 3*n
45 | override def base(n: Int): Int = 2*n
46 | }
47 |
48 | }
49 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/main/scala/e2e/root-package.scala:
--------------------------------------------------------------------------------
1 | import scala.scalajs.js
2 | import scala.scalajs.js.annotation.JSExportTopLevel
3 |
4 | @JSExportTopLevel("RootPackageClass")
5 | class RootPackageClass extends js.Object {
6 | val i = 1
7 | }
8 |
9 | @JSExportTopLevel("RootPackageObject")
10 | object RootPackageObjectTest extends js.Object {
11 | val x = 1
12 | }
13 |
14 |
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/abstract.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('abstract', function() {
4 |
5 | it('simple', function() {
6 | const c1 = new m.AbstractTestCase1('abc')
7 | expect(c1.x).toBe('abc')
8 | const c2 = new m.AbstractTestCase2(55)
9 | expect(c2.x).toBe(55)
10 |
11 | })
12 |
13 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/api-reference.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('api reference', function() {
4 |
5 | it('class-2-class', function() {
6 | expect.assertions(1)
7 | const o = m.convertInput2Output(m.createInput(0))
8 | if ('i' in o) {
9 | expect(o.i).toBe(0)
10 | }
11 | });
12 |
13 | it('class-2-class', function() {
14 | expect.assertions(1)
15 | const o = m.convertInput2Output(m.createInput(1))
16 | if ('s' in o) {
17 | expect(o.s).toBe('abc')
18 | }
19 | });
20 |
21 |
22 | });
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/bigint.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('abstract', function() {
4 |
5 | it('simple', function() {
6 | const digits = 30
7 | const s1 = '9'.repeat(digits)
8 | const b1 = m.BigIntInterop.string2BigInt(s1)
9 | const b2 = b1 + 1n
10 | const s2 = m.BigIntInterop.bigInt2String(b2)
11 | const e2 = '1' + '0'.repeat(digits)
12 | expect(s2).toBe(e2)
13 | })
14 |
15 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/bracket-notation.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('bracket notation', function() {
4 |
5 | it('simple', function() {
6 | expect(m.BracketNotation['!a']).toBe(1)
7 | expect(m.BracketNotation['!b']).toBe(1)
8 | m.BracketNotation['!b'] += 1
9 | expect(m.BracketNotation['!b']).toBe(2)
10 | expect(m.BracketNotation['!c']()).toBe(1)
11 | expect(m.BracketNotation['!d'](3)).toBe(3)
12 | expect(m.BracketNotation['!e']['!f']).toBe(1)
13 | })
14 |
15 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/ctor-param-export.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('ctor param export', function() {
4 |
5 | it('simple', function() {
6 | const c = new m.CtorParamExport('abc', 'uvw')
7 | expect(c.x).toBe('abc')
8 | expect(c.y).toBe('uvw')
9 | })
10 |
11 | })
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/date.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('js.Date', function() {
4 |
5 | it('construct', function() {
6 | const d = new Date('2020-06-08')
7 | expect(m.fullYearOfDate(d)).toBe(2020)
8 | });
9 |
10 | });
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/dictionary.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('js.dictionary', function() {
4 |
5 | it('construct', function() {
6 | const d = { 'a': 1, 'b': 2, 'c': 3}
7 | expect(m.sumDict(d)).toBe(6)
8 | m.addToDict('d', 4, d)
9 | expect(m.sumDict(d)).toBe(10)
10 | });
11 |
12 | });
--------------------------------------------------------------------------------
/sbt-scala-ts/src/sbt-test/scala-ts/dts/src/test/ts/spec/global.spec.ts:
--------------------------------------------------------------------------------
1 | import * as m from '../mod/scala-ts-mod'
2 |
3 | describe('WeakMap', function() {
4 |
5 | it('construct', function() {
6 | const map = new WeakMap