From b08c72f7ad1eb92ce80dec1f5d2fc875aefa64b1 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Fri, 29 Sep 2017 11:18:53 +0200 Subject: [PATCH 1/6] auto return type for accessors --- .gitignore | 1 + dub.json | 6 ++++++ src/accessors.d | 45 +++++++++++++++++++++++---------------------- test/PersonId.d | 5 +++++ test/main.d | 26 ++++++++++++++++++++++++++ 5 files changed, 61 insertions(+), 22 deletions(-) create mode 100644 test/PersonId.d create mode 100644 test/main.d diff --git a/.gitignore b/.gitignore index fa72530..310daa2 100644 --- a/.gitignore +++ b/.gitignore @@ -2,3 +2,4 @@ .dub __test__*__ /accessors-test-library +/accessors diff --git a/dub.json b/dub.json index 9634289..8396d94 100644 --- a/dub.json +++ b/dub.json @@ -11,6 +11,12 @@ "configurations": [ { "name": "library" + }, + { + "name": "unittest", + "targetType": "executable", + "sourcePaths": ["test"], + "mainSourceFile": "test/main.d" } ] } diff --git a/src/accessors.d b/src/accessors.d index 3b0a258..f61ee69 100644 --- a/src/accessors.d +++ b/src/accessors.d @@ -84,24 +84,24 @@ template GenerateReader(string name, alias field) static enum helper() { import std.string : format; - import std.traits : ForeachType, isArray, isSomeString, MutableOf; + import std.traits : isArray, isSomeString; enum visibility = getVisibility!(field, Read); - enum outputType = typeName!(typeof(field)); enum accessorName = accessor(name); static if (isArray!(typeof(field)) && !isSomeString!(typeof(field))) { - enum valueType = typeName!(MutableOf!(ForeachType!(typeof(field)))); - - return format("%s final @property inout(%s)[] %s() inout " ~ - "{ inout(%s)[] result = null; result ~= this.%s; return result; }", - visibility, valueType, accessorName, valueType, name); + return format("%s final @property auto %s() inout {" + ~ "import std.traits;" + ~ "inout(ForeachType!(typeof(this.%s)))[] result = null;" + ~ "return result ~ this.%s;" + ~ "}", + visibility, accessorName, name, name); } else { - return format("%s final @property inout(%s) %s() inout { return this.%s; }", - visibility, outputType, accessorName, name); + return format("%s final @property auto %s() inout { return this.%s; }", + visibility, accessorName, name); } } } @@ -114,12 +114,15 @@ unittest int[] intArrayValue; static assert(GenerateReader!("foo", integerValue) == - "public final @property inout(int) foo() inout { return this.foo; }"); + "public final @property auto foo() inout { return this.foo; }"); static assert(GenerateReader!("foo", stringValue) == - "public final @property inout(string) foo() inout { return this.foo; }"); + "public final @property auto foo() inout { return this.foo; }"); static assert(GenerateReader!("foo", intArrayValue) == - "public final @property inout(int)[] foo() inout " ~ - "{ inout(int)[] result = null; result ~= this.foo; return result; }"); + "public final @property auto foo() inout {" + ~ "import std.traits;" + ~ "inout(ForeachType!(typeof(this.foo)))[] result = null;" + ~ "return result ~ this.foo;" + ~ "}"); } template GenerateRefReader(string name, alias field) @@ -131,11 +134,10 @@ template GenerateRefReader(string name, alias field) import std.string : format; enum visibility = getVisibility!(field, RefRead); - enum outputType = typeName!(typeof(field)); enum accessorName = accessor(name); - return format("%s final @property ref %s %s() { return this.%s; }", - visibility, outputType, accessorName, name); + return format("%s final @property ref auto %s() { return this.%s; }", + visibility, accessorName, name); } } @@ -147,11 +149,11 @@ unittest int[] intArrayValue; static assert(GenerateRefReader!("foo", integerValue) == - "public final @property ref int foo() { return this.foo; }"); + "public final @property ref auto foo() { return this.foo; }"); static assert(GenerateRefReader!("foo", stringValue) == - "public final @property ref string foo() { return this.foo; }"); + "public final @property ref auto foo() { return this.foo; }"); static assert(GenerateRefReader!("foo", intArrayValue) == - "public final @property ref int[] foo() { return this.foo; }"); + "public final @property ref auto foo() { return this.foo; }"); } template GenerateConstReader(string name, alias field) @@ -163,11 +165,10 @@ template GenerateConstReader(string name, alias field) import std.string : format; enum visibility = getVisibility!(field, RefRead); - enum outputType = typeName!(typeof(field)); enum accessorName = accessor(name); - return format("%s final @property const(%s) %s() const { return this.%s; }", - visibility, outputType, accessorName, name); + return format("%s final @property auto %s() const { return this.%s; }", + visibility, accessorName, name); } } diff --git a/test/PersonId.d b/test/PersonId.d new file mode 100644 index 0000000..b844051 --- /dev/null +++ b/test/PersonId.d @@ -0,0 +1,5 @@ +module PersonId; + +class PersonId +{ +} diff --git a/test/main.d b/test/main.d new file mode 100644 index 0000000..a470fb8 --- /dev/null +++ b/test/main.d @@ -0,0 +1,26 @@ +import accessors; + +void main() +{ +} + +// Issue #11: https://github.com/funkwerk/accessors/issues/11 +pure nothrow @safe @nogc unittest +{ + import PersonId : AnotherPersonId = PersonId; + + class PersonId + { + } + + class Foo + { + @ConstRead + private AnotherPersonId anotherPersonId_; + + @Read + private AnotherPersonId[] personIdArray_; + + mixin(GenerateFieldAccessors); + } +} From 2c27990805f8e4c7c30f1da8ad14f956908775f6 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 4 Oct 2017 10:43:12 +0200 Subject: [PATCH 2/6] Sort unittest attributes --- test/main.d | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/main.d b/test/main.d index a470fb8..58ecbff 100644 --- a/test/main.d +++ b/test/main.d @@ -5,7 +5,7 @@ void main() } // Issue #11: https://github.com/funkwerk/accessors/issues/11 -pure nothrow @safe @nogc unittest +@nogc nothrow pure @safe unittest { import PersonId : AnotherPersonId = PersonId; From f5424b4dfe28c58eeb719d4b1c2a0f27121a47c8 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 4 Oct 2017 11:24:53 +0200 Subject: [PATCH 3/6] Specify ForeachType as imported symbol from std.traits --- src/accessors.d | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/accessors.d b/src/accessors.d index f61ee69..5068e94 100644 --- a/src/accessors.d +++ b/src/accessors.d @@ -92,7 +92,7 @@ template GenerateReader(string name, alias field) static if (isArray!(typeof(field)) && !isSomeString!(typeof(field))) { return format("%s final @property auto %s() inout {" - ~ "import std.traits;" + ~ "import std.traits : ForeachType;" ~ "inout(ForeachType!(typeof(this.%s)))[] result = null;" ~ "return result ~ this.%s;" ~ "}", @@ -119,7 +119,7 @@ unittest "public final @property auto foo() inout { return this.foo; }"); static assert(GenerateReader!("foo", intArrayValue) == "public final @property auto foo() inout {" - ~ "import std.traits;" + ~ "import std.traits : ForeachType;" ~ "inout(ForeachType!(typeof(this.foo)))[] result = null;" ~ "return result ~ this.foo;" ~ "}"); From 90b07e3e7030637c7b440d1dcf9e98eb6902480b Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Wed, 4 Oct 2017 14:21:07 +0200 Subject: [PATCH 4/6] Use "[] ~ this.%s" to avoid .dup for inout properties --- src/accessors.d | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/src/accessors.d b/src/accessors.d index 5068e94..07e8d2d 100644 --- a/src/accessors.d +++ b/src/accessors.d @@ -92,11 +92,9 @@ template GenerateReader(string name, alias field) static if (isArray!(typeof(field)) && !isSomeString!(typeof(field))) { return format("%s final @property auto %s() inout {" - ~ "import std.traits : ForeachType;" - ~ "inout(ForeachType!(typeof(this.%s)))[] result = null;" - ~ "return result ~ this.%s;" + ~ "return [] ~ this.%s;" ~ "}", - visibility, accessorName, name, name); + visibility, accessorName, name); } else { @@ -119,9 +117,7 @@ unittest "public final @property auto foo() inout { return this.foo; }"); static assert(GenerateReader!("foo", intArrayValue) == "public final @property auto foo() inout {" - ~ "import std.traits : ForeachType;" - ~ "inout(ForeachType!(typeof(this.foo)))[] result = null;" - ~ "return result ~ this.foo;" + ~ "return [] ~ this.foo;" ~ "}"); } From 2c368e6b3d44381d7444c31bc8c6a7b981b6b4e3 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 12 Oct 2017 16:34:58 +0200 Subject: [PATCH 5/6] Fix @Read returning arrays with immutable elements --- src/accessors.d | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/src/accessors.d b/src/accessors.d index 07e8d2d..e71adf0 100644 --- a/src/accessors.d +++ b/src/accessors.d @@ -91,7 +91,7 @@ template GenerateReader(string name, alias field) static if (isArray!(typeof(field)) && !isSomeString!(typeof(field))) { - return format("%s final @property auto %s() inout {" + return format("%s final @property auto %s() {" ~ "return [] ~ this.%s;" ~ "}", visibility, accessorName, name); @@ -116,7 +116,7 @@ unittest static assert(GenerateReader!("foo", stringValue) == "public final @property auto foo() inout { return this.foo; }"); static assert(GenerateReader!("foo", intArrayValue) == - "public final @property auto foo() inout {" + "public final @property auto foo() {" ~ "return [] ~ this.foo;" ~ "}"); } @@ -713,3 +713,24 @@ unittest mixin(GenerateFieldAccessors); } } + +/// @Read property returns array with mutable elements. +unittest +{ + struct Field + { + } + + struct S + { + @Read + Field[] foo_; + + mixin(GenerateFieldAccessors); + } + + with (S()) + { + Field[] arr = foo; + } +} From eef2834c3e30f8af956c73a2dcd84c0590277049 Mon Sep 17 00:00:00 2001 From: Eugen Wissner Date: Thu, 12 Oct 2017 16:36:56 +0200 Subject: [PATCH 6/6] Support dmd 2.074-2.076 --- .travis.yml | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 17a5ae7..0498ad9 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,8 +6,9 @@ os: language: d d: - - dmd-2.073.1 - - dmd-2.072.2 + - dmd-2.076.1 + - dmd-2.075.1 + - dmd-2.074.1 env: matrix: