diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml new file mode 100644 index 0000000..dcad521 --- /dev/null +++ b/.github/workflows/tests.yml @@ -0,0 +1,37 @@ +# This workflow uses actions that are not certified by GitHub. +# They are provided by a third-party and are governed by +# separate terms of service, privacy policy, and support +# documentation. +name: Unit Tests + +on: + push: + branches: [ "main" ] + +permissions: + contents: read + +jobs: + test: + name: 'Build & Test' + strategy: + matrix: + os: [macOS-latest] + arch: [x86_64, arm64] + dc: [ldc-beta, dmd-master] + build: [debug, release] + exclude: + - { dc: dmd-master, arch: arm64 } + + runs-on: ${{ matrix.os }} + steps: + - uses: actions/checkout@v4 + + - name: Install compiler + uses: dlang-community/setup-dlang@v1.4.0 + with: + compiler: ${{ matrix.dc }} + + - name: 'Build and test with ${{ matrix.os }} ${{ matrix.dc }} (${{ matrix.build }})' + run: | + dub test --config=unittest --build=${{ matrix.build }} \ No newline at end of file diff --git a/dub.sdl b/dub.sdl index b9a2744..4f34012 100644 --- a/dub.sdl +++ b/dub.sdl @@ -16,6 +16,13 @@ configuration "static" { lflags "-framework" "Foundation" "-all_load" } +configuration "unittest" { + platforms "osx" + + lflags "-framework" "Foundation" "-all_load" + dependency "silly" version="~>1.0" +} + # For platforms that don't support it. configuration "other_platforms" { targetType "none" diff --git a/source/foundation/nsarray.d b/source/foundation/nsarray.d index 43a54b9..12d9461 100644 --- a/source/foundation/nsarray.d +++ b/source/foundation/nsarray.d @@ -19,6 +19,9 @@ import core.attribute : selector, optional; private alias iter_func(T) = int delegate(T); private alias iter_i_func(T) = int delegate(size_t, T); +nothrow @nogc: +version(D_ObjectiveC): + /** A static ordered collection of objects. */ @@ -32,27 +35,31 @@ public: /** Creates and returns an empty array. */ - static NSArray!T array() @selector("array"); + static NSArray!T create() @selector("array"); /** Creates and returns an array containing the objects in another given array. */ - static NSArray!T array(ref NSArray!T array) @selector("arrayWithArray:"); + static NSArray!T create(ref NSArray!T array) @selector("arrayWithArray:"); /** Creates and returns an array containing a given object. */ - static NSArray!T array(T object) @selector("arrayWithObject:"); + static NSArray!T create(T object) @selector("arrayWithObject:"); /** Creates and returns an array containing the objects in the argument list. */ - static NSArray!T array(T firstObject, ...) @selector("arrayWithObjects:"); + static NSArray!T create(T* objects, NSUInteger count) @selector("arrayWithObjects:count:"); /** - Creates and returns an array containing the objects in the argument list. + Allows creating NSArrays from a D slice. */ - static NSArray!T array(T* objects, NSUInteger count) @selector("arrayWithObjects:count:"); + extern(D) + final // @suppress(dscanner.useless.final) + static NSArray!T create(T[] objects) { + return typeof(this).create(objects.ptr, objects.length); + } /** Allocates a new NSArray @@ -159,6 +166,7 @@ public: final int opApply(scope iter_func!T dg) { auto ngc_dg = assumeNothrowNoGC!(iter_func!T)(dg); + foreach (i; 0..length) { int result = ngc_dg(this[i]); if (result) @@ -224,12 +232,6 @@ public: alias opDollar = length; } -unittest { - NSString myString = NSString.alloc.init(""); - NSArray!NSString myArray = NSArray!(NSString).array(); - -} - /** A Mutable NSArray */ @@ -312,4 +314,38 @@ public: void opIndexAssign(DRTBindable value, size_t index) { this.message!void("insertObject:atIndex:", value, index); } +} + +@("NSArray: multiple template instantiation") +unittest { + NSArray!NSObject objarray; + NSArray!NSString strarray; +} + +@("NSArray: create and index") +unittest { + NSString myString = NSString.create("A"); + NSString myString2 = NSString.create("B"); + NSString[2] darray = [myString, myString2]; + + auto myArray = NSArray!(NSString).create(darray); + + foreach(i; 0..myArray.length) { + assert(myArray[i].isEqual(darray[i])); + } +} + +@("NSArray: foreach") +unittest { + NSString myString = NSString.create("A"); + NSString myString2 = NSString.create("B"); + NSString[2] darray = [myString, myString2]; + + auto myArray = NSArray!(NSString).create(darray); + + foreach(item; myArray) + assert(item !is null); + + foreach_reverse(item; myArray) + assert(item !is null); } \ No newline at end of file diff --git a/source/foundation/nsbundle.d b/source/foundation/nsbundle.d index 2de6c42..f20ff2d 100644 --- a/source/foundation/nsbundle.d +++ b/source/foundation/nsbundle.d @@ -15,8 +15,8 @@ import objc; import core.attribute : selector, optional; - nothrow @nogc: +version(D_ObjectiveC): /** Constants that describe the CPU types that a bundle’s executable code supports. diff --git a/source/foundation/nscoder.d b/source/foundation/nscoder.d index af29b0f..7fb857c 100644 --- a/source/foundation/nscoder.d +++ b/source/foundation/nscoder.d @@ -15,6 +15,9 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** A protocol that enables an object to be encoded and decoded for archiving and distribution. diff --git a/source/foundation/nsdictionary.d b/source/foundation/nsdictionary.d index f66ca3b..7847a1d 100644 --- a/source/foundation/nsdictionary.d +++ b/source/foundation/nsdictionary.d @@ -15,6 +15,8 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): /** NSDictionary diff --git a/source/foundation/nsenumerator.d b/source/foundation/nsenumerator.d index f002baf..a5d728c 100644 --- a/source/foundation/nsenumerator.d +++ b/source/foundation/nsenumerator.d @@ -14,9 +14,11 @@ import foundation; import objc; import core.attribute : selector, optional; - import core.stdc.config : c_ulong; +nothrow @nogc: +version(D_ObjectiveC): + /** This defines the structure used as contextual information in the NSFastEnumeration protocol. diff --git a/source/foundation/nserror.d b/source/foundation/nserror.d index ca0d66d..69f3871 100644 --- a/source/foundation/nserror.d +++ b/source/foundation/nserror.d @@ -15,6 +15,9 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** An error domain */ diff --git a/source/foundation/nsobject.d b/source/foundation/nsobject.d index eb35dad..d19b347 100644 --- a/source/foundation/nsobject.d +++ b/source/foundation/nsobject.d @@ -15,6 +15,9 @@ import objc.basetypes; import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** Base class of all Objective-C classes. */ @@ -269,4 +272,5 @@ auto ref inout(T) released(T)(auto ref inout(T) value) if (isObjcClassInstance!T auto ref inout(T) autoreleased(T)(auto ref inout(T) value) if (isObjcClassInstance!T) { (cast(T)value).autorelease(); return value; -} \ No newline at end of file +} + diff --git a/source/foundation/nsproto.d b/source/foundation/nsproto.d index b06b0aa..0df5f05 100644 --- a/source/foundation/nsproto.d +++ b/source/foundation/nsproto.d @@ -13,8 +13,12 @@ module foundation.nsproto; import foundation; import objc.basetypes; import objc.rt; + import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** The base protocol all Objective-C protocols should follow. */ diff --git a/source/foundation/nsset.d b/source/foundation/nsset.d index 17ec2f9..754f81f 100644 --- a/source/foundation/nsset.d +++ b/source/foundation/nsset.d @@ -11,4 +11,9 @@ */ module foundation.nsset; import foundation; -import objc; \ No newline at end of file +import objc; + + + +nothrow @nogc: +version(D_ObjectiveC): diff --git a/source/foundation/nsstring.d b/source/foundation/nsstring.d index 339f71a..f6c41a8 100644 --- a/source/foundation/nsstring.d +++ b/source/foundation/nsstring.d @@ -16,6 +16,9 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** The following constants are provided by NSString as possible string encodings. @@ -639,7 +642,8 @@ public: Converts to a D string. */ extern(D) - final string toString() { + final // @suppress(dscanner.useless.final) + string toString() { return cast(string)ptr[0..length]; } } diff --git a/source/foundation/nsurl.d b/source/foundation/nsurl.d index 5fe0c6e..5be467a 100644 --- a/source/foundation/nsurl.d +++ b/source/foundation/nsurl.d @@ -15,6 +15,9 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** An object that represents the location of a resource, such as an item on a remote server or the path to a local file. diff --git a/source/foundation/nsvalue.d b/source/foundation/nsvalue.d index 5d97328..ef78044 100644 --- a/source/foundation/nsvalue.d +++ b/source/foundation/nsvalue.d @@ -15,6 +15,9 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** A simple container for a single C or Objective-C data item. */ @@ -208,12 +211,4 @@ public: Gets whether this number is equal to another. */ bool isEqual(NSNumber other) @selector("isEqualToNumber:"); - - /** - Implements equality comparison - */ - extern(D) - bool opEquals(T)(T other) if (is(T : NSNumber)) { - return this.isEqual(other.self_); - } } \ No newline at end of file diff --git a/source/foundation/nszone.d b/source/foundation/nszone.d index 87f6fd7..ef17e67 100644 --- a/source/foundation/nszone.d +++ b/source/foundation/nszone.d @@ -15,6 +15,9 @@ import objc; import core.attribute : selector, optional; +nothrow @nogc: +version(D_ObjectiveC): + /** A protocol that objects adopt to provide functional copies of themselves. */