Skip to content

Commit ba240ef

Browse files
authored
Merge pull request #3863 from Vogel612/codeMetrics-fixes
Determine nesting levels based on blocks, not spaces
2 parents 7bc14f1 + 1f2d7a3 commit ba240ef

File tree

2 files changed

+35
-46
lines changed

2 files changed

+35
-46
lines changed

Rubberduck.Core/Navigation/CodeMetrics/CodeMetricsAnalyst.cs

Lines changed: 34 additions & 45 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,24 @@
1-
using System.Collections.Generic;
2-
using System.Linq;
3-
using Rubberduck.Parsing.VBA;
1+
using Antlr4.Runtime.Misc;
42
using Antlr4.Runtime.Tree;
53
using Rubberduck.Parsing.Grammar;
6-
using Rubberduck.VBEditor;
7-
using Antlr4.Runtime.Misc;
84
using Rubberduck.Parsing.Symbols;
9-
using Rubberduck.SmartIndenter;
5+
using Rubberduck.Parsing.VBA;
6+
using Rubberduck.VBEditor;
7+
using System.Collections.Generic;
8+
using System.Diagnostics;
9+
using System.Linq;
1010

1111
namespace Rubberduck.Navigation.CodeMetrics
1212
{
1313
public class CodeMetricsAnalyst : ICodeMetricsAnalyst
14-
{
15-
private readonly IIndenterSettings _indenterSettings;
16-
17-
public CodeMetricsAnalyst(IIndenterSettings indenterSettings)
18-
{
19-
_indenterSettings = indenterSettings;
20-
}
14+
{
15+
public CodeMetricsAnalyst() { }
2116

2217
public IEnumerable<ModuleMetricsResult> ModuleMetrics(RubberduckParserState state)
2318
{
2419
if (state == null || !state.AllUserDeclarations.Any())
2520
{
26-
// must not return Enumerable.Empty
21+
// can not explicitly return Enumerable.Empty, this is equivalent
2722
yield break;
2823
}
2924

@@ -42,8 +37,9 @@ public ModuleMetricsResult GetModuleResult(RubberduckParserState state, Qualifie
4237

4338
private ModuleMetricsResult GetModuleResult(QualifiedModuleName qmn, IParseTree moduleTree, DeclarationFinder declarationFinder)
4439
{
45-
// Consider rewrite as visitor? That should make subtrees easier and allow us to expand metrics
46-
var cmListener = new CodeMetricsListener(declarationFinder, _indenterSettings);
40+
// FIXME rewrite as visitor, see discussion on pulls#3522
41+
// That should make subtrees easier and allow us to expand metrics
42+
var cmListener = new CodeMetricsListener(declarationFinder);
4743
ParseTreeWalker.Default.Walk(cmListener, moduleTree);
4844
return cmListener.GetMetricsResult(qmn);
4945
}
@@ -52,31 +48,36 @@ private ModuleMetricsResult GetModuleResult(QualifiedModuleName qmn, IParseTree
5248
private class CodeMetricsListener : VBAParserBaseListener
5349
{
5450
private readonly DeclarationFinder _finder;
55-
private readonly IIndenterSettings _indenterSettings;
5651

5752
private Declaration _currentMember;
53+
private int _currentNestingLevel = 0;
54+
private int _currentMaxNesting = 0;
5855
private List<CodeMetricsResult> _results = new List<CodeMetricsResult>();
5956
private List<CodeMetricsResult> _moduleResults = new List<CodeMetricsResult>();
6057

6158
private List<MemberMetricsResult> _memberResults = new List<MemberMetricsResult>();
6259

63-
public CodeMetricsListener(DeclarationFinder finder, IIndenterSettings indenterSettings)
60+
public CodeMetricsListener(DeclarationFinder finder)
6461
{
6562
_finder = finder;
66-
_indenterSettings = indenterSettings;
6763
}
68-
69-
public override void EnterEndOfLine([NotNull] VBAParser.EndOfLineContext context)
64+
public override void EnterBlock([NotNull] VBAParser.BlockContext context)
7065
{
71-
int followingIndentationLevel = 0;
72-
// we have a proper newline
73-
if (context.NEWLINE() != null)
66+
_currentNestingLevel++;
67+
if (_currentNestingLevel > _currentMaxNesting)
7468
{
75-
// the last whitespace, which is the one in front of the next line's contents
76-
var followingWhitespace = context.whiteSpace().LastOrDefault();
77-
followingIndentationLevel = IndentationLevelFromWhitespace(followingWhitespace);
69+
_currentMaxNesting = _currentNestingLevel;
7870
}
79-
(_currentMember == null ? _moduleResults : _results).Add(new CodeMetricsResult(1, 0, followingIndentationLevel));
71+
}
72+
73+
public override void ExitBlock([NotNull] VBAParser.BlockContext context)
74+
{
75+
_currentNestingLevel--;
76+
}
77+
78+
public override void EnterEndOfLine([NotNull] VBAParser.EndOfLineContext context)
79+
{
80+
(_currentMember == null ? _moduleResults : _results).Add(new CodeMetricsResult(1, 0, 0));
8081
}
8182

8283
public override void EnterIfStmt([NotNull] VBAParser.IfStmtContext context)
@@ -160,27 +161,15 @@ public override void ExitPropertySetStmt([NotNull] VBAParser.PropertySetStmtCont
160161
{
161162
ExitMeasurableMember();
162163
}
163-
164-
public override void EnterBlockStmt([NotNull] VBAParser.BlockStmtContext context)
165-
{
166-
// there is a whitespace context here after the option of a statementLabel.
167-
// we need to account for that
168-
_results.Add(new CodeMetricsResult(0, 0, IndentationLevelFromWhitespace(context.whiteSpace())));
169-
}
170164

171-
private int IndentationLevelFromWhitespace(VBAParser.WhiteSpaceContext wsContext)
172-
{
173-
if (wsContext == null) return 0;
174-
// the only thing that contains underscores is the line-continuation at this point
175-
var lineContinuation = wsContext.children.LastOrDefault((tree) => tree.GetText().Contains("_"));
176-
var index = lineContinuation != null ? wsContext.children.IndexOf(lineContinuation) : 0;
177-
return (wsContext?.ChildCount ?? 0 - index) / _indenterSettings.IndentSpaces;
178-
}
179-
180165
private void ExitMeasurableMember()
181166
{
167+
Debug.Assert(_currentNestingLevel == 0, "Unexpected Nesting Level when exiting Measurable Member");
168+
_results.Add(new CodeMetricsResult(0, 0, _currentMaxNesting));
182169
_memberResults.Add(new MemberMetricsResult(_currentMember, _results));
183-
_results = new List<CodeMetricsResult>(); // reinitialize to drop results
170+
// reset state
171+
_results = new List<CodeMetricsResult>();
172+
_currentMaxNesting = 0;
184173
_currentMember = null;
185174
}
186175

RubberduckTests/Stats/ParseTreeMetricsAnalystTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ public class CodeMetricsAnalystTests
1616
[SetUp]
1717
public void Setup()
1818
{
19-
cut = new CodeMetricsAnalyst(IndenterSettingsTests.GetMockIndenterSettings());
19+
cut = new CodeMetricsAnalyst();
2020
}
2121

2222
[Test]

0 commit comments

Comments
 (0)