16
import * as webidl2 from "webidl2"
18
isAttribute, isCallback, isClass, isConstructor, isDictionary, isEnum, isInterface, isOperation, isOptional,
19
isPromiseTypeDescription,
20
isRecordTypeDescription,
21
isSequenceTypeDescription,
22
isSingleTypeDescription, isTypedef, isUnionTypeDescription
23
} from "./webidl2-utils"
24
import { toString } from "./toString"
26
createContainerType, createNumberType, createUnionType, IDLCallback, IDLConstructor, IDLEntry, IDLEnum, IDLEnumMember, IDLExtendedAttribute, IDLInterface, IDLKind,
27
IDLMethod, IDLModuleType, IDLParameter, IDLPrimitiveType, IDLProperty, IDLType, IDLTypedef
29
import { isDefined, stringOrNone } from "../util"
31
export function toIDLNode(file: string, node: webidl2.IDLRootType): IDLEntry {
33
return toIDLEnum(file, node)
36
return toIDLInterface(file, node)
38
if (isInterface(node)) {
39
return toIDLInterface(file, node)
41
if (isCallback(node)) {
42
return toIDLCallback(file, node)
44
if (isTypedef(node)) {
45
return toIDLTypedef(file, node)
47
if (isDictionary(node)) {
48
return toIDLDictionary(file, node)
50
if (isNamespace(node)) {
51
return toIDLNamespcae(file, node)
54
throw new Error(`unexpected node type: ${toString(node)}`)
58
function isNamespace(node: webidl2.IDLRootType): node is webidl2.NamespaceType {
59
return node.type === 'namespace'
61
function isCallable(node: webidl2.IDLInterfaceMemberType): boolean {
62
return node.extAttrs.some(it => it.name == "Invoke")
65
function toIDLInterface(file: string, node: webidl2.InterfaceType): IDLInterface {
67
kind: isClass(node) ? IDLKind.Class : IDLKind.Interface,
70
documentation: makeDocs(node),
71
inheritance: [node.inheritance]
73
.map(it => toIDLType(file, it)),
74
constructors: node.members
75
.filter(isConstructor)
76
.map(it => toIDLConstructor(file, it)),
77
properties: node.members
79
.map(it => toIDLProperty(file, it)),
82
.filter(it => !isCallable(it))
83
.map(it => toIDLMethod(file, it)),
84
extendedAttributes: toExtendedAttributes(node.extAttrs),
85
callables: node.members
87
.filter(it => isCallable(it))
88
.map(it => toIDLMethod(file, it)),
92
function toIDLType(file: string, type: webidl2.IDLTypeDescription | string): IDLType {
93
if (typeof type === "string") {
97
kind: IDLKind.ReferenceType
100
if (isUnionTypeDescription(type)) {
101
const unionTypes = type.idlType
102
return createUnionType(unionTypes
103
.map(it => toIDLType(file, it))
106
if (isSingleTypeDescription(type)) {
110
kind: IDLKind.ReferenceType,
111
extendedAttributes: toExtendedAttributes(type.extAttrs)
114
if (isSequenceTypeDescription(type) || isPromiseTypeDescription(type) || isRecordTypeDescription(type)) {
115
return createContainerType(
117
type.idlType.map(it => toIDLType(file, it))
121
throw new Error(`unexpected type: ${toString(type)}`)
125
function toIDLMethod(file: string, node: webidl2.OperationMemberType): IDLMethod {
127
throw new Error(`method with no type ${toString(node)}`)
130
name: node.name ?? "",
131
isStatic: node.special === "static",
132
parameters: node.arguments.map(it => toIDLParameter(file, it)),
133
documentation: makeDocs(node),
134
returnType: toIDLType(file, node.idlType),
135
extendedAttributes: toExtendedAttributes(node.extAttrs),
140
function toIDLConstructor(file: string, node: webidl2.ConstructorMemberType): IDLConstructor {
142
parameters: node.arguments.map(it => toIDLParameter(file, it)),
143
documentation: makeDocs(node),
144
kind: IDLKind.Constructor
148
function toIDLParameter(file: string, node: webidl2.Argument): IDLParameter {
150
kind: IDLKind.Parameter,
152
isVariadic: node.variadic,
153
isOptional: node.optional,
154
type: toIDLType(file, node.idlType),
159
function toIDLCallback(file: string, node: webidl2.CallbackType): IDLCallback {
161
kind: IDLKind.Callback,
164
parameters: node.arguments.map(it => toIDLParameter(file, it)),
165
extendedAttributes: toExtendedAttributes(node.extAttrs),
166
documentation: makeDocs(node),
167
returnType: toIDLType(file, node.idlType)
171
function toIDLTypedef(file: string, node: webidl2.TypedefType): IDLTypedef {
173
kind: IDLKind.Typedef,
174
type: toIDLType(file, node.idlType),
175
extendedAttributes: toExtendedAttributes(node.extAttrs),
176
documentation: makeDocs(node),
182
function toIDLDictionary(file: string, node: webidl2.DictionaryType): IDLEnum {
186
documentation: makeDocs(node),
187
extendedAttributes: toExtendedAttributes(node.extAttrs),
189
elements: node.members.map(it => toIDLEnumMember(file, it))
193
function toIDLNamespcae(file: string, node: webidl2.NamespaceType): IDLModuleType {
196
kind: IDLKind.ModuleType,
198
extendedAttributes: toExtendedAttributes(node.extAttrs),
203
function toIDLProperty(file: string, node: webidl2.AttributeMemberType): IDLProperty {
205
kind: IDLKind.Property,
207
documentation: makeDocs(node),
209
type: toIDLType(file, node.idlType),
210
isReadonly: node.readonly,
211
isStatic: node.special === "static",
212
isOptional: isOptional(node),
213
extendedAttributes: toExtendedAttributes(node.extAttrs)
217
function toIDLEnumMember(file: string, node: webidl2.DictionaryMemberType): IDLEnumMember {
218
let initializer = undefined
219
if (node.default?.type == "string") {
220
initializer = node.default?.value
221
} else if (node.default?.type == "number") {
222
initializer = +(node.default?.value)
223
} else if (node.default == null) {
224
initializer = undefined
226
throw new Error(`Unrepresentable enum initializer: ${node.default}`)
229
kind: IDLKind.EnumMember,
231
type: toIDLType(file, node.idlType) as IDLPrimitiveType,
232
extendedAttributes: toExtendedAttributes(node.extAttrs),
233
initializer: initializer
237
function toExtendedAttributes(extAttrs: webidl2.ExtendedAttribute[]): IDLExtendedAttribute[]|undefined {
239
return extAttrs.map(it => {
242
value: it.rhs?.value ? it.rhs?.value : undefined
243
} as IDLExtendedAttribute
247
function makeDocs(node: webidl2.AbstractBase): stringOrNone {
249
node.extAttrs.forEach(it => {
250
if (it.name == "Documentation") docs = it.rhs?.value
255
function toIDLEnum(file: string, node: webidl2.EnumType): IDLEnum {
260
documentation: makeDocs(node),
261
extendedAttributes: toExtendedAttributes(node.extAttrs),
262
elements: node.values.map((it: { value: string }) => {
264
kind: IDLKind.EnumMember,
266
type: createNumberType(),
267
initializer: undefined