Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,9 @@
<Compile Include="../Microsoft.Macios.Generator/Extensions/Delegates.cs" >
<Link>Generator/Extensions/Delegates.cs</Link>
</Compile>
<Compile Include="../Microsoft.Macios.Generator/Extensions/ParameterSymbolExtensions.cs" >
<Link>Generator/Extensions/ParameterSymbolExtensions.cs</Link>
</Compile>
<Compile Include="../Microsoft.Macios.Generator/Extensions/SpecialTypeExtensions.cs" >
<Link>Generator/Extensions/SpecialTypeExtensions.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ readonly partial struct DelegateParameter {
public static bool TryCreate (IParameterSymbol symbol,
[NotNullWhen (true)] out DelegateParameter? parameter)
{
parameter = new (symbol.Ordinal, new (symbol.Type), symbol.Name) {
parameter = new (symbol.Ordinal, new (symbol.Type), symbol.GetSafeName ()) {
ForcedType = symbol.GetForceTypeData (),
IsOptional = symbol.IsOptional,
IsParams = symbol.IsParams,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@ public bool NeedsNullCheck {
public static bool TryCreate (IParameterSymbol symbol, ParameterSyntax declaration, RootContext context,
[NotNullWhen (true)] out Parameter? parameter)
{
parameter = new (symbol.Ordinal, new (symbol.Type, context.Compilation), symbol.Name) {
parameter = new (symbol.Ordinal, new (symbol.Type, context.Compilation), symbol.GetSafeName ()) {
BindAs = symbol.GetBindFromData (),
ForcedType = symbol.GetForceTypeData (),
IsOptional = symbol.IsOptional,
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;

namespace Microsoft.Macios.Generator.Extensions;

public static class ParameterSymbolExtensions {

/// <summary>
/// Gets the safe name of the parameter symbol, prefixing with "@" if it's a C# keyword.
/// </summary>
/// <param name="symbol">The parameter symbol.</param>
/// <returns>The safe name of the parameter, suitable for use in generated C# code.
/// For example, if the parameter name is "event", this method returns "@event".
/// Otherwise, it returns the original parameter name.</returns>
public static string GetSafeName (this IParameterSymbol symbol)
{
// In C#, the @ symbol is used as an escape character to allow reserved keywords (like event) to be used as
// identifiers. However, when working with Roslyn's IParameterSymbol, the Name property returns the identifier
// without the @ prefix because the @ is only required in the source code to escape the keyword.
// Internally, the compiler treats the name as the unescaped version.
string parameterName = SyntaxFacts.GetKeywordKind (symbol.Name) != SyntaxKind.None
? "@" + symbol.Name
: symbol.Name;
return parameterName;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@

using System.Diagnostics.CodeAnalysis;
using Microsoft.CodeAnalysis;
using Microsoft.Macios.Generator.Extensions;
using Microsoft.Macios.Transformer.Attributes;

namespace Microsoft.Macios.Generator.DataModel;
Expand All @@ -17,7 +18,7 @@ readonly partial struct DelegateParameter {
public static bool TryCreate (IParameterSymbol symbol,
[NotNullWhen (true)] out DelegateParameter? parameter)
{
parameter = new (symbol.Ordinal, new (symbol.Type), symbol.Name) {
parameter = new (symbol.Ordinal, new (symbol.Type), symbol.GetSafeName ()) {
IsOptional = symbol.IsOptional,
IsParams = symbol.IsParams,
IsThis = symbol.IsThis,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ public static bool TryCreate (IParameterSymbol symbol, ParameterSyntax declarati
// retrieve the parameter attributes because those might affect the parameter type, for example, the
// NullAllowed attribute can change the parameter type to be nullable.
var parameterAttrs = symbol.GetAttributeData ();
parameter = new (symbol.Ordinal, new (symbol.Type, parameterAttrs), symbol.Name) {
parameter = new (symbol.Ordinal, new (symbol.Type, parameterAttrs), symbol.GetSafeName ()) {
IsOptional = symbol.IsOptional,
IsParams = symbol.IsParams,
IsThis = symbol.IsThis,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,9 @@
<Compile Include="../Microsoft.Macios.Generator/Extensions/FieldSymbolExtensions.cs">
<Link>Extensions/FieldSymbolExtensions.cs</Link>
</Compile>
<Compile Include="../Microsoft.Macios.Generator/Extensions/ParameterSymbolExtensions.cs">
<Link>Extensions/ParameterSymbolExtensions.cs</Link>
</Compile>
<Compile Include="../Microsoft.Macios.Generator/Extensions/ParameterSyntaxExtensions.cs">
<Link>Extensions/ParameterSyntaxExtensions.cs</Link>
</Compile>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -523,6 +523,65 @@ public void MyMethod ([BlockCallback] Callback cb) {}
]
)
];

const string customDelegateKeywordParam = @"
using System;

namespace NS {
public class MyClass {
public delegate int? Callback(string @event, string? middleName, params string[] surname);

public void MyMethod (Callback cb) {}
}
}
";

yield return [
customDelegateKeywordParam,
new Method (
type: "NS.MyClass",
name: "MyMethod",
returnType: ReturnTypeForVoid (),
symbolAvailability: new (),
exportMethodData: new (),
attributes: [],
modifiers: [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
],
parameters: [
new (
position: 0,
type: ReturnTypeForDelegate (
"NS.MyClass.Callback",
delegateInfo: new (
name: "Invoke",
returnType: ReturnTypeForInt (isNullable: true),
parameters: [
new (
position: 0,
type: ReturnTypeForString (),
name: "@event"
),
new (
position: 1,
type: ReturnTypeForString (isNullable: true),
name: "middleName"
),
new (
position: 2,
type: ReturnTypeForArray ("string", isBlittable: false),
name: "surname"
) {
IsParams = true,
},
]
)
),
name: "cb"
)
]
)
];
}

IEnumerator IEnumerable.GetEnumerator () => GetEnumerator ();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -161,6 +161,34 @@ public class MyClass {
)
];

const string singleParameterKeywordNameMethod = @"
using System;

namespace NS {
public class MyClass {
public string MyMethod (string @event) => $""{@event}_test"";
}
}
";

yield return [
singleParameterKeywordNameMethod,
new Method (
type: "NS.MyClass",
name: "MyMethod",
returnType: ReturnTypeForString (),
symbolAvailability: new (),
exportMethodData: new (),
attributes: [],
modifiers: [
SyntaxFactory.Token (SyntaxKind.PublicKeyword),
],
parameters: [
new (position: 0, type: ReturnTypeForString (), name: "@event"),
]
)
];

const string singleArrayParameterMethod = @"
using System;

Expand Down