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