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 @@ -28,7 +28,7 @@ static void Main(string[] args)
VerifyCSharpDiagnostic(source,
new DiagnosticResult
{
Id = "INTL0304",
Id = "INTL0202",
Severity = DiagnosticSeverity.Warning,
Message = "Using the symbol 'DateTimeOffset.implicit operator DateTimeOffset(DateTime)' can result in unpredictable behavior.",
Locations =
Expand Down Expand Up @@ -69,7 +69,7 @@ static void Main(string[] args)
VerifyCSharpDiagnostic(source,
new DiagnosticResult
{
Id = "INTL0304",
Id = "INTL0202",
Severity = DiagnosticSeverity.Warning,
Message = "Using the symbol 'DateTimeOffset.implicit operator DateTimeOffset(DateTime)' can result in unpredictable behavior.",
Locations =
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,15 +9,15 @@ namespace IntelliTect.Analyzer.Analyzers
[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class BanImplicitDateTimeToDateTimeOffsetConversion : DiagnosticAnalyzer
{
private const string Category = "Performance";
private const string Category = "Reliability";

private static readonly DiagnosticDescriptor _Rule304 = new DiagnosticDescriptor(Rule304.DiagnosticId,
Rule304.Title,
Rule304.MessageFormat,
Category, DiagnosticSeverity.Warning, true, Rule304.Description,
Rule304.HelpMessageUri);
private static readonly DiagnosticDescriptor _Rule202 = new DiagnosticDescriptor(Rule202.DiagnosticId,
Rule202.Title,
Rule202.MessageFormat,
Category, DiagnosticSeverity.Warning, true, Rule202.Description,
Rule202.HelpMessageUri);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(_Rule304);
public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(_Rule202);

public override void Initialize(AnalysisContext context)
{
Expand All @@ -44,16 +44,16 @@ private void AnalyzeInvocation(OperationAnalysisContext context)
INamedTypeSymbol dateTimeOffsetType = context.Compilation.GetTypeByMetadataName("System.DateTimeOffset");
if (containingType.Equals(dateTimeOffsetType))
{
context.ReportDiagnostic(Diagnostic.Create(_Rule304, conversionOperation.Syntax.GetLocation()));
context.ReportDiagnostic(Diagnostic.Create(_Rule202, conversionOperation.Syntax.GetLocation()));
}
}


}

private static class Rule304
private static class Rule202
{
internal const string DiagnosticId = "INTL0304";
internal const string DiagnosticId = "INTL0202";
internal const string Title = "Do not use implicit conversion from `DateTime` to `DateTimeOffset`";
internal const string MessageFormat = "Using the symbol 'DateTimeOffset.implicit operator DateTimeOffset(DateTime)' can result in unpredictable behavior.";
#pragma warning disable INTL0001 // Allow field to not be prefixed with an underscore to match the style
Expand Down
23 changes: 22 additions & 1 deletion docs/analyzers/02XX.Reliability.md
Original file line number Diff line number Diff line change
Expand Up @@ -27,4 +27,25 @@ public async void SomeMethod()

### When to suppress

The only acceptable use of `async void` is in a top level methods, such as event handlers. For these cases it is safe to suppress this warning. In all other cases, this warning should **NOT** be suppressed.
The only acceptable use of `async void` is in a top level methods, such as event handlers. For these cases it is safe to suppress this warning. In all other cases, this warning should **NOT** be suppressed.


#### INTL0202 - Do not implicitly convert from `DateTime` to `DateTimeOffset`.

Implicit conversion of `DateTime` to `DateTimeOffset` determines timezone offset based on the `DateTime.Kind` value, and for
`DateTimeKind.Unspecified` it assumes `DateTimeKind.Local`, which may lead to differing behavior between running locally
and on a server. Code relying on certain behaviors may function correctly when run in tests locally because all code will
be running in the same timezone. This same code will fail or have different behavior when some of it is running in a hosted
environment like Azure where the time zone is often set to UTC.

See the feature proposal to remove this from the [dotnet corelib](https://github.com/dotnet/runtime/issues/32954).

> Misleading usecase is that TimeZoneInfo.ConvertTime has 2 overloads for DateTime and DateTimeOffset. When result of the
> first one is assigned to DateTimeOffset typed variable, DateTimeOffset record with local time zone offset is created.
> This is unclear for common code reader there's something unintended behaviour may take a place ((hey, I've supplied date,
> time and timezone to this function, and expect it to return date&time object for this timezone)), because types of either
> DateTime or DateTimeOffset that comes to ConvertTime argument may be masked by complex computational expression.

### When to suppress

Do not suppress a warning from this rule.
16 changes: 2 additions & 14 deletions docs/analyzers/03XX.Performance.md
Original file line number Diff line number Diff line change
Expand Up @@ -36,18 +36,6 @@ Do not suppress a warning from this rule.

All local variables should be accessed, or replaced with [discards](https://docs.microsoft.com/dotnet/csharp/fundamentals/functional/discards) (underscore character) to indicate they are unused.

#### INTL0304 - Do not implicitly convert from `DateTime` to `DateTimeOffset`.

Implicit conversion of `DateTime` to `DateTimeOffset` determines timezone offset based on the `DateTime.Kind` value, and for
`DateTimeKind.Unspecified` it assumes `DateTimeKind.Local`, which may lead to differing behavior between running locally
and on a server. Code relying on certain behaviors may function correctly when run in tests locally because all code will
be running in the same timezone. This same code will fail or have different behavior when some of it is running in a hosted
environment like Azure where the time zone is often set to UTC.

See the feature proposal to remove this from the [dotnet corelib](https://github.com/dotnet/runtime/issues/32954).
### When to suppress

> Misleading usecase is that TimeZoneInfo.ConvertTime has 2 overloads for DateTime and DateTimeOffset. When result of the
> first one is assigned to DateTimeOffset typed variable, DateTimeOffset record with local time zone offset is created.
> This is unclear for common code reader there's something unintended behaviour may take a place ((hey, I've supplied date,
> time and timezone to this function, and expect it to return date&time object for this timezone)), because types of either
> DateTime or DateTimeOffset that comes to ConvertTime argument may be masked by complex computational expression.
Do not suppress a warning from this rule.