1
1
using System . Collections . Generic ;
2
2
using System . Linq ;
3
3
using Antlr4 . Runtime ;
4
+ using Microsoft . Vbe . Interop ;
4
5
using Rubberduck . Extensions ;
5
6
using Rubberduck . VBA ;
6
7
using Rubberduck . VBA . Grammar ;
9
10
10
11
namespace Rubberduck . Inspections
11
12
{
12
- //public class VariableNotAssignedInspection : IInspection
13
- //{
14
- // public VariableNotAssignedInspection()
15
- // {
16
- // Severity = CodeInspectionSeverity.Error;
17
- // }
18
-
19
- // public string Name { get { return InspectionNames.VariableNotAssigned; } }
20
- // public CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } }
21
- // public CodeInspectionSeverity Severity { get; set; }
22
-
23
- // public IEnumerable<CodeInspectionResultBase> GetInspectionResults(IEnumerable<VBComponentParseResult> parseResult)
24
- // {
25
- // var parseResults = parseResult.ToList();
26
-
27
- // /*
28
- // *
29
- // *
30
- // */
31
-
32
- // var assignments = parseResults.Select(result =>
33
- // new
34
- // {
35
- // Module = result.Component,
36
- // ParseTree = result.ParseTree.GetContexts<VariableAssignmentListener, VisualBasic6Parser.VariableCallStmtContext>(new VariableAssignmentListener())
37
- // }).ToList();
38
-
39
- // foreach (var result in parseResults)
40
- // {
41
- // var module = result; // to avoid access to modified closure in below lambdas
42
- // var declarations = result.ParseTree.GetContexts<DeclarationListener, ParserRuleContext>(new DeclarationListener()).ToList();
43
- // var localAssigns = assignments.Where(assign => assign.Module.QualifiedName().Equals(module.QualifiedName));
44
-
45
- // var variables = declarations.Where(declaration => declaration is VisualBasic6Parser.VariableSubStmtContext)
46
- // .Cast<VisualBasic6Parser.VariableSubStmtContext>()
47
- // .Where(variable => assignments.Where(a => a.Module.QualifiedName() != ).All(assigned => assigned.ambiguousIdentifier().GetText() != variable.ambiguousIdentifier().GetText()))
48
- // .Select(variable => new VariableNotAssignedInspetionResult(Name, Severity, variable, module.QualifiedName));
49
-
50
- // foreach (var variable in variables)
51
- // {
52
- // yield return variable;
53
- // }
54
- // }
55
- // }
56
- //}
13
+ public class VariableNotAssignedInspection : IInspection
14
+ {
15
+ public VariableNotAssignedInspection ( )
16
+ {
17
+ Severity = CodeInspectionSeverity . Error ;
18
+ }
19
+
20
+ public string Name { get { return InspectionNames . VariableNotAssigned ; } }
21
+ public CodeInspectionType InspectionType { get { return CodeInspectionType . CodeQualityIssues ; } }
22
+ public CodeInspectionSeverity Severity { get ; set ; }
23
+
24
+ public IEnumerable < CodeInspectionResultBase > GetInspectionResults ( IEnumerable < VBComponentParseResult > parseResult )
25
+ {
26
+ var parseResults = parseResult . ToList ( ) ;
27
+
28
+ // publics & globals delared at module-scope in standard modules:
29
+ var globals =
30
+ parseResults . Select ( result =>
31
+ new
32
+ {
33
+ Name = result . QualifiedName ,
34
+ Globals = result . ParseTree . GetContexts < DeclarationSectionListener , ParserRuleContext > ( new DeclarationSectionListener ( ) )
35
+ . OfType < VisualBasic6Parser . VariableStmtContext > ( )
36
+ . Where ( context =>
37
+ context . visibility ( ) != null &&
38
+ context . visibility ( ) . GetText ( ) != Tokens . Private )
39
+ . SelectMany ( context => context . variableListStmt ( ) . variableSubStmt ( )
40
+ . Select ( variable => variable . ambiguousIdentifier ( ) ) )
41
+ } )
42
+ . SelectMany ( module => module . Globals . Select ( global =>
43
+ new
44
+ {
45
+ Name = module . Name ,
46
+ Global = global
47
+ } ) ) . ToList ( ) ;
48
+
49
+ var assignedGlobals = new List < VisualBasic6Parser . AmbiguousIdentifierContext > ( ) ;
50
+ var unassignedDeclarations = new List < CodeInspectionResultBase > ( ) ;
51
+
52
+ foreach ( var result in parseResults )
53
+ {
54
+ // module-scoped in this module:
55
+ var declarations = result . ParseTree . GetContexts < DeclarationSectionListener , ParserRuleContext > ( new DeclarationSectionListener ( ) )
56
+ . OfType < VisualBasic6Parser . VariableSubStmtContext > ( )
57
+ . Where ( variable => globals . All ( global => global . Global . GetText ( ) != variable . GetText ( ) ) )
58
+ . ToList ( ) ;
59
+ var procedures = result . ParseTree . GetContexts < ProcedureListener , ParserRuleContext > ( new ProcedureListener ( ) ) . ToList ( ) ;
60
+
61
+ // fetch & scope all assignments:
62
+ var assignments = procedures . SelectMany (
63
+ procedure => procedure . GetContexts < VariableAssignmentListener , VisualBasic6Parser . AmbiguousIdentifierContext > ( new VariableAssignmentListener ( ) )
64
+ . Select ( context => new
65
+ {
66
+ Scope = new QualifiedMemberName ( result . QualifiedName , ( ( dynamic ) procedure ) . ambiguousIdentifier ( ) . GetText ( ) ) ,
67
+ Name = context . GetText ( )
68
+ } ) ) ;
69
+
70
+ // fetch & scope all procedure-scoped declarations:
71
+ var locals = procedures . SelectMany (
72
+ procedure => procedure . GetContexts < DeclarationListener , ParserRuleContext > ( new DeclarationListener ( ) )
73
+ . OfType < VisualBasic6Parser . VariableSubStmtContext > ( )
74
+ . Select ( context => new
75
+ {
76
+ Context = context ,
77
+ Scope = new QualifiedMemberName ( result . QualifiedName , ( ( dynamic ) procedure ) . ambiguousIdentifier ( ) . GetText ( ) ) ,
78
+ Name = context . ambiguousIdentifier ( ) . GetText ( )
79
+ } ) ) ;
80
+
81
+ // identify unassigned module-scoped declarations:
82
+ unassignedDeclarations . AddRange (
83
+ declarations . Select ( d => d . ambiguousIdentifier ( ) )
84
+ . Where ( d => assignments . All ( a => a . Name != d . GetText ( ) ) )
85
+ . Select ( identifier => new VariableNotAssignedInspetionResult ( Name , Severity , identifier , result . QualifiedName ) ) ) ;
86
+
87
+ // identify unassigned procedure-scoped declarations:
88
+ unassignedDeclarations . AddRange (
89
+ locals . Where ( local => assignments . All ( a => a . Name != local . Name ) )
90
+ . Select ( identifier => new VariableNotAssignedInspetionResult ( Name , Severity , identifier . Context . ambiguousIdentifier ( ) , result . QualifiedName ) ) ) ;
91
+
92
+ // identify globals assigned in this module:
93
+ assignedGlobals . AddRange ( globals . Where ( global => assignments . Any ( a => a . Name == global . Global . GetText ( ) ) )
94
+ . Select ( global => global . Global ) ) ;
95
+ }
96
+
97
+ // identify unassigned globals:
98
+ var assignedIdentifiers = assignedGlobals . Select ( assigned => assigned . GetText ( ) ) ;
99
+ var unassignedGlobals = globals . Where ( global => ! assignedIdentifiers . Contains ( global . Global . GetText ( ) ) )
100
+ . Select ( identifier => new VariableNotAssignedInspetionResult ( Name , Severity , identifier . Global , identifier . Name ) ) ;
101
+ unassignedDeclarations . AddRange ( unassignedGlobals ) ;
102
+
103
+ return unassignedDeclarations ;
104
+ }
105
+
106
+ private IEnumerable < VisualBasic6Parser . AmbiguousIdentifierContext > FindUnassignedLocals ( ParserRuleContext procedureContext , IEnumerable < VisualBasic6Parser . AmbiguousIdentifierContext > globals )
107
+ {
108
+ return procedureContext . GetRuleContexts < VisualBasic6Parser . VariableSubStmtContext > ( )
109
+ . Select ( variable => variable . ambiguousIdentifier ( ) )
110
+ . Union ( globals )
111
+ . Where ( identifier =>
112
+ procedureContext . GetContexts < VariableAssignmentListener , VisualBasic6Parser . AmbiguousIdentifierContext > ( new VariableAssignmentListener ( ) )
113
+ . All ( assignment => assignment . GetText ( ) != identifier . GetText ( ) ) ) ;
114
+ }
115
+ }
57
116
}
0 commit comments