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 @@ -61,26 +61,12 @@ private static bool IsAttributeApplicable(AttributeInfo attributeInfo, ISymbol s
type = named.TypeArguments[0];
}

return IsDateTimeType(type);
return type.IsDateTimeOrDateTimeOffset();
}

return true;
}

/// <summary>
/// Determines whether the given type is System.DateTime or System.DateTimeOffset
/// using robust symbol identity rather than brittle name comparisons.
/// </summary>
private static bool IsDateTimeType(ITypeSymbol type)
{
if (type.SpecialType == SpecialType.System_DateTime)
return true;

// DateTimeOffset has no SpecialType, so identify it by its fully-qualified name.
return type.Name == nameof(DateTimeOffset)
&& type.ContainingNamespace?.ToDisplayString() == "System";
}

/// <summary>
/// Validates all attributes on a symbol and reports diagnostics.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
using Microsoft.CodeAnalysis;

namespace Goa.Clients.Dynamo.Generator.Models;

/// <summary>
/// Helper extensions for inspecting Roslyn type symbols.
/// </summary>
internal static class TypeSymbolExtensions
{
/// <summary>
/// Determines whether the given type is System.DateTime or System.DateTimeOffset
/// using robust symbol identity rather than brittle name comparisons.
/// </summary>
public static bool IsDateTimeOrDateTimeOffset(this ITypeSymbol type)
{
if (type.SpecialType == SpecialType.System_DateTime)
return true;

// DateTimeOffset has no SpecialType, so identify it by its fully-qualified name.
return type.Name == nameof(DateTimeOffset)
&& type.ContainingNamespace?.ToDisplayString() == "System";
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,8 @@ public bool CanHandle(PropertyInfo propertyInfo)
{
var underlyingType = propertyInfo.UnderlyingType;
var hasUnixTimestamp = propertyInfo.Attributes.Any(a => a is UnixTimestampAttributeInfo);

return hasUnixTimestamp &&
(underlyingType.Name == nameof(DateTime) || underlyingType.Name == nameof(DateTimeOffset));

return hasUnixTimestamp && underlyingType.IsDateTimeOrDateTimeOffset();
}

public string GenerateToAttributeValue(PropertyInfo propertyInfo)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using Microsoft.CodeAnalysis;
using Goa.Clients.Dynamo.Generator.TypeHandlers;
using Goa.Clients.Dynamo.Generator.Tests.Helpers;

Expand Down Expand Up @@ -92,6 +93,33 @@ await Assert.That(result)
.IsFalse();
}

[Test]
public async Task CanHandle_WithUserDefinedTypeNamedDateTime_ShouldReturnFalse()
{
// Arrange: a user-defined type named "DateTime" outside the System namespace
// must not be treated as System.DateTime. The robust symbol-based check relies
// on SpecialType/namespace rather than the type name alone.
var spoofedDateTime = MockSymbolFactory.CreateNamedTypeSymbol(
"DateTime",
"MyApp.DateTime",
namespaceName: "MyApp",
specialType: SpecialType.None).Object;

var propertyInfo = TestModelBuilders.CreateUnixTimestampPropertyInfo(
"FakeTimestamp",
spoofedDateTime,
isNullable: false,
format: Models.UnixTimestampFormat.Seconds
);

// Act
var result = _handler.CanHandle(propertyInfo);

// Assert
await Assert.That(result)
.IsFalse();
}

[Test]
public async Task GenerateToAttributeValue_NonNullableDateTime_SecondsFormat_ShouldGenerateCorrectCode()
{
Expand Down
Loading