How to check if a macro-generated identifier needs backticks?

i guess the title says it all. i have a macro that adds arbitrary names, and some of those names form swift keywords.

//  ISO macrolanguage tags
//  ^~~ uh-oh

is there a way for the macro to check if the identifier needs escaping?

The question of whether an identifier needs escaping can’t be answered generically. For example, as is perfectly valid as a member lookup but not as a variable declaration let as = 1. init, on the other hand, also needs to be escaped for member access.

Depending on your use case, I would suggest parsing a little code snippet with your intended identifier name and checking if that produces no error. For example,

let myVariableName = "as"
var parser = Parser("var \(myVariableName)")
let decl = DeclSyntax.parse(from: &parser)
return decl.hasError

Or if you want to be extra careful and check that the parser did indeed parse the name as an identifier (this would be more interesting for the foo.init case if you want to make sure that you indeed escape init as a member name, which would parse fine as a keyword access as well).

if case .identifier = {
  return true
} else {
  return false
1 Like

i think this is a common enough use case it might benefit from a SwiftSyntax API :slight_smile:

I agree that SwiftSyntax should be able to handle this with types, but it is also never wrong to use backticks in positions where you definitely want an identifier. Backticks on normal identifier-strings are needless but also harmless. (As long as your input doesn’t already have backticks.)


what would be really nice is if i could do

extension ISO.Language
    enum AvailableCases
        case aa, ab, ... , `as`

and then the macro implementation could just vacuum up the enum case identifiers, which are already known to be valid identifiers. but an extension macro cannot itself be applied to an extension block.

i guess the next best thing would be to place AvailableCases in the main declaration.