Skip to content

Commit

Permalink
getting better
Browse files Browse the repository at this point in the history
  • Loading branch information
burner committed Jan 6, 2024
1 parent aaa62b9 commit 6e8119b
Show file tree
Hide file tree
Showing 62 changed files with 35,392 additions and 211,752 deletions.
23 changes: 22 additions & 1 deletion fakerjs2generator/source/app.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,19 +2,40 @@ import std.stdio;
import std.algorithm.iteration : filter;
import std.file : dirEntries, SpanMode, readText;
import std.string : lastIndexOf;
import std.uni : toLower;
import std.format;
import std.json;

import parser;
import defis;
import generator;

void buildBase() {
string en = "en.json";
JSONValue jv = parseJSON(readText(en));
JsonFile jf = parseJson!(JsonFile)(jv, [en]);
backFillMergeArray(jf);
string langName = en[0 .. $ - 5];
auto f = File("../source/faked/base.d", "w");
genTopMatter(jf, f.lockingTextWriter(), "en", true);
generate(jf.data, f.lockingTextWriter(), [], true);
f.writeln("}");
}

void main() {
buildBase();
foreach(j; dirEntries("", "*.json", SpanMode.shallow)
.filter!(it => it.name != "dub.json"))
.filter!(it => it.name != "dub.json")
.filter!(it => it.name != "en.json"))
{
writeln(j.name);
JSONValue jv = parseJSON(readText(j.name));
JsonFile jf = parseJson!(JsonFile)(jv, [j.name]);
backFillMergeArray(jf);
string langName = j.name[0 .. $ - 5];
auto f = File(format("../source/faked/faker_%s.d", langName.toLower()), "w");
genTopMatter(jf, f.lockingTextWriter(), langName, false);
generate(jf.data, f.lockingTextWriter(), [], false);
f.writeln("}");
}
}
124 changes: 88 additions & 36 deletions fakerjs2generator/source/generator.d
Original file line number Diff line number Diff line change
Expand Up @@ -5,63 +5,124 @@ import std.algorithm.iteration : filter;
import std.algorithm.searching : endsWith;
import std.exception : enforce;
import std.conv : to;
import std.uni : toUpper;
import std.format : formattedWrite;
import std.uni : toUpper , toLower;
import std.format : format, formattedWrite;
import std.range : empty;
import std.traits : FieldNameTuple;
import std.typecons : Nullable;
import std.stdio;
import std.sumtype;

import helper;
import defis;

void generate(Language lang, string langName) {
void generate(Language lang, string langName, const bool base) {
auto app = appender!string();
traverse(lang, app, []);
traverse(lang, app, [], base);
writeln(app.data);
writeln("\n\n\n");
}

void traverse(T,Out)(T t, ref Out o, string[] path) {
static if(T.stringof.endsWith("Folder") || is(T == Language)) {
void generate(Out)(Language lang, auto ref Out o, string[] path, const bool base) {
traverse(lang, o, path, base);
}

void traverse(T,Out)(T t, ref Out o, string[] path, const bool base) {
static if(T.stringof.endsWith("Folder")
|| is(T == Language)
|| is(T == Product_Name)
|| is(T == DateWeekday)
|| is(T == Title)
|| is(T == DateMonth))
{
static foreach(string mem; [FieldNameTuple!(T)].filter!(m => !m.empty)) {{
traverse(__traits(getMember, t, mem), o, path ~ mem);
traverse(__traits(getMember, t, mem), o, path ~ mem, base);
}}
} else static if(is(T == Nullable!F, F)) {
if(!t.isNull()) {
traverse(t.get(), o, path, base);
}
} else {
static if(is(T == string[])) {
genStringArray(t, o, path);
genStringArray(t, o, path, base);
formattedWrite(o, "\n\n");
} else static if(is(T == Mustache[])) {
genMustache(t, o, path, base);
formattedWrite(o, "\n\n");
} else static if(is(T == Number[])) {
//genNumberArray(t, o, path);
} else static if(is(T == ForwardToOther)) {
writeln("ForwardToOther");
genForwardToOther(t, o, path);
} else static if(is(T == SumType!(TT), TT...)) {
writeln("SumType");
enum m = buildForwarder!(TT);
mixin(m);
} else {
writefln("Unhandled %s", T.stringof);
}
}
}

void genForwardToOther(Out)(ForwardToOther fto, ref Out o, string[] path) {
iformat(o, 1, "string %s() {\n", pathToFuncName(path));
iformat(o, 2, "return %s();\n", fto.fwd);
iformat(o, 1, "}\n", fto.fwd);
void genTopMatter(Out)(ref JsonFile jf, auto ref Out o, const string language, const bool base) {
if(base) {
iformat(o, 0, `module faker.base;
import std.random;
import std.array;
import std.format;
import std.conv : to;
import std.string : toUpper;
import std.range : iota, take, repeat;
import std.algorithm : map, joiner;
class Faker {
@safe:
Random rnd;
this(int seed) {
this.rnd = Random(seed);
}
`);
} else {
string chain = jf.chain.length == 1 ? "en" : jf.chain[0];
chain = chain == "en"
? "Faker"
: "Faker_" ~ chain.toLower();
iformat(o, 0, `module faker.faker_%1$s;
import std.random;
import std.array;
import std.format;
import std.conv : to;
import std.string : toUpper;
import std.range : iota, take, repeat;
import std.algorithm : map, joiner;
import faker.base;%3$s
class Faker_%1$s : %2$s {
@safe:
this(int seed) {
super(seed);
}
`, language.toLower(), chain
, chain != "Faker" ? "\nimport faker.faker_%s;".format(jf.chain[0].toLower()) : "");
}
}

void genStringArray(Out)(string[] strs, ref Out o, string[] path) {
iformat(o, 1, "string %s() {\n", pathToFuncName(path));
void genStringArray(Out)(string[] strs, ref Out o, string[] path, const bool base) {
iformat(o, 1, "%sstring %s() {\n", base ? "" : "override ", pathToFuncName(path));
iformat(o, 2, "const string[] strs =\n\t\t[ ");
str80(o, strs, 2);
o.put(" ];\n\n");
iformat(o, 2, "return choice(strs, this.rnd);\n\t}\n");
iformat(o, 2, "return choice(strs, this.rnd);\n\t}");
}

void genMustache(Out)(Mustache[] m, ref Out o, string[] path, const bool base) {
iformat(o, 1, "%sstring %s() {\n", base ? "" : "override ", pathToFuncName(path));
iformat(o, 2, "assert(false);\n\t}");
}

string pathToFuncName(string[] path) {
enforce(path.length > 1, to!string(path));
string ret = path[0];
foreach(it; path[1 .. $]) {
char up = to!char(it[0].toUpper());
string ta = up ~ it[1 .. $];
string ta = up ~ it[1 .. $].camelCase();
ret ~= ta;
}
return ret;
Expand All @@ -84,9 +145,9 @@ void str80(Out)(ref Out o, string[] strs, size_t tabs) {
o.put(", ");
curLength += 2;
}
o.put('"');
o.put("q\"{");
o.put(s);
o.put('"');
o.put("}\"");
curLength += s.length + 2;
++curStrCount;
} else {
Expand All @@ -102,19 +163,10 @@ void str80(Out)(ref Out o, string[] strs, size_t tabs) {
o.put(", ");
curLength += 2;
}
o.put('"');
o.put("q\"{");
o.put(s);
o.put('"');
o.put("}\"");
curLength += s.length + 2;
}
}
}

string buildForwarder(TT...)() {
string ret = "t.match!(";
static foreach(T; TT) {
ret ~= "\n\t(" ~ T.stringof ~ " h) { writefln(\"\\tMatch %s\", `" ~ T.stringof ~ "`); traverse(h, o, path); }, ";
}
ret ~= "\n);\n";
return ret;
}
22 changes: 21 additions & 1 deletion fakerjs2generator/source/helper.d
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
module helper;

import std.algorithm.searching : endsWith, startsWith;
import std.algorithm.searching : canFind, endsWith, startsWith;
import std.algorithm.iteration : filter, joiner, map, splitter;
import std.file : exists, readText;
import std.stdio;
Expand Down Expand Up @@ -80,3 +80,23 @@ string stripTrailingUnderscore(string s) {
? s[0 .. $ - 1]
: s;
}

string camelCase(const string input, dchar[] separaters = ['_']) {
string output;
bool upcaseNext = false;
foreach(c; input) {
if (!separaters.canFind(c)) {
if (upcaseNext) {
output ~= c.toUpper;
upcaseNext = false;
}
else
output ~= c.toLower;
}
else {
upcaseNext = true;
}
}

return output;
}
35 changes: 24 additions & 11 deletions fakerjs2generator/source/parser.d
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ module parser;

import std.array : array;
import std.ascii : isAlphaNum;
import std.algorithm.searching : all, endsWith, startsWith;
import std.algorithm.searching : all, canFind, endsWith, startsWith;
import std.algorithm.iteration : filter, joiner, map, splitter;
import std.exception : enforce;
import std.conv : to;
Expand All @@ -13,7 +13,7 @@ import std.string : strip;
import std.stdio;
import std.typecons : Nullable, nullable;
import std.traits : FieldNameTuple, isArray, isIntegral, isSomeString;
import std.uni : toLower;
import std.uni : toLower, isControl;
import std.utf : byDchar;
import std.sumtype;
import std.json;
Expand All @@ -32,42 +32,36 @@ void backFillMergeArray(ref JsonFile l) {
if(l.data.person.isNull()) {
l.data.person = PersonFolder.init;
}
writeln("first_name");
l.data.person.get().first_name = l.first_name.get();
}
if(!l.last_name.isNull()) {
if(l.data.person.isNull()) {
l.data.person = PersonFolder.init;
}
writeln("last_name");
l.data.person.get().last_name = l.last_name.get();
}
if(!l.prefix.isNull()) {
if(l.data.person.isNull()) {
l.data.person = PersonFolder.init;
}
writeln("prefix");
l.data.person.get().prefix = l.prefix.get();
}
if(!l.female_middle_name.isNull()) {
if(l.data.person.isNull()) {
l.data.person = PersonFolder.init;
}
writeln("female_middle_name");
l.data.person.get().female_middle_name = l.female_middle_name.get();
}
if(!l.male_middle_name.isNull()) {
if(l.data.person.isNull()) {
l.data.person = PersonFolder.init;
}
writeln("male_middle_name");
l.data.person.get().male_middle_name = l.male_middle_name.get();
}
if(!l.county.isNull()) {
if(l.data.location.isNull()) {
l.data.location = LocationFolder.init;
}
writeln("county");
l.data.location.get().county = l.county.get();
}
}
Expand All @@ -76,14 +70,33 @@ T parseJson(T)(JSONValue jv) {
return parseJson!(T)(jv, []);
}

private bool containsControlCharacter(string s) {
dchar[] cs = [ '\u061C', '\u200E', '\u200F', '\u202A', '\u202B'
, '\u202C','\u202D', '\u202E', '\u2066', '\u2067', '\u2068', '\u2069'
];
foreach(dchar c; s) {
if(isControl(c) || canFind(cs, c)) {
return true;
}
}
return false;
}

private T parseJson(T)(JSONValue jv, string[] path) {
static if(isArray!T && !isSomeString!T) {
enforce(jv.type == JSONType.array, format("Got '%s' wanted array in %s type %s"
, jv, path, jv.type));
alias EET = ElementEncodingType!T;
return jv.arrayNoRef()
.map!(it => parseJson!(EET)(it, path))
.array;
static if(is(EET == string)) {
return jv.arrayNoRef()
.map!(it => parseJson!(EET)(it, path))
.filter!(s => !containsControlCharacter(s))
.array;
} else {
return jv.arrayNoRef()
.map!(it => parseJson!(EET)(it, path))
.array;
}
} else static if(is(T == Nullable!F, F)) {
return jv.type == JSONType.null_
? T.init
Expand Down
Loading

0 comments on commit 6e8119b

Please sign in to comment.