1
+ using System . Collections . Generic ;
2
+ using System . Linq ;
3
+ using Antlr4 . Runtime ;
4
+ using Rubberduck . Inspections . Abstract ;
5
+ using Rubberduck . Inspections . Results ;
6
+ using Rubberduck . Parsing ;
7
+ using Rubberduck . Parsing . Annotations ;
8
+ using Rubberduck . Parsing . Grammar ;
9
+ using Rubberduck . Parsing . Inspections ;
10
+ using Rubberduck . Parsing . Inspections . Abstract ;
11
+ using Rubberduck . Parsing . Symbols ;
12
+ using Rubberduck . Parsing . VBA ;
13
+ using Rubberduck . Parsing . VBA . Parsing ;
14
+ using Rubberduck . Resources . Inspections ;
15
+
16
+ namespace Rubberduck . Inspections . Concrete
17
+ {
18
+ [ CannotAnnotate ]
19
+ public sealed class MissingAttributeInspection : ParseTreeInspectionBase
20
+ {
21
+ public MissingAttributeInspection ( RubberduckParserState state )
22
+ : base ( state )
23
+ {
24
+ Listener = new MissingMemberAttributeListener ( state ) ;
25
+ }
26
+
27
+ public override CodeKind TargetKindOfCode => CodeKind . AttributesCode ;
28
+
29
+ public override IInspectionListener Listener { get ; }
30
+
31
+ protected override IEnumerable < IInspectionResult > DoGetInspectionResults ( )
32
+ {
33
+ return Listener . Contexts . Select ( context =>
34
+ {
35
+ var name = string . Format ( InspectionResults . MissingAttributeInspection , context . MemberName . MemberName ,
36
+ ( ( VBAParser . AnnotationContext ) context . Context ) . annotationName ( ) . GetText ( ) ) ;
37
+ return new QualifiedContextInspectionResult ( this , name , context ) ;
38
+ } ) ;
39
+ }
40
+
41
+ public class MissingMemberAttributeListener : ParseTreeListeners . AttributeAnnotationListener
42
+ {
43
+ public MissingMemberAttributeListener ( RubberduckParserState state ) : base ( state ) { }
44
+
45
+ public override void ExitAnnotation ( VBAParser . AnnotationContext context )
46
+ {
47
+ var annotationType = context . AnnotationType ;
48
+
49
+ if ( ! annotationType . HasFlag ( AnnotationType . Attribute ) )
50
+ {
51
+ return ;
52
+ }
53
+
54
+ var isMemberAnnotation = annotationType . HasFlag ( AnnotationType . MemberAnnotation ) ;
55
+ var isModuleScope = CurrentScopeDeclaration . DeclarationType . HasFlag ( DeclarationType . Module ) ;
56
+
57
+ if ( isModuleScope && ! isMemberAnnotation )
58
+ {
59
+ // module-level annotation
60
+ var module = State . DeclarationFinder . UserDeclarations ( DeclarationType . Module ) . Single ( m => m . QualifiedName . QualifiedModuleName . Equals ( CurrentModuleName ) ) ;
61
+ if ( ! module . Attributes . HasAttributeFor ( context . AnnotationType ) )
62
+ {
63
+ AddContext ( new QualifiedContext < ParserRuleContext > ( CurrentModuleName , context ) ) ;
64
+ }
65
+ }
66
+ else if ( isMemberAnnotation )
67
+ {
68
+ // member-level annotation is above the context for the first member in the module..
69
+ if ( isModuleScope )
70
+ {
71
+ CurrentScopeDeclaration = FirstMember ;
72
+ }
73
+
74
+ var member = Members . Value . Single ( m => m . Key . Equals ( CurrentScopeDeclaration . QualifiedName . MemberName ) ) ;
75
+ if ( ! member . Value . Attributes . HasAttributeFor ( context . AnnotationType , member . Key ) )
76
+ {
77
+ AddContext ( new QualifiedContext < ParserRuleContext > ( CurrentModuleName , context ) ) ;
78
+ }
79
+ }
80
+ else
81
+ {
82
+ // annotation is illegal. ignore.
83
+ }
84
+ }
85
+ }
86
+ }
87
+ }
0 commit comments