1
+ using System . Collections . Generic ;
2
+ using System . Linq ;
3
+ using Rubberduck . Inspections . Abstract ;
4
+ using Rubberduck . Inspections . Results ;
5
+ using Rubberduck . Parsing ;
6
+ using Rubberduck . Parsing . Annotations ;
7
+ using Rubberduck . Parsing . Grammar ;
8
+ using Rubberduck . Parsing . Inspections . Abstract ;
9
+ using Rubberduck . Parsing . Symbols ;
10
+ using Rubberduck . Parsing . VBA ;
11
+ using Rubberduck . Resources . Inspections ;
12
+ using Rubberduck . VBEditor . SafeComWrappers ;
13
+
14
+ namespace Rubberduck . Inspections . Inspections . Concrete
15
+ {
16
+ public sealed class MissingModuleAnnotationInspection : InspectionBase
17
+ {
18
+ public MissingModuleAnnotationInspection ( RubberduckParserState state )
19
+ : base ( state )
20
+ { }
21
+
22
+ protected override IEnumerable < IInspectionResult > DoGetInspectionResults ( )
23
+ {
24
+ var moduleDeclarationsWithAttributes = State . DeclarationFinder
25
+ . UserDeclarations ( DeclarationType . Module )
26
+ . Where ( decl => decl . Attributes . Any ( ) ) ;
27
+
28
+ var declarationsToInspect = moduleDeclarationsWithAttributes
29
+ . Where ( decl => decl . QualifiedModuleName . ComponentType != ComponentType . Document
30
+ && ! IsIgnoringInspectionResultFor ( decl , AnnotationName ) ) ;
31
+
32
+ var results = new List < DeclarationInspectionResult > ( ) ;
33
+ foreach ( var declaration in declarationsToInspect )
34
+ {
35
+ foreach ( var attribute in declaration . Attributes )
36
+ {
37
+ if ( IsDefaultAttribute ( declaration , attribute ) )
38
+ {
39
+ continue ;
40
+ }
41
+
42
+ if ( MissesCorrespondingModuleAnnotation ( declaration , attribute ) )
43
+ {
44
+ var description = string . Format ( InspectionResults . MissingMemberAnnotationInspection ,
45
+ declaration . IdentifierName ,
46
+ attribute . Name ,
47
+ attribute . Values ) ;
48
+
49
+ var result = new DeclarationInspectionResult ( this , description , declaration ,
50
+ new QualifiedContext ( declaration . QualifiedModuleName , declaration . Context ) ) ;
51
+ result . Properties . AttributeName = attribute . Name ;
52
+ result . Properties . AttributeValues = attribute . Values ;
53
+
54
+ results . Add ( result ) ;
55
+ }
56
+ }
57
+ }
58
+
59
+ return results ;
60
+ }
61
+
62
+ private static bool IsDefaultAttribute ( Declaration declaration , AttributeNode attribute )
63
+ {
64
+ switch ( attribute . Name )
65
+ {
66
+ case "VB_Name" :
67
+ return true ;
68
+ case "VB_GlobalNameSpace" :
69
+ return declaration . DeclarationType . HasFlag ( DeclarationType . ClassModule )
70
+ && attribute . Values [ 0 ] . Equals ( Tokens . False ) ;
71
+ case "VB_Exposed" :
72
+ return declaration . DeclarationType . HasFlag ( DeclarationType . ClassModule )
73
+ && attribute . Values [ 0 ] . Equals ( Tokens . False ) ;
74
+ case "VB_Creatable" :
75
+ return declaration . DeclarationType . HasFlag ( DeclarationType . ClassModule )
76
+ && attribute . Values [ 0 ] . Equals ( Tokens . False ) ;
77
+ case "VB_PredeclaredId" :
78
+ return ( declaration . QualifiedModuleName . ComponentType == ComponentType . ClassModule
79
+ && attribute . Values [ 0 ] . Equals ( Tokens . False ) )
80
+ || ( declaration . QualifiedModuleName . ComponentType == ComponentType . UserForm
81
+ && attribute . Values [ 0 ] . Equals ( Tokens . True ) ) ;
82
+ default :
83
+ return false ;
84
+ }
85
+ }
86
+
87
+ private static bool MissesCorrespondingModuleAnnotation ( Declaration declaration , AttributeNode attribute )
88
+ {
89
+ if ( string . IsNullOrEmpty ( attribute . Name ) || ! declaration . DeclarationType . HasFlag ( DeclarationType . Module ) )
90
+ {
91
+ return false ;
92
+ }
93
+
94
+ //VB_Ext_Key attributes are special in that identity also depends on the first value, the key.
95
+ if ( attribute . Name == "VB_Ext_Key" )
96
+ {
97
+ return ! declaration . Annotations . OfType < IAttributeAnnotation > ( )
98
+ . Any ( annotation => annotation . Attribute . Equals ( "VB_Ext_Key" ) && attribute . Values [ 0 ] . Equals ( annotation . AttributeValues [ 0 ] ) ) ;
99
+ }
100
+
101
+ return ! declaration . Annotations . OfType < IAttributeAnnotation > ( )
102
+ . Any ( annotation => annotation . Attribute . Equals ( attribute . Name ) ) ;
103
+ }
104
+ }
105
+ }
0 commit comments