提交 bc1c56c6 编写于 作者: fxy060608's avatar fxy060608

wip(uts): compiler

上级 84969ca6
......@@ -8,7 +8,7 @@ type GetBatteryInfoOptions = {
complete?: (res: UTSJSONObject) => void
}
export default async function getBatteryInfo(options: GetBatteryInfoOptions) {
export default function getBatteryInfo(options: GetBatteryInfoOptions) {
const res = {
errMsg: 'getBatteryInfo:ok',
level: UIDevice.current.batteryLevel * 100,
......
import DCUTSPlugin;
import UIKit;
@objc(UTSSDKModulesTestUniPluginGetBatteryInfoOptions)
@objcMembers
class GetBatteryInfoOptions : UTSJSONObject {
var name: String;
var pwd: NSNumber;
var success: UTSCallback?;
var fail: UTSCallback?;
var complete: UTSCallback?;
init(_ name: String, _ pwd: NSNumber, _ success: UTSCallback, _ fail: UTSCallback, _ complete: UTSCallback){
self.name = name;
self.pwd = pwd;
self.success = success;
self.fail = fail;
self.complete = complete;
}
public var name: String!;
public var pwd: NSNumber!;
public var success: UTSCallback?;
public var fail: UTSCallback?;
public var complete: UTSCallback?;
}
class Test1 : NSObject {
}
class Test : NSObject {
init(){
public init(){
Test1();
}
}
@objc(UTSSDKModulesTestUniPluginIndexSwift)
@objcMembers
class IndexSwift : NSObject {
static func async getBatteryInfo(_ options: GetBatteryInfoOptions) {
public static func getBatteryInfo(_ options: GetBatteryInfoOptions) {
var res = [
"errMsg": "getBatteryInfo:ok",
"level": UIDevice.current.batteryLevel * 100,
......@@ -37,7 +32,7 @@ class IndexSwift : NSObject {
options.complete!(res);
}
}
static func test1() {
public static func test1() {
console.log("test1", " at uni_modules/test-uniplugin/app-ios/index.uts:26");
}
}
{"version":3,"sources":["/Users/fxy/Projects/GitHub/uni-app/uni-app-next/packages/playground/uts/uni_modules/test-uniplugin/app-ios/index.uts"],"sourcesContent":["import { UIDevice } from 'UIKit'\n\ntype GetBatteryInfoOptions = {\n name: string\n pwd: number\n success?: (res: UTSJSONObject) => void\n fail?: (res: UTSJSONObject) => void\n complete?: (res: UTSJSONObject) => void\n}\n\nexport default async function getBatteryInfo(options: GetBatteryInfoOptions) {\n const res = {\n errMsg: 'getBatteryInfo:ok',\n level: UIDevice.current.batteryLevel * 100,\n isCharging: UIDevice.current.batteryState == UIDevice.BatteryState.charging,\n }\n if (options.success != null) {\n options.success!(res)\n }\n if (options.complete != null) {\n options.complete!(res)\n }\n}\n\nexport function test1() {\n console.log('test1')\n}\n\nclass Test1 {}\nexport class Test {\n constructor() {\n new Test1()\n }\n}\n"],"names":[],"mappings":";AAAA;AAE6B,MAAxB,qBAAqB;IACxB,IAAA,IAAI,EAAE,MAAM,CAAA;IACZ,IAAA,GAAG,EAAE,QAAM,CAAA;IACX,IAAA,OAAO,EAAC,WAA8B,EAAA;IACtC,IAAA,IAAI,EAAC,WAA8B,EAAA;IACnC,IAAA,QAAQ,EAAC,WAA8B,EAAA;WAJvC,IAAI,EAAE,MAAM,IACZ,GAAG,EAAE,QAAM,IACX,OAAO,EAAC,WAA8B,IACtC,IAAI,EAAC,WAA8B,IACnC,QAAQ,EAAC,WAA8B;;;;;;;CACxC;AAoBD,MAAM,KAAK;CAAG;AACP,MAAM,IAAI;IACf,MAAc;QACZ,AAAI,KAAK,EAAE;IACb;CACD;;;;sBAvB6B,cAAc,CAAC,EAAA,OAA8B,EAArB,qBAAqB,EAAE;QAC3E,IAAM,GAAG,GAAG;YACV,CAAA,MAAM,GAAE,mBAAmB;YAC3B,CAAA,KAAK,GAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,GAAG,GAAG;YAC1C,CAAA,UAAU,GAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,QAAQ;0BAC5E;QACD,IAAI,OAAO,CAAC,OAAO,IAAI,GAAI;YACzB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;;QAEvB,IAAI,OAAO,CAAC,QAAQ,IAAI,GAAI;YAC1B,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;;IAE1B;gBAEgB,KAAK,GAAG;QACtB,OAAO,CAAC,GAAG,CAAC,OAAO,wDAAC;IACtB"}
\ No newline at end of file
{"version":3,"sources":["/Users/fxy/Projects/GitHub/uni-app/uni-app-next/packages/playground/uts/uni_modules/test-uniplugin/app-ios/index.uts"],"sourcesContent":["import { UIDevice } from 'UIKit'\n\ntype GetBatteryInfoOptions = {\n name: string\n pwd: number\n success?: (res: UTSJSONObject) => void\n fail?: (res: UTSJSONObject) => void\n complete?: (res: UTSJSONObject) => void\n}\n\nexport default function getBatteryInfo(options: GetBatteryInfoOptions) {\n const res = {\n errMsg: 'getBatteryInfo:ok',\n level: UIDevice.current.batteryLevel * 100,\n isCharging: UIDevice.current.batteryState == UIDevice.BatteryState.charging,\n }\n if (options.success != null) {\n options.success!(res)\n }\n if (options.complete != null) {\n options.complete!(res)\n }\n}\n\nexport function test1() {\n console.log('test1')\n}\n\nclass Test1 {}\nexport class Test {\n constructor() {\n new Test1()\n }\n}\n"],"names":[],"mappings":";AAAA;AAEA;;AAA6B,MAAxB,qBAAqB;IACxB,WAAA,IAAI,EAAE,MAAM,EAAA;IACZ,WAAA,GAAG,EAAE,QAAM,EAAA;IACX,WAAA,OAAO,EAAC,WAA8B,EAAA;IACtC,WAAA,IAAI,EAAC,WAA8B,EAAA;IACnC,WAAA,QAAQ,EAAC,WAA8B,EAAA;CACxC;AAoBD,MAAM,KAAK;CAAG;AACP,MAAM,IAAI;IACf,aAAc;QACZ,AAAI,KAAK,EAAE;IACb;CACD;;;;uBAvBuB,cAAc,CAAC,EAAA,OAA8B,EAArB,qBAAqB,EAAE;QACrE,IAAM,GAAG,GAAG;YACV,CAAA,MAAM,GAAE,mBAAmB;YAC3B,CAAA,KAAK,GAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,GAAG,GAAG;YAC1C,CAAA,UAAU,GAAE,QAAQ,CAAC,OAAO,CAAC,YAAY,IAAI,QAAQ,CAAC,YAAY,CAAC,QAAQ;0BAC5E;QACD,IAAI,OAAO,CAAC,OAAO,IAAI,GAAI;YACzB,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC;;QAEvB,IAAI,OAAO,CAAC,QAAQ,IAAI,GAAI;YAC1B,OAAO,CAAC,QAAQ,EAAE,GAAG,CAAC;;IAE1B;uBAEgB,KAAK,GAAG;QACtB,OAAO,CAAC,GAAG,CAAC,OAAO,wDAAC;IACtB"}
\ No newline at end of file
......@@ -43,6 +43,10 @@ describe('uts-module', () => {
package: 'uts.modules.TestPlugin',
class: 'TestKt',
name: 'preparePermission',
params: [
{ name: 'options', type: 'PermissionOptions' },
{ name: 'callback', type: 'UTSCallback' },
],
})
/**
* {"package":"testPlugin","class":"","method":"preparePermission","params":[{"name":"foo","age":10,"success":7,"fail":8},9]}
......@@ -72,12 +76,21 @@ describe('uts-module', () => {
const WifiManager = initUtsProxyClass({
package: 'uni.modules.TestPlugin',
class: 'WifiManager',
constructor: {
params: [],
},
methods: {
preparePermission: {},
preparePermission: {
params: [
{ name: 'options', type: 'PermissionOptions' },
{ name: 'callback', type: 'UTSCallback' },
],
},
},
staticMethods: {
staticPreparePermission: {
async: true,
params: [{ name: 'num', type: 'number' }],
},
},
props: ['count'],
......
......@@ -183,7 +183,7 @@ function resolveSyncResult(res) {
function invokePropGetter(args) {
return resolveSyncResult(getProxy().invokeSync(args, () => { }));
}
function initProxyFunction(async, { package: pkg, class: cls, name: propOrMethod, id: instanceId, companion, }) {
function initProxyFunction(async, { package: pkg, class: cls, name: propOrMethod, companion, params: methodParams, }, instanceId) {
const invokeCallback = ({ id, name, params, keepAlive, }) => {
const callback = callbacks[id];
if (callback) {
......@@ -197,12 +197,13 @@ function initProxyFunction(async, { package: pkg, class: cls, name: propOrMethod
}
};
const baseArgs = instanceId
? { id: instanceId, name: propOrMethod }
? { id: instanceId, name: propOrMethod, method: methodParams }
: {
package: pkg,
class: cls,
name: propOrMethod,
companion,
method: methodParams,
};
return (...args) => {
const invokeArgs = shared.extend({}, baseArgs, {
......@@ -232,7 +233,7 @@ function initUtsStaticMethod(async, opts) {
return initProxyFunction(async, opts);
}
const initUtsProxyFunction = initUtsStaticMethod;
function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticProps, staticMethods, }) {
function initUtsProxyClass({ package: pkg, class: cls, constructor: { params: constructorParams }, methods, props, staticProps, staticMethods, }) {
const baseOptions = {
package: pkg,
class: cls,
......@@ -241,15 +242,17 @@ function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticPro
constructor(...params) {
const target = {};
// 初始化实例 ID
const instanceId = initProxyFunction(false, shared.extend({ name: 'constructor', params }, baseOptions)).apply(null, params);
const instanceId = initProxyFunction(false, shared.extend({ name: 'constructor', params: constructorParams }, baseOptions)).apply(null, params);
return new Proxy(this, {
get(_, name) {
if (!target[name]) {
//实例方法
if (shared.hasOwn(methods, name)) {
target[name] = initUtsInstanceMethod(!!methods[name].async, shared.extend({
const { async, params } = methods[name];
target[name] = initUtsInstanceMethod(!!async, shared.extend({
id: instanceId,
name,
params,
}, baseOptions));
}
else if (props.includes(name)) {
......@@ -267,8 +270,9 @@ function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticPro
get(target, name, receiver) {
if (shared.hasOwn(staticMethods, name)) {
if (!staticMethodCache[name]) {
const { async, params } = staticMethods[name];
// 静态方法
staticMethodCache[name] = initUtsStaticMethod(!!staticMethods[name].async, shared.extend({ name, companion: true }, baseOptions));
staticMethodCache[name] = initUtsStaticMethod(!!async, shared.extend({ name, companion: true, params }, baseOptions));
}
return staticMethodCache[name];
}
......
......@@ -39,11 +39,11 @@ export declare function getCurrentSubNVue(): any;
export declare function getSsrGlobalData(): any;
export declare function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticProps, staticMethods, }: ProxyClassOptions): any;
export declare function initUtsProxyClass({ package: pkg, class: cls, constructor: { params: constructorParams }, methods, props, staticProps, staticMethods, }: ProxyClassOptions): any;
export declare const initUtsProxyFunction: typeof initUtsStaticMethod;
declare function initUtsStaticMethod(async: boolean, opts: ProxyBaseOptions): (...args: unknown[]) => unknown;
declare function initUtsStaticMethod(async: boolean, opts: ProxyFunctionOptions): (...args: unknown[]) => unknown;
declare type LaunchOption = LaunchShowOption;
......@@ -171,42 +171,56 @@ declare interface PageScrollOption {
scrollTop: number;
}
declare interface ProxyBaseOptions {
/**
* 包名
*/
package: string;
/**
* 类名
*/
class: string;
/**
* 属性名或方法名
*/
declare interface Parameter {
name: string;
/**
* 是否是伴生对象
*/
companion?: boolean;
type: string;
}
declare interface ProxyClassOptions {
package: string;
class: string;
constructor: {
params: Parameter[];
};
props: string[];
staticProps: string[];
methods: {
[name: string]: {
async?: boolean;
params: Parameter[];
};
};
staticMethods: {
[name: string]: {
async?: boolean;
params: Parameter[];
};
};
}
declare interface ProxyFunctionOptions {
/**
* 包名
*/
package: string;
/**
* 类名
*/
class: string;
/**
* 属性名或方法名
*/
name: string;
/**
* 是否伴生对象
*/
companion?: boolean;
/**
* 方法参数列表
*/
params: Parameter[];
}
declare interface ReferrerInfo {
appId: string;
extraData?: any;
......
......@@ -151,7 +151,7 @@ function resolveSyncResult(res) {
function invokePropGetter(args) {
return resolveSyncResult(getProxy().invokeSync(args, () => { }));
}
function initProxyFunction(async, { package: pkg, class: cls, name: propOrMethod, id: instanceId, companion, }) {
function initProxyFunction(async, { package: pkg, class: cls, name: propOrMethod, companion, params: methodParams, }, instanceId) {
const invokeCallback = ({ id, name, params, keepAlive, }) => {
const callback = callbacks[id];
if (callback) {
......@@ -165,12 +165,13 @@ function initProxyFunction(async, { package: pkg, class: cls, name: propOrMethod
}
};
const baseArgs = instanceId
? { id: instanceId, name: propOrMethod }
? { id: instanceId, name: propOrMethod, method: methodParams }
: {
package: pkg,
class: cls,
name: propOrMethod,
companion,
method: methodParams,
};
return (...args) => {
const invokeArgs = extend({}, baseArgs, {
......@@ -200,7 +201,7 @@ function initUtsStaticMethod(async, opts) {
return initProxyFunction(async, opts);
}
const initUtsProxyFunction = initUtsStaticMethod;
function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticProps, staticMethods, }) {
function initUtsProxyClass({ package: pkg, class: cls, constructor: { params: constructorParams }, methods, props, staticProps, staticMethods, }) {
const baseOptions = {
package: pkg,
class: cls,
......@@ -209,15 +210,17 @@ function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticPro
constructor(...params) {
const target = {};
// 初始化实例 ID
const instanceId = initProxyFunction(false, extend({ name: 'constructor', params }, baseOptions)).apply(null, params);
const instanceId = initProxyFunction(false, extend({ name: 'constructor', params: constructorParams }, baseOptions)).apply(null, params);
return new Proxy(this, {
get(_, name) {
if (!target[name]) {
//实例方法
if (hasOwn(methods, name)) {
target[name] = initUtsInstanceMethod(!!methods[name].async, extend({
const { async, params } = methods[name];
target[name] = initUtsInstanceMethod(!!async, extend({
id: instanceId,
name,
params,
}, baseOptions));
}
else if (props.includes(name)) {
......@@ -235,8 +238,9 @@ function initUtsProxyClass({ package: pkg, class: cls, methods, props, staticPro
get(target, name, receiver) {
if (hasOwn(staticMethods, name)) {
if (!staticMethodCache[name]) {
const { async, params } = staticMethods[name];
// 静态方法
staticMethodCache[name] = initUtsStaticMethod(!!staticMethods[name].async, extend({ name, companion: true }, baseOptions));
staticMethodCache[name] = initUtsStaticMethod(!!async, extend({ name, companion: true, params }, baseOptions));
}
return staticMethodCache[name];
}
......
......@@ -16,7 +16,15 @@ export function normalizeArg(arg: unknown) {
return arg
}
interface ProxyBaseOptions {
function initUtsInstanceMethod(async: boolean, opts: ProxyFunctionOptions) {
return initProxyFunction(async, opts)
}
interface Parameter {
name: string
type: string
}
interface ProxyFunctionOptions {
/**
* 包名
*/
......@@ -30,52 +38,72 @@ interface ProxyBaseOptions {
*/
name: string
/**
* 是否伴生对象
* 是否伴生对象
*/
companion?: boolean
/**
* 方法参数列表
*/
params: Parameter[]
}
interface ProxyInstanceOptions extends ProxyBaseOptions {
id: number
}
/**
* 实例方法
*/
interface ProxyInstanceMethodOptions extends ProxyInstanceOptions {}
function initUtsInstanceMethod(
async: boolean,
opts: ProxyInstanceMethodOptions
) {
return initProxyFunction(async, opts)
}
interface ProxyClassOptions {
package: string
class: string
constructor: {
params: Parameter[]
}
props: string[]
staticProps: string[]
methods: {
[name: string]: {
async?: boolean
params: Parameter[]
}
}
staticMethods: {
[name: string]: {
async?: boolean
params: Parameter[]
}
}
}
type InvokeInstanceArgs =
// prop
| { id: number; name: string }
// method
| { id: number; name: string; params: unknown[] }
type InvokeArgs = (ProxyBaseOptions | InvokeInstanceArgs) & {
interface InvokeInstanceArgs {
id: number
name: string
params?: unknown[]
method?: Parameter[]
}
interface InvokeStaticArgs {
/**
* 包名
*/
package: string
/**
* 类名
*/
class: string
/**
* 属性名或方法名
*/
name: string
/**
* 执行方法时的真实参数列表
*/
params?: unknown[]
/**
* 方法定义的参数列表
*/
method?: Parameter[]
/**
* 是否是伴生对象
*/
companion?: boolean
}
type InvokeArgs = InvokeInstanceArgs | InvokeStaticArgs
interface InvokeCallbackReturnRes {
type: 'return'
params?: unknown[]
......@@ -118,38 +146,16 @@ function invokePropGetter(args: InvokeArgs) {
return resolveSyncResult(getProxy().invokeSync(args, () => {}))
}
interface InitProxyFunctionOptions {
/**
* 包名
*/
package: string
/**
* 类名
*/
class: string
/**
* 属性名或方法名
*/
name: string
/**
* 是否伴生对象
*/
companion?: boolean
/**
* 实例 ID
*/
id?: number
}
function initProxyFunction(
async: boolean,
{
package: pkg,
class: cls,
name: propOrMethod,
id: instanceId,
companion,
}: InitProxyFunctionOptions
params: methodParams,
}: ProxyFunctionOptions,
instanceId?: number
) {
const invokeCallback = ({
id,
......@@ -168,12 +174,13 @@ function initProxyFunction(
}
}
const baseArgs: InvokeArgs = instanceId
? { id: instanceId, name: propOrMethod }
? { id: instanceId, name: propOrMethod, method: methodParams }
: {
package: pkg,
class: cls,
name: propOrMethod,
companion,
method: methodParams,
}
return (...args: unknown[]) => {
const invokeArgs = extend({}, baseArgs, {
......@@ -198,7 +205,7 @@ function initProxyFunction(
}
}
function initUtsStaticMethod(async: boolean, opts: ProxyBaseOptions) {
function initUtsStaticMethod(async: boolean, opts: ProxyFunctionOptions) {
return initProxyFunction(async, opts)
}
export const initUtsProxyFunction = initUtsStaticMethod
......@@ -206,6 +213,7 @@ export const initUtsProxyFunction = initUtsStaticMethod
export function initUtsProxyClass({
package: pkg,
class: cls,
constructor: { params: constructorParams },
methods,
props,
staticProps,
......@@ -221,7 +229,7 @@ export function initUtsProxyClass({
// 初始化实例 ID
const instanceId = initProxyFunction(
false,
extend({ name: 'constructor', params }, baseOptions)
extend({ name: 'constructor', params: constructorParams }, baseOptions)
).apply(null, params) as number
return new Proxy(this, {
......@@ -229,12 +237,14 @@ export function initUtsProxyClass({
if (!target[name as string]) {
//实例方法
if (hasOwn(methods, name)) {
const { async, params } = methods[name]
target[name] = initUtsInstanceMethod(
!!methods[name].async,
!!async,
extend(
{
id: instanceId,
name,
params,
},
baseOptions
)
......@@ -254,10 +264,11 @@ export function initUtsProxyClass({
get(target, name, receiver) {
if (hasOwn(staticMethods, name)) {
if (!staticMethodCache[name as string]) {
const { async, params } = staticMethods[name]
// 静态方法
staticMethodCache[name] = initUtsStaticMethod(
!!staticMethods[name].async,
extend({ name, companion: true }, baseOptions)
!!async,
extend({ name, companion: true, params }, baseOptions)
)
}
return staticMethodCache[name]
......
......@@ -2,6 +2,7 @@ import type { Plugin } from 'vite'
import path from 'path'
import { isInHBuilderX, parseVueRequest } from '@dcloudio/uni-cli-shared'
import {
BindingIdentifier,
ClassDeclaration,
ClassExpression,
Expression,
......@@ -9,10 +10,7 @@ import {
FunctionExpression,
Identifier,
Module,
TsFunctionType,
TsInterfaceDeclaration,
TsType,
TsTypeAliasDeclaration,
Param,
TsTypeAnnotation,
VariableDeclaration,
} from '../../types/types'
......@@ -39,9 +37,10 @@ export function uniUtsV1Plugin(): Plugin {
if (path.extname(filename) !== '.uts') {
return
}
const { compile, parsePackage } = getCompiler(
process.env.UNI_UTS_PLATFORM === 'app-ios' ? 'swift' : 'kotlin'
)
const { compile, parsePackage, createResolveTypeReferenceName } =
getCompiler(
process.env.UNI_UTS_PLATFORM === 'app-ios' ? 'swift' : 'kotlin'
)
const pkg = parsePackage(filename)
if (!pkg.class) {
return
......@@ -54,7 +53,7 @@ export function uniUtsV1Plugin(): Plugin {
import { initUtsProxyClass, initUtsProxyFunction } from '@dcloudio/uni-app'
const pkg = '${pkg.package}'
const cls = '${pkg.class}'
${genProxyCode(ast)}
${genProxyCode(ast, createResolveTypeReferenceName(pkg.namespace, ast))}
`
const res = await compile(id)
if (process.env.UNI_UTS_PLATFORM === 'app-android') {
......@@ -82,17 +81,23 @@ ${genProxyCode(ast)}
function genProxyFunctionCode(
method: string,
async: boolean,
params: Parameter[],
isDefault: boolean = false
) {
if (isDefault) {
return `export default initUtsProxyFunction(${async}, { package: pkg, class: cls, name: '${method}'})`
return `export default initUtsProxyFunction(${async}, { package: pkg, class: cls, name: '${method}', params: ${JSON.stringify(
params
)}})`
}
return `export const ${method} = initUtsProxyFunction(${async}, { package: pkg, class: cls, name: '${method}'})`
return `export const ${method} = initUtsProxyFunction(${async}, { package: pkg, class: cls, name: '${method}', params: ${JSON.stringify(
params
)}})`
}
function genProxyClassCode(
cls: string,
options: {
constructor: { params: Parameter[] }
methods: Record<string, any>
staticMethods: Record<string, any>
props: string[]
......@@ -110,63 +115,95 @@ function genProxyClassCode(
)} })`
}
function genTsTypeAliasDeclarationCode(decl: TsTypeAliasDeclaration) {
if (isFunctionType(decl.typeAnnotation)) {
return genProxyFunctionCode(
decl.id.value,
isReturnPromise(decl.typeAnnotation.typeAnnotation)
)
interface Parameter {
name: string
type: string
}
type ResolveTypeReferenceName = (name: string) => string
function resolveIdentifierType(
ident: BindingIdentifier,
resolveTypeReferenceName: ResolveTypeReferenceName
) {
if (ident.typeAnnotation) {
const { typeAnnotation } = ident.typeAnnotation
if (typeAnnotation.type === 'TsKeywordType') {
return typeAnnotation.kind
} else if (
typeAnnotation.type === 'TsTypeReference' &&
typeAnnotation.typeName.type === 'Identifier'
) {
return resolveTypeReferenceName(typeAnnotation.typeName.value)
}
}
return ''
}
function genTsInterfaceDeclarationCode(
decl: TsInterfaceDeclaration,
isDefault: boolean = false
function resolveFunctionParams(
params: Param[],
resolveTypeReferenceName: ResolveTypeReferenceName
) {
const cls = decl.id.value
const methods: Record<string, { async?: boolean }> = {}
decl.body.body.forEach((item) => {
if (item.type === 'TsMethodSignature') {
if (item.key.type === 'Identifier') {
methods[item.key.value] = {
async: isReturnPromise(item.typeAnn),
}
}
const result: Parameter[] = []
params.forEach(({ pat }) => {
if (pat.type === 'Identifier') {
result.push({
name: pat.value,
type: resolveIdentifierType(
pat as BindingIdentifier,
resolveTypeReferenceName
),
})
} else {
result.push({ name: '', type: '' })
}
})
return genProxyClassCode(
cls,
{ methods, staticMethods: {}, props: [], staticProps: [] },
isDefault
)
return result
}
function genFunctionDeclarationCode(
decl: FunctionDeclaration | FunctionExpression,
resolveTypeReferenceName: ResolveTypeReferenceName,
isDefault: boolean = false
) {
return genProxyFunctionCode(
decl.identifier!.value,
decl.async || isReturnPromise(decl.returnType),
resolveFunctionParams(decl.params, resolveTypeReferenceName),
isDefault
)
}
function genClassDeclarationCode(
decl: ClassDeclaration | ClassExpression,
resolveTypeReferenceName: ResolveTypeReferenceName,
isDefault: boolean = false
) {
const cls = decl.identifier!.value
const methods: Record<string, { async?: boolean }> = {}
const staticMethods: Record<string, { async?: boolean }> = {}
const constructor: { params: Parameter[] } = { params: [] }
const methods: Record<string, { async?: boolean; params: Parameter[] }> = {}
const staticMethods: Record<
string,
{ async?: boolean; params: Parameter[] }
> = {}
const props: string[] = []
const staticProps: string[] = []
decl.body.forEach((item) => {
if (item.type === 'ClassMethod') {
if (item.type === 'Constructor') {
constructor.params = resolveFunctionParams(
item.params as Param[],
resolveTypeReferenceName
)
} else if (item.type === 'ClassMethod') {
if (item.key.type === 'Identifier') {
const name = item.key.value
const value = {
async:
item.function.async || isReturnPromise(item.function.returnType),
params: resolveFunctionParams(
item.function.params,
resolveTypeReferenceName
),
}
if (item.isStatic) {
staticMethods[name] = value
......@@ -186,7 +223,7 @@ function genClassDeclarationCode(
})
return genProxyClassCode(
cls,
{ methods, staticMethods, props, staticProps },
{ constructor, methods, staticMethods, props, staticProps },
isDefault
)
}
......@@ -228,24 +265,26 @@ function genVariableDeclarationCode(decl: VariableDeclaration) {
}
}
function genProxyCode({ body }: Module) {
function genProxyCode(
{ body }: Module,
resolveTypeReferenceName: ResolveTypeReferenceName
) {
const codes: string[] = []
body.forEach((item) => {
let code: string | undefined
if (item.type === 'ExportDeclaration') {
const decl = item.declaration
switch (decl.type) {
case 'FunctionDeclaration':
code = genFunctionDeclarationCode(decl, false)
code = genFunctionDeclarationCode(
decl,
resolveTypeReferenceName,
false
)
break
case 'ClassDeclaration':
code = genClassDeclarationCode(decl, false)
break
case 'TsTypeAliasDeclaration':
code = genTsTypeAliasDeclarationCode(decl)
break
case 'TsInterfaceDeclaration':
code = genTsInterfaceDeclarationCode(decl, false)
code = genClassDeclarationCode(decl, resolveTypeReferenceName, false)
break
case 'VariableDeclaration':
code = genVariableDeclarationCode(decl)
......@@ -253,16 +292,18 @@ function genProxyCode({ body }: Module) {
}
} else if (item.type === 'ExportDefaultDeclaration') {
const decl = item.decl
if (decl.type === 'TsInterfaceDeclaration') {
code = genTsInterfaceDeclarationCode(decl, true)
} else if (decl.type === 'ClassExpression') {
if (decl.type === 'ClassExpression') {
if (decl.identifier) {
// export default class test{}
code = genClassDeclarationCode(decl, false)
code = genClassDeclarationCode(decl, resolveTypeReferenceName, false)
}
} else if (decl.type === 'FunctionExpression') {
if (decl.identifier) {
code = genFunctionDeclarationCode(decl, true)
code = genFunctionDeclarationCode(
decl,
resolveTypeReferenceName,
true
)
}
}
}
......@@ -273,10 +314,6 @@ function genProxyCode({ body }: Module) {
return codes.join(`\n`)
}
function isFunctionType(type: TsType): type is TsFunctionType {
return type.type === 'TsFunctionType'
}
function isReturnPromise(anno?: TsTypeAnnotation) {
if (!anno) {
return false
......
import { compileKotlin, parseKotlinPackage } from './kotlin'
import { compileSwift, parseSwiftPackage } from './swift'
import {
compileKotlin,
parseKotlinPackage,
createKotlinResolveTypeReferenceName,
} from './kotlin'
import {
compileSwift,
parseSwiftPackage,
createSwiftResolveTypeReferenceName,
} from './swift'
export function getCompiler(type: 'kotlin' | 'swift') {
if (type === 'swift') {
return {
compile: compileSwift,
parsePackage: parseSwiftPackage,
createResolveTypeReferenceName: createSwiftResolveTypeReferenceName,
}
}
return {
compile: compileKotlin,
parsePackage: parseKotlinPackage,
createResolveTypeReferenceName: createKotlinResolveTypeReferenceName,
}
}
......@@ -18,14 +18,23 @@ import {
resolveUTSPlatformFile,
UTSPlatformResourceOptions,
} from './utils'
import { Module } from '../../../types/types'
export function createKotlinResolveTypeReferenceName(
_namespace: string,
_ast: Module
) {
return (name: string) => name
}
export function parseKotlinPackage(filename: string) {
const res = resolvePackage(filename)
if (!res) {
return { package: '', class: '' }
return { package: '', namespace: '', class: '' }
}
return {
package: 'uts.sdk.' + (res.is_uni_modules ? 'modules.' : '') + res.name,
namespace: '',
class: 'IndexKt',
}
}
......
import { isInHBuilderX, resolveSourceMapPath } from '@dcloudio/uni-cli-shared'
import { capitalize } from '@vue/shared'
import { Module, ModuleItem } from '../../../types/types'
import { genUTSPlatformResource, getUtsCompiler, resolvePackage } from './utils'
function resolveTypeAliasDeclNames(items: ModuleItem[]) {
const names: string[] = []
items.forEach((item) => {
if (item.type === 'TsTypeAliasDeclaration') {
names.push(item.id.value)
}
})
return names
}
export function createSwiftResolveTypeReferenceName(
namespace: string,
ast: Module
) {
const names = resolveTypeAliasDeclNames(ast.body)
return (name: string) => {
if (names.includes(name)) {
return namespace + capitalize(name)
}
return name
}
}
export function parseSwiftPackage(filename: string) {
const res = resolvePackage(filename)
if (!res) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册