Skip to content

Commit 440bdc6

Browse files
authored
Merge pull request #1 from itmo-is-dev/feat/must-be-partial
Feat/must be partial
2 parents 23c5d10 + aed9269 commit 440bdc6

28 files changed

+727
-51
lines changed

Directory.Packages.props

+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<Project>
2+
<PropertyGroup>
3+
<ManagePackageVersionsCentrally>true</ManagePackageVersionsCentrally>
4+
</PropertyGroup>
5+
<ItemGroup>
6+
<PackageVersion Include="Ben.Demystifier" Version="0.4.1" />
7+
<PackageVersion Include="coverlet.collector" Version="3.2.0" />
8+
<PackageVersion Include="FluentAssertions" Version="6.11.0" />
9+
<PackageVersion Include="Lokad.ILPack" Version="0.2.0" />
10+
<PackageVersion Include="Microsoft.CodeAnalysis.Analyzers" Version="3.3.4" />
11+
<PackageVersion Include="Microsoft.CodeAnalysis.Common" Version="4.5.0" />
12+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit" Version="1.1.1" />
13+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit" Version="1.1.1" />
14+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.5.0" />
15+
<PackageVersion Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.5.0" />
16+
<PackageVersion Include="Microsoft.CodeAnalysis.CSharp" Version="4.5.0"/>
17+
<PackageVersion Include="Microsoft.NET.Test.Sdk" Version="17.5.0" />
18+
<PackageVersion Include="PolySharp" Version="1.13.1" />
19+
<PackageVersion Include="Sigil" Version="5.0.0" />
20+
<PackageVersion Include="System.Reflection.Emit" Version="4.7.0" />
21+
<PackageVersion Include="System.Reflection.Emit.ILGeneration" Version="4.7.0" />
22+
<PackageVersion Include="System.Reflection.Emit.Lightweight" Version="4.7.0" />
23+
<PackageVersion Include="xunit" Version="2.4.2" />
24+
<PackageVersion Include="Xunit.DependencyInjection.Demystifier" Version="8.0.1" />
25+
<PackageVersion Include="xunit.runner.visualstudio" Version="2.4.5" />
26+
</ItemGroup>
27+
</Project>

LICENSE.md

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
MIT License
2+
3+
Copyright (c) 2023 ITMO is DEV
4+
5+
Permission is hereby granted, free of charge, to any person obtaining a copy
6+
of this software and associated documentation files (the "Software"), to deal
7+
in the Software without restriction, including without limitation the rights
8+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9+
copies of the Software, and to permit persons to whom the Software is
10+
furnished to do so, subject to the following conditions:
11+
12+
The above copyright notice and this permission notice shall be included in all
13+
copies or substantial portions of the Software.
14+
15+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21+
SOFTWARE.

NuGet.config

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<configuration>
3+
<packageSources>
4+
<add key="local-Analyzers.MustBePartial" value="src/analyzers/SourceKit.Analyzers.MustBePartial/bin/Release"/>
5+
<add key="local-Analyzers.MustBePartial.Annotations" value="src/analyzers/SourceKit.Analyzers.MustBePartial.Annotations/bin/Release"/>
6+
</packageSources>
7+
</configuration>

README.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
# SourceKit

SourceKit.Sample/.editorconfig

+3
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[*.cs]
2+
3+
dotnet_diagnostic.SK1000.severity = warning
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
using SourceKit.Analyzers.MustBePartial.Annotations;
2+
3+
namespace SourceKit.Sample.Analyzers.MustBePartial;
4+
5+
[DerivativesMustBePartial]
6+
public interface IPartialBase { }
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace SourceKit.Sample.Analyzers.MustBePartial;
2+
3+
public class NonPartialDerivative : IPartialBase
4+
{
5+
6+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
namespace SourceKit.Sample.Analyzers.MustBePartial;
2+
3+
public partial class PartialDerivative : IPartialBase
4+
{
5+
6+
}

SourceKit.Sample/Class1.cs

-1
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
using System;
22
using System.Collections.Generic;
33
using System.Linq;
4-
using System.Runtime.CompilerServices;
54
using SourceKit.Sample.Models;
65

76
namespace SourceKit.Sample;

SourceKit.Sample/Playground.cs

+1-4
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@ public class Playground
88
private static IEnumerable<int> A(IEnumerable<int> e)
99
=> e.Where(x => new[] { x }.Where(y => y > 1).Any());
1010

11-
public static void A()
11+
public static void Main()
1212
{
13-
var x = new int[,]
14-
{
15-
};
1613
}
1714
}
+21-2
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,27 @@
11
<Project Sdk="Microsoft.NET.Sdk">
22

33
<PropertyGroup>
4-
<TargetFramework>net7.0</TargetFramework>
4+
<TargetFramework>netstandard2.0</TargetFramework>
5+
<LangVersion>11</LangVersion>
56
<Nullable>enable</Nullable>
7+
<Configurations>Debug;Release;Package</Configurations>
8+
<Platforms>AnyCPU</Platforms>
69
</PropertyGroup>
710

8-
</Project>
11+
<ItemGroup>
12+
<ProjectReference Include="..\src\analyzers\SourceKit.Analyzers.MustBePartial\SourceKit.Analyzers.MustBePartial.csproj"
13+
OutputItemType="Analyzer"
14+
Condition="'$(Configuration)' != 'Package'"/>
15+
16+
<ProjectReference Include="..\src\SourceKit\SourceKit.csproj"
17+
OutputItemType="Analyzer"
18+
Condition="'$(Configuration)' != 'Package'"/>
19+
</ItemGroup>
20+
21+
<ItemGroup>
22+
<PackageReference Include="SourceKit.Analyzers.MustBePartial"
23+
Version="1.0.0"
24+
Condition="'$(Configuration)' == 'Package'"/>
25+
</ItemGroup>
26+
27+
</Project>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
using Microsoft.CodeAnalysis.CSharp.Testing;
2+
using Microsoft.CodeAnalysis.Testing.Verifiers;
3+
using SourceKit.Analyzers.MustBePartial.Analyzers;
4+
using SourceKit.Analyzers.MustBePartial.Annotations;
5+
using SourceKit.Sample.Analyzers.MustBePartial;
6+
using SourceKit.Tests.Tools;
7+
using Xunit;
8+
using AnalyzerVerifier = Microsoft.CodeAnalysis.CSharp.Testing.XUnit.AnalyzerVerifier<
9+
SourceKit.Analyzers.MustBePartial.Analyzers.DerivativesMustBePartialAnalyzer>;
10+
using CodeFixTest = Microsoft.CodeAnalysis.CSharp.Testing.CSharpCodeFixTest<
11+
SourceKit.Analyzers.MustBePartial.Analyzers.DerivativesMustBePartialAnalyzer,
12+
SourceKit.Analyzers.MustBePartial.CodeFixes.MakeTypePartialCodeFixProvider,
13+
Microsoft.CodeAnalysis.Testing.Verifiers.XUnitVerifier>;
14+
15+
namespace SourceKit.Tests.Analyzers;
16+
17+
public class MustBePartialTests
18+
{
19+
[Fact]
20+
public async Task DerivativesMustBePartial_ShouldReportDiagnostic_WhenTypeIsNotPartial()
21+
{
22+
var sourceFile = await SourceFile.LoadAsync("SourceKit.Sample/Analyzers/MustBePartial/NonPartialDerivative.cs");
23+
24+
var diagnostic = AnalyzerVerifier.Diagnostic(DerivativesMustBePartialAnalyzer.Descriptor)
25+
.WithLocation(sourceFile.Name, 3, 14)
26+
.WithArguments(nameof(NonPartialDerivative));
27+
28+
var test = new CSharpAnalyzerTest<DerivativesMustBePartialAnalyzer, XUnitVerifier>
29+
{
30+
TestState =
31+
{
32+
Sources =
33+
{
34+
sourceFile,
35+
await SourceFile.LoadAsync("SourceKit.Sample/Analyzers/MustBePartial/IPartialBase.cs"),
36+
},
37+
AdditionalReferences = { typeof(DerivativesMustBePartialAttribute).Assembly },
38+
},
39+
ExpectedDiagnostics = { diagnostic },
40+
};
41+
42+
await test.RunAsync();
43+
}
44+
45+
[Fact]
46+
public async Task DerivativesMustBePartial_ShouldReportNoDiagnostic_WhenTypeIsPartial()
47+
{
48+
var test = new CSharpAnalyzerTest<DerivativesMustBePartialAnalyzer, XUnitVerifier>
49+
{
50+
TestState =
51+
{
52+
Sources =
53+
{
54+
await SourceFile.LoadAsync("SourceKit.Sample/Analyzers/MustBePartial/PartialDerivative.cs"),
55+
await SourceFile.LoadAsync("SourceKit.Sample/Analyzers/MustBePartial/IPartialBase.cs"),
56+
},
57+
AdditionalReferences = { typeof(DerivativesMustBePartialAttribute).Assembly },
58+
},
59+
};
60+
61+
await test.RunAsync();
62+
}
63+
64+
[Fact]
65+
public async Task MakeTypePartial_ShouldMakeTypePartial_WhenDiagnosticReported()
66+
{
67+
var interfaceSource = await SourceFile.LoadAsync("SourceKit.Sample/Analyzers/MustBePartial/IPartialBase.cs");
68+
var sourceFile = await SourceFile.LoadAsync("SourceKit.Sample/Analyzers/MustBePartial/NonPartialDerivative.cs");
69+
var fixedContent = sourceFile.Content.Replace("public class", "public partial class");
70+
71+
var fixedSource = sourceFile with { Content = fixedContent };
72+
73+
var diagnostic = AnalyzerVerifier.Diagnostic(DerivativesMustBePartialAnalyzer.Descriptor)
74+
.WithLocation(sourceFile.Name, 3, 14)
75+
.WithArguments(nameof(NonPartialDerivative));
76+
77+
var test = new CodeFixTest
78+
{
79+
TestState =
80+
{
81+
Sources = { sourceFile, interfaceSource, },
82+
AdditionalReferences = { typeof(DerivativesMustBePartialAttribute).Assembly },
83+
},
84+
FixedState =
85+
{
86+
Sources = { fixedSource, interfaceSource },
87+
},
88+
ExpectedDiagnostics = { diagnostic },
89+
};
90+
91+
await test.RunAsync();
92+
}
93+
}

SourceKit.Tests/SourceKit.Tests.csproj

+19-22
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,43 @@
44
<TargetFramework>net7.0</TargetFramework>
55
<ImplicitUsings>enable</ImplicitUsings>
66
<Nullable>enable</Nullable>
7-
87
<IsPackable>false</IsPackable>
98
</PropertyGroup>
109

1110
<ItemGroup>
12-
<PackageReference Include="Ben.Demystifier" Version="0.4.1" />
13-
<PackageReference Include="Sigil" Version="5.0.0" />
14-
<PackageReference Include="FluentAssertions" Version="6.10.0" />
15-
<PackageReference Include="Microsoft.CodeAnalysis.Common" Version="4.2.0" />
16-
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces" Version="4.2.0" />
17-
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common" Version="4.2.0" />
18-
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.3.2" />
19-
<PackageReference Include="xunit" Version="2.4.2" />
20-
<PackageReference Include="Xunit.DependencyInjection.Demystifier" Version="8.0.1" />
21-
22-
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.5">
11+
<PackageReference Include="Ben.Demystifier"/>
12+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Analyzer.Testing.XUnit"/>
13+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.CodeFix.Testing.XUnit"/>
14+
<PackageReference Include="Sigil"/>
15+
<PackageReference Include="FluentAssertions"/>
16+
<PackageReference Include="Microsoft.CodeAnalysis.Common"/>
17+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp.Workspaces"/>
18+
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" VersionOverride="4.5.0"/>
19+
<PackageReference Include="Microsoft.CodeAnalysis.Workspaces.Common"/>
20+
<PackageReference Include="Microsoft.NET.Test.Sdk"/>
21+
<PackageReference Include="xunit"/>
22+
<PackageReference Include="Xunit.DependencyInjection.Demystifier"/>
23+
24+
<PackageReference Include="xunit.runner.visualstudio">
2325
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2426
<PrivateAssets>all</PrivateAssets>
2527
</PackageReference>
2628

27-
<PackageReference Include="coverlet.collector" Version="3.1.2">
29+
<PackageReference Include="coverlet.collector">
2830
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
2931
<PrivateAssets>all</PrivateAssets>
3032
</PackageReference>
3133

3234
</ItemGroup>
3335

3436
<ItemGroup>
35-
<ProjectReference Include="..\SourceKit.Sample\SourceKit.Sample.csproj" />
36-
<ProjectReference Include="..\src\SourceKit.Reflect\SourceKit.Reflect.csproj" />
37-
</ItemGroup>
38-
39-
<ItemGroup>
40-
<Content Include="..\SourceKit.Sample\**\*.cs" Exclude="..\SourceKit.Sample\obj\**\*.*" LinkBase="SourceKit.Sample\" CopyToOutputDirectory="Always" />
37+
<ProjectReference Include="..\SourceKit.Sample\SourceKit.Sample.csproj"/>
38+
<ProjectReference Include="..\src\SourceKit.Reflect\SourceKit.Reflect.csproj"/>
39+
<ProjectReference Include="..\src\analyzers\SourceKit.Analyzers.MustBePartial\SourceKit.Analyzers.MustBePartial.csproj"/>
4140
</ItemGroup>
4241

4342
<ItemGroup>
44-
<Reference Include="assembly_1">
45-
<HintPath>a.dll</HintPath>
46-
</Reference>
43+
<Content Include="..\SourceKit.Sample\**\*.cs" Exclude="..\SourceKit.Sample\obj\**\*.*" LinkBase="SourceKit.Sample\" CopyToOutputDirectory="Always"/>
4744
</ItemGroup>
4845

4946
</Project>

SourceKit.Tests/Tools/CompilationBuilder.cs

+1-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ public static Task<Compilation> CompileSampleProjectAsync()
3838
typeof(IEnumerable<>),
3939
typeof(Enumerable),
4040
};
41-
41+
4242
var project = solution.GetProject(projectId)!;
4343
project = project.WithCompilationOptions(new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
4444
project = project.AddMetadataReferences(GetAllReferencesNeededForTypes(referencedTypes));

SourceKit.Tests/Tools/SourceFile.cs

+15
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
namespace SourceKit.Tests.Tools;
2+
3+
public record struct SourceFile(string Name, string Content)
4+
{
5+
public static async Task<SourceFile> LoadAsync(string path)
6+
{
7+
var name = Path.GetFileName(path);
8+
var content = await File.ReadAllTextAsync(path);
9+
10+
return new SourceFile(name, content);
11+
}
12+
13+
public static implicit operator (string, string)(SourceFile sourceFile)
14+
=> (sourceFile.Name, sourceFile.Content);
15+
}

SourceKit.sln

+19-2
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Sample", "SourceK
1212
EndProject
1313
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Tests", "SourceKit.Tests\SourceKit.Tests.csproj", "{EE7B76B2-A19F-4F9D-B091-9E6EF9151164}"
1414
EndProject
15+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "analyzers", "analyzers", "{0506CF17-3170-420E-B120-3BEB0BDE68CF}"
16+
EndProject
17+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Analyzers.MustBePartial.Annotations", "src\analyzers\SourceKit.Analyzers.MustBePartial.Annotations\SourceKit.Analyzers.MustBePartial.Annotations.csproj", "{B94E98ED-AD2A-4DE0-B405-2C38F75FA000}"
18+
EndProject
19+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SourceKit.Analyzers.MustBePartial", "src\analyzers\SourceKit.Analyzers.MustBePartial\SourceKit.Analyzers.MustBePartial.csproj", "{18E723E4-9DA2-49D3-9B08-0923BEC3FD9F}"
20+
EndProject
1521
Global
1622
GlobalSection(SolutionConfigurationPlatforms) = preSolution
1723
Debug|Any CPU = Debug|Any CPU
@@ -22,6 +28,9 @@ Global
2228
{8EED1912-BB7A-4C97-9032-08E3219724DE} = {BBA45AFB-5727-47BB-9BBB-B05559BE892E}
2329
{701CE759-EAF3-439D-91BF-C158F5860B72} = {4B7FE6F2-BF92-4698-A01F-4C1E111B62CF}
2430
{EE7B76B2-A19F-4F9D-B091-9E6EF9151164} = {4B7FE6F2-BF92-4698-A01F-4C1E111B62CF}
31+
{0506CF17-3170-420E-B120-3BEB0BDE68CF} = {BBA45AFB-5727-47BB-9BBB-B05559BE892E}
32+
{B94E98ED-AD2A-4DE0-B405-2C38F75FA000} = {0506CF17-3170-420E-B120-3BEB0BDE68CF}
33+
{18E723E4-9DA2-49D3-9B08-0923BEC3FD9F} = {0506CF17-3170-420E-B120-3BEB0BDE68CF}
2534
EndGlobalSection
2635
GlobalSection(ProjectConfigurationPlatforms) = postSolution
2736
{637C01C1-3A3C-4FC6-9874-6CFBA4319A79}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
@@ -32,13 +41,21 @@ Global
3241
{8EED1912-BB7A-4C97-9032-08E3219724DE}.Debug|Any CPU.Build.0 = Debug|Any CPU
3342
{8EED1912-BB7A-4C97-9032-08E3219724DE}.Release|Any CPU.ActiveCfg = Release|Any CPU
3443
{8EED1912-BB7A-4C97-9032-08E3219724DE}.Release|Any CPU.Build.0 = Release|Any CPU
35-
{701CE759-EAF3-439D-91BF-C158F5860B72}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
36-
{701CE759-EAF3-439D-91BF-C158F5860B72}.Debug|Any CPU.Build.0 = Debug|Any CPU
3744
{701CE759-EAF3-439D-91BF-C158F5860B72}.Release|Any CPU.ActiveCfg = Release|Any CPU
3845
{701CE759-EAF3-439D-91BF-C158F5860B72}.Release|Any CPU.Build.0 = Release|Any CPU
46+
{701CE759-EAF3-439D-91BF-C158F5860B72}.Debug|Any CPU.ActiveCfg = Package|Any CPU
47+
{701CE759-EAF3-439D-91BF-C158F5860B72}.Debug|Any CPU.Build.0 = Package|Any CPU
3948
{EE7B76B2-A19F-4F9D-B091-9E6EF9151164}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
4049
{EE7B76B2-A19F-4F9D-B091-9E6EF9151164}.Debug|Any CPU.Build.0 = Debug|Any CPU
4150
{EE7B76B2-A19F-4F9D-B091-9E6EF9151164}.Release|Any CPU.ActiveCfg = Release|Any CPU
4251
{EE7B76B2-A19F-4F9D-B091-9E6EF9151164}.Release|Any CPU.Build.0 = Release|Any CPU
52+
{B94E98ED-AD2A-4DE0-B405-2C38F75FA000}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
53+
{B94E98ED-AD2A-4DE0-B405-2C38F75FA000}.Debug|Any CPU.Build.0 = Debug|Any CPU
54+
{B94E98ED-AD2A-4DE0-B405-2C38F75FA000}.Release|Any CPU.ActiveCfg = Release|Any CPU
55+
{B94E98ED-AD2A-4DE0-B405-2C38F75FA000}.Release|Any CPU.Build.0 = Release|Any CPU
56+
{18E723E4-9DA2-49D3-9B08-0923BEC3FD9F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
57+
{18E723E4-9DA2-49D3-9B08-0923BEC3FD9F}.Debug|Any CPU.Build.0 = Debug|Any CPU
58+
{18E723E4-9DA2-49D3-9B08-0923BEC3FD9F}.Release|Any CPU.ActiveCfg = Release|Any CPU
59+
{18E723E4-9DA2-49D3-9B08-0923BEC3FD9F}.Release|Any CPU.Build.0 = Release|Any CPU
4360
EndGlobalSection
4461
EndGlobal

0 commit comments

Comments
 (0)