Skip to content

Fix Accessor Macros Attached to Properties With Trailing Comments #2722

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

Conversation

AppAppWorks
Copy link
Contributor

Fixed #2614

Comment on lines 113 to 130
func testAccessorOnVariableDeclWithTrailingLineCommentAndAccessorBlock() {
assertMacroExpansion(
"""
@constantOne
var x: Int { // hello
1
}
""",
expandedSource: """
var x: Int { // hello
get {
1
}
get {
return 1
}
}
""",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I discovered that adding a trailing comment to the left brace of the accessor block will mess up the indentation levels of the generated getter.

@AppAppWorks
Copy link
Contributor Author

@bnbarham could you review this PR if @ahoppen isn't available?

@AppAppWorks AppAppWorks force-pushed the fix-accessor-macros-properties-with-trailing-comments branch from 5c6edb1 to 8a5f2d1 Compare July 12, 2024 03:16
@AppAppWorks AppAppWorks force-pushed the fix-accessor-macros-properties-with-trailing-comments branch from 8a5f2d1 to 552e539 Compare July 12, 2024 21:21
Copy link
Contributor

@bnbarham bnbarham left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks @AppAppWorks!


let expansion = expandAccessors(of: node, existingAccessors: binding.accessorBlock)

let bindingKeyPath = \VariableDeclSyntax.bindings[node.bindings.startIndex]
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I mildly prefer just keeping node.bindings[node.bindings.startIndex] TBH. Maybe we should have a mutate method or something similar to make this a little nicer, or just wait until we can use variadic generics and then update with...

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the bindings key path is a little confusing, it just seems a little over-complicated

What do you think about having var binding = node.bindings.first in the guard, then using binding.accessorBlock = … etc below and finalizing the new node by setting node.bindings = [binding]. That seems like the cleanest solution to me.

@bnbarham
Copy link
Contributor

@swift-ci please test

@AppAppWorks AppAppWorks force-pushed the fix-accessor-macros-properties-with-trailing-comments branch from 552e539 to 6ee8632 Compare July 15, 2024 02:22
@AppAppWorks
Copy link
Contributor Author

I've run swift-format, please test again.

@bnbarham
Copy link
Contributor

@swift-ci please test


let expansion = expandAccessors(of: node, existingAccessors: binding.accessorBlock)

let bindingKeyPath = \VariableDeclSyntax.bindings[node.bindings.startIndex]
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I agree that the bindings key path is a little confusing, it just seems a little over-complicated

What do you think about having var binding = node.bindings.first in the guard, then using binding.accessorBlock = … etc below and finalizing the new node by setting node.bindings = [binding]. That seems like the cleanest solution to me.

Comment on lines 939 to 944
if binding.accessorBlock == nil {
// remove the trailing trivia of the variable declaration and move it
// to the trailing trivia of the left brace of the newly created accessor block
node[keyPath: bindingKeyPath].trailingTrivia = []
expansion.accessors?.leftBrace.trailingTrivia = binding.trailingTrivia
}
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This would still be an issue if the macro expands to an accessor that doesn’t have a newline after the {, right? Ie. you have a macro that expands to { 1 } and has formatting disabled, so no newline gets added by BasicFormat.

If that’s the case, I would just move the trailing trivia after the closing brace. That way you can conceptually think of the accessor as being inserted before the binding’s trailing trivia.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

How could I disable formatting for a test case?

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You'll need to add a new macro and then set static let formatMode: FormatMode = .disabled in its definition. Also, nice catch @ahoppen! I forgot about that case :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I couldn't figure out how to make an AccessorMacro expand into something like { 1 }, how could I do this?

Copy link
Member

@ahoppen ahoppen Jul 17, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The following should test it

func testNew() {
  struct ConstantOneSingleLineGetter: AccessorMacro {
    static var formatMode: FormatMode { .disabled }

    static func expansion(
      of node: AttributeSyntax,
      providingAccessorsOf declaration: some DeclSyntaxProtocol,
      in context: some MacroExpansionContext
    ) throws -> [AccessorDeclSyntax] {
      return [
        """
        get { 1 }
        """
      ]
    }
  }

  assertMacroExpansion(
    """
    @constantOne
    var x: Int // hello
    """,
    expandedSource: """
      var x: Int { // hello
        get { 1 }
      }
      """,
    macros: ["constantOne": ConstantOneSingleLineGetter.self],
    indentationWidth: indentationWidth
  )
}

@ahoppen
Copy link
Member

ahoppen commented Jul 17, 2024

@swift-ci Please test Windows

@AppAppWorks AppAppWorks force-pushed the fix-accessor-macros-properties-with-trailing-comments branch from 6ee8632 to b3649bb Compare July 18, 2024 19:17
@ahoppen
Copy link
Member

ahoppen commented Jul 18, 2024

@swift-ci Please test

@ahoppen
Copy link
Member

ahoppen commented Jul 18, 2024

@swift-ci Please test Windows

@ahoppen
Copy link
Member

ahoppen commented Jul 19, 2024

@AppAppWorks Could you add the test case I suggested in #2722 (comment)?

fixed the bug that trailing comments of a property would stay in place after macro expansion, commenting out the left brace of the newly created accessor block
- the bug affected only properties without an accessor block while having trailing line comments
- fixed by moving the trailing trivia of the variable declaration to the trailing trivia of the left brace of the accessor block
added tests on properties with trailing comments and with/without an accessor block
@AppAppWorks AppAppWorks force-pushed the fix-accessor-macros-properties-with-trailing-comments branch from b3649bb to 8bb0a0a Compare July 20, 2024 02:14
@AppAppWorks
Copy link
Contributor Author

@AppAppWorks Could you add the test case I suggested in #2722 (comment)?

Done, please have a look.

@ahoppen
Copy link
Member

ahoppen commented Jul 22, 2024

@swift-ci Please test

@ahoppen ahoppen enabled auto-merge July 22, 2024 17:16
@AppAppWorks
Copy link
Contributor Author

Could you test Windows too? :)

@bnbarham
Copy link
Contributor

@swift-ci please test Windows platform

@ahoppen ahoppen merged commit 50590d6 into swiftlang:main Jul 31, 2024
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Accessor Macros applied to properties with trailing trivia comments lead to Swift that fails to compile.
3 participants