Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add DateTime operators to SYSTEMTIME #672

Merged
merged 2 commits into from
Sep 6, 2022
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
28 changes: 27 additions & 1 deletion src/Microsoft.Windows.CsWin32/Generator.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3726,6 +3726,7 @@ private StructDeclarationSyntax DeclareStruct(TypeDefinitionHandle typeDefHandle
{
case "RECT":
case "SIZE":
case "SYSTEMTIME":
elachlan marked this conversation as resolved.
Show resolved Hide resolved
members.AddRange(this.ExtractMembersFromTemplate(name.Identifier.ValueText));
break;
default:
Expand Down Expand Up @@ -6315,6 +6316,28 @@ internal WhitespaceRewriter()

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

public override SyntaxNode? VisitInitializerExpression(InitializerExpressionSyntax node)
{
node = node
.WithOpenBraceToken(Token(TriviaList(this.IndentTrivia), SyntaxKind.OpenBraceToken, TriviaList(LineFeed)))
.WithCloseBraceToken(Token(TriviaList(this.IndentTrivia), SyntaxKind.CloseBraceToken, TriviaList(LineFeed)))
.WithTrailingTrivia(TriviaList());
using var indent = new Indent(this);
return base.VisitInitializerExpression(node);
}

public override SyntaxNode? VisitAssignmentExpression(AssignmentExpressionSyntax node)
{
if (node.Parent is InitializerExpressionSyntax)
{
return base.VisitAssignmentExpression(this.WithIndentingTrivia(node));
}
else
{
return base.VisitAssignmentExpression(node);
}
}

public override SyntaxNode? VisitTryStatement(TryStatementSyntax node) => base.VisitTryStatement(this.WithIndentingTrivia(node));

public override SyntaxNode? VisitFinallyClause(FinallyClauseSyntax node) => base.VisitFinallyClause(this.WithIndentingTrivia(node));
Expand Down Expand Up @@ -6389,7 +6412,10 @@ internal WhitespaceRewriter()
}
}

public override SyntaxNode? VisitReturnStatement(ReturnStatementSyntax node) => base.VisitReturnStatement(node.WithLeadingTrivia(this.IndentTrivia));
public override SyntaxNode? VisitReturnStatement(ReturnStatementSyntax node)
{
return base.VisitReturnStatement(this.WithIndentingTrivia(node));
}

public override SyntaxToken VisitToken(SyntaxToken token)
{
Expand Down
42 changes: 42 additions & 0 deletions src/Microsoft.Windows.CsWin32/templates/SYSTEMTIME.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
partial struct SYSTEMTIME
: IEquatable<SYSTEMTIME>
{
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;
public override bool Equals(object obj) => obj is SYSTEMTIME other && this.Equals(other);
public override int GetHashCode() => (this.wYear, this.wMonth, this.wDayOfWeek, this.wDay, this.wHour, this.wMinute, this.wSecond, this.wMilliseconds).GetHashCode();
public static bool operator ==(SYSTEMTIME d1, SYSTEMTIME d2) => d1.Equals(d2);
public static bool operator !=(SYSTEMTIME d1, SYSTEMTIME d2) => !(d1 == d2);

public static explicit operator global::System.DateTime(SYSTEMTIME sysTime)
{
if (sysTime == default)
{
return default;
}

return new global::System.DateTime(sysTime.wYear, sysTime.wMonth, sysTime.wDay, sysTime.wHour, sysTime.wMinute, sysTime.wSecond, sysTime.wMilliseconds);
}

public static explicit operator SYSTEMTIME(global::System.DateTime time)
Copy link
Contributor Author

@elachlan elachlan Aug 27, 2022

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could maybe be implicit. But if it is ever used in a pinvoke it might cause issues because the minimum value for year is 1601.
https://docs.microsoft.com/en-us/windows/win32/api/minwinbase/ns-minwinbase-systemtime

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Let's leave it as explicit for now. It's safer to move from explicit to implicit later than the other way around.

{
if (time == default)
{
return default;
}

checked
{
return new SYSTEMTIME
{
wYear = (ushort)time.Year,
wMonth = (ushort)time.Month,
wDayOfWeek = (ushort)time.DayOfWeek,
wDay = (ushort)time.Day,
wHour = (ushort)time.Hour,
wMinute = (ushort)time.Minute,
wSecond = (ushort)time.Second,
wMilliseconds = (ushort)time.Millisecond,
};
}
}
}
18 changes: 18 additions & 0 deletions test/Microsoft.Windows.CsWin32.Tests/GeneratorTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -605,6 +605,24 @@ public void HandleStructsHaveStaticNullMember(string handleName)
this.AssertGeneratedMember(handleName, "Null", $"internal static {handleName} Null => default;");
}

[Theory]
[InlineData("BOOL")]
[InlineData("BOOLEAN")]
[InlineData("HRESULT")]
[InlineData("NTSTATUS")]
[InlineData("PCSTR")]
[InlineData("PCWSTR")]
[InlineData("RECT")]
[InlineData("SIZE")]
[InlineData("SYSTEMTIME")]
public void TemplateAPIsGenerate(string handleType)
{
this.generator = this.CreateGenerator();
Assert.True(this.generator.TryGenerate(handleType, CancellationToken.None));
this.CollectGeneratedCode(this.generator);
this.AssertNoDiagnostics();
}

[Theory]
[InlineData("HANDLE")]
[InlineData("HGDIOBJ")]
Expand Down