Skip to content

Commit e7dbdee

Browse files
authored
Merge pull request #4942 from retailcoder/WhileWendInspection
Introduces ObsoleteWhileWendStatementInspection
2 parents 327109b + 707f597 commit e7dbdee

20 files changed

+333
-25
lines changed
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
using Rubberduck.Inspections.Abstract;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using Antlr4.Runtime;
5+
using Rubberduck.Inspections.Inspections.Extensions;
6+
using Rubberduck.Inspections.Results;
7+
using Rubberduck.Parsing;
8+
using Rubberduck.Parsing.Grammar;
9+
using Rubberduck.Parsing.Inspections.Abstract;
10+
using Rubberduck.Parsing.VBA;
11+
using Rubberduck.Resources.Inspections;
12+
using Rubberduck.VBEditor;
13+
14+
namespace Rubberduck.CodeAnalysis.Inspections.Concrete
15+
{
16+
public sealed class ObsoleteWhileWendStatementInspection : ParseTreeInspectionBase
17+
{
18+
public ObsoleteWhileWendStatementInspection(RubberduckParserState state)
19+
: base(state)
20+
{
21+
Listener = new ObsoleteWhileWendStatementListener();
22+
}
23+
24+
public override IInspectionListener Listener { get; }
25+
26+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
27+
{
28+
return Listener.Contexts.Where(context =>
29+
!context.IsIgnoringInspectionResultFor(State.DeclarationFinder, AnnotationName))
30+
.Select(context => new QualifiedContextInspectionResult(this, InspectionResults.ObsoleteWhileWendStatementInspection, context));
31+
}
32+
33+
public class ObsoleteWhileWendStatementListener : VBAParserBaseListener, IInspectionListener
34+
{
35+
private readonly List<QualifiedContext<ParserRuleContext>> _contexts =
36+
new List<QualifiedContext<ParserRuleContext>>();
37+
38+
public IReadOnlyList<QualifiedContext<ParserRuleContext>> Contexts => _contexts;
39+
40+
public QualifiedModuleName CurrentModuleName { get; set; }
41+
42+
public void ClearContexts()
43+
{
44+
_contexts.Clear();
45+
}
46+
47+
public override void ExitWhileWendStmt(VBAParser.WhileWendStmtContext context)
48+
{
49+
_contexts.Add(new QualifiedContext<ParserRuleContext>(CurrentModuleName, context));
50+
}
51+
}
52+
}
53+
}
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
using Rubberduck.CodeAnalysis.Inspections.Concrete;
2+
using Rubberduck.Inspections.Abstract;
3+
using Rubberduck.Parsing.Grammar;
4+
using Rubberduck.Parsing.Inspections.Abstract;
5+
using Rubberduck.Parsing.Rewriter;
6+
7+
namespace Rubberduck.CodeAnalysis.QuickFixes
8+
{
9+
public sealed class ReplaceWhileWendWithDoWhileLoopQuickFix : QuickFixBase
10+
{
11+
public ReplaceWhileWendWithDoWhileLoopQuickFix()
12+
: base(typeof(ObsoleteWhileWendStatementInspection))
13+
{ }
14+
15+
public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
16+
{
17+
var rewriter = rewriteSession.CheckOutModuleRewriter(result.QualifiedSelection.QualifiedName);
18+
var context = (VBAParser.WhileWendStmtContext)result.Context;
19+
20+
rewriter.Replace(context.WHILE(), "Do While");
21+
rewriter.Replace(context.WEND(), "Loop");
22+
}
23+
24+
public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.ReplaceWhileWendWithDoWhileLoopQuickFix;
25+
26+
public override bool CanFixInProcedure => true;
27+
public override bool CanFixInModule => true;
28+
public override bool CanFixInProject => true;
29+
}
30+
}

Rubberduck.Core/UI/CodeExplorer/CodeExplorerControl.xaml

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -266,7 +266,12 @@
266266
<Menu VerticalContentAlignment="Center" Background="Transparent" >
267267
<MenuItem ItemsSource="{StaticResource AddModuleCommands}" VerticalContentAlignment="Center">
268268
<MenuItem.Header>
269-
<Image Style="{StaticResource ToolbarIconStyle}" Source="{StaticResource AddModuleImage}" />
269+
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
270+
<Image Style="{StaticResource ToolbarIconStyle}" Source="{StaticResource AddModuleImage}" />
271+
<Border Margin="4,0,0,0">
272+
<Path VerticalAlignment="Center" Width="6" Fill="{DynamicResource ToolBarGripper}" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z" />
273+
</Border>
274+
</StackPanel>
270275
</MenuItem.Header>
271276
<MenuItem.ToolTip>
272277
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.CodeExplorer.CodeExplorerUI, Key=CodeExplorer_Add}" />

Rubberduck.Core/UI/Inspections/InspectionResultsControl.xaml

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -84,11 +84,18 @@
8484
<Separator />
8585
<Menu Background="Transparent">
8686
<MenuItem VerticalAlignment="Center"
87-
Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=Fix}"
8887
ItemsSource="{Binding QuickFixes}" Background="Transparent">
8988
<MenuItem.Icon>
9089
<Image Source="{StaticResource FixImage}" />
9190
</MenuItem.Icon>
91+
<MenuItem.Header>
92+
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
93+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=Fix}" />
94+
<Border Margin="8,0,0,0">
95+
<Path VerticalAlignment="Center" Width="6" Fill="{DynamicResource ToolBarGripper}" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z" />
96+
</Border>
97+
</StackPanel>
98+
</MenuItem.Header>
9299
<MenuItem.ItemContainerStyle>
93100
<Style TargetType="{x:Type MenuItem}">
94101
<Setter Property="Icon">

Rubberduck.Core/UI/UnitTesting/TestExplorerControl.xaml

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,11 +282,19 @@
282282
<Separator />
283283

284284
<Menu Background="Transparent">
285-
<MenuItem VerticalAlignment="Center" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_RunMenuButtonText}"
285+
<MenuItem VerticalAlignment="Center"
286286
IsEnabled="{Binding Model.IsBusy, Converter={StaticResource InvertBoolValue}}">
287287
<MenuItem.Icon>
288288
<Image Source="{StaticResource RunImage}" Style="{StaticResource ToolbarImageOpacity}" />
289289
</MenuItem.Icon>
290+
<MenuItem.Header>
291+
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
292+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_RunMenuButtonText}" />
293+
<Border Margin="8,0,0,0">
294+
<Path VerticalAlignment="Center" Width="6" Fill="{DynamicResource ToolBarGripper}" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z" />
295+
</Border>
296+
</StackPanel>
297+
</MenuItem.Header>
290298
<MenuItem Command="{Binding RunAllTestsCommand}" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_RunMenuAllTests}">
291299
<MenuItem.Icon>
292300
<Image Source="{StaticResource RunAllTestsImage}" />
@@ -347,11 +355,19 @@
347355
<Separator />
348356

349357
<Menu Background="Transparent">
350-
<MenuItem VerticalAlignment="Center" Header="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=Add}"
358+
<MenuItem VerticalAlignment="Center"
351359
IsEnabled="{Binding Model.IsBusy, Converter={StaticResource InvertBoolValue}}">
352360
<MenuItem.Icon>
353361
<Image Source="{StaticResource AddIcon}" Style="{StaticResource ToolbarImageOpacity}" />
354362
</MenuItem.Icon>
363+
<MenuItem.Header>
364+
<StackPanel Orientation="Horizontal" VerticalAlignment="Center">
365+
<TextBlock Text="{Resx ResxName=Rubberduck.Resources.RubberduckUI, Key=Add}" />
366+
<Border Margin="8,0,0,0">
367+
<Path VerticalAlignment="Center" Width="6" Fill="{DynamicResource ToolBarGripper}" Stretch="Uniform" HorizontalAlignment="Right" Data="F1 M 301.14,-189.041L 311.57,-189.041L 306.355,-182.942L 301.14,-189.041 Z" />
368+
</Border>
369+
</StackPanel>
370+
</MenuItem.Header>
355371
<MenuItem Command="{Binding AddTestModuleCommand}" Header="{Resx ResxName=Rubberduck.Resources.UnitTesting.TestExplorer, Key=TestExplorer_AddTestModule}">
356372
</MenuItem>
357373
<Separator />

Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/Inspections/InspectionInfo.fr.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,7 @@ Si le paramètre peut être nul, ignorer ce résultat; passer une valeur nulle
379379
<data name="OnErrorGoToMinusOneInspection" xml:space="preserve">
380380
<value>Bien que légale, cette syntaxe a un effet peu documentée -- toute erreur courante est supprimée, en plus de désactiver la gestion d'erreurs. L'instruction peut également être ambiguë, si la procédure contient effectivement une ligne -1. La stratégie de gestion d'erreurs semble plus complexe que nécessaire et pourrait être à revoir.</value>
381381
</data>
382+
<data name="ObsoleteWhileWendStatementInspection" xml:space="preserve">
383+
<value>Les boucles 'While...Wend' existent pour compatibilité avec les anciennes versions de VB, et ont été remplaçées par l'introduction des structures itératives 'Do While...Loop', qui supportent l'instruction 'Exit Do'. Les boucles 'While...Wend' ne peuvent être terminées qu'en remplissant la condition de l'expression 'While'.</value>
384+
</data>
382385
</root>

Rubberduck.Resources/Inspections/InspectionInfo.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -379,4 +379,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu
379379
<data name="OnErrorGoToMinusOneInspection" xml:space="preserve">
380380
<value>While this is legal, this is poorly documented "feature" that means something different -- the error state is also cleared in addition to disabling any error handling. However, this can be ambiguous as a negative line label of -1 may end up as a target and excessively complex error handling usually indicates a need of refactoring the procedure.</value>
381381
</data>
382+
<data name="ObsoleteWhileWendStatementInspection" xml:space="preserve">
383+
<value>'While...Wend' loops exist for backward compatibility and have been superseded by the introduction of 'Do While...Loop' blocks, which support the 'Exit Do' exit statement. 'While...Wend' loops cannot be exited other than fulfilling the 'While' condition.</value>
384+
</data>
382385
</root>

Rubberduck.Resources/Inspections/InspectionNames.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/Inspections/InspectionNames.fr.resx

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -349,7 +349,7 @@
349349
<value>Utilisation d'un membre marqué '@Obsolete'</value>
350350
</data>
351351
<data name="OnLocalErrorInspection" xml:space="preserve">
352-
<value>Instruction 'On Local Error'</value>
352+
<value>Instruction obsolète 'On Local Error'</value>
353353
</data>
354354
<data name="UnderscoreInPublicClassModuleMemberInspection" xml:space="preserve">
355355
<value>Caractère de soulignement dans le nom d'un membre d'un module de classe</value>
@@ -363,4 +363,7 @@
363363
<data name="MissingModuleAnnotationInspection" xml:space="preserve">
364364
<value>Annotation manquante (module)</value>
365365
</data>
366+
<data name="ObsoleteWhileWendStatementInspection" xml:space="preserve">
367+
<value>Utilisation de l'instruction obsolète 'While...Wend'</value>
368+
</data>
366369
</root>

0 commit comments

Comments
 (0)