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

chore: Make TODO comments without URL to a GitHub issue compile error #1472

Draft
wants to merge 9 commits into
base: main
Choose a base branch
from
Draft
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
3 changes: 3 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@ indent_size = 4
insert_final_newline = true

[*.cs]
// TODO comments should have an associated issue URL
dotnet_diagnostic.TODO001.issueRegex = https://github.com/digdir/dialogporten/issues/\d+

# Attributes should be on a line above the item they are associated with
place_attribute_on_same_line = false

Expand Down
7 changes: 7 additions & 0 deletions Digdir.Domain.Dialogporten.sln
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Library.Utils.AspNet
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Tool.Dialogporten.SlackNotifier.Tests", "tests\Digdir.Tool.Dialogporten.SlackNotifier.Tests\Digdir.Tool.Dialogporten.SlackNotifier.Tests.csproj", "{F7DF2792-9C83-49F7-B7DD-556E8EC577DB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Digdir.Library.Analyzers", "src\Digdir.Library.Analyzers\Digdir.Library.Analyzers\Digdir.Library.Analyzers.csproj", "{88783EA8-EE64-490B-9C1E-E2365E861A88}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -165,6 +167,10 @@ Global
{F7DF2792-9C83-49F7-B7DD-556E8EC577DB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F7DF2792-9C83-49F7-B7DD-556E8EC577DB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F7DF2792-9C83-49F7-B7DD-556E8EC577DB}.Release|Any CPU.Build.0 = Release|Any CPU
{88783EA8-EE64-490B-9C1E-E2365E861A88}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{88783EA8-EE64-490B-9C1E-E2365E861A88}.Debug|Any CPU.Build.0 = Debug|Any CPU
{88783EA8-EE64-490B-9C1E-E2365E861A88}.Release|Any CPU.ActiveCfg = Release|Any CPU
{88783EA8-EE64-490B-9C1E-E2365E861A88}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down Expand Up @@ -196,6 +202,7 @@ Global
{E389C7C8-9610-40AC-86DC-769B1B7DC78E} = {CADB8189-4AA1-4732-844A-C41DBF3EC8B7}
{6A485C65-3613-4A49-A16F-2789119F6F38} = {096E9B69-6783-4446-A895-0B6D7729A0D9}
{F7DF2792-9C83-49F7-B7DD-556E8EC577DB} = {CADB8189-4AA1-4732-844A-C41DBF3EC8B7}
{88783EA8-EE64-490B-9C1E-E2365E861A88} = {096E9B69-6783-4446-A895-0B6D7729A0D9}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {B2FE67FF-7622-4AFB-AD8E-961B6A39D888}
Expand Down
4 changes: 4 additions & 0 deletions Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@
<AnalysisLevel>8</AnalysisLevel>
</PropertyGroup>

<ItemGroup>
<ProjectReference Include="..\Digdir.Library.Analyzers\Digdir.Library.Analyzers\Digdir.Library.Analyzers.csproj"
OutputItemType="Analyzer" ReferenceOutputAssembly="false"/>
</ItemGroup>
</Project>
Original file line number Diff line number Diff line change
Expand Up @@ -28,9 +28,8 @@ public static class ClaimsPrincipalExtensions
private const char ScopeClaimSeparator = ' ';
private const string PidClaim = "pid";


// TODO: This scope is also defined in WebAPI/GQL. Can this be fetched from a common auth lib?
// https://github.com/digdir/dialogporten/issues/647
// TODO: https://github.com/digdir/dialogporten/issues/647
// This scope is also defined in WebAPI/GQL. Can this be fetched from a common auth lib?
// This could be done for all claims/scopes/prefixes etc, there are duplicates
public const string ServiceProviderScope = "digdir:dialogporten.serviceprovider";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -62,8 +62,11 @@ public async Task<UserInformation> GetCurrentUserInformation(CancellationToken c
var userId = GetCurrentUserId();
var name = userId.Type switch
{
UserIdType.Person or UserIdType.ServiceOwnerOnBehalfOfPerson => await _partyNameRegistry.GetName(userId.ExternalIdWithPrefix, cancellationToken),
UserIdType.SystemUser => "System User",// TODO: Implement when SystemUsers are introduced?
UserIdType.Person or UserIdType.ServiceOwnerOnBehalfOfPerson =>
await _partyNameRegistry.GetName(userId.ExternalIdWithPrefix, cancellationToken),
// TODO: https://github.com/digdir/dialogporten/issues/
// Implement when SystemUsers are introduced?
UserIdType.SystemUser => "System User",
UserIdType.Unknown => throw new UnreachableException(),
UserIdType.ServiceOwner => throw new UnreachableException(),
_ => throw new UnreachableException()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -118,8 +118,8 @@ public async Task<GetDialogResult> Handle(GetDialogQuery request, CancellationTo
return new EntityDeleted<DialogEntity>(request.DialogId);
}

// TODO: What if name lookup fails
// https://github.com/digdir/dialogporten/issues/387
// TODO: https://github.com/digdir/dialogporten/issues/387
// What if name lookup fails?
dialog.UpdateSeenAt(
currentUserInformation.UserId.ExternalIdWithPrefix,
currentUserInformation.UserId.Type,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ public async Task<UpdateDialogResult> Handle(UpdateDialogCommand request, Cancel

if (dialog.Deleted)
{
// TODO: When restoration is implemented, add a hint to the error message.
// https://github.com/digdir/dialogporten/pull/406
// TODO: https://github.com/digdir/dialogporten/issues/...
// When restoration is implemented, add a hint to the error message.
return new BadRequest($"Entity '{nameof(DialogEntity)}' with key '{request.Id}' is removed, and cannot be updated.");
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,8 @@ public override async Task StartAsync(CancellationToken cancellationToken)
// This method will block the application from starting until
// snapshots are loaded and permissions are verified

// TODO: Remove when checkpoint migration exists
// TODO: https://github.com/digdir/dialogporten/issues/...
// Remove when checkpoint migration exists
// Ensure table exists
await _snapshotRepository.EnsureCheckpointTableExists(cancellationToken);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,8 @@ public CheckpointRepository(

public async Task EnsureCheckpointTableExists(CancellationToken ct = default)
{
// TODO: Dette burde ligge sammen med OutboxMessage opprettelsen i infrastruktur via EF
// TODO: https://github.com/digdir/dialogporten/issues/...
// This should be located together with the OutboxMessage creation in the infrastructure via EF
await using var command = _dataSource.CreateCommand(
$"""
CREATE TABLE IF NOT EXISTS cdc_checkpoint (
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,10 @@ public MassTransitSink(ISendEndpointProvider sender)

public async Task Send(IReadOnlyCollection<OutboxMessage> outboxMessages, CancellationToken cancellationToken)
{
// TODO: Configure uri
// TODO: Configure transaction
// TODO: https://github.com/digdir/dialogporten/issues/...
// Configure uri
// TODO: https://github.com/digdir/dialogporten/issues/...
// Configure transaction
var endpoint = await _sender.GetSendEndpoint(new Uri("exchange:Digdir.Domain.Dialogporten.Service"));
await endpoint.SendBatch(
outboxMessages,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,8 @@
CreatedAt = domainEvent.OccuredAt,
EventType = eventType.FullName!,
EventPayload = JsonSerializer.Serialize(domainEvent, eventType),
// TODO: Set correlation id
// TODO: https://github.com/digdir/dialogporten/issues/...

Check failure on line 26 in src/Digdir.Domain.Dialogporten.Domain/Outboxes/OutboxMessage.cs

View workflow job for this annotation

GitHub Actions / build / build-and-test

TODO comment must be followed by an issue URL (on the same line)

Check failure on line 26 in src/Digdir.Domain.Dialogporten.Domain/Outboxes/OutboxMessage.cs

View workflow job for this annotation

GitHub Actions / build / build-and-test

TODO comment must be followed by an issue URL (on the same line)
// Set correlation id
CorrelationId = Guid.NewGuid().ToString()
};
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,7 @@ private static XacmlJsonCategory CreateResourceCategory(string id, string servic
}
else if (ns == AttributeIdAppInstance)
{
// TODO!
// TODO: https://github.com/digdir/dialogporten/issues/...
// For app instances, we the syntax of the value is "{partyID}/{instanceID}".
// We do not have Altinn partyID in the request, so we cannot support this.
// This means we cannot easily support instance specific authorizations for apps.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
## Release 1.0

### New Rules

Rule ID | Category | Severity | Notes
--------|----------|----------|-------
TODO001 | Documentation | Error | TodoCommentAnalyzer
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
using System.Resources;

[assembly: NeutralResourcesLanguage("en")]
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<IsPackable>false</IsPackable>
<LangVersion>latest</LangVersion>

<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>

<RootNamespace>Digdir.Library.Analyzers</RootNamespace>
<AssemblyName>Digdir.Library.Analyzers</AssemblyName>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" Version="4.3.0"/>
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.3.0"/>
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
{
"$schema": "https://json.schemastore.org/launchsettings.json",
"profiles": {
"DebugRoslynAnalyzers": {
"commandName": "DebugRoslynComponent",
"targetProject": "../Digdir.Domain.Dialogporten.Application/Digdir.Domain.Dialogporten.Application.csproj",
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
using System.Collections.Immutable;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.Diagnostics;
using static System.Text.RegularExpressions.Regex;

namespace Digdir.Library.Analyzers;

[DiagnosticAnalyzer(LanguageNames.CSharp)]
public class TodoCommentAnalyzer : DiagnosticAnalyzer
{
public const string DiagnosticId = "TODO001";
private static readonly LocalizableString Title = "TODO comment must have an issue URL";
private static readonly LocalizableString MessageFormat = "TODO comment must be followed by an issue URL (on the same line)";
private static readonly LocalizableString Description = "TODO comments should be followed by an issue URL (on the same line).";

private const string Category = "Documentation";
private const string IssueRegexOptionKey = "dotnet_diagnostic.TODO001.issueRegex";

private static readonly DiagnosticDescriptor Rule = new(DiagnosticId, Title, MessageFormat, Category,
DiagnosticSeverity.Error, isEnabledByDefault: true, description: Description);

public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => [Rule];

public override void Initialize(AnalysisContext context)
{
context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
context.EnableConcurrentExecution();
context.RegisterSyntaxTreeAction(AnalyzeSyntaxTree);
}
private static void AnalyzeSyntaxTree(SyntaxTreeAnalysisContext context)
{
var options = context.Options.AnalyzerConfigOptionsProvider.GetOptions(context.Tree);
if (!options.TryGetValue(IssueRegexOptionKey, out var issueRegex) || string.IsNullOrEmpty(issueRegex))
{
return;
}

var trivia = context
.Tree
.GetRoot(context.CancellationToken)
.DescendantTrivia()
.Where(t => t.IsKind(SyntaxKind.SingleLineCommentTrivia));

foreach (var comment in trivia)
{
var commentText = comment.ToString();

if (!commentText.Contains("TODO")) continue;

if (IsMatch(commentText, issueRegex)) continue;

var diagnostic = Diagnostic.Create(Rule, comment.GetLocation());
context.ReportDiagnostic(diagnostic);
}
}
}
Loading