Compare commits
	
		
			3 Commits
		
	
	
		
			58e00a9ca3
			...
			number-to-
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
| b980af4b17 | |||
| 339d3006d6 | |||
| 97ce0ea9b5 | 
							
								
								
									
										42
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										42
									
								
								.vscode/tasks.json
									
									
									
									
										vendored
									
									
										Normal file
									
								
							@ -0,0 +1,42 @@
 | 
			
		||||
{
 | 
			
		||||
    "version": "2.0.0",
 | 
			
		||||
    "tasks": [
 | 
			
		||||
        {
 | 
			
		||||
            "label": "build",
 | 
			
		||||
            "command": "dotnet",
 | 
			
		||||
            "type": "process",
 | 
			
		||||
            "args": [
 | 
			
		||||
                "build",
 | 
			
		||||
                "${workspaceFolder}/examples/CSharp/Example/CSharp_Example.csproj",
 | 
			
		||||
                "/property:GenerateFullPaths=true",
 | 
			
		||||
                "/consoleloggerparameters:NoSummary"
 | 
			
		||||
            ],
 | 
			
		||||
            "problemMatcher": "$msCompile"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "label": "publish",
 | 
			
		||||
            "command": "dotnet",
 | 
			
		||||
            "type": "process",
 | 
			
		||||
            "args": [
 | 
			
		||||
                "publish",
 | 
			
		||||
                "${workspaceFolder}/examples/CSharp/Example/CSharp_Example.csproj",
 | 
			
		||||
                "/property:GenerateFullPaths=true",
 | 
			
		||||
                "/consoleloggerparameters:NoSummary"
 | 
			
		||||
            ],
 | 
			
		||||
            "problemMatcher": "$msCompile"
 | 
			
		||||
        },
 | 
			
		||||
        {
 | 
			
		||||
            "label": "watch",
 | 
			
		||||
            "command": "dotnet",
 | 
			
		||||
            "type": "process",
 | 
			
		||||
            "args": [
 | 
			
		||||
                "watch",
 | 
			
		||||
                "run",
 | 
			
		||||
                "${workspaceFolder}/examples/CSharp/Example/CSharp_Example.csproj",
 | 
			
		||||
                "/property:GenerateFullPaths=true",
 | 
			
		||||
                "/consoleloggerparameters:NoSummary"
 | 
			
		||||
            ],
 | 
			
		||||
            "problemMatcher": "$msCompile"
 | 
			
		||||
        }
 | 
			
		||||
    ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,7 @@
 | 
			
		||||
import "./import";
 | 
			
		||||
 | 
			
		||||
define csharp_namespace Example;
 | 
			
		||||
define rust_crate example;
 | 
			
		||||
 | 
			
		||||
enum TestEnum {
 | 
			
		||||
   VAL1,
 | 
			
		||||
@ -14,17 +15,17 @@ type Test {
 | 
			
		||||
   atom: TestAtom;
 | 
			
		||||
   array: TestAtom[];
 | 
			
		||||
   enumValue: TestEnum;
 | 
			
		||||
   map: {number, TestAtom};
 | 
			
		||||
   map: {int, TestAtom};
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
type AddValueRequest {
 | 
			
		||||
   value1: number;
 | 
			
		||||
   value2: number;
 | 
			
		||||
   value1: float;
 | 
			
		||||
   value2: float;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
type AddValueResponse {
 | 
			
		||||
   value: number;
 | 
			
		||||
   value: float;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
service TestService {
 | 
			
		||||
@ -36,11 +37,11 @@ service TestService {
 | 
			
		||||
   @Description("Add two numbers")
 | 
			
		||||
   @Param("value1", "The first value")
 | 
			
		||||
   @Param("value2", "The second value")
 | 
			
		||||
   AddValuesMultipleParams(value1: number, value2: number): number;
 | 
			
		||||
   AddValuesMultipleParams(value1: float, value2: float): float;
 | 
			
		||||
 | 
			
		||||
   @Description("Does literaly nothing")
 | 
			
		||||
   @Param("param1", "Some number")
 | 
			
		||||
   ReturningVoid(param1: number): void;
 | 
			
		||||
   ReturningVoid(param1: float): void;
 | 
			
		||||
 | 
			
		||||
   @Description("Just sends an Event with a String")
 | 
			
		||||
   @Param("param1", "Parameter with some string for event")
 | 
			
		||||
@ -49,5 +50,5 @@ service TestService {
 | 
			
		||||
   ThrowingError(): void;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
   FunctionWithArrayAsParamAndReturn(values1: number[], values2: number[]): number[];
 | 
			
		||||
   FunctionWithArrayAsParamAndReturn(values1: float[], values2: float[]): float[];
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
type TestAtom {
 | 
			
		||||
   val_number: number;
 | 
			
		||||
   val_number: float;
 | 
			
		||||
   val_boolean: boolean;
 | 
			
		||||
   val_string: string;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										30
									
								
								lib/jrpc.js
									
									
									
									
									
								
							
							
						
						
									
										30
									
								
								lib/jrpc.js
									
									
									
									
									
								
							@ -9876,7 +9876,7 @@ function parse(tokens, file) {
 | 
			
		||||
// src/ir.ts
 | 
			
		||||
var import_debug = __toESM(require_src());
 | 
			
		||||
var log = (0, import_debug.default)("app");
 | 
			
		||||
var BUILTIN = ["number", "string", "boolean"];
 | 
			
		||||
var BUILTIN = ["float", "int", "string", "boolean"];
 | 
			
		||||
var IRError = class extends Error {
 | 
			
		||||
  constructor(statement, message) {
 | 
			
		||||
    super("Error building IR: " + message);
 | 
			
		||||
@ -9912,7 +9912,7 @@ function get_ir(parsed) {
 | 
			
		||||
          if (depends.indexOf(field.fieldtype) < 0)
 | 
			
		||||
            depends.push(field.fieldtype);
 | 
			
		||||
        }
 | 
			
		||||
        if (field.map && field.map !== "number" && field.map !== "string") {
 | 
			
		||||
        if (field.map && field.map !== "int" && field.map !== "string") {
 | 
			
		||||
          throw new IRError(field, `Type ${field.map} is not valid as map key!`);
 | 
			
		||||
        }
 | 
			
		||||
        return {
 | 
			
		||||
@ -10046,7 +10046,8 @@ function get_ir(parsed) {
 | 
			
		||||
      ]);
 | 
			
		||||
    } else if (statement.type == "define") {
 | 
			
		||||
      options[statement.key] = statement.value;
 | 
			
		||||
      if (statement.key == "use_messagepack" && statement.value == "true") {
 | 
			
		||||
      if ((statement.key == "use_messagepack" || statement.key == "allow_bytes") && statement.value == "true") {
 | 
			
		||||
        options["allow_bytes"] = true;
 | 
			
		||||
        builtin.push("bytes");
 | 
			
		||||
      }
 | 
			
		||||
    } else {
 | 
			
		||||
@ -10074,10 +10075,14 @@ var CompileTarget = class {
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  writeFile(name, content) {
 | 
			
		||||
    let resPath = Path.join(this.outputFolder, name);
 | 
			
		||||
    let resDir = Path.dirname(resPath);
 | 
			
		||||
    if (!FS.existsSync(resDir))
 | 
			
		||||
      FS.mkdirSync(resDir, { recursive: true });
 | 
			
		||||
    if (content instanceof Promise) {
 | 
			
		||||
      content.then((res) => FS.writeFileSync(Path.join(this.outputFolder, name), res));
 | 
			
		||||
      content.then((res) => FS.writeFileSync(resPath, res));
 | 
			
		||||
    } else {
 | 
			
		||||
      FS.writeFileSync(Path.join(this.outputFolder, name), content);
 | 
			
		||||
      FS.writeFileSync(resPath, content);
 | 
			
		||||
    }
 | 
			
		||||
  }
 | 
			
		||||
  getTemplate(name) {
 | 
			
		||||
@ -10120,7 +10125,8 @@ function compile(ir, target) {
 | 
			
		||||
// src/targets/typescript.ts
 | 
			
		||||
var conversion = {
 | 
			
		||||
  boolean: "boolean",
 | 
			
		||||
  number: "number",
 | 
			
		||||
  int: "number",
 | 
			
		||||
  float: "number",
 | 
			
		||||
  string: "string",
 | 
			
		||||
  void: "void",
 | 
			
		||||
  bytes: "Uint8Array"
 | 
			
		||||
@ -10139,7 +10145,7 @@ var TypescriptTarget = class extends CompileTarget {
 | 
			
		||||
`;
 | 
			
		||||
  }
 | 
			
		||||
  generateImports(a, def) {
 | 
			
		||||
    a(0, this.generateImport(`{ VerificationError, apply_number, apply_string, apply_boolean, apply_void }`, `./ts_base`));
 | 
			
		||||
    a(0, this.generateImport(`{ VerificationError, apply_int, apply_float, apply_string, apply_boolean, apply_void }`, `./ts_base`));
 | 
			
		||||
    a(0, def.depends.map((dep) => this.generateImport(`${dep}, { apply_${dep} }`, "./" + dep)));
 | 
			
		||||
  }
 | 
			
		||||
  getFileName(typename) {
 | 
			
		||||
@ -10260,7 +10266,6 @@ var TypescriptTarget = class extends CompileTarget {
 | 
			
		||||
      const params = fnc.inputs.map((e) => `${e.name}: ${toJSType(e.type) + (e.array ? "[]" : "")}`).join(", ");
 | 
			
		||||
      if (!fnc.return) {
 | 
			
		||||
        a(1, `${fnc.name}(${params}): void {`);
 | 
			
		||||
        1;
 | 
			
		||||
        a(2, `this._provider.sendMessage({`);
 | 
			
		||||
        a(3, `jsonrpc: "2.0",`);
 | 
			
		||||
        a(3, `method: "${def.name}.${fnc.name}",`);
 | 
			
		||||
@ -10334,6 +10339,8 @@ var TypescriptTarget = class extends CompileTarget {
 | 
			
		||||
      a(2, `let p: any[] = [];`);
 | 
			
		||||
      a(2, `if(Array.isArray(params)){`);
 | 
			
		||||
      a(3, `p = params;`);
 | 
			
		||||
      a(3, `while(p.length < ${fnc.inputs.length})`);
 | 
			
		||||
      a(4, `p.push(undefined)`);
 | 
			
		||||
      a(2, `} else {`);
 | 
			
		||||
      for (const param of fnc.inputs) {
 | 
			
		||||
        a(3, `p.push(params["${param.name}"])`);
 | 
			
		||||
@ -10439,7 +10446,8 @@ var NodeJSTypescriptTarget = class extends TypescriptTarget {
 | 
			
		||||
// src/targets/csharp.ts
 | 
			
		||||
var conversion2 = {
 | 
			
		||||
  boolean: "bool",
 | 
			
		||||
  number: "double",
 | 
			
		||||
  int: "long",
 | 
			
		||||
  float: "double",
 | 
			
		||||
  string: "string",
 | 
			
		||||
  void: "void",
 | 
			
		||||
  bytes: ""
 | 
			
		||||
@ -10453,8 +10461,8 @@ var CSharpTarget = class extends CompileTarget {
 | 
			
		||||
    return this.options.csharp_namespace || "JRPC";
 | 
			
		||||
  }
 | 
			
		||||
  start() {
 | 
			
		||||
    if (this.options.use_messagepack == true) {
 | 
			
		||||
      throw new Error("C# has no support for MessagePack yet!");
 | 
			
		||||
    if (this.options.allow_bytes == true) {
 | 
			
		||||
      throw new Error("C# has no support for 'bytes' yet!");
 | 
			
		||||
    }
 | 
			
		||||
    this.writeFile(this.namespace + ".csproj", this.getTemplate("CSharp/CSharp.csproj"));
 | 
			
		||||
    const fixNS = (input) => input.replace("__NAMESPACE__", this.namespace);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										12
									
								
								meta.json
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								meta.json
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,12 @@
 | 
			
		||||
{
 | 
			
		||||
   "name": "jsonrpc",
 | 
			
		||||
   "version": "0.0.1",
 | 
			
		||||
   "description": "",
 | 
			
		||||
   "author": "Fabian Stamm <dev@fabianstamm.de>",
 | 
			
		||||
   "contributors": [],
 | 
			
		||||
   "files": [
 | 
			
		||||
      "**/*.ts",
 | 
			
		||||
      "**/*.js",
 | 
			
		||||
      "README.md"
 | 
			
		||||
   ]
 | 
			
		||||
}
 | 
			
		||||
@ -1,6 +1,6 @@
 | 
			
		||||
{
 | 
			
		||||
   "name": "@hibas123/jrpcgen",
 | 
			
		||||
   "version": "1.0.29",
 | 
			
		||||
   "version": "1.1.1",
 | 
			
		||||
   "main": "lib/index.js",
 | 
			
		||||
   "license": "MIT",
 | 
			
		||||
   "packageManager": "yarn@3.1.1",
 | 
			
		||||
@ -19,7 +19,7 @@
 | 
			
		||||
   "files": [
 | 
			
		||||
      "lib/jrpc.js",
 | 
			
		||||
      "templates/**",
 | 
			
		||||
      "examples/**",
 | 
			
		||||
      "examples/*.jrpc",
 | 
			
		||||
      "src/**",
 | 
			
		||||
      "tsconfig.json"
 | 
			
		||||
   ],
 | 
			
		||||
 | 
			
		||||
@ -1,5 +1,5 @@
 | 
			
		||||
import * as FS from "fs";
 | 
			
		||||
import * as FSE from "fs-extra"
 | 
			
		||||
import * as FSE from "fs-extra";
 | 
			
		||||
import * as Path from "path";
 | 
			
		||||
import {
 | 
			
		||||
   EnumDefinition,
 | 
			
		||||
@ -11,7 +11,10 @@ import {
 | 
			
		||||
 | 
			
		||||
export abstract class CompileTarget<T = any> {
 | 
			
		||||
   abstract name: string;
 | 
			
		||||
   constructor(private outputFolder: string, protected options: T & { use_messagepack: boolean }) {
 | 
			
		||||
   constructor(
 | 
			
		||||
      private outputFolder: string,
 | 
			
		||||
      protected options: T & { allow_bytes: boolean }
 | 
			
		||||
   ) {
 | 
			
		||||
      if (!FS.existsSync(outputFolder)) {
 | 
			
		||||
         FS.mkdirSync(outputFolder, {
 | 
			
		||||
            recursive: true,
 | 
			
		||||
@ -30,12 +33,13 @@ export abstract class CompileTarget<T = any> {
 | 
			
		||||
   abstract finalize(steps: Step[]): void;
 | 
			
		||||
 | 
			
		||||
   protected writeFile(name: string, content: string | Promise<string>) {
 | 
			
		||||
      let resPath = Path.join(this.outputFolder, name);
 | 
			
		||||
      let resDir = Path.dirname(resPath);
 | 
			
		||||
      if (!FS.existsSync(resDir)) FS.mkdirSync(resDir, { recursive: true });
 | 
			
		||||
      if (content instanceof Promise) {
 | 
			
		||||
         content.then((res) =>
 | 
			
		||||
            FS.writeFileSync(Path.join(this.outputFolder, name), res)
 | 
			
		||||
         );
 | 
			
		||||
         content.then((res) => FS.writeFileSync(resPath, res));
 | 
			
		||||
      } else {
 | 
			
		||||
         FS.writeFileSync(Path.join(this.outputFolder, name), content);
 | 
			
		||||
         FS.writeFileSync(resPath, content);
 | 
			
		||||
      }
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
@ -59,12 +63,10 @@ export abstract class CompileTarget<T = any> {
 | 
			
		||||
      return res.join("\n");
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   protected loadTemplateFolder(name:string) {
 | 
			
		||||
   protected loadTemplateFolder(name: string) {
 | 
			
		||||
      let root = Path.join(__dirname, "../templates/", name);
 | 
			
		||||
      
 | 
			
		||||
      FSE.copySync(root, this.outputFolder, {
 | 
			
		||||
 | 
			
		||||
      });
 | 
			
		||||
      FSE.copySync(root, this.outputFolder, {});
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										117
									
								
								src/ir.ts
									
									
									
									
									
								
							
							
						
						
									
										117
									
								
								src/ir.ts
									
									
									
									
									
								
							@ -2,7 +2,7 @@ import type { Parsed, StatementNode } from "./parser";
 | 
			
		||||
import dbg from "debug";
 | 
			
		||||
const log = dbg("app");
 | 
			
		||||
 | 
			
		||||
const BUILTIN = ["number", "string", "boolean"];
 | 
			
		||||
const BUILTIN = ["float", "int", "string", "boolean"];
 | 
			
		||||
 | 
			
		||||
export class IRError extends Error {
 | 
			
		||||
   constructor(public statement: StatementNode, message: string) {
 | 
			
		||||
@ -36,17 +36,17 @@ export interface EnumDefinition {
 | 
			
		||||
export type ServiceFunctionDecorators = {
 | 
			
		||||
   description: string;
 | 
			
		||||
   parameters: {
 | 
			
		||||
      name:string;
 | 
			
		||||
      name: string;
 | 
			
		||||
      description: string;
 | 
			
		||||
   }[];
 | 
			
		||||
   returns: string;
 | 
			
		||||
}
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export interface ServiceFunctionParamsDefinition {
 | 
			
		||||
   name: string;
 | 
			
		||||
   inputs: { type: string; name: string, array: boolean }[];
 | 
			
		||||
   return: { type: string, array: boolean } | undefined;
 | 
			
		||||
   decorators: ServiceFunctionDecorators
 | 
			
		||||
   inputs: { type: string; name: string; array: boolean }[];
 | 
			
		||||
   return: { type: string; array: boolean } | undefined;
 | 
			
		||||
   decorators: ServiceFunctionDecorators;
 | 
			
		||||
}
 | 
			
		||||
export type ServiceFunctionDefinition = ServiceFunctionParamsDefinition;
 | 
			
		||||
 | 
			
		||||
@ -62,8 +62,8 @@ export type Step = [
 | 
			
		||||
];
 | 
			
		||||
 | 
			
		||||
export type IR = {
 | 
			
		||||
   options: { [key:string]: string},
 | 
			
		||||
   steps: Step[]
 | 
			
		||||
   options: { [key: string]: string };
 | 
			
		||||
   steps: Step[];
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
@ -101,7 +101,10 @@ export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (defined.indexOf(field.fieldtype) < 0) {
 | 
			
		||||
               if (builtin.indexOf(field.fieldtype) < 0 && field.fieldtype !== statement.name) {
 | 
			
		||||
               if (
 | 
			
		||||
                  builtin.indexOf(field.fieldtype) < 0 &&
 | 
			
		||||
                  field.fieldtype !== statement.name
 | 
			
		||||
               ) {
 | 
			
		||||
                  throw new IRError(
 | 
			
		||||
                     field,
 | 
			
		||||
                     `Type ${field.fieldtype} is not defined!`
 | 
			
		||||
@ -112,11 +115,7 @@ export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
                  depends.push(field.fieldtype);
 | 
			
		||||
            }
 | 
			
		||||
 | 
			
		||||
            if (
 | 
			
		||||
               field.map &&
 | 
			
		||||
               field.map !== "number" &&
 | 
			
		||||
               field.map !== "string"
 | 
			
		||||
            ) {
 | 
			
		||||
            if (field.map && field.map !== "int" && field.map !== "string") {
 | 
			
		||||
               throw new IRError(
 | 
			
		||||
                  field,
 | 
			
		||||
                  `Type ${field.map} is not valid as map key!`
 | 
			
		||||
@ -200,7 +199,10 @@ export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
                  if (!depends.some((a) => a === fnc.return_type.type))
 | 
			
		||||
                     depends.push(fnc.return_type.type);
 | 
			
		||||
               } else {
 | 
			
		||||
                  if (fnc.return_type.type !== "void" && builtin.indexOf(fnc.return_type.type) < 0) {
 | 
			
		||||
                  if (
 | 
			
		||||
                     fnc.return_type.type !== "void" &&
 | 
			
		||||
                     builtin.indexOf(fnc.return_type.type) < 0
 | 
			
		||||
                  ) {
 | 
			
		||||
                     throw new IRError(
 | 
			
		||||
                        fnc,
 | 
			
		||||
                        `Type ${fnc.return_type.type} is not defined`
 | 
			
		||||
@ -225,51 +227,73 @@ export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
 | 
			
		||||
            let decorators = {} as ServiceFunctionDecorators;
 | 
			
		||||
 | 
			
		||||
            fnc.decorators.forEach((values, key)=>{
 | 
			
		||||
               for(const val of values) {
 | 
			
		||||
                  switch(key) {
 | 
			
		||||
            fnc.decorators.forEach((values, key) => {
 | 
			
		||||
               for (const val of values) {
 | 
			
		||||
                  switch (key) {
 | 
			
		||||
                     case "Description":
 | 
			
		||||
                        if(decorators.description)
 | 
			
		||||
                           throw new IRError(fnc, `Decorator 'Description' can only be used once!`);
 | 
			
		||||
                        if(val.length != 1)
 | 
			
		||||
                           throw new IRError(fnc, `Decorator 'Description' requires exactly one parameter!`);
 | 
			
		||||
                        if (decorators.description)
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Description' can only be used once!`
 | 
			
		||||
                           );
 | 
			
		||||
                        if (val.length != 1)
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Description' requires exactly one parameter!`
 | 
			
		||||
                           );
 | 
			
		||||
                        decorators.description = val[0];
 | 
			
		||||
                        break;
 | 
			
		||||
                     case "Returns":
 | 
			
		||||
                           if(decorators.returns)
 | 
			
		||||
                              throw new IRError(fnc, `Decorator 'Returns' can only be used once!`);
 | 
			
		||||
                           if(val.length != 1)
 | 
			
		||||
                              throw new IRError(fnc, `Decorator 'Returns' requires exactly one parameter!`);
 | 
			
		||||
                           decorators.returns = val[0];
 | 
			
		||||
                           break;
 | 
			
		||||
                        if (decorators.returns)
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Returns' can only be used once!`
 | 
			
		||||
                           );
 | 
			
		||||
                        if (val.length != 1)
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Returns' requires exactly one parameter!`
 | 
			
		||||
                           );
 | 
			
		||||
                        decorators.returns = val[0];
 | 
			
		||||
                        break;
 | 
			
		||||
                     case "Param":
 | 
			
		||||
                        if(!decorators.parameters)
 | 
			
		||||
                           decorators.parameters = [];
 | 
			
		||||
                        if(val.length != 2)
 | 
			
		||||
                           throw new IRError(fnc, `Decorator 'Param' requires exactly two parameters!`);
 | 
			
		||||
                        if (!decorators.parameters) decorators.parameters = [];
 | 
			
		||||
                        if (val.length != 2)
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Param' requires exactly two parameters!`
 | 
			
		||||
                           );
 | 
			
		||||
                        const [name, description] = val;
 | 
			
		||||
                        if(!fnc.inputs.find(e=>e.name == name))
 | 
			
		||||
                           throw new IRError(fnc, `Decorator 'Param' requires the first param to equal the name of a function parameter!`);
 | 
			
		||||
                        if(decorators.parameters.find(e=>e.name == name))
 | 
			
		||||
                           throw new IRError(fnc, `Decorator 'Param' has already been set for the parameter ${name}!`);
 | 
			
		||||
                        if (!fnc.inputs.find((e) => e.name == name))
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Param' requires the first param to equal the name of a function parameter!`
 | 
			
		||||
                           );
 | 
			
		||||
                        if (decorators.parameters.find((e) => e.name == name))
 | 
			
		||||
                           throw new IRError(
 | 
			
		||||
                              fnc,
 | 
			
		||||
                              `Decorator 'Param' has already been set for the parameter ${name}!`
 | 
			
		||||
                           );
 | 
			
		||||
 | 
			
		||||
                        decorators.parameters.push({
 | 
			
		||||
                           name,
 | 
			
		||||
                           description,
 | 
			
		||||
                        })
 | 
			
		||||
                        });
 | 
			
		||||
                        break;
 | 
			
		||||
                     default:
 | 
			
		||||
                        throw new IRError(fnc, `Decorator ${key} is not a valid decorator!`);
 | 
			
		||||
                        throw new IRError(
 | 
			
		||||
                           fnc,
 | 
			
		||||
                           `Decorator ${key} is not a valid decorator!`
 | 
			
		||||
                        );
 | 
			
		||||
                  }
 | 
			
		||||
               }
 | 
			
		||||
            })
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
            return {
 | 
			
		||||
               name: fnc.name,
 | 
			
		||||
               inputs: fnc.inputs,
 | 
			
		||||
               return: fnc.return_type,
 | 
			
		||||
               decorators
 | 
			
		||||
               decorators,
 | 
			
		||||
            } as ServiceFunctionDefinition;
 | 
			
		||||
         });
 | 
			
		||||
 | 
			
		||||
@ -281,9 +305,14 @@ export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
               functions,
 | 
			
		||||
            } as ServiceDefinition,
 | 
			
		||||
         ]);
 | 
			
		||||
      } else if(statement.type == "define") {
 | 
			
		||||
      } else if (statement.type == "define") {
 | 
			
		||||
         options[statement.key] = statement.value;
 | 
			
		||||
         if(statement.key == "use_messagepack" && statement.value == "true") {
 | 
			
		||||
         if (
 | 
			
		||||
            (statement.key == "use_messagepack" ||
 | 
			
		||||
               statement.key == "allow_bytes") &&
 | 
			
		||||
            statement.value == "true"
 | 
			
		||||
         ) {
 | 
			
		||||
            options["allow_bytes"] = true;
 | 
			
		||||
            builtin.push("bytes");
 | 
			
		||||
         }
 | 
			
		||||
      } else {
 | 
			
		||||
@ -293,6 +322,6 @@ export default function get_ir(parsed: Parsed): IR {
 | 
			
		||||
 | 
			
		||||
   return {
 | 
			
		||||
      options,
 | 
			
		||||
      steps
 | 
			
		||||
      steps,
 | 
			
		||||
   };
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
@ -22,7 +22,6 @@ Targets.set("ts-esm", ESMTypescriptTarget);
 | 
			
		||||
Targets.set("ts-node", NodeJSTypescriptTarget);
 | 
			
		||||
Targets.set("c#", CSharpTarget as typeof CompileTarget);
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
function indexToLineAndCol(src: string, index: number) {
 | 
			
		||||
   let line = 1;
 | 
			
		||||
   let col = 1;
 | 
			
		||||
 | 
			
		||||
@ -12,10 +12,11 @@ type lineAppender = (ind: number, line: string | string[]) => void;
 | 
			
		||||
 | 
			
		||||
const conversion = {
 | 
			
		||||
   boolean: "bool",
 | 
			
		||||
   number: "double",
 | 
			
		||||
   int: "long",
 | 
			
		||||
   float: "double",
 | 
			
		||||
   string: "string",
 | 
			
		||||
   void: "void",
 | 
			
		||||
   bytes: ""
 | 
			
		||||
   bytes: "",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function toCSharpType(type: string): string {
 | 
			
		||||
@ -30,8 +31,8 @@ export class CSharpTarget extends CompileTarget<{ csharp_namespace: string }> {
 | 
			
		||||
   }
 | 
			
		||||
 | 
			
		||||
   start(): void {
 | 
			
		||||
      if(this.options.use_messagepack == true) {
 | 
			
		||||
         throw new Error("C# has no support for MessagePack yet!");
 | 
			
		||||
      if (this.options.allow_bytes == true) {
 | 
			
		||||
         throw new Error("C# has no support for 'bytes' yet!");
 | 
			
		||||
      }
 | 
			
		||||
      this.writeFile(
 | 
			
		||||
         this.namespace + ".csproj",
 | 
			
		||||
 | 
			
		||||
@ -13,10 +13,11 @@ type lineAppender = (ind: number, line: string | string[]) => void;
 | 
			
		||||
 | 
			
		||||
const conversion = {
 | 
			
		||||
   boolean: "boolean",
 | 
			
		||||
   number: "number",
 | 
			
		||||
   int: "number",
 | 
			
		||||
   float: "number",
 | 
			
		||||
   string: "string",
 | 
			
		||||
   void: "void",
 | 
			
		||||
   bytes: "Uint8Array"
 | 
			
		||||
   bytes: "Uint8Array",
 | 
			
		||||
};
 | 
			
		||||
 | 
			
		||||
function toJSType(type: string): string {
 | 
			
		||||
@ -45,17 +46,14 @@ export class TypescriptTarget extends CompileTarget {
 | 
			
		||||
      a(
 | 
			
		||||
         0,
 | 
			
		||||
         this.generateImport(
 | 
			
		||||
            `{ VerificationError, apply_number, apply_string, apply_boolean, apply_void }`,
 | 
			
		||||
            `{ VerificationError, apply_int, apply_float, apply_string, apply_boolean, apply_void }`,
 | 
			
		||||
            `./ts_base`
 | 
			
		||||
         )
 | 
			
		||||
      );
 | 
			
		||||
      a(
 | 
			
		||||
         0,
 | 
			
		||||
         def.depends.map((dep) =>
 | 
			
		||||
            this.generateImport(
 | 
			
		||||
               `${dep}, { apply_${dep} }`,
 | 
			
		||||
               "./" + dep
 | 
			
		||||
            )
 | 
			
		||||
            this.generateImport(`${dep}, { apply_${dep} }`, "./" + dep)
 | 
			
		||||
         )
 | 
			
		||||
      );
 | 
			
		||||
   }
 | 
			
		||||
@ -128,17 +126,29 @@ export class TypescriptTarget extends CompileTarget {
 | 
			
		||||
         `export function apply_${def.name}(data: ${def.name}): ${def.name} {`
 | 
			
		||||
      );
 | 
			
		||||
      {
 | 
			
		||||
         a(1, `if(typeof data !== "object") throw new VerificationError("${def.name}", undefined, data);`)
 | 
			
		||||
         a(
 | 
			
		||||
            1,
 | 
			
		||||
            `if(typeof data !== "object") throw new VerificationError("${def.name}", undefined, data);`
 | 
			
		||||
         );
 | 
			
		||||
         a(1, `let res = new ${def.name}() as any;`);
 | 
			
		||||
         def.fields.forEach((field) => {
 | 
			
		||||
            a(1, `if(data["${field.name}"] !== null && data["${field.name}"] !== undefined) {`)
 | 
			
		||||
            a(
 | 
			
		||||
               1,
 | 
			
		||||
               `if(data["${field.name}"] !== null && data["${field.name}"] !== undefined) {`
 | 
			
		||||
            );
 | 
			
		||||
            if (field.array) {
 | 
			
		||||
               a(2, `if(!Array.isArray(data["${field.name}"])) throw new VerificationError("array", "${field.name}", data["${field.name}"]);`)
 | 
			
		||||
               a(
 | 
			
		||||
                  2,
 | 
			
		||||
                  `if(!Array.isArray(data["${field.name}"])) throw new VerificationError("array", "${field.name}", data["${field.name}"]);`
 | 
			
		||||
               );
 | 
			
		||||
               a(2, `res["${field.name}"] = data["${field.name}"].map(elm=>`);
 | 
			
		||||
               a(3, `apply_${field.type}(elm)`);
 | 
			
		||||
               a(2, `)`);
 | 
			
		||||
            } else if (field.map) {
 | 
			
		||||
               a(2, `if(typeof data["${field.name}"] !== "object") throw new VerificationError("map", "${field.name}", data["${field.name}"]);`)
 | 
			
		||||
               a(
 | 
			
		||||
                  2,
 | 
			
		||||
                  `if(typeof data["${field.name}"] !== "object") throw new VerificationError("map", "${field.name}", data["${field.name}"]);`
 | 
			
		||||
               );
 | 
			
		||||
               a(2, `res["${field.name}"] = {}`);
 | 
			
		||||
               a(
 | 
			
		||||
                  2,
 | 
			
		||||
@ -255,7 +265,7 @@ export class TypescriptTarget extends CompileTarget {
 | 
			
		||||
         // }
 | 
			
		||||
 | 
			
		||||
         if (!fnc.return) {
 | 
			
		||||
            a(1, `${fnc.name}(${params}): void {`);1
 | 
			
		||||
            a(1, `${fnc.name}(${params}): void {`);
 | 
			
		||||
            a(2, `this._provider.sendMessage({`);
 | 
			
		||||
            a(3, `jsonrpc: "2.0",`);
 | 
			
		||||
            a(3, `method: "${def.name}.${fnc.name}",`);
 | 
			
		||||
@ -361,6 +371,8 @@ export class TypescriptTarget extends CompileTarget {
 | 
			
		||||
         a(2, `let p: any[] = [];`);
 | 
			
		||||
         a(2, `if(Array.isArray(params)){`);
 | 
			
		||||
         a(3, `p = params;`);
 | 
			
		||||
         a(3, `while(p.length < ${fnc.inputs.length})`);
 | 
			
		||||
         a(4, `p.push(undefined)`);
 | 
			
		||||
         a(2, `} else {`);
 | 
			
		||||
         for (const param of fnc.inputs) {
 | 
			
		||||
            a(3, `p.push(params["${param.name}"])`);
 | 
			
		||||
@ -383,7 +395,10 @@ export class TypescriptTarget extends CompileTarget {
 | 
			
		||||
         a(2, ``);
 | 
			
		||||
         a(2, `p.push(ctx);`);
 | 
			
		||||
 | 
			
		||||
         a(2, `//@ts-ignore This will cause a typescript error when strict checking, since p is not a tuple`)
 | 
			
		||||
         a(
 | 
			
		||||
            2,
 | 
			
		||||
            `//@ts-ignore This will cause a typescript error when strict checking, since p is not a tuple`
 | 
			
		||||
         );
 | 
			
		||||
         a(
 | 
			
		||||
            2,
 | 
			
		||||
            `return this.${fnc.name}.call(this, ...p)` + //TODO: Refactor. This line is way to compicated for anyone to understand, including me
 | 
			
		||||
@ -466,10 +481,7 @@ export class TypescriptTarget extends CompileTarget {
 | 
			
		||||
                     "./" + def.name
 | 
			
		||||
                  )
 | 
			
		||||
               );
 | 
			
		||||
               a(
 | 
			
		||||
                  0,
 | 
			
		||||
                  `export { ${def.name}, apply_${def.name} }`
 | 
			
		||||
               );
 | 
			
		||||
               a(0, `export { ${def.name}, apply_${def.name} }`);
 | 
			
		||||
               a(0, ``);
 | 
			
		||||
               break;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
@ -4,13 +4,24 @@ export class VerificationError extends Error {
 | 
			
		||||
      public readonly field?: string,
 | 
			
		||||
      public readonly value?: any
 | 
			
		||||
   ) {
 | 
			
		||||
      super("Parameter verification failed! " +(type ? "Expected " + type + "! " :"") + (field ? "At: " + field + "! " : ""));
 | 
			
		||||
      super(
 | 
			
		||||
         "Parameter verification failed! " +
 | 
			
		||||
            (type ? "Expected " + type + "! " : "") +
 | 
			
		||||
            (field ? "At: " + field + "! " : "")
 | 
			
		||||
      );
 | 
			
		||||
   }
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function apply_number(data: any) {
 | 
			
		||||
export function apply_int(data: any) {
 | 
			
		||||
   data = Math.floor(Number(data));
 | 
			
		||||
   if (Number.isNaN(data)) throw new VerificationError("int", undefined, data);
 | 
			
		||||
   return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
export function apply_float(data: any) {
 | 
			
		||||
   data = Number(data);
 | 
			
		||||
   if(Number.isNaN(data)) throw new VerificationError("number", undefined, data);
 | 
			
		||||
   if (Number.isNaN(data))
 | 
			
		||||
      throw new VerificationError("float", undefined, data);
 | 
			
		||||
   return data;
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		Reference in New Issue
	
	Block a user