Skip to content

Commit 399dd45

Browse files
authored
Merge pull request #3357 from BZngr/3246_InspectionEmptySelectCaseBlock
Add more Empty Block Inspections
2 parents d7841e7 + a257f18 commit 399dd45

17 files changed

+924
-143
lines changed
Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,81 @@
1+
using Antlr4.Runtime;
2+
using Rubberduck.Parsing;
3+
using Rubberduck.Parsing.Grammar;
4+
using Rubberduck.Parsing.Inspections.Abstract;
5+
using Rubberduck.VBEditor;
6+
using System.Collections.Generic;
7+
using System.Diagnostics;
8+
9+
namespace Rubberduck.Inspections.Concrete
10+
{
11+
public class EmptyBlockInspectionListenerBase : VBAParserBaseListener, IInspectionListener
12+
{
13+
private readonly List<QualifiedContext<ParserRuleContext>> _contexts = new List<QualifiedContext<ParserRuleContext>>();
14+
public IReadOnlyList<QualifiedContext<ParserRuleContext>> Contexts => _contexts;
15+
16+
public QualifiedModuleName CurrentModuleName { get; set; }
17+
18+
public void ClearContexts()
19+
{
20+
_contexts.Clear();
21+
}
22+
23+
public void InspectBlockForExecutableStatements<T>(VBAParser.BlockContext block, T context) where T : ParserRuleContext
24+
{
25+
if (!BlockContainsExecutableStatements(block))
26+
{
27+
AddResult(new QualifiedContext<ParserRuleContext>(CurrentModuleName, context));
28+
}
29+
}
30+
31+
public void AddResult(QualifiedContext<ParserRuleContext> qualifiedContext)
32+
{
33+
_contexts.Add(qualifiedContext);
34+
}
35+
36+
private bool BlockContainsExecutableStatements(VBAParser.BlockContext block)
37+
{
38+
return block != null && block.children != null && ContainsExecutableStatements(block);
39+
}
40+
41+
private bool ContainsExecutableStatements(VBAParser.BlockContext block)
42+
{
43+
foreach (var child in block.children)
44+
{
45+
if (child is VBAParser.BlockStmtContext)
46+
{
47+
var blockStmt = (VBAParser.BlockStmtContext)child;
48+
var mainBlockStmt = blockStmt.mainBlockStmt();
49+
50+
if (mainBlockStmt == null)
51+
{
52+
continue; //We have a lone line lable, which is not executable.
53+
}
54+
55+
Debug.Assert(mainBlockStmt.ChildCount == 1);
56+
57+
// exclude variables and consts because they are not executable statements
58+
if (mainBlockStmt.GetChild(0) is VBAParser.VariableStmtContext ||
59+
mainBlockStmt.GetChild(0) is VBAParser.ConstStmtContext)
60+
{
61+
continue;
62+
}
63+
64+
return true;
65+
}
66+
67+
if (child is VBAParser.RemCommentContext ||
68+
child is VBAParser.CommentContext ||
69+
child is VBAParser.CommentOrAnnotationContext ||
70+
child is VBAParser.EndOfStatementContext)
71+
{
72+
continue;
73+
}
74+
75+
return true;
76+
}
77+
78+
return false;
79+
}
80+
}
81+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Antlr4.Runtime.Misc;
2+
using Rubberduck.Inspections.Abstract;
3+
using Rubberduck.Inspections.Results;
4+
using Rubberduck.Parsing.Grammar;
5+
using Rubberduck.Parsing.Inspections.Abstract;
6+
using Rubberduck.Parsing.Inspections.Resources;
7+
using Rubberduck.Parsing.VBA;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
12+
namespace Rubberduck.Inspections.Concrete
13+
{
14+
internal class EmptyCaseBlockInspection : ParseTreeInspectionBase
15+
{
16+
public EmptyCaseBlockInspection(RubberduckParserState state)
17+
: base(state, CodeInspectionSeverity.Suggestion) { }
18+
19+
public override IInspectionListener Listener { get; } =
20+
new EmptyCaseBlockListener();
21+
22+
public override Type Type => typeof(EmptyCaseBlockInspection);
23+
24+
public override CodeInspectionType InspectionType => CodeInspectionType.CodeQualityIssues;
25+
26+
public override IEnumerable<IInspectionResult> GetInspectionResults()
27+
{
28+
return Listener.Contexts
29+
.Where(result => !IsIgnoringInspectionResultFor(result.ModuleName, result.Context.Start.Line))
30+
.Select(result => new QualifiedContextInspectionResult(this,
31+
InspectionsUI.EmptyCaseBlockInspectionResultFormat,
32+
result));
33+
}
34+
35+
public class EmptyCaseBlockListener : EmptyBlockInspectionListenerBase
36+
{
37+
public override void EnterCaseClause([NotNull] VBAParser.CaseClauseContext context)
38+
{
39+
InspectBlockForExecutableStatements(context.block(), context);
40+
}
41+
}
42+
}
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Antlr4.Runtime.Misc;
2+
using Rubberduck.Inspections.Abstract;
3+
using Rubberduck.Inspections.Results;
4+
using Rubberduck.Parsing.Grammar;
5+
using Rubberduck.Parsing.Inspections.Abstract;
6+
using Rubberduck.Parsing.Inspections.Resources;
7+
using Rubberduck.Parsing.VBA;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
12+
namespace Rubberduck.Inspections.Concrete
13+
{
14+
internal class EmptyDoWhileBlockInspection : ParseTreeInspectionBase
15+
{
16+
public EmptyDoWhileBlockInspection(RubberduckParserState state)
17+
: base(state, CodeInspectionSeverity.Suggestion) { }
18+
19+
public override Type Type => typeof(EmptyDoWhileBlockInspection);
20+
21+
public override CodeInspectionType InspectionType => CodeInspectionType.CodeQualityIssues;
22+
23+
public override IEnumerable<IInspectionResult> GetInspectionResults()
24+
{
25+
return Listener.Contexts
26+
.Where(result => !IsIgnoringInspectionResultFor(result.ModuleName, result.Context.Start.Line))
27+
.Select(result => new QualifiedContextInspectionResult(this,
28+
InspectionsUI.EmptyDoWhileBlockInspectionResultFormat,
29+
result));
30+
}
31+
32+
public override IInspectionListener Listener { get; } =
33+
new EmptyDoWhileBlockListener();
34+
35+
public class EmptyDoWhileBlockListener : EmptyBlockInspectionListenerBase
36+
{
37+
public override void EnterDoLoopStmt([NotNull] VBAParser.DoLoopStmtContext context)
38+
{
39+
InspectBlockForExecutableStatements(context.block(), context);
40+
}
41+
}
42+
}
43+
}

Rubberduck.Inspections/Concrete/EmptyElseBlockInspection.cs

Lines changed: 12 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,30 +1,25 @@
1-
using System;
2-
using System.Collections.Generic;
3-
using System.Linq;
4-
using Antlr4.Runtime;
5-
using Rubberduck.Parsing.Grammar;
1+
using Antlr4.Runtime.Misc;
62
using Rubberduck.Inspections.Abstract;
73
using Rubberduck.Inspections.Results;
8-
using Rubberduck.Parsing;
4+
using Rubberduck.Parsing.Grammar;
95
using Rubberduck.Parsing.Inspections.Abstract;
106
using Rubberduck.Parsing.Inspections.Resources;
117
using Rubberduck.Parsing.VBA;
12-
using Rubberduck.VBEditor;
13-
using System.Diagnostics;
14-
using Antlr4.Runtime.Misc;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
1511

1612
namespace Rubberduck.Inspections.Concrete
1713
{
1814
internal class EmptyElseBlockInspection : ParseTreeInspectionBase
1915
{
20-
public EmptyElseBlockInspection(RubberduckParserState state) : base(state, CodeInspectionSeverity.Suggestion) { }
16+
public EmptyElseBlockInspection(RubberduckParserState state)
17+
: base(state, CodeInspectionSeverity.Suggestion) { }
2118

2219
public override Type Type => typeof(EmptyElseBlockInspection);
2320

2421
public override CodeInspectionType InspectionType => CodeInspectionType.CodeQualityIssues;
2522

26-
public override IInspectionListener Listener { get; } = new EmptyElseBlockListener();
27-
2823
public override IEnumerable<IInspectionResult> GetInspectionResults()
2924
{
3025
return Listener.Contexts
@@ -34,65 +29,14 @@ public override IEnumerable<IInspectionResult> GetInspectionResults()
3429
result));
3530
}
3631

37-
public class EmptyElseBlockListener : VBAParserBaseListener, IInspectionListener
32+
public override IInspectionListener Listener { get; }
33+
= new EmptyElseBlockListener();
34+
35+
public class EmptyElseBlockListener : EmptyBlockInspectionListenerBase
3836
{
3937
public override void EnterElseBlock([NotNull] VBAParser.ElseBlockContext context)
4038
{
41-
var block = context.block();
42-
if (block == null || block.children == null || !ContainsExecutableStatements(block))
43-
{
44-
_contexts.Add(new QualifiedContext<ParserRuleContext>(CurrentModuleName, context));
45-
}
46-
base.EnterElseBlock(context);
47-
}
48-
49-
private readonly List<QualifiedContext<ParserRuleContext>> _contexts = new List<QualifiedContext<ParserRuleContext>>();
50-
public IReadOnlyList<QualifiedContext<ParserRuleContext>> Contexts => _contexts;
51-
52-
public QualifiedModuleName CurrentModuleName { get; set; }
53-
54-
public void ClearContexts()
55-
{
56-
_contexts.Clear();
57-
}
58-
59-
private bool ContainsExecutableStatements(VBAParser.BlockContext block)
60-
{
61-
foreach (var child in block.children)
62-
{
63-
if (child is VBAParser.BlockStmtContext)
64-
{
65-
var blockStmt = (VBAParser.BlockStmtContext)child;
66-
var mainBlockStmt = blockStmt.mainBlockStmt();
67-
68-
if(mainBlockStmt == null)
69-
{
70-
continue; //Lone line label, which isn't executable.
71-
}
72-
73-
Debug.Assert(mainBlockStmt.ChildCount == 1);
74-
75-
if (mainBlockStmt.GetChild(0) is VBAParser.VariableStmtContext ||
76-
mainBlockStmt.GetChild(0) is VBAParser.ConstStmtContext)
77-
{
78-
continue;
79-
}
80-
81-
return true;
82-
}
83-
84-
if (child is VBAParser.RemCommentContext ||
85-
child is VBAParser.CommentContext ||
86-
child is VBAParser.CommentOrAnnotationContext ||
87-
child is VBAParser.EndOfStatementContext)
88-
{
89-
continue;
90-
}
91-
92-
return true;
93-
}
94-
95-
return false;
39+
InspectBlockForExecutableStatements(context.block(), context);
9640
}
9741
}
9842
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Antlr4.Runtime.Misc;
2+
using Rubberduck.Inspections.Abstract;
3+
using Rubberduck.Inspections.Results;
4+
using Rubberduck.Parsing.Grammar;
5+
using Rubberduck.Parsing.Inspections.Abstract;
6+
using Rubberduck.Parsing.Inspections.Resources;
7+
using Rubberduck.Parsing.VBA;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
12+
namespace Rubberduck.Inspections.Concrete
13+
{
14+
internal class EmptyForEachBlockInspection : ParseTreeInspectionBase
15+
{
16+
public EmptyForEachBlockInspection(RubberduckParserState state)
17+
: base(state, CodeInspectionSeverity.Suggestion) { }
18+
19+
public override Type Type => typeof(EmptyForEachBlockInspection);
20+
21+
public override CodeInspectionType InspectionType => CodeInspectionType.CodeQualityIssues;
22+
23+
public override IEnumerable<IInspectionResult> GetInspectionResults()
24+
{
25+
return Listener.Contexts
26+
.Where(result => !IsIgnoringInspectionResultFor(result.ModuleName, result.Context.Start.Line))
27+
.Select(result => new QualifiedContextInspectionResult(this,
28+
InspectionsUI.EmptyForEachBlockInspectionResultFormat,
29+
result));
30+
}
31+
32+
public override IInspectionListener Listener { get; } =
33+
new EmptyForEachBlockListener();
34+
35+
public class EmptyForEachBlockListener : EmptyBlockInspectionListenerBase
36+
{
37+
public override void EnterForEachStmt([NotNull] VBAParser.ForEachStmtContext context)
38+
{
39+
InspectBlockForExecutableStatements(context.block(), context);
40+
}
41+
}
42+
}
43+
}
Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
using Antlr4.Runtime.Misc;
2+
using Rubberduck.Inspections.Abstract;
3+
using Rubberduck.Inspections.Results;
4+
using Rubberduck.Parsing.Grammar;
5+
using Rubberduck.Parsing.Inspections.Abstract;
6+
using Rubberduck.Parsing.Inspections.Resources;
7+
using Rubberduck.Parsing.VBA;
8+
using System;
9+
using System.Collections.Generic;
10+
using System.Linq;
11+
12+
namespace Rubberduck.Inspections.Concrete
13+
{
14+
internal class EmptyForLoopBlockInspection : ParseTreeInspectionBase
15+
{
16+
public EmptyForLoopBlockInspection(RubberduckParserState state)
17+
: base(state, CodeInspectionSeverity.Suggestion) { }
18+
19+
public override Type Type => typeof(EmptyForLoopBlockInspection);
20+
21+
public override CodeInspectionType InspectionType => CodeInspectionType.CodeQualityIssues;
22+
23+
public override IEnumerable<IInspectionResult> GetInspectionResults()
24+
{
25+
return Listener.Contexts
26+
.Where(result => !IsIgnoringInspectionResultFor(result.ModuleName, result.Context.Start.Line))
27+
.Select(result => new QualifiedContextInspectionResult(this,
28+
InspectionsUI.EmptyForLoopBlockInspectionResultFormat,
29+
result));
30+
}
31+
32+
public override IInspectionListener Listener { get; } =
33+
new EmptyForloopBlockListener();
34+
35+
public class EmptyForloopBlockListener : EmptyBlockInspectionListenerBase
36+
{
37+
public override void EnterForNextStmt([NotNull] VBAParser.ForNextStmtContext context)
38+
{
39+
InspectBlockForExecutableStatements(context.block(), context);
40+
}
41+
}
42+
}
43+
}

0 commit comments

Comments
 (0)