• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1/*
2* Copyright (c) 2022 Shenzhen Kaihong Digital Industry Development 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*/
15const { generateFunctionDirect } = require("./function_direct");
16const { generateFunctionSync } = require("./function_sync");
17const { generateFunctionAsync } = require("./function_async");
18const { generateInterface } = require("./interface");
19const { generateClass } = require("./class");
20const { generateType } = require("./type");
21const { FuncType, InterfaceList, EnumList, TypeList } = require("../tools/common");
22const { generateEnum } = require("./enum");
23const { generateFunctionOnOff } = require("./function_onoff");
24const { NapiLog } = require("../tools/NapiLog");
25const { addUniqFunc2List, addUniqObj2List } = require("../tools/tool");
26
27function findParentByName(parentName, data) {
28    for (let i in data.interface) {
29        if (parentName == data.interface[i].name) {
30            return data.interface[i]
31        }
32    }
33
34    for (let i in data.class) {
35        if (parentName == data.class[i].name) {
36            return data.class[i]
37        }
38    }
39    return null
40}
41
42/**
43 * 生成父类的成员变量和方法
44 * @param currentObj 当前类
45 * @param data 全局数据上下文
46 * @param parentBody 输出参数,保存父类的成员变量和方法
47 * @returns void
48 */
49function genParentPropties(currentObj, data, parentBody) {
50    for (let i in currentObj.body.parentNameList) {
51        let parentName = currentObj.body.parentNameList[i]
52        let parentObj = findParentByName(parentName, data)
53        if (!parentObj) {
54            NapiLog.logError("Failed to find %s's parent by name [%s]".format(currentObj.body.name, parentName))
55            return
56        }
57
58        // 为父类添加子类的对象信息
59        addUniqObj2List(currentObj, parentObj.body.childList)
60
61        // 为当前类添加父类对象信息
62        addUniqObj2List(parentObj, currentObj.body.parentList)
63
64        for (let i in parentObj.body.value) {
65            // 添加父类的所有成员属性到parentBody
66            addUniqObj2List(parentObj.body.value[i], parentBody.value)
67        }
68        for (let i in parentObj.body.function) {
69            // 添加父类的所有成员方法到parentBody
70            addUniqFunc2List(parentObj.body.function[i], parentBody.function)
71        }
72        if (parentObj.body.parentNameList.length > 0) {
73            // 递归查找父类的父类
74            genParentPropties(parentObj, data, parentBody)
75        }
76    }
77}
78
79// 为有继承关系的interface和class类型建立父子类关系信息
80function genExtendsRelation(data) {
81    for (let i in data.interface) {
82        let ifObj = data.interface[i]
83        if (ifObj && ifObj.body.parentNameList && ifObj.body.parentNameList.length > 0) {
84            ifObj.body.parentBody = {value:[], function:[]}
85            genParentPropties(ifObj, data, ifObj.body.parentBody)
86        }
87    }
88
89    for (let i in data.class) {
90        let classObj = data.class[i]
91        if (classObj.body.parentName) {
92            classObj.body.parentBody = {value:[], function:[]}
93            genParentPropties(classObj, data, classObj.body.parentBody)
94        }
95    }
96}
97
98//生成module_middle.cpp、module.h、module.cpp
99function generateNamespace(name, data, inNamespace = "") {
100    let namespaceResult = { implH: "", implCpp: "", middleFunc: "", middleInit: "" }
101    namespaceResult.middleInit += formatMiddleInit(inNamespace, name)
102    genExtendsRelation(data)
103    InterfaceList.push(data.interface)
104    TypeList.push(data.type)
105    EnumList.push(data.enum)
106    enumNamespaceFunction(data, namespaceResult);
107    for (let i in data.type) {
108      let ii = data.type[i]
109      let result = generateType(ii.name, ii.body, inNamespace + name + "::")
110      namespaceResult = getNamespaceResult(result, namespaceResult)
111    }
112    for (let i in data.interface) {
113        let ii = data.interface[i]
114        let result = generateInterface(ii.name, ii.body, inNamespace + name + "::")
115        namespaceResult = getNamespaceResult(result, namespaceResult)
116    }
117    for (let i in data.class) {
118        let ii = data.class[i]
119        let result = generateClass(ii.name, ii.body, inNamespace + name + "::", ii.functiontType)
120        namespaceResult = getNamespaceResult(result, namespaceResult)
121    }
122    for (let i in data.function) {
123        let func = data.function[i]
124        let tmp = generateFunction(func, data)
125        namespaceResult.middleFunc += tmp[0]
126        namespaceResult.implH += tmp[1]
127        namespaceResult.implCpp += tmp[2]
128        namespaceResult.middleInit += '    pxt->DefineFunction("%s", %s%s::%s_middle%s);\n'
129            .format(func.name, inNamespace, name, func.name, inNamespace.length > 0 ? ", " + name : "")
130    }
131    for (let i in data.namespace) {
132        let ns = data.namespace[i]
133        let result = generateNamespace(ns.name, ns.body, inNamespace + name + "::")
134        namespaceResult = getNamespaceResult(result, namespaceResult)
135    }
136    InterfaceList.pop();
137    TypeList.pop();
138    EnumList.pop();
139    if (inNamespace.length > 0) {
140        namespaceResult.middleInit += "}"
141    }
142    return generateResult(name, namespaceResult.implH, namespaceResult.implCpp, namespaceResult.middleFunc,
143        namespaceResult.middleInit)
144}
145
146function enumNamespaceFunction(data, namespaceResult) {
147  let result = generateEnumResult(data);
148  namespaceResult.implH += result.implH;
149  namespaceResult.implCpp += result.implCpp;
150  namespaceResult.middleInit += result.middleInit;
151}
152
153function getNamespaceResult(subResult, returnResult) {
154    returnResult.middleFunc += subResult.middleBody
155    returnResult.implH += subResult.implH
156    returnResult.implCpp += subResult.implCpp
157    returnResult.middleInit += subResult.middleInit
158    return returnResult
159}
160
161function generateEnumResult(data) {
162    let resultEnum = {
163        implH: "",
164        implCpp: "",
165        middleInit: ""
166    }
167
168    for (let i in data.enum) {
169        let enumm = data.enum[i]
170        let result = generateEnum(enumm.name, enumm.body)
171        resultEnum.implH += result.implH
172        resultEnum.implCpp += result.implCpp
173        resultEnum.middleInit += result.midInitEnum
174    }
175    return resultEnum
176}
177
178function generateResult(name, implH, implCpp, middleFunc, middleInit) {
179    let result = {
180        implH: `\nnamespace %s {%s\n}`.format(name, implH),
181        implCpp: `\nnamespace %s {%s}`.format(name, implCpp),
182        middleBody: `\nnamespace %s {%s}`.format(name, middleFunc),
183        middleInit: middleInit
184    }
185    return result;
186}
187
188function generateFunction(func, data) {
189    let tmp;
190    if (func.name === 'on' || func.name === 'off' ) {
191        return generateFunctionOnOff(func, data)
192    }
193    switch (func.type) {
194        case FuncType.DIRECT:
195            tmp = generateFunctionDirect(func, data)
196            break;
197        case FuncType.SYNC:
198            tmp = generateFunctionSync(func, data)
199            break
200        case FuncType.ASYNC:
201        case FuncType.PROMISE:
202            tmp = generateFunctionAsync(func, data)
203            break
204        default:
205            return
206    }
207    return tmp
208}
209
210function formatMiddleInit(inNamespace, name) {
211    let middleInit = ""
212    if (inNamespace.length > 0) {
213        let nsl = inNamespace.split("::")
214        nsl.pop()
215        let parentNs = nsl[nsl.length - 1]
216        middleInit = `{\nnapi_value %s = pxt->CreateSubObject(%s, "%s");\n`
217            .format(name, nsl.length == 1 ? "exports" : parentNs, name)
218    }
219    return middleInit
220}
221
222module.exports = {
223    generateNamespace,
224    getNamespaceResult,
225    generateEnumResult,
226    generateResult,
227    generateFunction,
228    formatMiddleInit
229}