Skip to content
Open
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
6 changes: 6 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -91,3 +91,9 @@ artifacts/
docfx/artifacts/
local_packages/
*.cast

# Graphic memory & plan markdown files
GRAPHIC_MEMORY.md
plans/
*.skill.md

7 changes: 5 additions & 2 deletions Directory.Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
</PropertyGroup>
<ItemGroup>
<!-- Enable Nuget Source Link for github -->
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="5.9.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.11.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing" Version="1.1.2" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing" Version="1.1.2" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.14.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.VisualBasic.Workspaces" Version="4.14.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.MSBuild" Version="4.14.0" />
Expand All @@ -13,7 +15,8 @@
<PackageVersion Include="Microsoft.SourceLink.GitHub" Version="10.0.203" />
<PackageVersion Include="Microsoft.CodeAnalysis" Version="4.14.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.14.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="5.9.0" />
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.14.0" />

<PackageVersion Include="Microsoft.Extensions.Configuration" Version="10.0.12" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Binder" Version="10.0.12" />
<PackageVersion Include="Microsoft.Extensions.Configuration.Json" Version="10.0.12" />
Expand Down
24 changes: 24 additions & 0 deletions Terminal.Gui.Analyzers/Terminal.Gui.Analyzers.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<!-- Roslyn Analyzers must target netstandard2.0 for MSBuild and Visual Studio compatibility -->
<TargetFramework>netstandard2.0</TargetFramework>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
<RootNamespace>Terminal.Gui.Analyzers</RootNamespace>
<EnforceExtendedAnalyzerRules>true</EnforceExtendedAnalyzerRules>
<IsRoslynComponent>true</IsRoslynComponent>
<NoWarn>$(NoWarn);RS2008;RS1032;RS1038</NoWarn>
</PropertyGroup>


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

</Project>
108 changes: 108 additions & 0 deletions Terminal.Gui.Analyzers/V1ApiCodeFixProvider.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,108 @@
using System.Collections.Immutable;
using System.Composition;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.CodeAnalysis;
using Microsoft.CodeAnalysis.CodeActions;
using Microsoft.CodeAnalysis.CodeFixes;
using Microsoft.CodeAnalysis.CSharp;
using Microsoft.CodeAnalysis.CSharp.Syntax;

namespace Terminal.Gui.Analyzers
{
[ExportCodeFixProvider(LanguageNames.CSharp, Name = nameof(V1ApiCodeFixProvider)), Shared]
public class V1ApiCodeFixProvider : CodeFixProvider
{
public sealed override ImmutableArray<string> FixableDiagnosticIds => ImmutableArray.Create(new[] {
V1ApiDiagnosticAnalyzer.RuleClicked.Id,
V1ApiDiagnosticAnalyzer.RuleToplevel.Id,
V1ApiDiagnosticAnalyzer.RuleBounds.Id,
V1ApiDiagnosticAnalyzer.RuleTabView.Id,
V1ApiDiagnosticAnalyzer.RuleRadioGroup.Id,
V1ApiDiagnosticAnalyzer.RuleAcceptingIgnoresArgs.Id });

public sealed override FixAllProvider GetFixAllProvider() => WellKnownFixAllProviders.BatchFixer;

public sealed override async Task RegisterCodeFixesAsync(CodeFixContext context)
{
var root = await context.Document.GetSyntaxRootAsync(context.CancellationToken).ConfigureAwait(false);
if (root == null)
{
return;
}

foreach (var diagnostic in context.Diagnostics)
{
var diagnosticSpan = diagnostic.Location.SourceSpan;
var token = root.FindToken(diagnosticSpan.Start);

if (diagnostic.Id == V1ApiDiagnosticAnalyzer.RuleClicked.Id)
{
context.RegisterCodeFix(
CodeAction.Create(
title: "Replace with 'Accepted'",
createChangedDocument: c => ReplaceTokenAsync(context.Document, root, token, "Accepted", c),
equivalenceKey: "UseAccepted"),
diagnostic);
}
else if (diagnostic.Id == V1ApiDiagnosticAnalyzer.RuleBounds.Id)
{
context.RegisterCodeFix(
CodeAction.Create(
title: "Replace with 'Viewport'",
createChangedDocument: c => ReplaceTokenAsync(context.Document, root, token, "Viewport", c),
equivalenceKey: "UseViewport"),
diagnostic);
}
else if (diagnostic.Id == V1ApiDiagnosticAnalyzer.RuleToplevel.Id)
{
context.RegisterCodeFix(
CodeAction.Create(
title: "Replace with 'Window'",
createChangedDocument: c => ReplaceTokenAsync(context.Document, root, token, "Window", c),
equivalenceKey: "UseWindow"),
diagnostic);
}
else if (diagnostic.Id == V1ApiDiagnosticAnalyzer.RuleTabView.Id)
{
context.RegisterCodeFix(
CodeAction.Create(
title: "Replace with 'Tabs'",
createChangedDocument: c => ReplaceTokenAsync(context.Document, root, token, "Tabs", c),
equivalenceKey: "UseTabs"),
diagnostic);
}
else if (diagnostic.Id == V1ApiDiagnosticAnalyzer.RuleRadioGroup.Id)
{
context.RegisterCodeFix(
CodeAction.Create(
title: "Replace with 'OptionSelector'",
createChangedDocument: c => ReplaceTokenAsync(context.Document, root, token, "OptionSelector", c),
equivalenceKey: "UseOptionSelector"),
Comment on lines +75 to +81
diagnostic);
}
else if (diagnostic.Id == V1ApiDiagnosticAnalyzer.RuleAcceptingIgnoresArgs.Id)
{
var node = root.FindNode(diagnosticSpan);
if (node is AssignmentExpressionSyntax assignment && assignment.Left is MemberAccessExpressionSyntax memberAccess)
{
var eventToken = memberAccess.Name.Identifier;
context.RegisterCodeFix(
CodeAction.Create(
title: "Switch event to 'Accepted'",
createChangedDocument: c => ReplaceTokenAsync(context.Document, root, eventToken, "Accepted", c),
equivalenceKey: "SwitchToAccepted"),
diagnostic);
}
}
}
}

private static Task<Document> ReplaceTokenAsync(Document document, SyntaxNode root, SyntaxToken oldToken, string newName, CancellationToken cancellationToken)
{
var newToken = SyntaxFactory.Identifier(oldToken.LeadingTrivia, newName, oldToken.TrailingTrivia);
var newRoot = root.ReplaceToken(oldToken, newToken);
return Task.FromResult(document.WithSyntaxRoot(newRoot));
}
}
}
Loading
Loading