idlize

Форк
0
/
deserialize.ts 
271 строка · 8.7 Кб
1
/*
2
 * Copyright (c) 2024 Huawei Device Co., Ltd.
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15

16
import * as webidl2 from "webidl2"
17
import {
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"
25
import {
26
    createContainerType, createNumberType, createUnionType, IDLCallback, IDLConstructor, IDLEntry, IDLEnum, IDLEnumMember, IDLExtendedAttribute, IDLInterface, IDLKind,
27
    IDLMethod, IDLModuleType, IDLParameter, IDLPrimitiveType, IDLProperty, IDLType, IDLTypedef
28
} from "../idl"
29
import { isDefined, stringOrNone } from "../util"
30

31
export function toIDLNode(file: string, node: webidl2.IDLRootType): IDLEntry {
32
    if (isEnum(node)) {
33
        return toIDLEnum(file, node)
34
    }
35
    if (isClass(node)) {
36
        return toIDLInterface(file, node)
37
    }
38
    if (isInterface(node)) {
39
        return toIDLInterface(file, node)
40
    }
41
    if (isCallback(node)) {
42
        return toIDLCallback(file, node)
43
    }
44
    if (isTypedef(node)) {
45
        return toIDLTypedef(file, node)
46
    }
47
    if (isDictionary(node)) {
48
        return toIDLDictionary(file, node)
49
    }
50
    if (isNamespace(node)) {
51
        return toIDLNamespcae(file, node)
52
    }
53

54
    throw new Error(`unexpected node type: ${toString(node)}`)
55
}
56

57

58
function isNamespace(node: webidl2.IDLRootType): node is webidl2.NamespaceType {
59
    return node.type === 'namespace'
60
}
61
function isCallable(node: webidl2.IDLInterfaceMemberType): boolean {
62
    return node.extAttrs.some(it => it.name == "Invoke")
63
}
64

65
function toIDLInterface(file: string, node: webidl2.InterfaceType): IDLInterface {
66
    return {
67
        kind: isClass(node) ? IDLKind.Class : IDLKind.Interface,
68
        name: node.name,
69
        fileName: file,
70
        documentation: makeDocs(node),
71
        inheritance: [node.inheritance]
72
            .filter(isDefined)
73
            .map(it => toIDLType(file, it)),
74
        constructors: node.members
75
            .filter(isConstructor)
76
            .map(it => toIDLConstructor(file, it)),
77
        properties: node.members
78
            .filter(isAttribute)
79
            .map(it => toIDLProperty(file, it)),
80
        methods: node.members
81
            .filter(isOperation)
82
            .filter(it => !isCallable(it))
83
            .map(it => toIDLMethod(file, it)),
84
        extendedAttributes: toExtendedAttributes(node.extAttrs),
85
        callables: node.members
86
            .filter(isOperation)
87
            .filter(it => isCallable(it))
88
            .map(it => toIDLMethod(file, it)),
89
    }
90
}
91

92
function toIDLType(file: string, type: webidl2.IDLTypeDescription | string): IDLType {
93
    if (typeof type === "string") {
94
        return {
95
            name: type,
96
            fileName: file,
97
            kind: IDLKind.ReferenceType
98
        }
99
    }
100
    if (isUnionTypeDescription(type)) {
101
        const unionTypes = type.idlType
102
        return createUnionType(unionTypes
103
            .map(it => toIDLType(file, it))
104
            .filter(isDefined))
105
    }
106
    if (isSingleTypeDescription(type)) {
107
        return {
108
            name: type.idlType,
109
            fileName: file,
110
            kind: IDLKind.ReferenceType,
111
            extendedAttributes: toExtendedAttributes(type.extAttrs)
112
        }
113
    }
114
    if (isSequenceTypeDescription(type) || isPromiseTypeDescription(type) || isRecordTypeDescription(type)) {
115
        return createContainerType(
116
            type.generic,
117
            type.idlType.map(it => toIDLType(file, it))
118
        )
119
    }
120

121
    throw new Error(`unexpected type: ${toString(type)}`)
122
}
123

124

125
function toIDLMethod(file: string, node: webidl2.OperationMemberType): IDLMethod {
126
    if (!node.idlType) {
127
        throw new Error(`method with no type ${toString(node)}`)
128
    }
129
    return {
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),
136
        kind: IDLKind.Method
137
    }
138
}
139

140
function toIDLConstructor(file: string, node: webidl2.ConstructorMemberType): IDLConstructor {
141
    return {
142
        parameters: node.arguments.map(it => toIDLParameter(file, it)),
143
        documentation: makeDocs(node),
144
        kind: IDLKind.Constructor
145
    }
146
}
147

148
function toIDLParameter(file: string, node: webidl2.Argument): IDLParameter {
149
    return {
150
        kind: IDLKind.Parameter,
151
        fileName: file,
152
        isVariadic: node.variadic,
153
        isOptional: node.optional,
154
        type: toIDLType(file, node.idlType),
155
        name: node.name
156
    }
157
}
158

159
function toIDLCallback(file: string, node: webidl2.CallbackType): IDLCallback {
160
    return {
161
        kind: IDLKind.Callback,
162
        name: node.name,
163
        fileName: file,
164
        parameters: node.arguments.map(it => toIDLParameter(file, it)),
165
        extendedAttributes: toExtendedAttributes(node.extAttrs),
166
        documentation: makeDocs(node),
167
        returnType: toIDLType(file, node.idlType)
168
    }
169
}
170

171
function toIDLTypedef(file: string, node: webidl2.TypedefType): IDLTypedef {
172
    return {
173
        kind: IDLKind.Typedef,
174
        type: toIDLType(file, node.idlType),
175
        extendedAttributes: toExtendedAttributes(node.extAttrs),
176
        documentation: makeDocs(node),
177
        fileName: file,
178
        name: node.name
179
    }
180
}
181

182
function toIDLDictionary(file: string, node: webidl2.DictionaryType): IDLEnum {
183
    return {
184
        kind: IDLKind.Enum,
185
        name: node.name,
186
        documentation: makeDocs(node),
187
        extendedAttributes: toExtendedAttributes(node.extAttrs),
188
        fileName: file,
189
        elements: node.members.map(it => toIDLEnumMember(file, it))
190
    }
191
}
192

193
function toIDLNamespcae(file: string, node: webidl2.NamespaceType): IDLModuleType {
194

195
    return {
196
        kind: IDLKind.ModuleType,
197
        name: node.name,
198
        extendedAttributes: toExtendedAttributes(node.extAttrs),
199
        fileName: file
200
    }
201
}
202

203
function toIDLProperty(file: string, node: webidl2.AttributeMemberType): IDLProperty {
204
    return {
205
        kind: IDLKind.Property,
206
        name: node.name,
207
        documentation: makeDocs(node),
208
        fileName: file,
209
        type: toIDLType(file, node.idlType),
210
        isReadonly: node.readonly,
211
        isStatic: node.special === "static",
212
        isOptional: isOptional(node),
213
        extendedAttributes: toExtendedAttributes(node.extAttrs)
214
    }
215
}
216

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
225
    } else {
226
        throw new Error(`Unrepresentable enum initializer: ${node.default}`)
227
    }
228
    return {
229
        kind: IDLKind.EnumMember,
230
        name: node.name,
231
        type: toIDLType(file, node.idlType) as IDLPrimitiveType,
232
        extendedAttributes: toExtendedAttributes(node.extAttrs),
233
        initializer: initializer
234
    }
235
}
236

237
function toExtendedAttributes(extAttrs: webidl2.ExtendedAttribute[]): IDLExtendedAttribute[]|undefined {
238
    // TODO: be smarter about RHS.
239
    return extAttrs.map(it => {
240
        return {
241
            name: it.name,
242
            value: it.rhs?.value ? it.rhs?.value : undefined
243
        } as IDLExtendedAttribute
244
    })
245
}
246

247
function makeDocs(node: webidl2.AbstractBase): stringOrNone {
248
    let docs = undefined
249
    node.extAttrs.forEach(it => {
250
        if (it.name == "Documentation") docs = it.rhs?.value
251
    })
252
    return docs
253
}
254

255
function toIDLEnum(file: string, node: webidl2.EnumType): IDLEnum {
256
    return {
257
        kind: IDLKind.Enum,
258
        name: node.name,
259
        fileName: file,
260
        documentation: makeDocs(node),
261
        extendedAttributes: toExtendedAttributes(node.extAttrs),
262
        elements: node.values.map((it: { value: string }) => {
263
            return {
264
                kind: IDLKind.EnumMember,
265
                name: it.value,
266
                type: createNumberType(),
267
                initializer: undefined
268
            }
269
        })
270
    }
271
}
272

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.