Skip to content

Commit

Permalink
No longer automatically rewrite types to js.Promise and `js.Thenabl…
Browse files Browse the repository at this point in the history
…e`. Instead provide `toPromise` and `toFuture` operations implicitly.

It's just too complicated and it currently breaks a bunch of libs. This fixes #404, see that for some details
  • Loading branch information
oyvindberg committed Sep 30, 2022
1 parent 3598592 commit f514ce0
Show file tree
Hide file tree
Showing 43 changed files with 579 additions and 203 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -44,8 +44,6 @@ class ImportType(stdNames: QualifiedName.StdNames) {
TsQIdent.Std.ConcatArray -> NameMapping(stdNames.ConcatArray, stdNames.ConcatArray, QualifiedName.JsArray),
TsQIdent.Std.Function -> FunctionM,
TsQIdent.Std.Object -> ObjectM,
TsQIdent.Std.PromiseLike -> NameMapping(stdNames.PromiseLike, stdNames.PromiseLike, QualifiedName.JsThenable),
TsQIdent.Std.Promise -> NameMapping(QualifiedName.JsPromise, stdNames.Promise, QualifiedName.JsPromise),
TsQIdent.Std.ReadonlyArray -> NameMapping(stdNames.ReadonlyArray, stdNames.ReadonlyArray, QualifiedName.JsArray),
TsQIdent.Std.String -> StringM,
TsQIdent.string -> StringM,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,122 @@
package org.scalablytyped.converter.internal
package scalajs
package flavours

object GenPromiseOps extends TreeTransformation {
override def leaveContainerTree(scope: TreeScope)(s: ContainerTree): ContainerTree =
if (scope.libName == Name.std && s.name == Name.std) {
val newCompanions = IArray
.fromOptions(
flaff(s, Name("Promise")),
flaff(s, Name("PromiseLike")),
)
.toMap

val filteredMembers = s.members.filter {
case x: ModuleTree if newCompanions.contains(x.name) => false
case _ => true
}
s.withMembers(filteredMembers ++ IArray.fromTraversable(newCompanions.values))
} else s

def flaff(s: ContainerTree, name: Name): Option[(Name, ModuleTree)] = {
val (existingClass, existingModule, _) = s.index
.getOrElse(name, IArray.Empty)
.partitionCollect2({ case x: ClassTree => x }, { case x: ModuleTree => x })

existingClass match {
case IArray.first(cls) =>
val mod = existingModule.headOption.getOrElse(
ModuleTree(
Empty,
level = ProtectionLevel.Public,
name = cls.name,
parents = Empty,
members = Empty,
comments = NoComments,
codePath = cls.codePath,
isOverride = false,
),
)
val ops = genPromiseOps(cls, mod)
val mod1 = mod.copy(members = mod.members :+ ops)
Some((name, mod1))
case _ => None
}
}

def genPromiseOps(cls: ClassTree, mod: ModuleTree) = {
val paramName = Name("promise")
val Ops = Name(cls.name.unescaped + "Ops")
val OpsCP = mod.codePath + Ops

val toPromise = {
val name = Name("toPromise")
val tpe = TypeRef(QualifiedName.JsPromise, TypeParamTree.asTypeArgs(cls.tparams), NoComments)
MethodTree(
annotations = Empty,
level = ProtectionLevel.Public,
name = name,
tparams = Empty,
params = Empty,
impl = ExprTree.Cast(ExprTree.Ref(paramName), tpe),
resultType = tpe,
isOverride = false,
comments = NoComments,
codePath = OpsCP + name,
isImplicit = false,
)
}

val toFuture = {
val name = Name("toFuture")
val tpe = TypeRef(
QualifiedName(IArray(Name.scala, Name("concurrent"), Name("Future"))),
TypeParamTree.asTypeArgs(cls.tparams),
NoComments,
)
MethodTree(
annotations = Empty,
level = ProtectionLevel.Public,
name = name,
tparams = Empty,
params = Empty,
impl = ExprTree.Select(ExprTree.Ref(toPromise.name), Name("toFuture")),
resultType = tpe,
isOverride = false,
comments = NoComments,
codePath = OpsCP + name,
isImplicit = false,
)
}
ClassTree(
isImplicit = true,
annotations = IArray(Annotation.Inline),
level = ProtectionLevel.Public,
name = Ops,
tparams = cls.tparams,
parents = IArray(TypeRef.AnyVal),
ctors = IArray(
CtorTree(
ProtectionLevel.Public,
IArray(
ParamTree(
name = paramName,
isImplicit = false,
isVal = true,
tpe = TypeRef(cls.codePath, TypeParamTree.asTypeArgs(cls.tparams), NoComments),
default = NotImplemented,
comments = NoComments,
),
),
NoComments,
),
),
members = IArray(toPromise, toFuture),
classType = ClassType.Class,
isSealed = false,
comments = NoComments,
codePath = OpsCP,
)
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ case class JapgollyFlavour(
val genStBuildingComponent = new JapgollyGenStBuildingComponent(outputPkg, versions.scala)
val genComponents =
new JapgollyGenComponents(findProps, genStBuildingComponent, reactNamesProxy, enableLongApplyMethod)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod) >> GenPromiseOps

final override def rewrittenTree(scope: TreeScope, tree: PackageTree): PackageTree = {
val withCompanions = genCompanions.visitPackageTree(scope)(tree)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ case class NormalFlavour(

val memberToProp = new MemberToProp.Default(rewrites)
val findProps = new FindProps(new CleanIllegalNames(outputPkg), memberToProp, parentsResolver)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod) >> GenPromiseOps

final override def rewrittenTree(scope: TreeScope, tree: PackageTree): PackageTree =
genCompanions.visitPackageTree(scope)(tree)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ case class SlinkyFlavour(

val memberToProp = new MemberToProp.Default(rewrites)
val findProps = new FindProps(new CleanIllegalNames(outputPkg), memberToProp, parentsResolver)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod) >> GenPromiseOps
val genStBuildingComponent = new SlinkyGenStBuildingComponent(outputPkg, versions.scala)

/* we need the actual typescript react definitions at runtime to compute this lazily */
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ case class SlinkyNativeFlavour(
val findProps = new FindProps(new CleanIllegalNames(outputPkg), memberToProp, parentsResolver)
val genStBuildingComponent = new SlinkyGenStBuildingComponent(outputPkg, versions.scala)
val gen = new SlinkyGenComponents(SlinkyGenComponents.Native(()), findProps, genStBuildingComponent, reactNamesProxy)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod)
val genCompanions = new GenCompanions(findProps, enableLongApplyMethod) >> GenPromiseOps

final override def rewrittenTree(scope: TreeScope, tree: PackageTree): PackageTree = {
val withCompanions = genCompanions.visitPackageTree(scope)(tree)
Expand Down
4 changes: 2 additions & 2 deletions tests/elasticsearch-js/check-3/e/elasticsearch-js/build.sbt
Original file line number Diff line number Diff line change
@@ -1,11 +1,11 @@
organization := "org.scalablytyped"
name := "elasticsearch-js"
version := "0.0-unknown-e3106b"
version := "0.0-unknown-d0fe82"
scalaVersion := "3.1.2"
enablePlugins(ScalaJSPlugin)
libraryDependencies ++= Seq(
"com.olvind" %%% "scalablytyped-runtime" % "2.4.2",
"org.scalablytyped" %%% "std" % "0.0-unknown-befc3c")
"org.scalablytyped" %%% "std" % "0.0-unknown-184a14")
publishArtifact in packageDoc := false
scalacOptions ++= List("-encoding", "utf-8", "-feature", "-language:implicitConversions", "-language:higherKinds", "-language:existentials", "-no-indent", "-source:future")
licenses += ("MIT", url("http://opensource.org/licenses/MIT"))
Original file line number Diff line number Diff line change
@@ -1,27 +1,22 @@
package typings.elasticsearchJs

import typings.std.Promise
import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}

object mod {

trait TransportRequestPromise[T]
extends js.Promise[T] {
extends StObject
with Promise[T] {

def abort(): Unit
}
object TransportRequestPromise {

inline def apply[T](
abort: () => Unit,
`catch`: js.UndefOr[js.Function1[Any, Any | js.Thenable[Any]]] => js.Promise[Any],
executor: (js.Function1[T | js.Thenable[T], ?], js.Function1[Any, ?]) => ?,
`then`: ((js.Function1[T, Any | js.Thenable[Any]]) | Unit, js.UndefOr[js.Function1[Any, Any | js.Thenable[Any]]]) => js.Promise[Any]
): TransportRequestPromise[T] = {
val __obj = js.Dynamic.literal(abort = js.Any.fromFunction0(abort), executor = js.Any.fromFunction2(executor))
__obj.updateDynamic("catch")(js.Any.fromFunction1(`catch`))
__obj.updateDynamic("then")(js.Any.fromFunction2(`then`))
inline def apply[T](abort: () => Unit): TransportRequestPromise[T] = {
val __obj = js.Dynamic.literal(abort = js.Any.fromFunction0(abort))
__obj.asInstanceOf[TransportRequestPromise[T]]
}

Expand Down
2 changes: 1 addition & 1 deletion tests/elasticsearch-js/check-3/s/std/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
organization := "org.scalablytyped"
name := "std"
version := "0.0-unknown-befc3c"
version := "0.0-unknown-184a14"
scalaVersion := "3.1.2"
enablePlugins(ScalaJSPlugin)
libraryDependencies ++= Seq(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,17 @@
package typings.std

import scala.concurrent.Future
import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}

trait Promise[T] extends StObject
object Promise {

extension [T](promise: Promise[T]) {

def toFuture: Future[T] = toPromise.toFuture

def toPromise: js.Promise[T] = promise.asInstanceOf[js.Promise[T]]
}
}
2 changes: 1 addition & 1 deletion tests/monaco-editor/check-3/m/monaco-editor/build.sbt
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
organization := "org.scalablytyped"
name := "monaco-editor"
version := "0.0-unknown-615b53"
version := "0.0-unknown-e0fdf0"
scalaVersion := "3.1.2"
enablePlugins(ScalaJSPlugin)
libraryDependencies ++= Seq(
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
package typings.monacoEditor

import typings.monacoEditor.anon.Key
import typings.std.PromiseLike
import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}
Expand All @@ -15,14 +16,14 @@ object global {
extends StObject
with typings.monacoEditor.monaco.Promise[T, TProgress] {
def this(executor: js.Function3[
/* resolve */ js.Function1[/* value */ T | js.Thenable[T], Unit],
/* resolve */ js.Function1[/* value */ T | PromiseLike[T], Unit],
/* reject */ js.Function1[/* reason */ Any, Unit],
/* progress */ js.Function1[/* progress */ TProgress, Unit],
Unit
]) = this()
def this(
executor: js.Function3[
/* resolve */ js.Function1[/* value */ T | js.Thenable[T], Unit],
/* resolve */ js.Function1[/* value */ T | PromiseLike[T], Unit],
/* reject */ js.Function1[/* reason */ Any, Unit],
/* progress */ js.Function1[/* progress */ TProgress, Unit],
Unit
Expand All @@ -37,7 +38,7 @@ object global {
@js.native
val ^ : js.Any = js.native

inline def any[T](promises: js.Array[T | js.Thenable[T]]): typings.monacoEditor.monaco.Promise[Key[T], Any] = ^.asInstanceOf[js.Dynamic].applyDynamic("any")(promises.asInstanceOf[js.Any]).asInstanceOf[typings.monacoEditor.monaco.Promise[Key[T], Any]]
inline def any[T](promises: js.Array[T | PromiseLike[T]]): typings.monacoEditor.monaco.Promise[Key[T], Any] = ^.asInstanceOf[js.Dynamic].applyDynamic("any")(promises.asInstanceOf[js.Any]).asInstanceOf[typings.monacoEditor.monaco.Promise[Key[T], Any]]
}
}
}
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package typings.monacoEditor

import typings.std.PromiseLike
import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}
Expand All @@ -8,5 +9,5 @@ object monaco {

trait Promise[T, TProgress] extends StObject

type Thenable[T] = js.Thenable[T]
type Thenable[T] = PromiseLike[T]
}
11 changes: 11 additions & 0 deletions tests/prisma/check-3/p/prisma/build.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
organization := "org.scalablytyped"
name := "prisma"
version := "0.0-unknown-7a849c"
scalaVersion := "3.1.2"
enablePlugins(ScalaJSPlugin)
libraryDependencies ++= Seq(
"com.olvind" %%% "scalablytyped-runtime" % "2.4.2",
"org.scalablytyped" %%% "std" % "0.0-unknown-ba7c78")
publishArtifact in packageDoc := false
scalacOptions ++= List("-encoding", "utf-8", "-feature", "-language:implicitConversions", "-language:higherKinds", "-language:existentials", "-no-indent", "-source:future")
licenses += ("MIT", url("http://opensource.org/licenses/MIT"))
1 change: 1 addition & 0 deletions tests/prisma/check-3/p/prisma/project/build.properties
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
sbt.version=1.7.1
1 change: 1 addition & 0 deletions tests/prisma/check-3/p/prisma/project/plugins.sbt
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
addSbtPlugin("org.scala-js" %% "sbt-scalajs" % "1.10.0")
15 changes: 15 additions & 0 deletions tests/prisma/check-3/p/prisma/readme.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@

# Scala.js typings for prisma




## Note
This library has been generated from typescript code from first party type definitions.

Provided with :purple_heart: from [ScalablyTyped](https://github.com/oyvindberg/ScalablyTyped)

## Usage
See [the main readme](../../readme.md) for instructions.


Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package typings.prisma

import typings.prisma.prismaStrings.PrismaClientPromise
import typings.std.Promise
import typings.std.PromiseLike
import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}

object mod {

@JSImport("prisma", "Prisma__ColumnClient")
@js.native
open class PrismaColumnClient[T] ()
extends StObject
with PrismaPromise[T] {

def `catch`[TResult](): js.Promise[T | TResult] = js.native
def `catch`[TResult](onrejected: js.Function1[/* reason */ Any, TResult | PromiseLike[TResult]]): js.Promise[T | TResult] = js.native

def `finally`(): js.Promise[T] = js.native
def `finally`(onfinally: js.Function0[Unit]): js.Promise[T] = js.native

def `then`[TResult1, TResult2](): js.Promise[TResult1 | TResult2] = js.native
def `then`[TResult1, TResult2](onfulfilled: js.Function1[/* value */ T, TResult1 | PromiseLike[TResult1]]): js.Promise[TResult1 | TResult2] = js.native
def `then`[TResult1, TResult2](
onfulfilled: js.Function1[/* value */ T, TResult1 | PromiseLike[TResult1]],
onrejected: js.Function1[/* reason */ Any, TResult2 | PromiseLike[TResult2]]
): js.Promise[TResult1 | TResult2] = js.native
def `then`[TResult1, TResult2](onfulfilled: Null, onrejected: js.Function1[/* reason */ Any, TResult2 | PromiseLike[TResult2]]): js.Promise[TResult1 | TResult2] = js.native
def `then`[TResult1, TResult2](onfulfilled: Unit, onrejected: js.Function1[/* reason */ Any, TResult2 | PromiseLike[TResult2]]): js.Promise[TResult1 | TResult2] = js.native

@JSName(js.Symbol.toStringTag)
val toStringTag: PrismaClientPromise = js.native
}

@js.native
trait PrismaPromise[A]
extends StObject
with Promise[A]
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
package typings.prisma

import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}

/* This can be used to `require` the library as a side effect.
If it is a global library this will make scalajs-bundler include it */
@JSImport("prisma", JSImport.Namespace)
@js.native
object prismaRequire extends StObject
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
package typings.prisma

import org.scalablytyped.runtime.StObject
import scala.scalajs.js
import scala.scalajs.js.annotation.{JSGlobalScope, JSGlobal, JSImport, JSName, JSBracketAccess}

object prismaStrings {

@js.native
sealed trait PrismaClientPromise extends StObject
inline def PrismaClientPromise: PrismaClientPromise = "PrismaClientPromise".asInstanceOf[PrismaClientPromise]
}
Loading

0 comments on commit f514ce0

Please sign in to comment.