diff --git a/.gitignore b/.gitignore index 4d40434..1a6e326 100644 --- a/.gitignore +++ b/.gitignore @@ -21,3 +21,8 @@ *.i*86 *.x86_64 *.hex + +# DUB +.dub +inifiled-test-library +test/filenameTmp.ini diff --git a/.travis.yml b/.travis.yml index 9b21265..27c5e9a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,16 +2,14 @@ language: d sudo: false d: + - dmd-nightly + - dmd-beta - dmd + - ldc-beta - ldc - - dmd-2.069.0 - - dmd-2.070.2 - - dmd-2.071.2 - dmd-2.072.2 - dmd-2.073.2 - - dmd-2.074.0 - - ldc-1.0.0 - - ldc-1.1.1 + - dmd-2.074.1 script: - dub test diff --git a/source/inifiled.d b/source/inifiled.d index 12153e2..84ac6b8 100644 --- a/source/inifiled.d +++ b/source/inifiled.d @@ -173,8 +173,9 @@ unittest { string buildSectionParse(T)() @safe { import std.traits : hasUDA, fullyQualifiedName, isBasicType, isSomeString, isArray; + import std.array : join; import std.format : format; - string ret = "switch(getSection(line)) { // " ~ fullyQualifiedName!T ~ "\n"; + string[] ret; foreach(it; __traits(allMembers, T)) { if(hasUDA!(__traits(getMember, T, it), INI) @@ -183,14 +184,20 @@ string buildSectionParse(T)() @safe { && !isArray!(typeof(__traits(getMember, T, it)))) { ret ~= ("case \"%s\": { line = readINIFileImpl" ~ - "(t.%s, input, deaph+1); goto repeatL; }\n"). + "(t.%s, input, deaph+1); } "). format(fullyQualifiedName!(typeof(__traits(getMember, T, it))), it ); } } - return ret ~ "default: return line;\n}\n"; + // Avoid DMD switch fallthrough warnings + if (ret.length) { + return "switch(getSection(line)) { // " ~ fullyQualifiedName!T ~ "\n" ~ + ret.join("goto case; \n") ~ "goto default;\n default: return line;\n}\n"; + } else { + return "return line;"; + } } string buildValueParse(T)() @safe { @@ -234,7 +241,6 @@ string readINIFileImpl(T,IRange)(ref T t, ref IRange input, int deaph = 0) line = input.front().idup; input.popFront(); - repeatL: if(line.startsWith(";")) { continue; } @@ -511,12 +517,12 @@ unittest { p.dog.kg = 3.14; Person p2; - readINIFile(p2, "filename.ini"); + readINIFile(p2, "test/filename.ini"); writefln("\n%s\n", p2); - writeINIFile(p2, "filenameTmp.ini"); + writeINIFile(p2, "test/filenameTmp.ini"); Person p3; - readINIFile(p3, "filenameTmp.ini"); + readINIFile(p3, "test/filenameTmp.ini"); if(p2 != p3) { writefln("\n%s\n%s", p2, p3); @@ -537,3 +543,37 @@ unittest { assert(false); } } + +version(unittest) { + enum Check : string { disabled = "disabled"} + + @INI + struct StaticAnalysisConfig { + @INI + string style_check = Check.disabled; + + @INI + ModuleFilters filters; + } + + private template ModuleFiltersMixin(A) { + const string ModuleFiltersMixin = () { + string s; + foreach (mem; __traits(allMembers, StaticAnalysisConfig)) + static if (is(typeof(__traits(getMember, StaticAnalysisConfig, mem)) == string)) + s ~= `@INI string[] ` ~ mem ~ ";\n"; + + return s; + }(); + } + + @INI + struct ModuleFilters { mixin(ModuleFiltersMixin!int); } +} + +unittest { + StaticAnalysisConfig config; + readINIFile(config, "test/dscanner.ini"); + assert(config.style_check == "disabled"); + assert(config.filters.style_check == ["+std.algorithm"]); +} diff --git a/test/dscanner.ini b/test/dscanner.ini new file mode 100644 index 0000000..d0a04d5 --- /dev/null +++ b/test/dscanner.ini @@ -0,0 +1,4 @@ +[inifiled.StaticAnalysisConfig] +style_check="disabled" +[inifiled.ModuleFilters] +style_check = "+std.algorithm" diff --git a/filename.ini b/test/filename.ini similarity index 100% rename from filename.ini rename to test/filename.ini