Brightify / Cuckoo

Boilerplate-free mocking framework for Swift!
MIT License
1.67k stars 174 forks source link

Error: Expected member name or constructor call after type name #475

Closed pauluhn closed 7 months ago

pauluhn commented 1 year ago

Xcode 15

GeneratedMocks.swift is showing errors for:

return DefaultValueRegistry.defaultValue(for: (Observable<T>).self)

\\ Expected member name or constructor call after type name
\\ Use '.self' to reference the type object <Fix>

If I edit it to:

return DefaultValueRegistry.defaultValue(for: Observable.self)

the error goes away.

If I fix the errors in the generated file and skip the Cuckoo script phase, I am able to compile and run unit tests in both Xcode 15 and Xcode 14.3.1

fraune commented 1 year ago

I also have noticed the same issue when upgrading my project today

MatyasKriz commented 1 year ago

Hey, thanks for reporting this. I don't have Xcode 15 installed yet, but I'll update and try fixing this.

MatyasKriz commented 1 year ago

I tried just removing the parentheses and that will unfortunately not work, they are required for closure types. Does (Observable).self work or not?

fraune commented 1 year ago

Here is an excerpt of a file Cuckoo generated for me today. Xcode 15.0/RxSwift 6.5.

In my case (Observable).self does not work.

Screenshot 2023-09-28 at 4 58 38 PM
MatyasKriz commented 1 year ago

I see, thanks for the info. I wonder why they broke that functionality.

This is then unfortunately also blocked by the current flawed type implementation. I'll see what I can do.

fraune commented 1 year ago

I don't know if it will help because I didn't yet try updating all my failing types with it, but the compiler seems happy when I change the line in my example to either:

return DefaultValueRegistry.defaultValue(for: (Observable<BluetoothState>.self))
return DefaultValueRegistry.defaultValue(for: (Observable<BluetoothState>.self).self)
bnandhinidevi commented 1 year ago

I tried the above solution but cannot edit GeneratedMocks.swift.

when it's rebuilt, the changes go off. unable to execute unit tests because of this issue

fraune commented 1 year ago

I did not intent to suggest that manually editing GeneratedMocks would be a suitable workaround.

MatyasKriz commented 1 year ago

Good news is that over the weekend I managed to find the time to implement a new type system using the SwiftSyntax structure, so it should also be more rigid.

I haven't gotten around to creating a project with new Swift version to find out what exact changes I need to do.

fraune commented 1 year ago

Awesome. If it helps, I created a new repo for reproducing the issue, with Cuckoo and RxSwift 6.6. This gives passing tests in Xcode 14, and the type error in Xcode 15. git@github.com:fraune/CuckooSwiftTest.git

(Using this method to run both Xcodes next to each other. https://stackoverflow.com/a/74500488/13944515)

MatyasKriz commented 1 year ago

That's great, thank you! 🙂 I should be able to look at fixing this today.

MatyasKriz commented 1 year ago

Awesome. If it helps, I created a new repo for reproducing the issue, with Cuckoo and RxSwift 6.6. This gives passing tests in Xcode 14, and the type error in Xcode 15. git@github.com:fraune/CuckooSwiftTest.git

I'd very much like to know why this only occurs with Observable from RxSwift, at least that we have here. I've been trying (and failing) to reproduce this error with any other generic type, including protocols with primary associated type.

Another issue I've found is that simply removing parentheses works for just Observable<T>, but for closure () -> Observable<T> I wasn't able to get it working (and it requires parentheses as a closure).

However, I've found a workaround that seems to fix the main issue along with this edge-case while keeping the default value registry working as intended. It will require generating a private typealias above each property with the type it uses, then TypealiasName.self works every time for all types that I've tried.

I'll implement the full workaround into Cuckoo 2.0; but since this seems like a blocker, I'll release a new 1.x version with a simple workaround by using the type without parentheses if it's not a closure, probably tomorrow.

MatyasKriz commented 1 year ago

@fraune I've actually used the idea with the typealias for the 1.x version as well as it's easier to do. There's a branch fix/swift-5.9-type that contains the changes, could you please test it out with RxSwift? As I've mentioned, I haven't seen it have problems with any other generic type.

fraune commented 1 year ago

I love that idea. Do I need to do anything special to download the cuckoo_generator file for a branch that isn't tagged?

function download_generator seems to want to download either the latest release or a specified tag.

MatyasKriz commented 1 year ago

Oh, right. The generator needs to be built in this case. Downloading is done through GitHub releases only. It should be available for download in this comment.

cuckoo_generator.zip

EDIT: I've tried to run this generator with the sample project and it compiles! 😁

fraune commented 1 year ago

Thanks for providing that. It looks like a huge reduction in the errors that are showing up in my team's project.

I still have a handful of errors remaining — I'm working to reproduce them in the test project, since I am unable to share team code. I'll hopefully have a better test project for you tomorrow.

fraune commented 1 year ago

I've oddly had a difficult time reproducing my remaining errors in the test project, but I'll give an update on where I've gotten with it.

It appears the only remaining errors in my team project are specifically with the RxSwift Observable type. Interestingly, RxSwift's Single and Completable, types work just fine.

Screenshot 2023-10-06 at 12 28 19 AM Screenshot 2023-10-06 at 12 28 37 AM

I don't know enough about Swift types, or how Cuckoo picks them up, but it looks like something is going on with elements that get type-erased, like Observable. https://github.com/ReactiveX/RxSwift/blob/473b7a7180df6ff58925a5bd1ed039bccdc35250/RxSwift/Observable.swift

I'll see if any fresh ideas come overnight, or perhaps the weekend.

MatyasKriz commented 1 year ago

I'm stumped as well, Observable seems to be an ordinary type, but its behavior is anything but.

@TadeasKriz have you ever encountered this? If you have a suggestion, that'd be great!

TadeasKriz commented 1 year ago

Is this Xcode 15? I think Observable is now a macro for SwiftUI, so maybe try RxSwift.Observable<IBluetoothPeripheral>, that might work.

fraune commented 1 year ago

@TadeasKriz That was it! Tricky, because when I use Xcode to click into the Observable it would take me to RxSwift's type.

After updating my protocols to use RxSwift.Observable over Observable, my remaining project errors have been resolved.

fraune commented 1 year ago

Hi – not trying to sound pushy, but is there an approximate timeline for this work to be released? Thanks!

MatyasKriz commented 1 year ago

Hey, changing the types to RxSwift.Observable didn't make all the errors related to it go away? The change that's in the pipeline is just the typealias we discussed, I can't add RxSwift. in the generator automatically as the parser has no clue nor does it care where the Observable comes from.

fraune commented 1 year ago

Good question. I meant to double check that.

fraune commented 1 year ago

It looks like you're correct. Although your update on that branch fixed many of the errors in my project, I was able to get it all working with the current Cuckoo version by explicitly renaming the remaining Observable uses.

pauluhn commented 1 year ago

Haven't had a chance to revisit this until now. 😅

Based on all the comments, I added RxSwift. to all the Observables in GeneratedMocks.swift and it does make all the previous errors go away.

So I'm not sure how to resolve this on the generator side, but I've resolved it for my project by adding a Run Script Phase with the following:

sed -i '' -e 's/Observable/RxSwift.Observable/g' <path to GeneratedMocks.swift>

Will leave Foundation.Observable vs RxSwift.Observable debate for another time.

chirag05k commented 1 year ago

Issue Description:

Environment Details:

  1. Xcode Version: 15.0
  2. Pod Configuration:
    
    target 'CoreTests' do
    inherit! :search_paths
    pod 'Cuckoo', :git => 'https://github.com/Brightify/Cuckoo.git', :branch => 'fix/swift-5.9-type'
    pod 'RxBlocking', '~> 6.0'
    pod 'RxTest', '~> 6.0'
    pod 'Quick', '6.0.1'
    pod 'Nimble', '13.0.0'
    end
    end

post_install do |pi| pi.pods_project.targets.each do |t| t.build_configurations.each do |config| config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '13.0' end end end


 3. macOS Version: Sonoma
 4. macOS Version Number: 14.0 (23A344)
 5. Machine: Apple M1

CC: @MatyasKriz @TadeasKriz @fraune @pauluhn 

**Build Phase Reference** 

![Screenshot 2023-10-22 at 3 58 03 PM](https://github.com/Brightify/Cuckoo/assets/89680122/58976726-b64e-4056-8ac5-97f2453a97b2)
![Screenshot 2023-10-22 at 3 58 39 PM](https://github.com/Brightify/Cuckoo/assets/89680122/5f920c43-2b1b-4229-b9e6-ff64ccac456d)

**Xcode test case failed reference** 

![Screenshot 2023-10-22 at 3 59 43 PM](https://github.com/Brightify/Cuckoo/assets/89680122/460685bf-a41b-4b3f-8d5b-9a47918b9b46)
![Screenshot 2023-10-22 at 4 00 06 PM](https://github.com/Brightify/Cuckoo/assets/89680122/3e839f35-ac5c-4785-8b80-c73e4255d184)
fraune commented 1 year ago

@chirag05k If your case is like mine, you don't need to use a special branch of Cuckoo. Try renaming Observable to RxSwift.Observable in the class you're mocking out (e.g. rename your startSession method's return type).

Swift 5.9 added a new Observable type that now shadows RxSwift's Observable.

MatyasKriz commented 7 months ago

Nothing we can do about this unfortunately AFAIK, closing.