Add Array support to functions
This commit is contained in:
parent
a8f49d117d
commit
db21c1c42e
@ -42,4 +42,7 @@ service TestService {
|
|||||||
@Description("Just sends an Event with a String")
|
@Description("Just sends an Event with a String")
|
||||||
@Param("param1", "Parameter with some string for event")
|
@Param("param1", "Parameter with some string for event")
|
||||||
notification OnEvent(param1: string);
|
notification OnEvent(param1: string);
|
||||||
|
|
||||||
|
|
||||||
|
FunctionWithArrayAsParamAndReturn(values1: number[], values2: number[]): number[];
|
||||||
}
|
}
|
||||||
|
@ -39,6 +39,10 @@ class TestService extends Server.TestService<undefined> {
|
|||||||
OnEvent(param1: string, ctx: undefined): void {
|
OnEvent(param1: string, ctx: undefined): void {
|
||||||
console.log("Received notification", param1);
|
console.log("Received notification", param1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async FunctionWithArrayAsParamAndReturn(vals1, vals2) {
|
||||||
|
return [...vals1, ...vals2];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
server.addService(new TestService());
|
server.addService(new TestService());
|
||||||
@ -70,6 +74,22 @@ async function run() {
|
|||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
console.log("Found expected error!", err.message);
|
console.log("Found expected error!", err.message);
|
||||||
});
|
});
|
||||||
|
|
||||||
|
console.log("Test with arrays:");
|
||||||
|
console.log(await test
|
||||||
|
//@ts-ignore
|
||||||
|
.FunctionWithArrayAsParamAndReturn([1,2,3], [4,5,6]));
|
||||||
|
|
||||||
|
console.log("Let with Array fail!");
|
||||||
|
await test
|
||||||
|
//@ts-ignore
|
||||||
|
.FunctionWithArrayAsParamAndReturn([1,2,3], [4,"asd",6])
|
||||||
|
.then(() => {
|
||||||
|
console.log("!!!!This should have failed!!!!");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.log("Found expected error!", err.message);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
run();
|
run();
|
||||||
|
51
lib/jrpc.js
51
lib/jrpc.js
@ -7193,7 +7193,12 @@ function parse(tokens, file) {
|
|||||||
const [name2] = eatText();
|
const [name2] = eatText();
|
||||||
eatToken(":");
|
eatToken(":");
|
||||||
const [type] = eatText();
|
const [type] = eatText();
|
||||||
inputs.push({ name: name2, type });
|
let array = false;
|
||||||
|
if (currentToken.type === "array") {
|
||||||
|
array = true;
|
||||||
|
eatToken("[]");
|
||||||
|
}
|
||||||
|
inputs.push({ name: name2, type, array });
|
||||||
if (currentToken.value !== ",")
|
if (currentToken.value !== ",")
|
||||||
break;
|
break;
|
||||||
eatToken(",");
|
eatToken(",");
|
||||||
@ -7203,7 +7208,16 @@ function parse(tokens, file) {
|
|||||||
let return_type = void 0;
|
let return_type = void 0;
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
eatToken(":");
|
eatToken(":");
|
||||||
return_type = eatText()[0];
|
let [type] = eatText();
|
||||||
|
let array = false;
|
||||||
|
if (currentToken.type === "array") {
|
||||||
|
array = true;
|
||||||
|
eatToken("[]");
|
||||||
|
}
|
||||||
|
return_type = {
|
||||||
|
type,
|
||||||
|
array
|
||||||
|
};
|
||||||
}
|
}
|
||||||
eatToken(";");
|
eatToken(";");
|
||||||
return {
|
return {
|
||||||
@ -7365,11 +7379,11 @@ function get_ir(parsed) {
|
|||||||
throw new IRError(fnc, `Function with name ${fnc.name} already defined!`);
|
throw new IRError(fnc, `Function with name ${fnc.name} already defined!`);
|
||||||
alreadyFoundFunctions.add(fnc.name);
|
alreadyFoundFunctions.add(fnc.name);
|
||||||
if (fnc.return_type) {
|
if (fnc.return_type) {
|
||||||
if (defined.indexOf(fnc.return_type) >= 0) {
|
if (defined.indexOf(fnc.return_type.type) >= 0) {
|
||||||
if (!depends.some((a) => a === fnc.return_type))
|
if (!depends.some((a) => a === fnc.return_type.type))
|
||||||
depends.push(fnc.return_type);
|
depends.push(fnc.return_type.type);
|
||||||
} else {
|
} else {
|
||||||
if (fnc.return_type !== "void" && builtin.indexOf(fnc.return_type) < 0) {
|
if (fnc.return_type.type !== "void" && builtin.indexOf(fnc.return_type.type) < 0) {
|
||||||
throw new IRError(fnc, `Type ${fnc.return_type} is not defined`);
|
throw new IRError(fnc, `Type ${fnc.return_type} is not defined`);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -7642,7 +7656,7 @@ var TypescriptTarget = class extends CompileTarget {
|
|||||||
a(2, `super(provider, "${def.name}");`);
|
a(2, `super(provider, "${def.name}");`);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
for (const fnc of def.functions) {
|
for (const fnc of def.functions) {
|
||||||
const params = fnc.inputs.map((e) => `${e.name}: ${toJSType(e.type)}`).join(",");
|
const params = fnc.inputs.map((e) => `${e.name}: ${toJSType(e.type) + (e.array ? "[]" : "")}`).join(", ");
|
||||||
if (!fnc.return) {
|
if (!fnc.return) {
|
||||||
a(1, `${fnc.name}(${params}): void {`);
|
a(1, `${fnc.name}(${params}): void {`);
|
||||||
a(2, `this._provider.sendMessage({`);
|
a(2, `this._provider.sendMessage({`);
|
||||||
@ -7652,7 +7666,7 @@ var TypescriptTarget = class extends CompileTarget {
|
|||||||
a(2, `});`);
|
a(2, `});`);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
} else {
|
} else {
|
||||||
const retType = fnc.return ? toJSType(fnc.return) : "void";
|
const retType = fnc.return ? toJSType(fnc.return.type) + (fnc.return.array ? "[]" : "") : "void";
|
||||||
a(1, `${fnc.name}(${params}): Promise<${retType}> {`);
|
a(1, `${fnc.name}(${params}): Promise<${retType}> {`);
|
||||||
a(2, `return new Promise<${retType}>((ok, err) => {`);
|
a(2, `return new Promise<${retType}>((ok, err) => {`);
|
||||||
a(3, `this._provider.sendMessage({`);
|
a(3, `this._provider.sendMessage({`);
|
||||||
@ -7664,7 +7678,13 @@ var TypescriptTarget = class extends CompileTarget {
|
|||||||
a(4, `ok, err`);
|
a(4, `ok, err`);
|
||||||
a(3, `});`);
|
a(3, `});`);
|
||||||
a(2, `}).then(result => {`);
|
a(2, `}).then(result => {`);
|
||||||
a(3, `if(!verify_${fnc.return}(result)) throw new Error("Invalid result data!");`);
|
if (fnc.return.array) {
|
||||||
|
a(2, `for(const elm of result) {`);
|
||||||
|
a(3, `if(!verify_${fnc.return.type}(elm)) throw new Error("Invalid result data!");`);
|
||||||
|
a(2, `}`);
|
||||||
|
} else {
|
||||||
|
a(3, `if(!verify_${fnc.return.type}(result)) throw new Error("Invalid result data!");`);
|
||||||
|
}
|
||||||
a(3, `return result;`);
|
a(3, `return result;`);
|
||||||
a(2, `});`);
|
a(2, `});`);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
@ -7675,6 +7695,7 @@ var TypescriptTarget = class extends CompileTarget {
|
|||||||
this.writeFormattedFile(this.getFileName(def.name + "_client"), lines.join("\n"));
|
this.writeFormattedFile(this.getFileName(def.name + "_client"), lines.join("\n"));
|
||||||
}
|
}
|
||||||
generateServiceServer(def) {
|
generateServiceServer(def) {
|
||||||
|
var _a;
|
||||||
let lines = [];
|
let lines = [];
|
||||||
const a = (i, t) => {
|
const a = (i, t) => {
|
||||||
if (!Array.isArray(t)) {
|
if (!Array.isArray(t)) {
|
||||||
@ -7703,10 +7724,10 @@ var TypescriptTarget = class extends CompileTarget {
|
|||||||
a(0, ``);
|
a(0, ``);
|
||||||
for (const fnc of def.functions) {
|
for (const fnc of def.functions) {
|
||||||
const params = [
|
const params = [
|
||||||
...fnc.inputs.map((e) => `${e.name}: ${toJSType(e.type)}`),
|
...fnc.inputs.map((e) => `${e.name}: ${toJSType(e.type) + (e.array ? "[]" : "")}`),
|
||||||
`ctx: T`
|
`ctx: T`
|
||||||
].join(", ");
|
].join(", ");
|
||||||
const retVal = fnc.return ? `Promise<${toJSType(fnc.return)}>` : `void`;
|
const retVal = fnc.return ? `Promise<${toJSType(fnc.return.type) + (fnc.return.array ? "[]" : "")}>` : `void`;
|
||||||
a(1, `abstract ${fnc.name}(${params}): ${retVal};`);
|
a(1, `abstract ${fnc.name}(${params}): ${retVal};`);
|
||||||
a(1, `_${fnc.name}(params: any[] | any, ctx: T): ${retVal} {`);
|
a(1, `_${fnc.name}(params: any[] | any, ctx: T): ${retVal} {`);
|
||||||
a(2, `let p: any[] = [];`);
|
a(2, `let p: any[] = [];`);
|
||||||
@ -7720,12 +7741,18 @@ var TypescriptTarget = class extends CompileTarget {
|
|||||||
a(2, ``);
|
a(2, ``);
|
||||||
for (let i = 0; i < fnc.inputs.length; i++) {
|
for (let i = 0; i < fnc.inputs.length; i++) {
|
||||||
a(2, `if(p[${i}] !== null && p[${i}] !== undefined) {`);
|
a(2, `if(p[${i}] !== null && p[${i}] !== undefined) {`);
|
||||||
|
if (fnc.inputs[i].array) {
|
||||||
|
a(2, `for(const elm of p[${i}]) {`);
|
||||||
|
a(3, `if(!verify_${fnc.inputs[i].type}(elm)) throw new Error("Parameter verification failed!")`);
|
||||||
|
a(2, `}`);
|
||||||
|
} else {
|
||||||
a(2, `if(!verify_${fnc.inputs[i].type}(p[${i}])) throw new Error("Parameter verification failed!")`);
|
a(2, `if(!verify_${fnc.inputs[i].type}(p[${i}])) throw new Error("Parameter verification failed!")`);
|
||||||
|
}
|
||||||
a(2, `}`);
|
a(2, `}`);
|
||||||
}
|
}
|
||||||
a(2, ``);
|
a(2, ``);
|
||||||
a(2, `p.push(ctx);`);
|
a(2, `p.push(ctx);`);
|
||||||
a(2, `return this.${fnc.name}.call(this, ...p)${fnc.return == "void" ? ".then(res => undefined)" : ""};`);
|
a(2, `return this.${fnc.name}.call(this, ...p)${((_a = fnc.return) == null ? void 0 : _a.type) == "void" ? ".then(res => undefined)" : ""};`);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
a(0, ``);
|
a(0, ``);
|
||||||
}
|
}
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@hibas123/jrpcgen",
|
"name": "@hibas123/jrpcgen",
|
||||||
"version": "1.0.4",
|
"version": "1.0.5",
|
||||||
"main": "lib/index.js",
|
"main": "lib/index.js",
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"packageManager": "yarn@3.1.1",
|
"packageManager": "yarn@3.1.1",
|
||||||
|
12
src/ir.ts
12
src/ir.ts
@ -44,8 +44,8 @@ export type ServiceFunctionDecorators = {
|
|||||||
|
|
||||||
export interface ServiceFunctionParamsDefinition {
|
export interface ServiceFunctionParamsDefinition {
|
||||||
name: string;
|
name: string;
|
||||||
inputs: { type: string; name: string }[];
|
inputs: { type: string; name: string, array: boolean }[];
|
||||||
return: string | undefined;
|
return: { type: string, array: boolean } | undefined;
|
||||||
decorators: ServiceFunctionDecorators
|
decorators: ServiceFunctionDecorators
|
||||||
}
|
}
|
||||||
export type ServiceFunctionDefinition = ServiceFunctionParamsDefinition;
|
export type ServiceFunctionDefinition = ServiceFunctionParamsDefinition;
|
||||||
@ -191,11 +191,11 @@ export default function get_ir(parsed: Parsed): IR {
|
|||||||
);
|
);
|
||||||
alreadyFoundFunctions.add(fnc.name);
|
alreadyFoundFunctions.add(fnc.name);
|
||||||
if (fnc.return_type) {
|
if (fnc.return_type) {
|
||||||
if (defined.indexOf(fnc.return_type) >= 0) {
|
if (defined.indexOf(fnc.return_type.type) >= 0) {
|
||||||
if (!depends.some((a) => a === fnc.return_type))
|
if (!depends.some((a) => a === fnc.return_type.type))
|
||||||
depends.push(fnc.return_type);
|
depends.push(fnc.return_type.type);
|
||||||
} else {
|
} else {
|
||||||
if (fnc.return_type !== "void" && builtin.indexOf(fnc.return_type) < 0) {
|
if (fnc.return_type.type !== "void" && builtin.indexOf(fnc.return_type.type) < 0) {
|
||||||
throw new IRError(
|
throw new IRError(
|
||||||
fnc,
|
fnc,
|
||||||
`Type ${fnc.return_type} is not defined`
|
`Type ${fnc.return_type} is not defined`
|
||||||
|
@ -42,6 +42,12 @@ export interface TypeStatement extends DefinitionNode {
|
|||||||
export interface IServiceFunctionInput {
|
export interface IServiceFunctionInput {
|
||||||
name: string;
|
name: string;
|
||||||
type: string;
|
type: string;
|
||||||
|
array: boolean;
|
||||||
|
}
|
||||||
|
|
||||||
|
export interface IServiceFunctionReturn {
|
||||||
|
type: string;
|
||||||
|
array: boolean;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -51,7 +57,7 @@ export interface ServiceFunctionStatement extends DefinitionNode {
|
|||||||
type: "service_function";
|
type: "service_function";
|
||||||
inputs: IServiceFunctionInput[];
|
inputs: IServiceFunctionInput[];
|
||||||
name: string;
|
name: string;
|
||||||
return_type: string | undefined; // Makes it a notification
|
return_type: IServiceFunctionReturn | undefined; // Makes it a notification
|
||||||
decorators: Decorators;
|
decorators: Decorators;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -334,7 +340,12 @@ export default function parse(tokens: Token[], file: string): Parsed {
|
|||||||
const [name] = eatText();
|
const [name] = eatText();
|
||||||
eatToken(":");
|
eatToken(":");
|
||||||
const [type] = eatText();
|
const [type] = eatText();
|
||||||
inputs.push({ name, type });
|
let array = false;
|
||||||
|
if (currentToken.type === "array") {
|
||||||
|
array = true;
|
||||||
|
eatToken("[]");
|
||||||
|
}
|
||||||
|
inputs.push({ name, type, array });
|
||||||
if (currentToken.value !== ",") break;
|
if (currentToken.value !== ",") break;
|
||||||
eatToken(",");
|
eatToken(",");
|
||||||
}
|
}
|
||||||
@ -342,11 +353,20 @@ export default function parse(tokens: Token[], file: string): Parsed {
|
|||||||
|
|
||||||
eatToken(")");
|
eatToken(")");
|
||||||
|
|
||||||
let return_type = undefined;
|
let return_type: IServiceFunctionReturn | undefined = undefined;
|
||||||
if (!notification) {
|
if (!notification) {
|
||||||
eatToken(":");
|
eatToken(":");
|
||||||
|
|
||||||
return_type = eatText()[0];
|
let [type] = eatText();
|
||||||
|
let array = false;
|
||||||
|
if (currentToken.type === "array") {
|
||||||
|
array = true;
|
||||||
|
eatToken("[]");
|
||||||
|
}
|
||||||
|
return_type = {
|
||||||
|
type,
|
||||||
|
array
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
eatToken(";");
|
eatToken(";");
|
||||||
|
@ -15,7 +15,7 @@ const conversion = {
|
|||||||
boolean: "boolean",
|
boolean: "boolean",
|
||||||
number: "number",
|
number: "number",
|
||||||
string: "string",
|
string: "string",
|
||||||
void: "void"
|
void: "void",
|
||||||
};
|
};
|
||||||
|
|
||||||
function toJSType(type: string): string {
|
function toJSType(type: string): string {
|
||||||
@ -196,7 +196,6 @@ export class TypescriptTarget extends CompileTarget {
|
|||||||
this.getTemplate("ts_service_client.ts")
|
this.getTemplate("ts_service_client.ts")
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
let lines: string[] = [];
|
let lines: string[] = [];
|
||||||
const a: lineAppender = (i, t) => {
|
const a: lineAppender = (i, t) => {
|
||||||
if (!Array.isArray(t)) {
|
if (!Array.isArray(t)) {
|
||||||
@ -238,8 +237,10 @@ export class TypescriptTarget extends CompileTarget {
|
|||||||
|
|
||||||
for (const fnc of def.functions) {
|
for (const fnc of def.functions) {
|
||||||
const params = fnc.inputs
|
const params = fnc.inputs
|
||||||
.map((e) => `${e.name}: ${toJSType(e.type)}`)
|
.map(
|
||||||
.join(",");
|
(e) => `${e.name}: ${toJSType(e.type) + (e.array ? "[]" : "")}`
|
||||||
|
)
|
||||||
|
.join(", ");
|
||||||
//TODO: Prio 2 : Add optional parameters to this and the declaration file
|
//TODO: Prio 2 : Add optional parameters to this and the declaration file
|
||||||
if (!fnc.return) {
|
if (!fnc.return) {
|
||||||
a(1, `${fnc.name}(${params}): void {`);
|
a(1, `${fnc.name}(${params}): void {`);
|
||||||
@ -250,7 +251,9 @@ export class TypescriptTarget extends CompileTarget {
|
|||||||
a(2, `});`);
|
a(2, `});`);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
} else {
|
} else {
|
||||||
const retType = fnc.return ? toJSType(fnc.return) : "void";
|
const retType = fnc.return
|
||||||
|
? toJSType(fnc.return.type) + (fnc.return.array ? "[]" : "")
|
||||||
|
: "void";
|
||||||
a(1, `${fnc.name}(${params}): Promise<${retType}> {`);
|
a(1, `${fnc.name}(${params}): Promise<${retType}> {`);
|
||||||
a(2, `return new Promise<${retType}>((ok, err) => {`);
|
a(2, `return new Promise<${retType}>((ok, err) => {`);
|
||||||
a(3, `this._provider.sendMessage({`);
|
a(3, `this._provider.sendMessage({`);
|
||||||
@ -262,10 +265,19 @@ export class TypescriptTarget extends CompileTarget {
|
|||||||
a(4, `ok, err`);
|
a(4, `ok, err`);
|
||||||
a(3, `});`);
|
a(3, `});`);
|
||||||
a(2, `}).then(result => {`);
|
a(2, `}).then(result => {`);
|
||||||
|
if (fnc.return.array) {
|
||||||
|
a(2, `for(const elm of result) {`);
|
||||||
a(
|
a(
|
||||||
3,
|
3,
|
||||||
`if(!verify_${fnc.return}(result)) throw new Error("Invalid result data!");`
|
`if(!verify_${fnc.return.type}(elm)) throw new Error("Invalid result data!");`
|
||||||
);
|
);
|
||||||
|
a(2, `}`);
|
||||||
|
} else {
|
||||||
|
a(
|
||||||
|
3,
|
||||||
|
`if(!verify_${fnc.return.type}(result)) throw new Error("Invalid result data!");`
|
||||||
|
);
|
||||||
|
}
|
||||||
a(3, `return result;`);
|
a(3, `return result;`);
|
||||||
a(2, `});`);
|
a(2, `});`);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
@ -332,11 +344,15 @@ export class TypescriptTarget extends CompileTarget {
|
|||||||
|
|
||||||
for (const fnc of def.functions) {
|
for (const fnc of def.functions) {
|
||||||
const params = [
|
const params = [
|
||||||
...fnc.inputs.map((e) => `${e.name}: ${toJSType(e.type)}`),
|
...fnc.inputs.map(
|
||||||
|
(e) => `${e.name}: ${toJSType(e.type) + (e.array ? "[]" : "")}`
|
||||||
|
),
|
||||||
`ctx: T`,
|
`ctx: T`,
|
||||||
].join(", ");
|
].join(", ");
|
||||||
const retVal = fnc.return
|
const retVal = fnc.return
|
||||||
? `Promise<${toJSType(fnc.return)}>`
|
? `Promise<${
|
||||||
|
toJSType(fnc.return.type) + (fnc.return.array ? "[]" : "")
|
||||||
|
}>`
|
||||||
: `void`;
|
: `void`;
|
||||||
a(1, `abstract ${fnc.name}(${params}): ${retVal};`);
|
a(1, `abstract ${fnc.name}(${params}): ${retVal};`);
|
||||||
|
|
||||||
@ -353,15 +369,32 @@ export class TypescriptTarget extends CompileTarget {
|
|||||||
a(2, `}`);
|
a(2, `}`);
|
||||||
a(2, ``);
|
a(2, ``);
|
||||||
|
|
||||||
for(let i = 0; i < fnc.inputs.length; i++) {
|
for (let i = 0; i < fnc.inputs.length; i++) {
|
||||||
a(2, `if(p[${i}] !== null && p[${i}] !== undefined) {`);
|
a(2, `if(p[${i}] !== null && p[${i}] !== undefined) {`);
|
||||||
a(2, `if(!verify_${fnc.inputs[i].type}(p[${i}])) throw new Error("Parameter verification failed!")`);
|
if (fnc.inputs[i].array) {
|
||||||
|
a(2, `for(const elm of p[${i}]) {`);
|
||||||
|
a(
|
||||||
|
3,
|
||||||
|
`if(!verify_${fnc.inputs[i].type}(elm)) throw new Error("Parameter verification failed!")`
|
||||||
|
);
|
||||||
|
a(2, `}`);
|
||||||
|
} else {
|
||||||
|
a(
|
||||||
|
2,
|
||||||
|
`if(!verify_${fnc.inputs[i].type}(p[${i}])) throw new Error("Parameter verification failed!")`
|
||||||
|
);
|
||||||
|
}
|
||||||
a(2, `}`);
|
a(2, `}`);
|
||||||
}
|
}
|
||||||
|
|
||||||
a(2, ``);
|
a(2, ``);
|
||||||
a(2, `p.push(ctx);`);
|
a(2, `p.push(ctx);`);
|
||||||
a(2, `return this.${fnc.name}.call(this, ...p)${fnc.return == "void" ? ".then(res => undefined)" : ""};`);
|
a(
|
||||||
|
2,
|
||||||
|
`return this.${fnc.name}.call(this, ...p)${
|
||||||
|
fnc.return?.type == "void" ? ".then(res => undefined)" : ""
|
||||||
|
};`
|
||||||
|
);
|
||||||
a(1, `}`);
|
a(1, `}`);
|
||||||
a(0, ``);
|
a(0, ``);
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user