JS: add support of Promise<T> in IDL2K
This commit is contained in:
@@ -50,6 +50,7 @@
|
||||
<version>${antlr.version}</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>antlr</id>
|
||||
<goals>
|
||||
<goal>antlr4</goal>
|
||||
</goals>
|
||||
|
||||
@@ -465,7 +465,7 @@ nonAnyType
|
||||
| 'DOMString' typeSuffix
|
||||
| 'USVString' typeSuffix
|
||||
| IDENTIFIER_WEBIDL typeSuffix
|
||||
| 'sequence' '<' type '>' null_
|
||||
| sequenceType null_
|
||||
| 'object' typeSuffix
|
||||
| 'Date' typeSuffix
|
||||
| 'RegExp' typeSuffix
|
||||
@@ -506,6 +506,11 @@ integerType
|
||||
| 'long'+
|
||||
;
|
||||
|
||||
sequenceType
|
||||
: 'sequence' '<' type '>'
|
||||
| 'FrozenArray' '<' type '>'
|
||||
;
|
||||
|
||||
promiseType
|
||||
: 'Promise' '<' returnType '>'
|
||||
;
|
||||
|
||||
@@ -20,6 +20,7 @@ import org.antlr.v4.runtime.CharStream
|
||||
import org.antlr.v4.runtime.CommonTokenStream
|
||||
import org.antlr.v4.runtime.ParserRuleContext
|
||||
import org.antlr.v4.runtime.tree.ParseTree
|
||||
import org.antlr.v4.runtime.tree.RuleNode
|
||||
import org.antlr.v4.runtime.tree.TerminalNode
|
||||
import org.antlr.webidl.WebIDLBaseVisitor
|
||||
import org.antlr.webidl.WebIDLLexer
|
||||
@@ -130,11 +131,24 @@ class UnionTypeVisitor(val namespace: String) : WebIDLBaseVisitor<List<Type>>()
|
||||
|
||||
class TypeVisitor(val namespace: String) : WebIDLBaseVisitor<Type>() {
|
||||
private var type: Type = AnyType()
|
||||
private var awaitingSimpleType = false
|
||||
|
||||
override fun defaultResult() = type
|
||||
|
||||
override fun visitType(ctx: TypeContext?): Type {
|
||||
type = super.visitType(ctx)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitReturnType(ctx: ReturnTypeContext?): Type {
|
||||
awaitingSimpleType = true
|
||||
type = super.visitReturnType(ctx)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitNonAnyType(ctx: WebIDLParser.NonAnyTypeContext): Type {
|
||||
type = SimpleType(ctx.text, false)
|
||||
awaitingSimpleType = true
|
||||
type = super.visitNonAnyType(ctx)
|
||||
return type
|
||||
}
|
||||
|
||||
@@ -143,19 +157,62 @@ class TypeVisitor(val namespace: String) : WebIDLBaseVisitor<Type>() {
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitPromiseType(ctx: PromiseTypeContext): Type {
|
||||
type = PromiseType(TypeVisitor(namespace).visitChildren(ctx), false)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitSequenceType(ctx: SequenceTypeContext): Type {
|
||||
val mutable = ctx.getChild(0).text == "sequence"
|
||||
type = ArrayType(TypeVisitor(namespace).visitChildren(ctx), mutable = mutable, nullable = false)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitTypeSuffix(ctx: TypeSuffixContext): Type {
|
||||
when (ctx.text?.trim()) {
|
||||
"?" -> type = type.toNullable()
|
||||
"[]" -> type = ArrayType(type, false)
|
||||
"[]?" -> type = ArrayType(type, true)
|
||||
"?[]" -> type = ArrayType(type.toNullable(), false)
|
||||
"[]" -> type = ArrayType(type, mutable = true, nullable = false)
|
||||
"[]?" -> type = ArrayType(type, mutable = true, nullable = false)
|
||||
"?[]" -> type = ArrayType(type.toNullable(), mutable = true, nullable = false)
|
||||
}
|
||||
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitNull_(ctx: Null_Context): Type {
|
||||
if (ctx.text?.trim() == "?") {
|
||||
type = type.toNullable()
|
||||
}
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitTerminal(node: TerminalNode): Type {
|
||||
type = SimpleType(node.text, false)
|
||||
if (awaitingSimpleType) {
|
||||
type = SimpleType(node.text, false)
|
||||
awaitingSimpleType = false
|
||||
}
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitUnsignedIntegerType(ctx: UnsignedIntegerTypeContext): Type {
|
||||
awaitingSimpleType = false
|
||||
type = super.visitUnsignedIntegerType(ctx)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitUnrestrictedFloatType(ctx: UnrestrictedFloatTypeContext): Type {
|
||||
awaitingSimpleType = false
|
||||
type = super.visitUnrestrictedFloatType(ctx)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitFloatType(ctx: FloatTypeContext): Type {
|
||||
type = SimpleType(ctx.text, false)
|
||||
return type
|
||||
}
|
||||
|
||||
override fun visitIntegerType(ctx: IntegerTypeContext): Type {
|
||||
type = SimpleType(ctx.text, false)
|
||||
return type
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,6 +63,8 @@ fun Type.dynamicIfUnknownType(allTypes: Set<String>, standardTypes: Set<Type> =
|
||||
this is ArrayType -> copy(memberType = this.memberType.dynamicIfUnknownType(allTypes, standardTypes))
|
||||
this is UnionType -> if (this.name !in allTypes) DynamicType else this
|
||||
this is FunctionType -> copy(returnType = returnType.dynamicIfUnknownType(allTypes, standardTypes), parameterTypes = parameterTypes.map { it.copy(type = it.type.dynamicIfUnknownType(allTypes, standardTypes)) })
|
||||
this is PromiseType ->
|
||||
copy(valueType = valueType.dynamicIfUnknownType(allTypes, standardTypes))
|
||||
|
||||
else -> DynamicType
|
||||
}
|
||||
@@ -74,19 +76,14 @@ internal fun mapType(repository: Repository, type: Type): Type = when (type) {
|
||||
val typeName = type.type
|
||||
when {
|
||||
typeName in typeMapper -> typeMapper[typeName]!!.withNullability(type.nullable)
|
||||
typeName.endsWith("?") -> mapType(repository, SimpleType(typeName.removeSuffix("?"), false)).toNullable()
|
||||
typeName.endsWith("[]") -> ArrayType(memberType = mapType(repository, SimpleType(typeName.removeSuffix("[]"), false)), nullable = type.nullable)
|
||||
typeName.startsWith("unrestricted") -> mapType(repository, SimpleType(typeName.removePrefix("unrestricted"), false))
|
||||
typeName.startsWith("sequence<") -> ArrayType(mapType(repository, SimpleType(typeName.removePrefix("sequence<").removeSuffix(">").trim(), false)), type.nullable)
|
||||
typeName == "sequence" -> ArrayType(DynamicType, type.nullable)
|
||||
typeName in repository.interfaces -> type
|
||||
typeName in repository.typeDefs -> mapTypedef(repository, type)
|
||||
typeName in repository.enums -> SimpleType("String", type.nullable)
|
||||
typeName.startsWith("Promise<") -> DynamicType
|
||||
|
||||
else -> type
|
||||
}
|
||||
}
|
||||
is PromiseType -> type.copy(valueType = mapType(repository, type.valueType))
|
||||
is ArrayType -> type.copy(memberType = mapType(repository, type.memberType))
|
||||
is UnionType -> UnionType(type.namespace, type.memberTypes.map { mt -> mapType(repository, mt) }, type.nullable).toSingleTypeIfPossible()
|
||||
is FunctionType -> type.copy(
|
||||
@@ -94,7 +91,10 @@ internal fun mapType(repository: Repository, type: Type): Type = when (type) {
|
||||
returnType = mapType(repository, type.returnType).dynamicIfAnyType(),
|
||||
parameterTypes = type.parameterTypes.takeWhile { !it.vararg }.map { it.copy(type = mapType(repository, it.type)) }
|
||||
)
|
||||
else -> type
|
||||
|
||||
is AnyType,
|
||||
is UnitType,
|
||||
is DynamicType -> type
|
||||
}
|
||||
|
||||
private fun mapTypedef(repository: Repository, type: SimpleType): Type {
|
||||
|
||||
@@ -2,40 +2,43 @@ package org.jetbrains.idl2k
|
||||
|
||||
import java.util.*
|
||||
|
||||
interface Type {
|
||||
val nullable: Boolean
|
||||
fun render(): String
|
||||
sealed class Type {
|
||||
abstract val nullable: Boolean
|
||||
abstract fun render(): String
|
||||
}
|
||||
|
||||
private fun String.appendNullabilitySuffix(type: Type) = if (type.nullable) "$this?" else this
|
||||
|
||||
object UnitType : Type {
|
||||
object UnitType : Type() {
|
||||
override val nullable: Boolean
|
||||
get() = false
|
||||
|
||||
override fun render() = "Unit"
|
||||
}
|
||||
object DynamicType : Type {
|
||||
object DynamicType : Type() {
|
||||
override val nullable: Boolean
|
||||
get() = false
|
||||
|
||||
override fun render() = "dynamic"
|
||||
}
|
||||
data class AnyType(override val nullable: Boolean = true) : Type {
|
||||
data class AnyType(override val nullable: Boolean = true) : Type() {
|
||||
override fun render() = "Any".appendNullabilitySuffix(this)
|
||||
}
|
||||
data class SimpleType(val type: String, override val nullable: Boolean) : Type {
|
||||
data class SimpleType(val type: String, override val nullable: Boolean) : Type() {
|
||||
override fun render() = type.appendNullabilitySuffix(this)
|
||||
}
|
||||
data class FunctionType(val parameterTypes : List<Attribute>, val returnType : Type, override val nullable: Boolean) : Type {
|
||||
data class FunctionType(val parameterTypes : List<Attribute>, val returnType : Type, override val nullable: Boolean) : Type() {
|
||||
override fun render() = if (nullable) "(${renderImpl()})?" else renderImpl()
|
||||
private fun renderImpl() = "(${parameterTypes.joinToString(", ") { it.type.render() }}) -> ${returnType.render()}"
|
||||
}
|
||||
data class PromiseType(val valueType: Type, override val nullable: Boolean) : Type() {
|
||||
override fun render() = "Promise<${valueType.render()}>".appendNullabilitySuffix(this)
|
||||
}
|
||||
|
||||
val FunctionType.arity : Int
|
||||
get() = parameterTypes.size
|
||||
|
||||
class UnionType(val namespace: String, types: Collection<Type>, override val nullable: Boolean) : Type {
|
||||
class UnionType(val namespace: String, types: Collection<Type>, override val nullable: Boolean) : Type() {
|
||||
val memberTypes: Set<Type> = LinkedHashSet(types.sortedBy { it.toString() })
|
||||
val name = "Union${this.memberTypes.map { it.render() }.joinToString("Or")}"
|
||||
|
||||
@@ -52,8 +55,8 @@ class UnionType(val namespace: String, types: Collection<Type>, override val nul
|
||||
|
||||
fun UnionType.toSingleTypeIfPossible() = if (this.memberTypes.size == 1) this.memberTypes.single().withNullability(nullable) else this
|
||||
|
||||
data class ArrayType(val memberType: Type, override val nullable: Boolean) : Type {
|
||||
override fun render(): String = "Array<${memberType.render()}>".appendNullabilitySuffix(this)
|
||||
data class ArrayType(val memberType: Type, val mutable: Boolean, override val nullable: Boolean) : Type() {
|
||||
override fun render(): String = "Array<${if (mutable) "" else "out "}${memberType.render()}>".appendNullabilitySuffix(this)
|
||||
}
|
||||
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
@@ -66,6 +69,7 @@ private fun <T: Type> T.copyWithNullability(nullable: Boolean): T = when (this)
|
||||
is FunctionType -> this.copy(nullable = nullable)
|
||||
is UnionType -> this.copy(types = this.memberTypes, nullable = nullable)
|
||||
is ArrayType -> this.copy(nullable = nullable)
|
||||
is PromiseType -> this.copy(nullable = nullable)
|
||||
else -> throw UnsupportedOperationException()
|
||||
} as T
|
||||
|
||||
|
||||
Reference in New Issue
Block a user