Skip to content

Commit 13365b5

Browse files
committed
Fix parameter name issue (#1)
1 parent 0e03fc9 commit 13365b5

1 file changed

Lines changed: 64 additions & 2 deletions

File tree

NativeInvoke/Generator/NativeImportGenerator.cs

Lines changed: 64 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,23 @@ namespace NativeInvoke.Generator;
55
[Generator]
66
public sealed class NativeImportGenerator : IIncrementalGenerator
77
{
8+
private static readonly HashSet<string> ContextualKeywordsThatNeedEscaping;
9+
10+
static NativeImportGenerator()
11+
{
12+
ContextualKeywordsThatNeedEscaping = new HashSet<string>(StringComparer.Ordinal)
13+
{
14+
// Query keywords
15+
"from", "where", "select", "group", "into", "orderby", "join", "on", "equals", "by",
16+
"ascending", "descending", "let",
17+
// Async keywords
18+
"async", "await",
19+
// Other contextual keywords
20+
"when", "yield", "partial", "file", "required", "init", "set", "get", "add", "remove",
21+
"nameof", "var", "dynamic"
22+
};
23+
}
24+
825
public void Initialize(IncrementalGeneratorInitializationContext context)
926
{
1027
// Incremental source generator is awesome
@@ -334,8 +351,8 @@ private static string GenerateSource(
334351
{
335352
var m = data.Method;
336353
var ret = m.ReturnType.ToDisplayString();
337-
var paramsList = string.Join(", ", m.Parameters.Select(static p => $"{p.Type.ToDisplayString()} {p.Name}"));
338-
var argsList = string.Join(", ", m.Parameters.Select(static p => p.Name));
354+
var paramsList = string.Join(", ", m.Parameters.Select(static p => $"{p.Type.ToDisplayString()} {EscapeParameterName(p)}"));
355+
var argsList = string.Join(", ", m.Parameters.Select(static p => EscapeParameterName(p)));
339356

340357
if (data.ShouldInclude)
341358
{
@@ -595,6 +612,51 @@ private static string GetAccessibilityString(ISymbol symbol) =>
595612
Accessibility.ProtectedAndInternal => "private protected ",
596613
_ => ""
597614
};
615+
616+
private static string EscapeParameterName(IParameterSymbol parameter)
617+
{
618+
// https://github.com/Cheatoid/NativeInvoke/issues/1
619+
// Try to get the raw parameter name from source to preserve @ prefix if it exists
620+
var rawName = GetRawParameterName(parameter);
621+
if (!string.IsNullOrEmpty(rawName))
622+
{
623+
// If we have the raw name with @ prefix, use it directly
624+
return rawName;
625+
}
626+
627+
// Fallback: Use the symbol name and escape if it's a keyword
628+
var name = parameter.Name;
629+
return ShouldEscapeIdentifier(name) ? $"@{name}" : name;
630+
}
631+
632+
private static string GetRawParameterName(IParameterSymbol parameter)
633+
{
634+
// Try to get the syntax reference for this parameter
635+
var syntaxReferences = parameter.DeclaringSyntaxReferences;
636+
if (syntaxReferences.Length == 0) return string.Empty;
637+
638+
var syntax = syntaxReferences[0].GetSyntax();
639+
if (syntax is ParameterSyntax parameterSyntax)
640+
{
641+
// Get the identifier text which preserves the @ prefix
642+
return parameterSyntax.Identifier.Text;
643+
}
644+
645+
return string.Empty;
646+
}
647+
648+
private static bool ShouldEscapeIdentifier(string identifier)
649+
{
650+
// Use Roslyn's SyntaxFacts to check if it's a keyword
651+
if (SyntaxFacts.GetKeywordKind(identifier) != SyntaxKind.None)
652+
{
653+
return true;
654+
}
655+
656+
// Check for contextual keywords that need escaping in certain contexts
657+
// These are keywords that are only reserved in specific contexts
658+
return ContextualKeywordsThatNeedEscaping.Contains(identifier);
659+
}
598660
}
599661

600662
internal static partial class Extensions

0 commit comments

Comments
 (0)