CSLA.NET 6.0.0
CSLA .NET is a software development framework that helps you build a reusable, maintainable object-oriented business layer for your app.
EvaluatePropertiesForSimplicityAnalyzer.cs
Go to the documentation of this file.
1using Microsoft.CodeAnalysis;
2using Microsoft.CodeAnalysis.CSharp;
3using Microsoft.CodeAnalysis.CSharp.Syntax;
4using Microsoft.CodeAnalysis.Diagnostics;
5using System.Collections.Immutable;
6using System.Linq;
8
9namespace Csla.Analyzers
10{
11 [DiagnosticAnalyzer(LanguageNames.CSharp)]
13 : DiagnosticAnalyzer
14 {
15 private static readonly DiagnosticDescriptor onlyUseCslaPropertyMethodsInGetSetRule =
16 new DiagnosticDescriptor(
17 Constants.AnalyzerIdentifiers.OnlyUseCslaPropertyMethodsInGetSetRule, OnlyUseCslaPropertyMethodsInGetSetRuleConstants.Title,
18 OnlyUseCslaPropertyMethodsInGetSetRuleConstants.Message, Constants.Categories.Usage,
19 DiagnosticSeverity.Warning, true,
20 helpLinkUri: HelpUrlBuilder.Build(
21 Constants.AnalyzerIdentifiers.OnlyUseCslaPropertyMethodsInGetSetRule, nameof(EvaluatePropertiesForSimplicityAnalyzer)));
22
23 public override ImmutableArray<DiagnosticDescriptor> SupportedDiagnostics => ImmutableArray.Create(onlyUseCslaPropertyMethodsInGetSetRule);
24
25 public override void Initialize(AnalysisContext context)
26 {
27 context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.Analyze | GeneratedCodeAnalysisFlags.ReportDiagnostics);
28 context.EnableConcurrentExecution();
29 context.RegisterSyntaxNodeAction(AnalyzePropertyDeclaration, SyntaxKind.PropertyDeclaration);
30 }
31
32 private static void AnalyzePropertyDeclaration(SyntaxNodeAnalysisContext context)
33 {
34 var propertyNode = (PropertyDeclarationSyntax)context.Node;
35
36 if(!propertyNode.ContainsDiagnostics)
37 {
38 var propertySymbol = context.SemanticModel.GetDeclaredSymbol(propertyNode);
39 var classSymbol = propertySymbol.ContainingType;
40
41 if (propertySymbol != null && classSymbol != null &&
42 classSymbol.IsStereotype() && !propertySymbol.IsAbstract &&
43 !propertySymbol.IsStatic)
44 {
45 if (propertySymbol.GetMethod != null)
46 {
47 AnalyzePropertyGetter(propertyNode, context);
48 }
49
50 if (propertySymbol.SetMethod != null)
51 {
52 AnalyzePropertySetter(propertyNode, context);
53 }
54 }
55 }
56 }
57
58 private static void AnalyzePropertyGetter(PropertyDeclarationSyntax propertyNode, SyntaxNodeAnalysisContext context)
59 {
60 if (propertyNode.ExpressionBody == null)
61 {
62 AnalyzePropertyGetterWithGet(propertyNode, context);
63 }
64 else
65 {
66 AnalyzePropertyGetterWithExpressionBody(propertyNode, context);
67 }
68 }
69
70 private static void AnalyzePropertyGetterWithExpressionBody(PropertyDeclarationSyntax propertyNode, SyntaxNodeAnalysisContext context)
71 {
72 var getterExpression = propertyNode.ExpressionBody.Expression;
73 var getterChildren = getterExpression.DescendantNodes(_ => true).ToImmutableArray();
74
75 if (getterChildren.Length > 1)
76 {
77 var getterWalker = new FindGetOrReadInvocationsWalker(
78 getterExpression, context.SemanticModel);
79
80 if (getterWalker.Invocation != null &&
81 getterChildren.Contains(getterWalker.Invocation))
82 {
83 context.ReportDiagnostic(Diagnostic.Create(
84 onlyUseCslaPropertyMethodsInGetSetRule,
85 getterExpression.GetLocation()));
86 }
87 }
88 }
89
90 private static void AnalyzePropertyGetterWithGet(PropertyDeclarationSyntax propertyNode, SyntaxNodeAnalysisContext context)
91 {
92 var getter = propertyNode.AccessorList.Accessors.Single(
93 _ => _.IsKind(SyntaxKind.GetAccessorDeclaration)).Body;
94
95 var getterWalker = new FindGetOrReadInvocationsWalker(getter, context.SemanticModel);
96
97 if (getterWalker.Invocation != null)
98 {
99 var getterStatements = getter.Statements;
100
101 if (getterStatements.Count != 1)
102 {
103 context.ReportDiagnostic(Diagnostic.Create(
104 onlyUseCslaPropertyMethodsInGetSetRule,
105 getter.GetLocation()));
106 }
107 else
108 {
109
110 if (!(getterStatements[0] is ReturnStatementSyntax returnNode))
111 {
112 context.ReportDiagnostic(Diagnostic.Create(
113 onlyUseCslaPropertyMethodsInGetSetRule,
114 getter.GetLocation()));
115 }
116 else
117 {
118
119 if (!(returnNode.ChildNodes().SingleOrDefault(
120 _ => _.IsKind(SyntaxKind.InvocationExpression)) is InvocationExpressionSyntax invocation) || invocation != getterWalker.Invocation)
121 {
122 context.ReportDiagnostic(Diagnostic.Create(
123 onlyUseCslaPropertyMethodsInGetSetRule,
124 getter.GetLocation()));
125 }
126 }
127 }
128 }
129 }
130
131 private static void AnalyzePropertySetter(PropertyDeclarationSyntax propertyNode, SyntaxNodeAnalysisContext context)
132 {
133 var setter = propertyNode.AccessorList.Accessors.Single(
134 _ => _.IsKind(SyntaxKind.SetAccessorDeclaration)).Body;
135
136 var setterWalker = new FindSetOrLoadInvocationsWalker(setter, context.SemanticModel);
137
138 if (setterWalker.Invocation != null)
139 {
140 var setterStatements = setter.Statements;
141
142 if (setterStatements.Count() != 1)
143 {
144 context.ReportDiagnostic(Diagnostic.Create(
145 onlyUseCslaPropertyMethodsInGetSetRule,
146 setter.GetLocation()));
147 }
148 else
149 {
150
151 if (!(setterStatements[0] is ExpressionStatementSyntax expressionNode))
152 {
153 context.ReportDiagnostic(Diagnostic.Create(
154 onlyUseCslaPropertyMethodsInGetSetRule,
155 setter.GetLocation()));
156 }
157 else
158 {
159
160 if (!(expressionNode.ChildNodes().SingleOrDefault(
161 _ => _.IsKind(SyntaxKind.InvocationExpression)) is InvocationExpressionSyntax invocation) || invocation != setterWalker.Invocation)
162 {
163 context.ReportDiagnostic(Diagnostic.Create(
164 onlyUseCslaPropertyMethodsInGetSetRule,
165 setter.GetLocation()));
166 }
167 }
168 }
169 }
170 }
171 }
172}
override ImmutableArray< DiagnosticDescriptor > SupportedDiagnostics