This repository has been archived by the owner on Jul 26, 2023. It is now read-only.
-
-
Notifications
You must be signed in to change notification settings - Fork 225
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #131 from AArnott/fix130_codegen
Add code generator for IntPtr property accessors
- Loading branch information
Showing
10 changed files
with
138 additions
and
7 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
107 changes: 107 additions & 0 deletions
107
src/CodeGeneration/OfferIntPtrPropertyAccessorsGenerator.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,107 @@ | ||
// Copyright (c) to owners found in https://github.com/AArnott/pinvoke/blob/master/COPYRIGHT.md. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
|
||
namespace PInvoke | ||
{ | ||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using System.Text; | ||
using System.Threading; | ||
using System.Threading.Tasks; | ||
using CodeGeneration.Roslyn; | ||
using Microsoft.CodeAnalysis; | ||
using Microsoft.CodeAnalysis.CSharp; | ||
using Microsoft.CodeAnalysis.CSharp.Syntax; | ||
|
||
/// <summary> | ||
/// Generates property accessors that expose native pointer fields | ||
/// as <see cref="IntPtr"/> properties. | ||
/// </summary> | ||
public class OfferIntPtrPropertyAccessorsGenerator : ICodeGenerator | ||
{ | ||
private static readonly TypeSyntax VoidStar = SyntaxFactory.ParseTypeName("void*"); | ||
|
||
private static readonly TypeSyntax IntPtrTypeSyntax = SyntaxFactory.ParseTypeName("System.IntPtr"); | ||
|
||
/// <summary> | ||
/// Initializes a new instance of the <see cref="OfferIntPtrPropertyAccessorsGenerator"/> class. | ||
/// </summary> | ||
/// <param name="data">Generator attribute data.</param> | ||
public OfferIntPtrPropertyAccessorsGenerator(AttributeData data) | ||
{ | ||
} | ||
|
||
/// <inheritdoc /> | ||
public Task<SyntaxList<MemberDeclarationSyntax>> GenerateAsync(MemberDeclarationSyntax applyTo, Document document, IProgress<Diagnostic> progress, CancellationToken cancellationToken) | ||
{ | ||
var applyToStruct = applyTo as StructDeclarationSyntax; | ||
var applyToClass = applyTo as ClassDeclarationSyntax; | ||
var applyToType = applyTo as TypeDeclarationSyntax; | ||
|
||
var generatedMembers = SyntaxFactory.List<MemberDeclarationSyntax>(); | ||
var nativePointerFields = from field in applyToType.Members.OfType<FieldDeclarationSyntax>() | ||
where field.Declaration.Type is PointerTypeSyntax && field.Modifiers.Any(m => m.IsKind(SyntaxKind.PublicKeyword)) | ||
select field; | ||
foreach (var field in nativePointerFields) | ||
{ | ||
foreach (var variable in field.Declaration.Variables) | ||
{ | ||
generatedMembers = generatedMembers.Add( | ||
SyntaxFactory.PropertyDeclaration(IntPtrTypeSyntax, variable.Identifier.ValueText + "_IntPtr") | ||
.WithModifiers(field.Modifiers) | ||
//// get { return new IntPtr(this.field); } | ||
//// set { this.field = (byte*)value.ToPointer(); } | ||
.AddAccessorListAccessors( | ||
SyntaxFactory.AccessorDeclaration( | ||
SyntaxKind.GetAccessorDeclaration, | ||
SyntaxFactory.Block( | ||
SyntaxFactory.ReturnStatement( | ||
SyntaxFactory.ObjectCreationExpression(IntPtrTypeSyntax) | ||
.AddArgumentListArguments(SyntaxFactory.Argument(ThisDot(variable.Identifier)))))), | ||
SyntaxFactory.AccessorDeclaration( | ||
SyntaxKind.SetAccessorDeclaration, | ||
SyntaxFactory.Block( | ||
SyntaxFactory.ExpressionStatement( | ||
SyntaxFactory.AssignmentExpression( | ||
SyntaxKind.SimpleAssignmentExpression, | ||
ThisDot(variable.Identifier), | ||
TypedAs( | ||
SyntaxFactory.InvocationExpression( | ||
SyntaxFactory.MemberAccessExpression( | ||
SyntaxKind.SimpleMemberAccessExpression, | ||
SyntaxFactory.IdentifierName("value"), | ||
SyntaxFactory.IdentifierName(nameof(IntPtr.ToPointer))), | ||
SyntaxFactory.ArgumentList()), | ||
field.Declaration.Type))))))); | ||
} | ||
} | ||
|
||
var generatedType = (TypeDeclarationSyntax)applyToStruct?.WithMembers(generatedMembers) | ||
.WithAttributeLists(SyntaxFactory.List<AttributeListSyntax>()) | ||
?? applyToClass?.WithMembers(generatedMembers) | ||
.WithAttributeLists(SyntaxFactory.List<AttributeListSyntax>()); | ||
return Task.FromResult(SyntaxFactory.SingletonList<MemberDeclarationSyntax>(generatedType)); | ||
} | ||
|
||
private static MemberAccessExpressionSyntax ThisDot(SyntaxToken memberName) | ||
{ | ||
return ThisDot(SyntaxFactory.IdentifierName(memberName.ValueText)); | ||
} | ||
|
||
private static MemberAccessExpressionSyntax ThisDot(SimpleNameSyntax memberName) | ||
{ | ||
return SyntaxFactory.MemberAccessExpression( | ||
SyntaxKind.SimpleMemberAccessExpression, | ||
SyntaxFactory.ThisExpression(), | ||
memberName); | ||
} | ||
|
||
private static ExpressionSyntax TypedAs(ExpressionSyntax expression, TypeSyntax requiredType) | ||
{ | ||
return VoidStar.Equals(requiredType) | ||
? expression | ||
: SyntaxFactory.CastExpression(requiredType, expression); | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
20 changes: 20 additions & 0 deletions
20
src/CodeGenerationAttributes/OfferIntPtrPropertyAccessorsAttribute.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
// Copyright (c) to owners found in https://github.com/AArnott/pinvoke/blob/master/COPYRIGHT.md. All rights reserved. | ||
// Licensed under the MIT license. See LICENSE.txt file in the project root for full license information. | ||
|
||
namespace PInvoke | ||
{ | ||
using System; | ||
using System.Diagnostics; | ||
using CodeGeneration.Roslyn; | ||
|
||
/// <summary> | ||
/// Causes generation of property accessors that expose native pointer fields | ||
/// as <see cref="IntPtr"/> properties. | ||
/// </summary> | ||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)] | ||
[CodeGenerationAttribute("PInvoke.OfferIntPtrPropertyAccessorsGenerator, CodeGeneration, Version=0.1.0.0, Culture=neutral, PublicKeyToken=9e300f9f87f04a7a")] | ||
[Conditional("CodeGeneration")] | ||
public class OfferIntPtrPropertyAccessorsAttribute : Attribute | ||
{ | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters