Skip to content

Commit 190eebe

Browse files
committed
Add DateTime operators to SYSTEMTIME and implement IEquatable
Add Tests for Template structs Fix up output formatting
1 parent 22521d1 commit 190eebe

File tree

3 files changed

+87
-1
lines changed

3 files changed

+87
-1
lines changed

src/Microsoft.Windows.CsWin32/Generator.cs

Lines changed: 27 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3726,6 +3726,7 @@ private StructDeclarationSyntax DeclareStruct(TypeDefinitionHandle typeDefHandle
37263726
{
37273727
case "RECT":
37283728
case "SIZE":
3729+
case "SYSTEMTIME":
37293730
members.AddRange(this.ExtractMembersFromTemplate(name.Identifier.ValueText));
37303731
break;
37313732
default:
@@ -6315,6 +6316,28 @@ internal WhitespaceRewriter()
63156316

63166317
public override SyntaxNode? VisitExpressionStatement(ExpressionStatementSyntax node) => base.VisitExpressionStatement(this.WithIndentingTrivia(node));
63176318

6319+
public override SyntaxNode? VisitInitializerExpression(InitializerExpressionSyntax node)
6320+
{
6321+
node = node
6322+
.WithOpenBraceToken(Token(TriviaList(this.IndentTrivia), SyntaxKind.OpenBraceToken, TriviaList(LineFeed)))
6323+
.WithCloseBraceToken(Token(TriviaList(this.IndentTrivia), SyntaxKind.CloseBraceToken, TriviaList(LineFeed)))
6324+
.WithTrailingTrivia(TriviaList());
6325+
using var indent = new Indent(this);
6326+
return base.VisitInitializerExpression(node);
6327+
}
6328+
6329+
public override SyntaxNode? VisitAssignmentExpression(AssignmentExpressionSyntax node)
6330+
{
6331+
if (node.Parent is InitializerExpressionSyntax)
6332+
{
6333+
return base.VisitAssignmentExpression(this.WithIndentingTrivia(node));
6334+
}
6335+
else
6336+
{
6337+
return base.VisitAssignmentExpression(node);
6338+
}
6339+
}
6340+
63186341
public override SyntaxNode? VisitTryStatement(TryStatementSyntax node) => base.VisitTryStatement(this.WithIndentingTrivia(node));
63196342

63206343
public override SyntaxNode? VisitFinallyClause(FinallyClauseSyntax node) => base.VisitFinallyClause(this.WithIndentingTrivia(node));
@@ -6389,7 +6412,10 @@ internal WhitespaceRewriter()
63896412
}
63906413
}
63916414

6392-
public override SyntaxNode? VisitReturnStatement(ReturnStatementSyntax node) => base.VisitReturnStatement(node.WithLeadingTrivia(this.IndentTrivia));
6415+
public override SyntaxNode? VisitReturnStatement(ReturnStatementSyntax node)
6416+
{
6417+
return base.VisitReturnStatement(this.WithIndentingTrivia(node));
6418+
}
63936419

63946420
public override SyntaxToken VisitToken(SyntaxToken token)
63956421
{
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
partial struct SYSTEMTIME
2+
: IEquatable<SYSTEMTIME>
3+
{
4+
public bool Equals(SYSTEMTIME other) => this.wYear == other.wYear && this.wMonth == other.wMonth && this.wDayOfWeek == other.wDayOfWeek && this.wDay == other.wDay && this.wHour == other.wHour && this.wMinute == other.wMinute && this.wSecond == other.wSecond && this.wMilliseconds == other.wMilliseconds;
5+
public override bool Equals(object obj) => obj is SYSTEMTIME other && this.Equals(other);
6+
public override int GetHashCode() => (this.wYear, this.wMonth, this.wDayOfWeek, this.wDay, this.wHour, this.wMinute, this.wSecond, this.wMilliseconds).GetHashCode();
7+
public static bool operator ==(SYSTEMTIME d1, SYSTEMTIME d2) => d1.wYear == d2.wYear && d1.wMonth == d2.wMonth && d1.wDayOfWeek == d2.wDayOfWeek && d1.wDay == d2.wDay && d1.wHour == d2.wHour && d1.wMinute == d2.wMinute && d1.wSecond == d2.wSecond && d1.wMilliseconds == d2.wMilliseconds;
8+
public static bool operator !=(SYSTEMTIME d1, SYSTEMTIME d2) => d1.wYear != d2.wYear && d1.wMonth != d2.wMonth && d1.wDayOfWeek != d2.wDayOfWeek && d1.wDay != d2.wDay && d1.wHour != d2.wHour && d1.wMinute != d2.wMinute && d1.wSecond != d2.wSecond && d1.wMilliseconds != d2.wMilliseconds;
9+
10+
public static explicit operator global::System.DateTime(SYSTEMTIME sysTime)
11+
{
12+
if (sysTime == default(SYSTEMTIME) || sysTime.wYear <= 0 || sysTime.wMonth <= 0 || sysTime.wDay <= 0)
13+
{
14+
return default;
15+
}
16+
17+
// DateTime gets DayOfWeek automatically
18+
return new global::System.DateTime(sysTime.wYear,
19+
sysTime.wMonth, sysTime.wDay, sysTime.wHour,
20+
sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
21+
}
22+
23+
public static explicit operator SYSTEMTIME(global::System.DateTime time)
24+
{
25+
if (time == default)
26+
{
27+
return default;
28+
}
29+
30+
return new SYSTEMTIME
31+
{
32+
wYear = checked((ushort)time.Year),
33+
wMonth = checked((ushort)time.Month),
34+
wDayOfWeek = checked((ushort)time.DayOfWeek),
35+
wDay = checked((ushort)time.Day),
36+
wHour = checked((ushort)time.Hour),
37+
wMinute = checked((ushort)time.Minute),
38+
wSecond = checked((ushort)time.Second),
39+
wMilliseconds = checked((ushort)time.Millisecond)
40+
};
41+
}
42+
}

test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -605,6 +605,24 @@ public void HandleStructsHaveStaticNullMember(string handleName)
605605
this.AssertGeneratedMember(handleName, "Null", $"internal static {handleName} Null => default;");
606606
}
607607

608+
[Theory]
609+
[InlineData("BOOL")]
610+
[InlineData("BOOLEAN")]
611+
[InlineData("HRESULT")]
612+
[InlineData("NTSTATUS")]
613+
[InlineData("PCSTR")]
614+
[InlineData("PCWSTR")]
615+
[InlineData("RECT")]
616+
[InlineData("SIZE")]
617+
[InlineData("SYSTEMTIME")]
618+
public void TemplateAPIsGenerate(string handleType)
619+
{
620+
this.generator = this.CreateGenerator();
621+
Assert.True(this.generator.TryGenerate(handleType, CancellationToken.None));
622+
this.CollectGeneratedCode(this.generator);
623+
this.AssertNoDiagnostics();
624+
}
625+
608626
[Theory]
609627
[InlineData("HANDLE")]
610628
[InlineData("HGDIOBJ")]

0 commit comments

Comments
 (0)