1
+ using System . Collections . Immutable ;
2
+ using System . Diagnostics ;
3
+ using Microsoft . CodeAnalysis ;
4
+ using Microsoft . CodeAnalysis . Diagnostics ;
5
+ using SourceKit . Analyzers . MustBePartial . Tools ;
6
+ using SourceKit . Extensions ;
7
+
8
+ namespace SourceKit . Analyzers . MustBePartial . Analyzers ;
9
+
10
+ [ DiagnosticAnalyzer ( LanguageNames . CSharp , LanguageNames . VisualBasic ) ]
11
+ public class DerivativesMustBePartialAnalyzer : DiagnosticAnalyzer
12
+ {
13
+ public const string DiagnosticId = "SK1000" ;
14
+ public const string Title = nameof ( DerivativesMustBePartialAnalyzer ) ;
15
+
16
+ public const string Format = """Type "{0}" must be partial""" ;
17
+
18
+ public static readonly DiagnosticDescriptor Descriptor = new DiagnosticDescriptor (
19
+ DiagnosticId ,
20
+ Title ,
21
+ Format ,
22
+ "Class definition" ,
23
+ DiagnosticSeverity . Error ,
24
+ true ) ;
25
+
26
+ public override ImmutableArray < DiagnosticDescriptor > SupportedDiagnostics { get ; } =
27
+ ImmutableArray . Create ( Descriptor ) ;
28
+
29
+ public override void Initialize ( AnalysisContext context )
30
+ {
31
+ context . EnableConcurrentExecution ( ) ;
32
+ context . ConfigureGeneratedCodeAnalysis (
33
+ GeneratedCodeAnalysisFlags . Analyze | GeneratedCodeAnalysisFlags . ReportDiagnostics ) ;
34
+
35
+ context . RegisterCompilationStartAction ( compilationContext =>
36
+ {
37
+ var derivativesMustBePartialAttributeType = compilationContext . Compilation
38
+ . GetTypeByMetadataName ( Constants . DerivativesMustBePartialAttributeFullyQualifiedName ) ;
39
+
40
+ if ( derivativesMustBePartialAttributeType is null )
41
+ return ;
42
+
43
+ compilationContext . RegisterSymbolAction (
44
+ x => AnalyzeTypeSymbol ( x , derivativesMustBePartialAttributeType ) ,
45
+ SymbolKind . NamedType ) ;
46
+ } ) ;
47
+ }
48
+
49
+ private static void AnalyzeTypeSymbol ( SymbolAnalysisContext context , INamedTypeSymbol attributeSymbol )
50
+ {
51
+ context . CancellationToken . ThrowIfCancellationRequested ( ) ;
52
+
53
+ var typeSymbol = ( INamedTypeSymbol ) context . Symbol ;
54
+
55
+ IEnumerable < INamedTypeSymbol > baseTypesAndInterfaces = typeSymbol . GetBaseTypesAndInterfaces ( ) ;
56
+
57
+ var mustBePartial = baseTypesAndInterfaces . Any ( x => x . HasAttribute ( attributeSymbol ) ) ;
58
+ var isPartial = typeSymbol . IsPartial ( ) ;
59
+
60
+ if ( ( mustBePartial , isPartial ) is not ( true , false ) )
61
+ return ;
62
+
63
+ var location = typeSymbol . GetSignatureLocations ( ) . Single ( ) ;
64
+ var diagnostic = Diagnostic . Create ( Descriptor , location , typeSymbol . Name ) ;
65
+
66
+ context . ReportDiagnostic ( diagnostic ) ;
67
+ }
68
+ }
0 commit comments