Skip to content

Conversation

@jamieQ
Copy link
Contributor

@jamieQ jamieQ commented Oct 10, 2025

follow-up to #84224 in an attempt to address: #84145

@@ -272,18 +272,33 @@ extension PatternBindingListSyntax {

extension VariableDeclSyntax {
func privatePrefixed(_ prefix: String, addingAttribute attribute: AttributeSyntax, removingAttribute toRemove: AttributeSyntax, in context: LocalMacroExpansionContext<some MacroExpansionContext>) -> VariableDeclSyntax {
var newAttribute = attribute
newAttribute.leadingTrivia = .newline
Copy link
Contributor

Choose a reason for hiding this comment

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

This removes any existing leading trivia, as does the leadingTrivia:... in the bindingSpecifier below. I'm not sure that's a bad thing though.

IMO in an ideal world we'd just strip all trivia for the added var, then let BasicFormat handle adding the appropriate whitespace on the resulting var. Any opinions @hamishknight / @rintaro / @phausler?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

IIUC in this particular case, we'd be stripping the leading trivia from the addingAttribute parameter, which is currently only ever ObservableMacro.ignoredAttribute (AFAICT). an alternative i played with was just making the ignoredAttribute (and its sibling) automatically be surrounded by newline trivia to 'break them off' to an extent from wherever they get inserted. ultimately went with this strategy first per your earlier suggestions. the leadingTrivia: passed to the new binding specifier token syntax should still basically have the same behavior as before just with different whitespace, right?

Copy link
Contributor

@bnbarham bnbarham Oct 24, 2025

Choose a reason for hiding this comment

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

Hmm, fair enough. I'd really prefer:

IMO in an ideal world we'd just strip all trivia for the added var, then let BasicFormat handle adding the appropriate whitespace on the resulting var

here, but it's up to you if you want to tackle that or not. Adding the newline at least fixes the trailing comment case, so if you'd like to stop there that's okay with me :)

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@bnbarham thanks for the feedback – i'm happy to take a shot at implementing your preferred solution, but i may be stumbling around for a bit (and have further questions) before i get there.

Copy link
Contributor

Choose a reason for hiding this comment

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

It's a much larger change - we can take this one either way. Want to fix up the -target and then I'll run tests?

Comment on lines 1 to 10
// REQUIRES: swift_swift_parser, asserts
//
// UNSUPPORTED: back_deploy_concurrency
// REQUIRES: concurrency
// REQUIRES: observation
//
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t-scratch)

// RUN: %target-swift-frontend -typecheck -target %target-swift-5.7-abi-triple -plugin-path %swift-plugin-dir -I %t -dump-macro-expansions %s 2>&1 | %FileCheck %s --color
Copy link
Contributor Author

Choose a reason for hiding this comment

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

if anyone has suggestions about the right preamble to use here i'd be glad to learn more. i basically just randomly copied things from other tests that included the -dump-macro-expansions option until things seemed to work okay when running with lit. in particular, is there some way to avoid having to add the availability annotations on everything below?

Copy link
Contributor

Choose a reason for hiding this comment

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

You shouldn't need -target - it'll be added by %target-swift-frontend already. Probably want a -swift-version 5 as we default to 4 otherwise, but the rest LGTM

Copy link
Contributor Author

Choose a reason for hiding this comment

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

thanks! updated the setup, and made some minor test adjustments.

tangential, but i also noticed that there is a weird issue with the fact that the dump-macro-expansion output can end up re-emitting source comments, and those comments can themselves be FileCheck directives... so i added some 'dummy' expressions to ensure the FileCheck trivia doesn't accidentally show up in the expansion patterns that are verified. if there's a better way to deal with that problem, i can take a look as a follow-up.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

ah, i may have misunderstood this suggestion... i removed the entire -target %target-swift-5.7-abi-triple options, but perhaps you meant that only the -target was redundant. like i said i just copied this from some other test (@Distributed macro stuff maybe?), and don't have a great understanding of why you'd pick a particular target substitution of that form... now that i look at the Testing.md docs a bit more closely it seems i likely should have used %target-typecheck-verify-swift here. still a bit unclear on exactly what the extra 'abi-triple' stuff controls and when you'd want to use it though. please lmk if you think any of this should be changed before merging.


// CHECK-LABEL: {{.*}}CommentOnSameLineNoAnnotation{{.*}}ObservationTracked{{.*}}.swift
// CHECK: /* Innocent comment */
// CHECK-NEXT: @ObservationIgnored
Copy link
Contributor Author

@jamieQ jamieQ Oct 11, 2025

Choose a reason for hiding this comment

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

in 'reality' the dump macro expansion output had some leading whitespace here, but i guess that is ignored in this form of filecheck expectation. is there a way to test for that? i.e. the 'true' output looked something like:

------------------------------
@__swiftmacro_38observation_macro_expansion_observable29CommentOnSameLineNoAnnotationC2it18ObservationTrackedfMp_.swift
------------------------------
/* Innocent comment */
  @ObservationIgnored
private final /*2*/  var _it /*4*/  /*4*/ = 0

edit: also, note how the whitespace between the comments also appears to be slightly different from the dumped output and what we're testing against (2 spaces in the actual output b/w the '/4/' comments vs only 1 in the tests)... anyone know why that is (and why the test works in this case)?

Copy link
Contributor

Choose a reason for hiding this comment

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

For the latter question, file check canonicalizes all whitespace by default - you can turn that off and test for it with --strict-whitespace when running FileCheck.

As for why we're getting 2 here, I assume it's because we're getting a copy of the /*4*/ trivia from somewhere 😅

…n invalid macro expansion. The comment was 'eating' the generated variable declaration, preventing it from being visible to the compiler.
@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 11, 2025

@swift-ci please smoke test macos

@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 17, 2025

@bnbarham / @hamishknight / @rintaro / @phausler – any further thoughts or feedback on this approach, or better alternative ways to solve this?

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.

Sorry for the late reply @jamieQ and thanks again for looking at this!


// CHECK-LABEL: {{.*}}CommentOnSameLineNoAnnotation{{.*}}ObservationTracked{{.*}}.swift
// CHECK: /* Innocent comment */
// CHECK-NEXT: @ObservationIgnored
Copy link
Contributor

Choose a reason for hiding this comment

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

For the latter question, file check canonicalizes all whitespace by default - you can turn that off and test for it with --strict-whitespace when running FileCheck.

As for why we're getting 2 here, I assume it's because we're getting a copy of the /*4*/ trivia from somewhere 😅

@@ -272,18 +272,33 @@ extension PatternBindingListSyntax {

extension VariableDeclSyntax {
func privatePrefixed(_ prefix: String, addingAttribute attribute: AttributeSyntax, removingAttribute toRemove: AttributeSyntax, in context: LocalMacroExpansionContext<some MacroExpansionContext>) -> VariableDeclSyntax {
var newAttribute = attribute
newAttribute.leadingTrivia = .newline
Copy link
Contributor

@bnbarham bnbarham Oct 24, 2025

Choose a reason for hiding this comment

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

Hmm, fair enough. I'd really prefer:

IMO in an ideal world we'd just strip all trivia for the added var, then let BasicFormat handle adding the appropriate whitespace on the resulting var

here, but it's up to you if you want to tackle that or not. Adding the newline at least fixes the trailing comment case, so if you'd like to stop there that's okay with me :)

Comment on lines 1 to 10
// REQUIRES: swift_swift_parser, asserts
//
// UNSUPPORTED: back_deploy_concurrency
// REQUIRES: concurrency
// REQUIRES: observation
//
// RUN: %empty-directory(%t)
// RUN: %empty-directory(%t-scratch)

// RUN: %target-swift-frontend -typecheck -target %target-swift-5.7-abi-triple -plugin-path %swift-plugin-dir -I %t -dump-macro-expansions %s 2>&1 | %FileCheck %s --color
Copy link
Contributor

Choose a reason for hiding this comment

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

You shouldn't need -target - it'll be added by %target-swift-frontend already. Probably want a -swift-version 5 as we default to 4 otherwise, but the rest LGTM

@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 25, 2025

@swift-ci please smoke test

@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 25, 2025

@swift-ci please test source compatibility

interaction with comments

Adds logic to insert newlines in various places to try and resolve the
fact that the current expansion produces invalid code in some cases
depending on comment location. Adds some basic tests of the expansion
output.
@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 26, 2025

@swift-ci please smoke test

@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 26, 2025

@swift-ci Please Test Source Compatibility Debug

@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 26, 2025

@swift-ci please clean smoke test macos

@jamieQ
Copy link
Contributor Author

jamieQ commented Oct 27, 2025

@bnbarham i made some minor changes to the tests per your feedback (and some additional discoveries). if this looks okay to you please merge when convenient, or let me know if there's anything else you think needs to be addressed first. thanks!

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 @jamieQ!

@bnbarham bnbarham merged commit c978386 into swiftlang:main Oct 31, 2025
4 checks passed
@jamieQ jamieQ deleted the obs-macro-ii branch November 1, 2025 09:39
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.

3 participants