Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement helper macro to reduce boilerplate in Type implementation #8

Open
stackotter opened this issue Oct 10, 2023 · 4 comments
Open
Labels
enhancement New feature or request hacktoberfest

Comments

@stackotter
Copy link
Owner

The Type enum has two computed properties specifically for extracting certain cases: asSimpleType and asFunctionType. To implement such properties for all cases would require a lot of boilerplate code, and considering that similar properties will eventually need to be implemented for many other enums in the code base, I think it would be best to create a MacroToolkitHelperMacros target with a macro designed to automatically generate these computed properties for enums. Somewhat ironically, the macro won't be able to use the toolkit because it'll be used to implement the toolkit 😅

The macro should be an attached member macro which works something like this; (just throw an error if any of the enum cases don't have exactly one associated value)

input.swift

@CaseAccessors // Feel free to come up with a better name
enum Type {
    case simpleType(SimpleType)
    case functionType(FunctionType)
    // ...
}

expanded.swift

enum Type {
    case simpleType(SimpleType)
    case functionType(FunctionType)
    // ...
    
    var asSimpleType: SimpleType? {
        switch self {
            case let .simpleType(value): value
            default: nil
        }
    }
    
    var asFunctionType: FunctionType? {
        switch self {
            case let .functionType(value): value
            default: nil
        }
    }
    
    // ...
}

The macro must be implemented in a separate target from the Toolkit (hence the MacroToolkitHelpers target suggestion), however the macro can be declared in the MacroToolkit target (declaration is separate from implementation):

// This declaration is taken from the proposal, so the API may have changed since
// then, I haven't kept up with all that
@attached(member, names: arbitrary) macro CaseAccessors()

After implementing the macro you can apply it to Type, AttributeListElement, DestructuredType, and EnumCaseValue (I can't see any others that would make sense to use it on).

This could be quite involved, so feel free (as always) to contact me on Discord (@stackotter), Twitter (X) (@stackotter), or via email (stackotter@stackotter.dev)

@stackotter stackotter added hacktoberfest enhancement New feature or request labels Oct 10, 2023
@ajkolean
Copy link
Contributor

Pointfree's case paths macro essentially does this amongst other things 😉

@stackotter
Copy link
Owner Author

Pointfree's case paths macro essentially does this amongst other things 😉

Woah, thanks for bringing that to my attention! I hadn't checked out case paths since macros, didn't realise that they had that handy macro now.

Due to MacroToolkit being a foundational library for making macros, it'd be best not to get to tied to whatever swift-syntax version pointfree's case paths macros are built on (and maybe case paths will want to use macro toolkit one day hahah). I reckon it'd be best for the toolkit to reimplement a similar macro to use internally so that we don't have to depend on case paths.

@ajkolean
Copy link
Contributor

Ahh yeah totally derped on that, especially with the volatility syntax has been exhibiting. Anyway the source might be beneficial when implementing this. Also the CaseDetection macro example in the swift-syntax library and this one (Although doesn't seem maintained so syntax will be a little outdated)

@stackotter
Copy link
Owner Author

Yeah definitely 👍

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request hacktoberfest
Projects
None yet
Development

No branches or pull requests

2 participants