329 lines
9.4 KiB
TypeScript
329 lines
9.4 KiB
TypeScript
import { TypeDefinition, ServiceDefinition, EnumDefinition, Step } from "../ir";
|
|
|
|
import { CompileTarget } from "../compile";
|
|
import { LineAppender, lineAppender } from "../utils";
|
|
import chalk from "chalk";
|
|
|
|
const conversion = {
|
|
boolean: "bool",
|
|
int: "int",
|
|
float: "double",
|
|
string: "String",
|
|
void: "void",
|
|
// bytes: "Uint8List", //TODO: Check this
|
|
};
|
|
|
|
function toDartType(type: string): string {
|
|
return (conversion as any)[type] || type;
|
|
}
|
|
|
|
export class DartTarget extends CompileTarget<{ dart_library_name: string }> {
|
|
name: string = "dart";
|
|
|
|
start(): void {
|
|
if (this.options.allow_bytes == true) {
|
|
throw new Error("Dart has no support for 'bytes' yet!");
|
|
}
|
|
|
|
if (!this.options.dart_library_name) {
|
|
throw new Error(
|
|
"Setting dart_library_name is required for DART target!"
|
|
);
|
|
}
|
|
}
|
|
|
|
getImport(name: string) {
|
|
return `import "./${name}.dart";`;
|
|
}
|
|
|
|
generateImports(a: lineAppender, def: TypeDefinition | ServiceDefinition) {
|
|
a(0, `import "./base.dart";`);
|
|
def.depends.forEach((dep) => {
|
|
a(0, this.getImport(dep));
|
|
});
|
|
}
|
|
|
|
getTypeParse(type: string, value: string) {
|
|
if (conversion[type]) {
|
|
return `${toDartType(type)}_fromJson(${value})`;
|
|
} else {
|
|
return `${toDartType(type)}.fromJson(${value})`;
|
|
}
|
|
}
|
|
|
|
generateType(definition: TypeDefinition): void {
|
|
const { a, getResult } = LineAppender(2);
|
|
|
|
this.generateImports(a, definition);
|
|
|
|
a(0, ``);
|
|
a(0, `class ${definition.name} {`);
|
|
for (const field of definition.fields) {
|
|
if (field.array) {
|
|
a(1, `List<${toDartType(field.type)}>? ${field.name};`);
|
|
} else if (field.map) {
|
|
a(
|
|
1,
|
|
`Map<${toDartType(field.map)},${toDartType(field.type)}>? ${
|
|
field.name
|
|
};`
|
|
);
|
|
} else {
|
|
a(1, `${toDartType(field.type)}? ${field.name};`);
|
|
}
|
|
}
|
|
|
|
a(0, ``);
|
|
a(
|
|
1,
|
|
`${definition.name}({${definition.fields
|
|
.map((e) => `this.${e.name}`)
|
|
.join(", ")}});`
|
|
);
|
|
a(0, ``);
|
|
a(1, `${definition.name}.fromJson(Map<String, dynamic> json) {`);
|
|
for (const field of definition.fields) {
|
|
a(2, `if(json.containsKey("${field.name}")) {`);
|
|
|
|
if (field.array) {
|
|
a(3, `this.${field.name} = [];`);
|
|
a(3, `(json["${field.name}"] as List<dynamic>).forEach((e) => {`);
|
|
a(
|
|
4,
|
|
`this.${field.name}!.add(${this.getTypeParse(field.type, "e")})`
|
|
);
|
|
a(3, `});`);
|
|
} else if (field.map) {
|
|
a(3, `this.${field.name} = {};`);
|
|
a(
|
|
3,
|
|
`(json["${field.name}"] as Map<${toDartType(
|
|
field.map
|
|
)},dynamic>).forEach((key, value) => {`
|
|
);
|
|
a(
|
|
4,
|
|
`this.${field.name}![key] = ${this.getTypeParse(
|
|
field.type,
|
|
"value"
|
|
)}`
|
|
);
|
|
a(3, `});`);
|
|
} else {
|
|
a(
|
|
3,
|
|
`this.${field.name} = ${this.getTypeParse(
|
|
field.type,
|
|
`json["${field.name}"]`
|
|
)};`
|
|
);
|
|
}
|
|
a(2, `} else {`);
|
|
a(3, `this.${field.name} = null;`);
|
|
a(2, `}`);
|
|
a(0, ``);
|
|
}
|
|
|
|
a(1, `}`);
|
|
|
|
a(1, `Map<String, dynamic> toJson() {`);
|
|
a(2, `Map<String, dynamic> res = {};`);
|
|
for (const field of definition.fields) {
|
|
if (conversion[field.type]) {
|
|
a(2, `res["${field.name}"] = this.${field.name};`);
|
|
} else {
|
|
if (field.array) {
|
|
a(
|
|
2,
|
|
`res["${field.name}"] = this.${field.name}?.map((entry) => entry.toJson()).toList();`
|
|
);
|
|
} else if (field.map) {
|
|
// dict.map((key, value) => MapEntry(key, value.toString()));
|
|
a(
|
|
2,
|
|
`res["${field.name}"] = this.${field.name}?.map((key, value) => MapEntry(key, value.toJson()));`
|
|
);
|
|
} else {
|
|
a(2, `res["${field.name}"] = this.${field.name};`);
|
|
}
|
|
}
|
|
}
|
|
a(2, `return res;`);
|
|
a(1, `}`);
|
|
|
|
a(0, `}`);
|
|
|
|
this.writeFile(`lib/src/${definition.name}.dart`, getResult());
|
|
}
|
|
|
|
generateEnum(definition: EnumDefinition): void {
|
|
const { a, getResult } = LineAppender(2);
|
|
|
|
a(0, `enum ${definition.name} {`);
|
|
for (const entry of definition.values) {
|
|
const isLast =
|
|
definition.values[definition.values.length - 1] == entry;
|
|
a(1, `${entry.name}(${entry.value})${isLast ? ";" : ","}`);
|
|
}
|
|
a(0, ``);
|
|
a(1, `final int val;`);
|
|
a(1, `const ${definition.name}(int valT) : val= valT;`);
|
|
a(1, `static ${definition.name}? fromJson(int val) {`);
|
|
a(2, `switch(val){`);
|
|
for (const entry of definition.values) {
|
|
a(3, `case ${entry.value}:`);
|
|
a(4, `return ${definition.name}.${entry.name};`);
|
|
}
|
|
a(3, `default:`);
|
|
a(4, `return null;`);
|
|
a(2, `}`);
|
|
a(1, `}`);
|
|
|
|
a(0, ``);
|
|
|
|
a(1, `int toJson() {`);
|
|
a(2, `return this.val;`);
|
|
a(1, `}`);
|
|
|
|
a(0, ``);
|
|
a(0, `}`);
|
|
|
|
a(0, ``);
|
|
|
|
this.writeFile(`lib/src/${definition.name}.dart`, getResult());
|
|
}
|
|
|
|
generateServiceClient(definition: ServiceDefinition): void {
|
|
const { a, getResult } = LineAppender(2);
|
|
|
|
this.generateImports(a, definition);
|
|
a(0, `import "./service_client.dart";`);
|
|
a(0, ``);
|
|
a(0, `class ${definition.name}Client extends Service {`);
|
|
a(0, ``);
|
|
|
|
a(
|
|
1,
|
|
`${definition.name}Client(ServiceProvider provider):super(provider, "${definition.name}");`
|
|
);
|
|
|
|
a(0, ``);
|
|
|
|
for (const func of definition.functions) {
|
|
const args = func.inputs
|
|
.map(
|
|
(inp) =>
|
|
(inp.array
|
|
? `List<${toDartType(inp.type)}>`
|
|
: toDartType(inp.type)) +
|
|
" " +
|
|
inp.name
|
|
)
|
|
.join(", ");
|
|
|
|
const asParams = func.inputs.map((e) => e.name).join(", ");
|
|
|
|
if (!func.return) {
|
|
a(1, `void ${func.name}(${args}) {`);
|
|
a(
|
|
2,
|
|
`provider.sendNotification("${definition.name}.${func.name}", [${asParams}]);`
|
|
);
|
|
a(1, `}`);
|
|
} else {
|
|
const baseReturnType =
|
|
func.return.type != "void"
|
|
? toDartType(func.return.type) + "?"
|
|
: toDartType(func.return.type);
|
|
const returnType = func.return.array
|
|
? `List<${baseReturnType}>`
|
|
: baseReturnType;
|
|
|
|
a(1, `Future<${returnType}> ${func.name}(${args}) async {`);
|
|
a(
|
|
2,
|
|
`var res = await this.provider.sendRequest("${definition.name}.${func.name}", [${asParams}]);`
|
|
);
|
|
if (func.return.type !== "void") {
|
|
if (func.return.array) {
|
|
a(
|
|
2,
|
|
`return res.map((entry) =>${this.getTypeParse(
|
|
func.return.type,
|
|
"entry"
|
|
)}).toList();`
|
|
);
|
|
} else {
|
|
a(2, `return ${this.getTypeParse(func.return.type, "res")};`);
|
|
}
|
|
}
|
|
a(1, `}`);
|
|
}
|
|
a(0, ``);
|
|
}
|
|
a(0, `}`);
|
|
a(0, ``);
|
|
|
|
this.writeFile(`lib/src/${definition.name}Client.dart`, getResult());
|
|
}
|
|
|
|
generateServiceServer(definition: ServiceDefinition): void {
|
|
console.log(
|
|
chalk.yellow("[DART] WARNING:"),
|
|
"DART support for services is not yet there. Service generation is currently limited to clients!"
|
|
);
|
|
}
|
|
|
|
generateService(definition: ServiceDefinition): void {
|
|
this.generateServiceClient(definition);
|
|
this.writeFile(
|
|
"lib/src/service_client.dart",
|
|
this.getTemplate("Dart/service_client.dart")
|
|
);
|
|
}
|
|
|
|
finalize(steps: Step[]): void {
|
|
const { a, getResult } = LineAppender(2);
|
|
|
|
a(0, `library ${this.options.dart_library_name};`);
|
|
a(0, ``);
|
|
|
|
let hasService = false;
|
|
|
|
steps.forEach(([type, def]) => {
|
|
switch (type) {
|
|
case "type":
|
|
a(0, `export 'src/${def.name}.dart';`);
|
|
break;
|
|
case "enum":
|
|
a(0, `export 'src/${def.name}.dart';`);
|
|
break;
|
|
case "service":
|
|
a(0, `export 'src/${def.name}Client.dart';`);
|
|
hasService = true;
|
|
break;
|
|
default:
|
|
console.warn(
|
|
chalk.yellow("[DART] WARNING:"),
|
|
"unimplemented step found:",
|
|
type
|
|
);
|
|
}
|
|
});
|
|
|
|
if (hasService) {
|
|
a(0, `export 'src/service_client.dart';`);
|
|
}
|
|
|
|
this.writeFile(`lib/${this.options.dart_library_name}.dart`, getResult());
|
|
this.writeFile(
|
|
`pubspec.yaml`,
|
|
this.getTemplate("Dart/pubspec.yaml").replace(
|
|
"__NAME__",
|
|
this.options.dart_library_name
|
|
)
|
|
);
|
|
this.writeFile(`lib/src/base.dart`, this.getTemplate("Dart/base.dart"));
|
|
}
|
|
}
|