@@ -23,6 +23,7 @@ public IEnumerable<ModuleMetricsResult> ModuleMetrics(RubberduckParserState stat
23
23
{
24
24
if ( state == null || ! state . AllUserDeclarations . Any ( ) )
25
25
{
26
+ // must not return Enumerable.Empty
26
27
yield break ;
27
28
}
28
29
@@ -68,24 +69,31 @@ public CodeMetricsListener(DeclarationFinder finder, IIndenterSettings indenterS
68
69
69
70
public override void EnterEndOfLine ( [ NotNull ] VBAParser . EndOfLineContext context )
70
71
{
71
- ( currentMember == null ? moduleResults : results ) . Add ( new CodeMetricsResult ( 1 , 0 , 0 ) ) ;
72
+ int followingIndentationLevel = 0 ;
73
+ // we have a proper newline
74
+ if ( context . NEWLINE ( ) != null )
75
+ {
76
+ // the last whitespace, which is the one in front of the next line's contents
77
+ var followingWhitespace = context . whiteSpace ( ) . LastOrDefault ( ) ;
78
+ followingIndentationLevel = IndentationLevelFromWhitespace ( followingWhitespace ) ;
79
+ }
80
+ ( currentMember == null ? moduleResults : results ) . Add ( new CodeMetricsResult ( 1 , 0 , followingIndentationLevel ) ) ;
72
81
}
73
82
74
83
public override void EnterIfStmt ( [ NotNull ] VBAParser . IfStmtContext context )
75
84
{
76
- // one additional path beside the default
77
85
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
78
86
}
79
87
80
88
public override void EnterElseIfBlock ( [ NotNull ] VBAParser . ElseIfBlockContext context )
81
89
{
82
- // one additonal path beside the default
83
90
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
84
91
}
85
92
93
+ // notably: NO additional complexity for an Else-Block
94
+
86
95
public override void EnterForEachStmt ( [ NotNull ] VBAParser . ForEachStmtContext context )
87
96
{
88
- // one additional path
89
97
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
90
98
}
91
99
@@ -101,78 +109,73 @@ public override void EnterCaseClause([NotNull] VBAParser.CaseClauseContext conte
101
109
102
110
public override void EnterSubStmt ( [ NotNull ] VBAParser . SubStmtContext context )
103
111
{
104
- // this is the default path through the sub
105
112
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
106
-
107
- // if First borks, we got a bigger problems
108
113
currentMember = _finder . DeclarationsWithType ( DeclarationType . Procedure ) . Where ( d => d . Context == context ) . First ( ) ;
109
114
}
110
115
111
116
public override void ExitSubStmt ( [ NotNull ] VBAParser . SubStmtContext context )
112
117
{
113
- // well, we're done here
114
118
ExitMeasurableMember ( ) ;
115
119
}
116
120
117
121
public override void EnterFunctionStmt ( [ NotNull ] VBAParser . FunctionStmtContext context )
118
122
{
119
- // this is the default path through the function
120
123
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
121
-
122
- // if First borks, we got bigger problems
123
124
currentMember = _finder . DeclarationsWithType ( DeclarationType . Function ) . Where ( d => d . Context == context ) . First ( ) ;
124
125
}
125
126
126
127
public override void ExitFunctionStmt ( [ NotNull ] VBAParser . FunctionStmtContext context )
127
128
{
128
- // well, we're done here
129
129
ExitMeasurableMember ( ) ;
130
130
}
131
131
132
132
public override void EnterPropertyGetStmt ( [ NotNull ] VBAParser . PropertyGetStmtContext context )
133
133
{
134
134
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
135
-
136
135
currentMember = _finder . DeclarationsWithType ( DeclarationType . PropertyGet ) . Where ( d => d . Context == context ) . First ( ) ;
137
136
}
138
137
139
138
public override void ExitPropertyGetStmt ( [ NotNull ] VBAParser . PropertyGetStmtContext context )
140
139
{
141
- // well, we're done here
142
140
ExitMeasurableMember ( ) ;
143
141
}
144
142
145
143
public override void EnterPropertyLetStmt ( [ NotNull ] VBAParser . PropertyLetStmtContext context )
146
144
{
147
145
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
148
-
149
146
currentMember = _finder . DeclarationsWithType ( DeclarationType . PropertyLet ) . Where ( d => d . Context == context ) . First ( ) ;
150
147
}
151
148
152
149
public override void ExitPropertyLetStmt ( [ NotNull ] VBAParser . PropertyLetStmtContext context )
153
150
{
154
- // well, we're done here
155
151
ExitMeasurableMember ( ) ;
156
152
}
157
153
158
154
public override void EnterPropertySetStmt ( [ NotNull ] VBAParser . PropertySetStmtContext context )
159
155
{
160
156
results . Add ( new CodeMetricsResult ( 0 , 1 , 0 ) ) ;
161
-
162
157
currentMember = _finder . DeclarationsWithType ( DeclarationType . PropertySet ) . Where ( d => d . Context == context ) . First ( ) ;
163
158
}
164
159
165
160
public override void ExitPropertySetStmt ( [ NotNull ] VBAParser . PropertySetStmtContext context )
166
- {
167
- // well, we're done here
161
+ {
168
162
ExitMeasurableMember ( ) ;
169
163
}
170
164
171
165
public override void EnterBlockStmt ( [ NotNull ] VBAParser . BlockStmtContext context )
172
166
{
173
- var ws = context . whiteSpace ( ) ;
174
- // FIXME only take the last contiguous non-linebreak into account
175
- results . Add ( new CodeMetricsResult ( 0 , 0 , ( ws ? . ChildCount ?? 0 ) / _indenterSettings . IndentSpaces ) ) ;
167
+ // there is a whitespace context here after the option of a statementLabel.
168
+ // we need to account for that
169
+ results . Add ( new CodeMetricsResult ( 0 , 0 , IndentationLevelFromWhitespace ( context . whiteSpace ( ) ) ) ) ;
170
+ }
171
+
172
+ private int IndentationLevelFromWhitespace ( VBAParser . WhiteSpaceContext wsContext )
173
+ {
174
+ if ( wsContext == null ) return 0 ;
175
+ // the only thing that contains underscores is the line-continuation at this point
176
+ var lineContinuation = wsContext . children . LastOrDefault ( ( tree ) => tree . GetText ( ) . Contains ( "_" ) ) ;
177
+ var index = lineContinuation != null ? wsContext . children . IndexOf ( lineContinuation ) : 0 ;
178
+ return ( wsContext ? . ChildCount ?? 0 - index ) / _indenterSettings . IndentSpaces ;
176
179
}
177
180
178
181
private void ExitMeasurableMember ( )
0 commit comments