diff --git a/src/Microsoft.Windows.CsWin32/Generator.cs b/src/Microsoft.Windows.CsWin32/Generator.cs index 7fbf9b4c..fc1e7e5f 100644 --- a/src/Microsoft.Windows.CsWin32/Generator.cs +++ b/src/Microsoft.Windows.CsWin32/Generator.cs @@ -3763,11 +3763,6 @@ private ClassDeclarationSyntax DeclareCocreatableClass(TypeDefinition typeDef) private StructDeclarationSyntax DeclareTypeDefStruct(TypeDefinition typeDef, TypeDefinitionHandle typeDefHandle) { IdentifierNameSyntax name = IdentifierName(this.Reader.GetString(typeDef.Name)); - if (name.Identifier.ValueText == "BOOL") - { - return this.DeclareTypeDefBOOLStruct(typeDef); - } - bool isHandle = name.Identifier.ValueText == "HGDIOBJ"; foreach (CustomAttributeHandle attHandle in typeDef.GetCustomAttributes()) { @@ -3870,6 +3865,7 @@ private StructDeclarationSyntax DeclareTypeDefStruct(TypeDefinition typeDef, Typ break; case "HRESULT": case "NTSTATUS": + case "BOOL": case "BOOLEAN": members = members.AddRange(this.ExtractMembersFromTemplate(name.Identifier.ValueText)); break; @@ -4146,91 +4142,6 @@ private MethodDeclarationSyntax CreateAsSpanMethodOverValueAndLength(TypeSyntax .WithLeadingTrivia(StrAsSpanComment); } - private StructDeclarationSyntax DeclareTypeDefBOOLStruct(TypeDefinition typeDef) - { - IdentifierNameSyntax name = IdentifierName("BOOL"); - - FieldDefinition fieldDef = this.Reader.GetFieldDefinition(typeDef.GetFields().Single()); - CustomAttributeHandleCollection fieldAttributes = fieldDef.GetCustomAttributes(); - IdentifierNameSyntax fieldName = IdentifierName("value"); - VariableDeclaratorSyntax fieldDeclarator = VariableDeclarator(fieldName.Identifier); - (TypeSyntax FieldType, SyntaxList AdditionalMembers, AttributeSyntax? MarshalAs) fieldInfo = - this.ReinterpretFieldType(fieldDef, fieldDef.DecodeSignature(SignatureHandleProvider.Instance, null).ToTypeSyntax(this.fieldTypeSettings, fieldAttributes).Type, fieldAttributes, this.DefaultContext); - SyntaxList members = List(); - - FieldDeclarationSyntax fieldSyntax = FieldDeclaration( - VariableDeclaration(fieldInfo.FieldType).AddVariables(fieldDeclarator)) - .AddModifiers(TokenWithSpace(SyntaxKind.PrivateKeyword), TokenWithSpace(SyntaxKind.ReadOnlyKeyword)); - members = members.Add(fieldSyntax); - MemberAccessExpressionSyntax fieldAccessExpression = MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, ThisExpression(), IdentifierName("value")); - - // Add property accessor - members = members.Add(PropertyDeclaration(PredefinedType(TokenWithSpace(SyntaxKind.IntKeyword)), "Value") - .WithExpressionBody(ArrowExpressionClause(fieldAccessExpression)).WithSemicolonToken(SemicolonWithLineFeed) - .AddModifiers(TokenWithSpace(this.Visibility))); - - // unsafe BOOL(bool value) => this.value = *(sbyte*)&value; - IdentifierNameSyntax valueParameter = IdentifierName("value"); - ExpressionSyntax boolToSByte = PrefixUnaryExpression( - SyntaxKind.PointerIndirectionExpression, - CastExpression( - PointerType(PredefinedType(TokenWithNoSpace(SyntaxKind.SByteKeyword))), - PrefixUnaryExpression(SyntaxKind.AddressOfExpression, valueParameter))); - members = members.Add(ConstructorDeclaration(name.Identifier) - .AddModifiers(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.UnsafeKeyword)) - .AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(PredefinedType(TokenWithSpace(SyntaxKind.BoolKeyword)))) - .WithExpressionBody(ArrowExpressionClause(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, fieldAccessExpression, boolToSByte).WithOperatorToken(TokenWithSpaces(SyntaxKind.EqualsToken)))) - .WithSemicolonToken(SemicolonWithLineFeed)); - - // BOOL(int value) => this.value = value; - members = members.Add(ConstructorDeclaration(name.Identifier) - .AddModifiers(TokenWithSpace(this.Visibility)) - .AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(PredefinedType(TokenWithSpace(SyntaxKind.IntKeyword)))) - .WithExpressionBody(ArrowExpressionClause(AssignmentExpression(SyntaxKind.SimpleAssignmentExpression, fieldAccessExpression, valueParameter).WithOperatorToken(TokenWithSpaces(SyntaxKind.EqualsToken)))) - .WithSemicolonToken(SemicolonWithLineFeed)); - - // public unsafe static implicit operator bool(BOOL value) - // { - // sbyte v = checked((sbyte)value.value); - // return *(bool*)&v; - // } - IdentifierNameSyntax localVarName = IdentifierName("v"); - ExpressionSyntax sbyteToBool = PrefixUnaryExpression( - SyntaxKind.PointerIndirectionExpression, - CastExpression( - PointerType(PredefinedType(TokenWithNoSpace(SyntaxKind.BoolKeyword))), - PrefixUnaryExpression(SyntaxKind.AddressOfExpression, localVarName))); - BlockSyntax? implicitBOOLtoBoolBody = Block().AddStatements( - LocalDeclarationStatement(VariableDeclaration(PredefinedType(Token(SyntaxKind.SByteKeyword)))).AddDeclarationVariables( - VariableDeclarator(localVarName.Identifier).WithInitializer(EqualsValueClause(CheckedExpression(SyntaxKind.CheckedExpression, CastExpression(PredefinedType(Token(SyntaxKind.SByteKeyword)), MemberAccessExpression(SyntaxKind.SimpleMemberAccessExpression, valueParameter, fieldName)))))), - ReturnStatement(sbyteToBool)); - members = members.Add(ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), PredefinedType(Token(SyntaxKind.BoolKeyword))) - .AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(name.WithTrailingTrivia(TriviaList(Space)))) - .WithBody(implicitBOOLtoBoolBody) - .AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword), TokenWithSpace(SyntaxKind.UnsafeKeyword))); // operators MUST be public - - // public static implicit operator BOOL(bool value) => new BOOL(value); - members = members.Add(ConversionOperatorDeclaration(Token(SyntaxKind.ImplicitKeyword), name) - .AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(PredefinedType(TokenWithSpace(SyntaxKind.BoolKeyword)))) - .WithExpressionBody(ArrowExpressionClause(ObjectCreationExpression(name).AddArgumentListArguments(Argument(valueParameter)))) - .AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword)) // operators MUST be public - .WithSemicolonToken(SemicolonWithLineFeed)); - - // public static explicit operator BOOL(int value) => new BOOL(value); - members = members.Add(ConversionOperatorDeclaration(Token(SyntaxKind.ExplicitKeyword), name) - .AddParameterListParameters(Parameter(valueParameter.Identifier).WithType(PredefinedType(TokenWithSpace(SyntaxKind.IntKeyword)))) - .WithExpressionBody(ArrowExpressionClause(ObjectCreationExpression(name).AddArgumentListArguments(Argument(valueParameter)))) - .AddModifiers(TokenWithSpace(SyntaxKind.PublicKeyword), TokenWithSpace(SyntaxKind.StaticKeyword)) // operators MUST be public - .WithSemicolonToken(SemicolonWithLineFeed)); - - StructDeclarationSyntax result = StructDeclaration(name.Identifier) - .WithMembers(members) - .WithModifiers(TokenList(TokenWithSpace(this.Visibility), TokenWithSpace(SyntaxKind.ReadOnlyKeyword), TokenWithSpace(SyntaxKind.PartialKeyword))); - - result = this.AddApiDocumentation(name.Identifier.ValueText, result); - return result; - } - private EnumDeclarationSyntax DeclareEnum(TypeDefinition typeDef) { bool flagsEnum = false; diff --git a/src/Microsoft.Windows.CsWin32/templates/BOOL.cs b/src/Microsoft.Windows.CsWin32/templates/BOOL.cs new file mode 100644 index 00000000..81711235 --- /dev/null +++ b/src/Microsoft.Windows.CsWin32/templates/BOOL.cs @@ -0,0 +1,11 @@ +partial struct BOOL +{ + internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value; + public static unsafe implicit operator bool(BOOL value) + { + sbyte v = checked((sbyte)value.Value); + return *(bool*)&v; + } + + public static implicit operator BOOL(bool value) => new BOOL(value); +} diff --git a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs index 22cc60a3..b0dc3180 100644 --- a/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs +++ b/test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs @@ -1576,20 +1576,31 @@ namespace Windows.Win32 namespace Foundation { + [DebuggerDisplay(""{Value}"")] internal readonly partial struct BOOL + : IEquatable { - private readonly int value; + internal readonly int Value; + internal BOOL(int value) => this.Value = value; + public static implicit operator int(BOOL value) => value.Value; + public static explicit operator BOOL(int value) => new BOOL(value); + public static bool operator ==(BOOL left, BOOL right) => left.Value == right.Value; + public static bool operator !=(BOOL left, BOOL right) => !(left == right); + + public bool Equals(BOOL other) => this.Value == other.Value; - internal int Value => this.value; - internal unsafe BOOL(bool value) => this.value = *(sbyte*)&value; - internal BOOL(int value) => this.value = value; + public override bool Equals(object obj) => obj is BOOL other && this.Equals(other); + + public override int GetHashCode() => this.Value.GetHashCode(); + internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value; public static unsafe implicit operator bool(BOOL value) + { - sbyte v = checked((sbyte)value.value); + sbyte v = checked((sbyte)value.Value); return *(bool*)&v; } + public static implicit operator BOOL(bool value) => new BOOL(value); - public static explicit operator BOOL(int value) => new BOOL(value); } } } @@ -1837,20 +1848,31 @@ namespace Windows.Win32 namespace Foundation { + [DebuggerDisplay(""{Value}"")] internal readonly partial struct BOOL + : IEquatable { - private readonly int value; + internal readonly int Value; + internal BOOL(int value) => this.Value = value; + public static implicit operator int(BOOL value) => value.Value; + public static explicit operator BOOL(int value) => new BOOL(value); + public static bool operator ==(BOOL left, BOOL right) => left.Value == right.Value; + public static bool operator !=(BOOL left, BOOL right) => !(left == right); + + public bool Equals(BOOL other) => this.Value == other.Value; + + public override bool Equals(object obj) => obj is BOOL other && this.Equals(other); - internal int Value => this.value; - internal unsafe BOOL(bool value) => this.value = *(sbyte*)&value; - internal BOOL(int value) => this.value = value; + public override int GetHashCode() => this.Value.GetHashCode(); + internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value; public static unsafe implicit operator bool(BOOL value) + { - sbyte v = checked((sbyte)value.value); + sbyte v = checked((sbyte)value.Value); return *(bool*)&v; } + public static implicit operator BOOL(bool value) => new BOOL(value); - public static explicit operator BOOL(int value) => new BOOL(value); } } } @@ -2149,20 +2171,31 @@ namespace Windows.Win32 namespace Foundation { + [DebuggerDisplay(""{Value}"")] internal readonly partial struct BOOL + : IEquatable { - private readonly int value; + internal readonly int Value; + internal BOOL(int value) => this.Value = value; + public static implicit operator int(BOOL value) => value.Value; + public static explicit operator BOOL(int value) => new BOOL(value); + public static bool operator ==(BOOL left, BOOL right) => left.Value == right.Value; + public static bool operator !=(BOOL left, BOOL right) => !(left == right); - internal int Value => this.value; - internal unsafe BOOL(bool value) => this.value = *(sbyte*)&value; - internal BOOL(int value) => this.value = value; + public bool Equals(BOOL other) => this.Value == other.Value; + + public override bool Equals(object obj) => obj is BOOL other && this.Equals(other); + + public override int GetHashCode() => this.Value.GetHashCode(); + internal unsafe BOOL(bool value) => this.Value = *(sbyte*)&value; public static unsafe implicit operator bool(BOOL value) + { - sbyte v = checked((sbyte)value.value); + sbyte v = checked((sbyte)value.Value); return *(bool*)&v; } + public static implicit operator BOOL(bool value) => new BOOL(value); - public static explicit operator BOOL(int value) => new BOOL(value); } } }