@wuapi/generator
Version:
307 lines (298 loc) • 13.2 kB
JavaScript
"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
const essential_1 = require("@wuapi/essential");
const plugin_base_1 = require("./plugin_base");
const fs_1 = __importDefault(require("fs"));
const path_1 = __importDefault(require("path"));
const brace_1 = require("./brace");
const dedent_1 = __importDefault(require("dedent"));
const lodash_1 = __importDefault(require("lodash"));
/**
* Swift code plugin.
*/
class SwiftPlugin extends plugin_base_1.BasePlugin {
/**
* Returns the description of this plugin.
*/
getDescription() {
return {
name: "swift",
abbreviation: "s",
version: "1.0.0",
description: "Generate Swift code.",
arguments: [],
};
}
process(project, outputDir, args) {
new SwiftProcessor(this, project, outputDir, args).process();
}
}
exports.default = SwiftPlugin;
/**
* The Swift project processor
*/
class SwiftProcessor extends plugin_base_1.ProjectProcessor {
/**
* Write entity
*/
writeEntity(b, pth, entity) {
const self = this;
//
function calcSuffix(extra) {
let unsolved = entity.getGenericUnsolved(self.project);
if (extra) {
unsolved = lodash_1.default.concat(unsolved, [extra]);
}
return (unsolved.length > 0) ? `<${unsolved.join(", ")}>` : "";
}
//
function calcExtSuffix(extra) {
let punsolved = entity.parent?.asEntityOf(self.project)?.getGenericUnsolved(self.project) ?? [];
let result = [];
punsolved.forEach((name) => {
let solved = entity.genericMap[name];
let item = (solved) ? genericTypeName(solved.type) : name;
result.push(item);
});
if (extra) {
result.push(extra);
}
return (result.length > 0) ? `<${result.join(", ")}>` : "";
}
//
function memberTypeName(type) {
switch (type.member.type) {
case "TBoolean": return "Bool";
case "TInteger": return "Int";
case "TLong": return "Int64";
case "TID": return "Int64";
case "TDouble": return "Double";
case "TString": return "String";
case "TURL": return "String";
case "TDateTime": return "String";
case "TSSMap": return "[String: String]";
case "TEnum": return type.member.enu.name;
case "TObject": return type.member.entity.name;
case "TUnknown": return type.member.unknown;
case "TList": throw Error("List can not contain list!");
default: throw new Error(`Unknown list type "${type.member.type}" in "${pth.module}/${pth.name}"`);
}
}
//
function genericTypeName(type) {
switch (type.type) {
case "TBoolean": return "Bool";
case "TInteger": return "Int";
case "TLong": return "Int64";
case "TID": return "Int64";
case "TDouble": return "Double";
case "TString": return "String";
case "TURL": return "String";
case "TDateTime": return "String";
case "TSSMap": return "[String: String]";
case "TEnum": return type.enu.name;
case "TObject": return type.entity.name;
case "TList": return memberTypeName(type);
default: throw new Error(`Unknown generic type "${type.type}" in "${pth.module}/${pth.name}"`);
}
}
//
function generateField(name, f) {
// b(f.comments.toLineComment()
if (f.fixedValue) {
switch (f.type.type) {
case "TBoolean": return `public var ${name}: Bool = ${f.fixedValue};`;
case "TInteger": return `public var ${name}: Int = ${f.fixedValue};`;
case "TLong": return `public var ${name}: Int64 = ${f.fixedValue};`;
case "TID": return `public var ${name}: Int64 = ${f.fixedValue};`;
case "TDouble": return `public var ${name}: Double = ${f.fixedValue};`;
case "TString": return `public var ${name}: String = "${f.fixedValue}";`;
case "TURL": return `public var ${name}: String = "${f.fixedValue}";`;
case "TDateTime": return `public var ${name}: String = "${f.fixedValue}";`;
default: throw Error(`Field '${name}' in "${pth.module}/${pth.name}" with type ${f.type.type} can NOT have fixed value!`);
}
}
else if (f.isOptional) {
switch (f.type.type) {
case "TBoolean": return `public var ${name}: Bool? = nil`;
case "TInteger": return `public var ${name}: Int? = nil`;
case "TLong": return `public var ${name}: Int64? = nil`;
case "TID": return `public var ${name}: Int64? = nil`;
case "TDouble": return `public var ${name}: Double? = nil`;
case "TString": return `public var ${name}: String? = nil`;
case "TURL": return `public var ${name}: String? = nil`;
case "TDateTime": return `public var ${name}: String? = nil`;
case "TSSMap": return `public var ${name}: [String: String]? = nil`;
case "TEnum": return `public var ${name}: ${f.type.enu.name}? = nil`;
case "TObject": return `public var ${name}: ${f.type.entity.name}? = nil`;
case "TList": return `public var ${name}: [${memberTypeName(f.type)}]? = nil`;
case "TUnknown": return `public var ${name}: ${f.type.unknown}? = nil`;
default: throw Error(`Type "${f.type.type}" of Field "${name}" in "${pth.module}/${pth.name}" is invalid.`);
}
}
else {
switch (f.type.type) {
case "TBoolean": return `public var ${name}: Bool = false`;
case "TInteger": return `public var ${name}: Int = 0`;
case "TLong": return `public var ${name}: Int64 = 0`;
case "TID": return `public var ${name}: Int64 = 0`;
case "TDouble": return `public var ${name}: Double = 0`;
case "TString": return `public var ${name}: String = ""`;
case "TURL": return `public var ${name}: String = ""`;
case "TDateTime": return `public var ${name}: String = ""`;
case "TSSMap": return `public var ${name}: [String: String] = [:]()`;
case "TEnum": {
let fe = f.type;
return `public var ${name}: ${fe.enu.name} = ${fe.enu.name}.${fe.enu.asEnumOf(self.project).first()}`;
}
case "TObject": {
let fo = f.type;
return `public var ${name}: ${fo.entity.name} = ${fo.entity.name}()`;
}
case "TList": {
let fl = f.type;
if (fl.member.type == "TUnknown") {
return `public var ${name}: [${fl.member.unknown}] = [${fl.member.unknown}]()`;
}
else {
return `public var ${name}: [${memberTypeName(fl)}] = [${memberTypeName(fl)}]()`;
}
}
case "TUnknown": throw Error(`Field '${name}' in "${pth.module}/${pth.name}" can NOT be unknown!`);
default: throw Error(`Type "${f.type.type}" of Field "${name}" in "${pth.module}/${pth.name}" is invalid.`);
}
}
}
// b(toBlockComment(entity))
let suffix = "";
let pname = "";
let extSuf = "";
switch (entity.type) {
case essential_1.$EntityType.REQUEST: {
let resName = entity.response?.name;
pname = entity.parent?.name ?? 'AbsReq';
suffix = calcSuffix(entity.isAbstract ? "R: AbsRes" : undefined);
extSuf = calcExtSuffix(entity.isAbstract ? "R" : (resName ?? undefined));
break;
}
case essential_1.$EntityType.RESPONSE: {
pname = entity.parent?.name ?? 'AbsRes';
suffix = calcSuffix();
extSuf = calcExtSuffix();
break;
}
case essential_1.$EntityType.OBJECT: {
pname = entity.parent?.name ?? 'AbsBase';
suffix = calcSuffix();
extSuf = calcExtSuffix();
break;
}
}
b.bra(`public class ${pth.name}${suffix}: ${pname}${extSuf}`).add((b) => {
if (entity.type == essential_1.$EntityType.REQUEST && !entity.isAbstract) {
b((0, dedent_1.default) `
public override func obtainPath() -> String {
return "${entity.path}"
}
`);
b((0, dedent_1.default) `
public override func obtainMethod() -> String {
return "${entity.method}"
}
`);
}
b((0, dedent_1.default) `
public required init?(map: Map) {
super.init(map: map)
}
public required init(){
super.init()
}\n
`);
lodash_1.default.forIn(entity.fieldsLocal, (f, name) => {
b(generateField(name, f));
});
b.bra("public override func mapping(map: Map)").add((b) => {
b("super.mapping(map: map)");
lodash_1.default.forIn(entity.fieldsLocal, (f, name) => {
// TODO: filter out generics ?
let realname = f.realname ?? pth.name;
b(`${pth.name} <- map["${realname}"]`);
});
});
});
}
/**
* Write enum class
*/
writeEnum(b, pth, enu) {
b.bra(`public enum ${pth.name}: String`).add((b) => {
// enu.intMap.keys.sorted().forEach {
enu.flat().forEach(({ name, item }) => {
b(`case ${name}`);
});
b("");
b.bra("public func code() -> Int").add((b) => {
b.bra("switch self").add((b) => {
enu.flat().forEach(({ name, item }) => {
b(`case .${name}: return ${item.value}`);
});
});
});
});
}
/**
* Process the project.
*/
process() {
fs_1.default.rmSync(this.rootDir, { recursive: true, force: true });
fs_1.default.mkdirSync(this.rootDir, { recursive: true });
const filePath = this.rootDir + path_1.default.sep + `${this.project.name}Entities.swift`;
const file = fs_1.default.openSync(filePath, 'w');
fs_1.default.writeFileSync(file, (0, brace_1.flatBra)("").add((b) => {
b((0, dedent_1.default) `
public class AbsBase: NSObject, Mappable {
public required init?(map: Map){}
public override required init(){}
public func mapping(map: Map){}
public func obtainExtra() -> [String:String] { return [String:String]() }
}
public class AbsReq<T: AbsRes>: AbsBase {
public func obtainPath() -> String{ return "" }
public func obtainMethod() -> String {return "" }
public func obtainRes(json: String) -> T? { return Mapper<T>().map(JSONString: json) }
public required init?(map: Map) {
super.init(map: map)
}
public required init() {
super.init()
}
public override func mapping(map: Map) {
super.mapping(map: map)
}
}
public class AbsRes: AbsBase {
public func obtainSuccessCode() -> Int { return 200 }
public required init?(map: Map) {
super.init(map: map)
}
public required init() {
super.init()
}
public override func mapping(map: Map) {
super.mapping(map: map)
}
}
`);
this.project.flatEntities().forEach(({ path, entity }) => {
this.writeEntity(b, path, entity);
});
this.project.flatEnums().forEach(({ path, enu }) => {
this.writeEnum(b, path, enu);
});
}).toString());
}
}