Skip to content

MacroExpansionContext.lexicalContext always empty for freestanding macros? #2907

Closed
@Jeehut

Description

@Jeehut

Description

I am currently writing a freestanding macro using version 600.0.1 which needs to read some information about its enclosing code. According to this thread on the forums @DougGregor has implemented exactly what I need in #1554 inside the lexicalContext property. But when I call context.lexicalContext I always get an empty array, even though my freestanding macro is placed inside a SwiftUI body within a Button initializer like this:

import SwiftUI
      
struct MyView: View {
   var body: some View {
      Button(#tk("Save Changes")) { 
         self.handleSave()
      }
   }
}

The purpose of my macro is to auto-generate a semantic localization key based on the context. The expected expansion:

import SwiftUI

struct MyView: View {
   var body: some View {
      Button(String(localized: "MyView.Body.Button.saveChanges", defaultValue: "Save Changes")) { 
         self.handleSave()
      }
   }
}

I got everything working, except that I can't access the context. I would expect lexicalContext to be something like ["Button", "body", "MyView"] or at least contain these texts in some kind of structure so I can read them out. But it's completely empty for me. Am I missing something?

Steps to Reproduce

This is the helper function in my ExpressionMacro I'm trying to implement:

   /// Returns `MyView.body.Button.SaveChanges` for the following view:
   /// ```swift
   /// struct MyView: View {
   ///    var body: some View {
   ///       Button(#tk("Save Changes")) {
   ///          self.handleSave()
   ///       }
   ///    }
   /// }
   /// ```
   /// Or `MyModel.DisplayName.Movie.movie` and `MyModel.DisplayName.Series.tvShow` for the following model:
   /// ```swift
   /// enum MyModel: String, CaseIterable, Codable {
   ///    case movie
   ///    case series
   ///
   ///    var displayName: String {
   ///       switch self {
   ///       case .movie: #tk("Movie")
   ///       case .series: #tk("TV Show")
   ///       }
   ///    }
   /// }
   /// ```
   /// - NOTE: Use https://swift-ast-explorer.com for development.
   private static func semanticKey(
      of node: some FreestandingMacroExpansionSyntax,
      in context: some MacroExpansionContext
   ) -> String {
      // node-based approach
      return node.parent?.description ?? "N/A"  // always returns `"N/A"`

      // context-based approach
      return context.lexicalContext.description  // always returns `"[]"`
   }

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't working

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions