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

wip(uts): compiler

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