Forge
csharpdeeb25a2
1using System.Collections.Immutable;
2using System.Globalization;
3using Basic.Reference.Assemblies;
4using Microsoft.CodeAnalysis;
5using Microsoft.CodeAnalysis.CSharp;
6using Microsoft.CodeAnalysis.Diagnostics;
7using Xunit;
8
9namespace CascadeIDE.ArchitectureAnalyzers.Tests;
10
11public sealed class IdeDisplayLayerArchitectureAnalyzerTests
12{
13 private static async Task<ImmutableArray<Diagnostic>> RunAnalyzerAsync(params (string Path, string Text)[] files)
14 {
15 var trees = new List<SyntaxTree>(files.Length);
16 foreach (var (path, text) in files)
17 trees.Add(CSharpSyntaxTree.ParseText(text, path: path));
18
19 var compilation = CSharpCompilation.Create(
20 "TestAssembly",
21 trees,
22 Net80.References.All,
23 new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
24
25 var analyzer = new IdeDisplayLayerArchitectureAnalyzer();
26 var withAnalyzers = compilation.WithAnalyzers(ImmutableArray.Create<DiagnosticAnalyzer>(analyzer));
27 return await withAnalyzers.GetAnalyzerDiagnosticsAsync();
28 }
29
30 [Fact]
31 public async Task CASCOPE013_UsingCockpit_InIdeDisplay_Reports()
32 {
33 var diags = await RunAnalyzerAsync((
34 @"D:\repo\IdeDisplay\Bad.cs",
35 """
36 using CascadeIDE.Cockpit.Channels;
37
38 namespace CascadeIDE.IdeDisplay.Example;
39
40 public static class C { }
41 """));
42
43 var d = Assert.Single(diags);
44 Assert.Equal(IdeDisplayLayerArchitectureAnalyzer.CockpitNamespaceId, d.Id);
45 }
46
47 [Fact]
48 public async Task CASCOPE014_UsingAvalonia_InIdeDisplay_Reports()
49 {
50 var diags = await RunAnalyzerAsync((
51 @"D:\repo\IdeDisplay\Bad.cs",
52 """
53 using Avalonia.Media;
54
55 namespace CascadeIDE.IdeDisplay.Example;
56
57 public static class C { }
58 """));
59
60 var d = Assert.Single(diags);
61 Assert.Equal(IdeDisplayLayerArchitectureAnalyzer.AvaloniaNamespaceId, d.Id);
62 }
63
64 [Fact]
65 public async Task CASCOPE015_UsingUiChrome_InIdeDisplay_Reports()
66 {
67 var diags = await RunAnalyzerAsync((
68 @"D:\repo\IdeDisplay\Bad.cs",
69 """
70 using CascadeIDE.Features.UiChrome;
71
72 namespace CascadeIDE.IdeDisplay.Example;
73
74 public static class C { }
75 """));
76
77 var d = Assert.Single(diags);
78 Assert.Equal(IdeDisplayLayerArchitectureAnalyzer.FeaturesUiChromeId, d.Id);
79 }
80
81 [Fact]
82 public async Task IdeDisplay_WithoutRestrictedUsings_Clean()
83 {
84 var diags = await RunAnalyzerAsync((
85 @"D:\repo\IdeDisplay\Ok.cs",
86 """
87 namespace CascadeIDE.IdeDisplay.Example;
88
89 public static class C { }
90 """));
91
92 Assert.Empty(diags);
93 }
94
95 [Fact]
96 public async Task CASCOPE014_AvaloniaTypeInMember_InIdeDisplayNamespace_Reports()
97 {
98 var diags = await RunAnalyzerAsync(
99 (@"D:\repo\Support\AvaloniaStub.cs", """
100namespace Avalonia.Controls;
101
102public sealed class Control { }
103"""),
104 (@"D:\repo\IdeDisplay\Bad.cs", """
105namespace CascadeIDE.IdeDisplay.Example;
106
107public sealed class Host
108{
109 public Avalonia.Controls.Control? Widget { get; set; }
110}
111"""));
112
113 var d = Assert.Single(diags);
114 Assert.Equal(IdeDisplayLayerArchitectureAnalyzer.AvaloniaNamespaceId, d.Id);
115 Assert.Contains("Avalonia", d.GetMessage(CultureInfo.InvariantCulture), StringComparison.Ordinal);
116 }
117
118 [Fact]
119 public async Task CASCOPE013_CockpitTypeInMember_InIdeDisplayNamespace_Reports()
120 {
121 var diags = await RunAnalyzerAsync(
122 (@"D:\repo\Support\CockpitStub.cs", """
123namespace CascadeIDE.Cockpit.Channels;
124
125public sealed class ChannelState { }
126"""),
127 (@"D:\repo\IdeDisplay\Bad.cs", """
128namespace CascadeIDE.IdeDisplay.Example;
129
130public sealed class Host
131{
132 public CascadeIDE.Cockpit.Channels.ChannelState? State { get; set; }
133}
134"""));
135
136 var d = Assert.Single(diags);
137 Assert.Equal(IdeDisplayLayerArchitectureAnalyzer.CockpitNamespaceId, d.Id);
138 }
139}
140
View only · write via MCP/CIDE