krzysztofzablocki / Sourcery

Meta-programming for Swift, stop writing boilerplate code.
http://merowing.info
MIT License
7.68k stars 618 forks source link

Annotations not parsed when running Sourcery with the same template but different output files #1357

Open alexdmotoc opened 3 months ago

alexdmotoc commented 3 months ago

Hi!

I have a setup where I have one AutoMockable.stencil file that I use as template for 2 configurations. One configuration outputs in a file in the unit tests target, and one in the App target.

I use this to generate mocks for SwiftUI previews and also have them for unit tests.

Another note is, I use 2 // sourcery: AutoMockable annotations:

I also have some custom flags configured in the .sourcery.yml to be able to differentiate which configuration is run (the unit tests or app) in order to customize the resulting mocks.

Finally, the super-weird part is that some times it works, but if I run sourcery multiple times consecutively, it breaks and doesn't find the annotations in one of the configurations

My .sourcery.yml looks like this

configurations:
  - sources: 
      - Sources/
    templates:
      - /Stencils/AutoMockable.stencil
    output: Tests/Mocks/GeneratedMocks.swift
    args:
      isTestTargetMocks: true
      autoMockableImports: [
        "Combine",
      ]
      autoMockableTestableImports: [
        "MyApp"
      ]
  - sources: 
      - Sources/
    templates:
      - /Stencils/AutoMockable.stencil
    output: MyApp/Core/Generators/GeneratedBuilders.swift
    args:
      isAppTargetMocks: true
      autoMockableImports: [
        "Combine",
      ]

The AutoMockable.stencil is the same like the template one on this repo, just modified it a bit to not generate CalledCount, etc for the App target mocks.

Mocked protocol looks like this

// sourcery: AutoMockable
// sourcery: AutoMockableApp
protocol ArticlePagedLoaderType: ObservableObject {
    var articles: [Article] { get }
    var isLoading: Bool { get }
}

Attached photos of the output in the App target

Any ideas what could be the problem?

Screenshot 2024-08-10 at 21 39 13 Screenshot 2024-08-10 at 21 39 33

alexdmotoc commented 3 months ago

I investigated a bit, and it turns out you can reproduce it quite easily. The setup is:

protocol SomeTypeUsingGenericConstraint: AutoMockable {
    associatedtype MyGenericConstraint: SomeTypeToBeUsedAsGenericConstraint
}

protocol SomeTypeToBeUsedAsGenericConstraint: AutoMockable {
    func doStuff()
}

You just need to run sourcery multiple times, one after the other. I tried with --disableCache but it still fails. SomeTypeToBeUsedAsGenericConstraint is not generated anymore, only SomeTypeUsingGenericConstraint

We have sourcery as a pre-build phase (don't ask why, it was there when I found it 😸 ) and since we're working with SwiftUI and Previews, you can imagine sourcery is called quite often when the previews are built.

Would appreciate any insight on this.