Skip to content

Commit 605df66

Browse files
authored
Merge pull request #2791 from retailcoder/rd-next
Quickfix and module extensions
2 parents 61bde9f + 01ca2e0 commit 605df66

40 files changed

+329
-122
lines changed

RetailCoder.VBE/App.cs

Lines changed: 3 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,8 +9,8 @@
99
using System;
1010
using System.Globalization;
1111
using System.Windows.Forms;
12+
using Rubberduck.Inspections.Resources;
1213
using Rubberduck.UI.Command;
13-
using Rubberduck.UI.Command.MenuItems.CommandBars;
1414
using Rubberduck.VBEditor.SafeComWrappers.Abstract;
1515
using Rubberduck.VersionCheck;
1616
using Application = System.Windows.Forms.Application;
@@ -23,7 +23,6 @@ public sealed class App : IDisposable
2323
private readonly AutoSave.AutoSave _autoSave;
2424
private readonly IGeneralConfigService _configService;
2525
private readonly IAppMenu _appMenus;
26-
private readonly RubberduckCommandBar _stateBar;
2726
private readonly IRubberduckHooks _hooks;
2827
private readonly IVersionCheck _version;
2928
private readonly CommandBase _checkVersionCommand;
@@ -36,7 +35,6 @@ public App(IVBE vbe,
3635
IMessageBox messageBox,
3736
IGeneralConfigService configService,
3837
IAppMenu appMenus,
39-
RubberduckCommandBar stateBar,
4038
IRubberduckHooks hooks,
4139
IVersionCheck version,
4240
CommandBase checkVersionCommand)
@@ -45,7 +43,6 @@ public App(IVBE vbe,
4543
_configService = configService;
4644
_autoSave = new AutoSave.AutoSave(vbe, _configService);
4745
_appMenus = appMenus;
48-
_stateBar = stateBar;
4946
_hooks = hooks;
5047
_version = version;
5148
_checkVersionCommand = checkVersionCommand;
@@ -61,7 +58,6 @@ private void _configService_SettingsChanged(object sender, ConfigurationChangedE
6158
_hooks.HookHotkeys();
6259
// also updates the ShortcutKey text
6360
_appMenus.Localize();
64-
_stateBar.Localize();
6561
UpdateLoggingLevel();
6662

6763
if (e.LanguageChanged)
@@ -97,7 +93,6 @@ public void Startup()
9793
LoadConfig();
9894
CheckForLegacyIndenterSettings();
9995
_appMenus.Initialize();
100-
_stateBar.Initialize();
10196
_hooks.HookHotkeys(); // need to hook hotkeys before we localize menus, to correctly display ShortcutTexts
10297
_appMenus.Localize();
10398

@@ -130,8 +125,9 @@ private void LoadConfig()
130125
try
131126
{
132127
CultureManager.UICulture = CultureInfo.GetCultureInfo(_config.UserSettings.GeneralSettings.Language.Code);
128+
RubberduckUI.Culture = CultureInfo.CurrentUICulture;
129+
InspectionsUI.Culture = CultureInfo.CurrentUICulture;
133130
_appMenus.Localize();
134-
_stateBar.Localize();
135131
}
136132
catch (CultureNotFoundException exception)
137133
{

RetailCoder.VBE/AppMenu.cs

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
using Rubberduck.Parsing.VBA;
66
using Rubberduck.UI;
77
using Rubberduck.UI.Command.MenuItems;
8+
using Rubberduck.UI.Command.MenuItems.CommandBars;
89
using Rubberduck.UI.Command.MenuItems.ParentMenus;
910

1011
namespace Rubberduck
@@ -14,19 +15,22 @@ public class AppMenu : IAppMenu, IDisposable
1415
private readonly IReadOnlyList<IParentMenuItem> _menus;
1516
private readonly IParseCoordinator _parser;
1617
private readonly ISelectionChangeService _selectionService;
18+
private readonly RubberduckCommandBar _stateBar;
1719

18-
public AppMenu(IEnumerable<IParentMenuItem> menus, IParseCoordinator parser, ISelectionChangeService selectionService)
20+
public AppMenu(IEnumerable<IParentMenuItem> menus, IParseCoordinator parser, ISelectionChangeService selectionService, RubberduckCommandBar stateBar)
1921
{
2022
_menus = menus.ToList();
2123
_parser = parser;
2224
_selectionService = selectionService;
25+
_stateBar = stateBar;
2326

2427
_parser.State.StateChanged += OnParserStateChanged;
2528
_selectionService.SelectedDeclarationChanged += OnSelectedDeclarationChange;
2629
}
2730

2831
public void Initialize()
2932
{
33+
_stateBar.Initialize();
3034
foreach (var menu in _menus)
3135
{
3236
menu.Initialize();
@@ -53,6 +57,8 @@ public void EvaluateCanExecute(RubberduckParserState state)
5357

5458
public void Localize()
5559
{
60+
_stateBar.Localize();
61+
_stateBar.SetStatusLabelCaption(_parser.State.Status);
5662
foreach (var menu in _menus)
5763
{
5864
menu.Localize();

RetailCoder.VBE/Common/CodeModuleExtensions.cs

Lines changed: 66 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
using System.Linq;
55
using Antlr4.Runtime;
66
using Rubberduck.Parsing;
7+
using Rubberduck.Parsing.Grammar;
78
using Rubberduck.Parsing.Symbols;
89
using Rubberduck.Parsing.VBA;
910
using Rubberduck.VBEditor;
@@ -162,10 +163,74 @@ private static string RemoveExtraComma(string str, int numParams, int indexRemov
162163

163164
public static void Remove(this ICodeModule module, IdentifierReference target)
164165
{
165-
var parent = target.Context.Parent as ParserRuleContext;
166+
var parent = (ParserRuleContext)target.Context.Parent;
167+
if (target.IsAssignment)
168+
{
169+
// target is LHS of assignment; need to know if there's a procedure call in RHS
170+
var letStmt = parent as VBAParser.LetStmtContext;
171+
var setStmt = parent as VBAParser.SetStmtContext;
172+
173+
string argList;
174+
if (HasProcedureCall(letStmt, out argList) || HasProcedureCall(setStmt, out argList))
175+
{
176+
// need to remove LHS only; RHS expression may have side-effects
177+
var original = parent.GetText();
178+
var replacement = ReplaceStringAtIndex(original, target.IdentifierName + " = ", string.Empty, 0);
179+
if (argList != null)
180+
{
181+
var atIndex = replacement.IndexOf(argList, StringComparison.OrdinalIgnoreCase);
182+
var plainArgs = " " + argList.Substring(1, argList.Length - 2);
183+
replacement = ReplaceStringAtIndex(replacement, argList, plainArgs, atIndex);
184+
}
185+
module.ReplaceLine(parent.Start.Line, replacement);
186+
return;
187+
}
188+
}
189+
166190
module.Remove(parent.GetSelection(), parent);
167191
}
168192

193+
private static bool HasProcedureCall(VBAParser.LetStmtContext context, out string argList)
194+
{
195+
if (context == null)
196+
{
197+
argList = null;
198+
return false;
199+
}
200+
return HasProcedureCall(context.expression(), out argList);
201+
}
202+
203+
private static bool HasProcedureCall(VBAParser.SetStmtContext context, out string argList)
204+
{
205+
if (context == null)
206+
{
207+
argList = null;
208+
return false;
209+
}
210+
return HasProcedureCall(context.expression(), out argList);
211+
}
212+
213+
private static bool HasProcedureCall(VBAParser.ExpressionContext context, out string argList)
214+
{
215+
// bug: what if complex expression has multiple arg lists?
216+
argList = GetArgListString(context.FindChildren<VBAParser.ArgListContext>().FirstOrDefault())
217+
?? GetArgListString(context.FindChildren<VBAParser.ArgumentListContext>().FirstOrDefault());
218+
219+
return !(context is VBAParser.LiteralExprContext
220+
|| context is VBAParser.NewExprContext
221+
|| context is VBAParser.BuiltInTypeExprContext);
222+
}
223+
224+
private static string GetArgListString(VBAParser.ArgListContext context)
225+
{
226+
return context == null ? null : context.GetText();
227+
}
228+
229+
private static string GetArgListString(VBAParser.ArgumentListContext context)
230+
{
231+
return context == null ? null : "(" + context.GetText() + ")";
232+
}
233+
169234
public static void Remove(this ICodeModule module, IEnumerable<IdentifierReference> targets)
170235
{
171236
foreach (var target in targets.OrderByDescending(e => e.Selection))

RetailCoder.VBE/Common/DeclarationExtensions.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Diagnostics;
44
using System.Diagnostics.CodeAnalysis;
5+
using System.Globalization;
56
using System.Linq;
67
using System.Windows.Media.Imaging;
78
using Rubberduck.Parsing;
@@ -11,7 +12,6 @@
1112
using Rubberduck.Properties;
1213
using Rubberduck.UI;
1314
using Rubberduck.VBEditor;
14-
using Rubberduck.VBEditor.Extensions;
1515
using Rubberduck.VBEditor.SafeComWrappers;
1616

1717
// ReSharper disable LocalizableElement
@@ -24,7 +24,7 @@ public static class DeclarationExtensions
2424

2525
public static string ToLocalizedString(this DeclarationType type)
2626
{
27-
return RubberduckUI.ResourceManager.GetString("DeclarationType_" + type, UI.Settings.Settings.Culture);
27+
return RubberduckUI.ResourceManager.GetString("DeclarationType_" + type, CultureInfo.CurrentUICulture);
2828
}
2929

3030
public static BitmapImage BitmapImage(this Declaration declaration)

RetailCoder.VBE/Inspections/Abstract/InspectionBase.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
using System;
22
using System.Collections.Generic;
3+
using System.Globalization;
34
using System.Linq;
45
using Rubberduck.Inspections.Resources;
56
using Rubberduck.Parsing.Annotations;
@@ -57,13 +58,13 @@ protected InspectionBase(RubberduckParserState state, CodeInspectionSeverity def
5758
/// <summary>
5859
/// Meta-information about why an inspection exists.
5960
/// </summary>
60-
public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta", UI.Settings.Settings.Culture); } }
61+
public virtual string Meta { get { return InspectionsUI.ResourceManager.GetString(Name + "Meta", CultureInfo.CurrentUICulture); } }
6162

6263
/// <summary>
6364
/// Gets a localized string representing the type of inspection.
6465
/// <see cref="InspectionType"/>
6566
/// </summary>
66-
public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString(), UI.Settings.Settings.Culture); } }
67+
public virtual string InspectionTypeName { get { return InspectionsUI.ResourceManager.GetString(InspectionType.ToString(), CultureInfo.CurrentUICulture); } }
6768

6869
/// <summary>
6970
/// Gets a string representing the text that must be present in an

RetailCoder.VBE/Inspections/Abstract/QuickFixBase.cs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Windows.Threading;
1+
using System.Globalization;
2+
using System.Windows.Threading;
23
using Antlr4.Runtime;
34
using Rubberduck.VBEditor;
45

@@ -12,8 +13,8 @@ public abstract class QuickFixBase
1213

1314
public QuickFixBase(ParserRuleContext context, QualifiedSelection selection, string description)
1415
{
15-
Dispatcher.CurrentDispatcher.Thread.CurrentCulture = UI.Settings.Settings.Culture;
16-
Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = UI.Settings.Settings.Culture;
16+
Dispatcher.CurrentDispatcher.Thread.CurrentCulture = CultureInfo.CurrentUICulture;
17+
Dispatcher.CurrentDispatcher.Thread.CurrentUICulture = CultureInfo.CurrentUICulture;
1718

1819
_context = context;
1920
_selection = selection;

RetailCoder.VBE/Inspections/Concrete/Inspector.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System;
22
using System.Collections.Concurrent;
33
using System.Collections.Generic;
4+
using System.Globalization;
45
using System.Linq;
56
using System.Threading;
67
using System.Threading.Tasks;
@@ -104,7 +105,7 @@ public async Task<IEnumerable<IInspectionResult>> FindIssuesAsync(RubberduckPars
104105
.Select(kv => new AggregateInspectionResult(kv.Value.OrderBy(i => i.QualifiedSelection).First(), kv.Value.Count)))
105106
.ToList();
106107

107-
state.OnStatusMessageUpdate(RubberduckUI.ResourceManager.GetString("ParserState_" + state.Status, UI.Settings.Settings.Culture)); // should be "Ready"
108+
state.OnStatusMessageUpdate(RubberduckUI.ResourceManager.GetString("ParserState_" + state.Status, CultureInfo.CurrentUICulture)); // should be "Ready"
108109
return results;
109110
}
110111

RetailCoder.VBE/Inspections/QuickFixes/RenameDeclarationQuickFix.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
using System.Globalization;
12
using System.Windows.Forms;
23
using Antlr4.Runtime;
34
using Rubberduck.Inspections.Abstract;
@@ -20,7 +21,7 @@ public class RenameDeclarationQuickFix : QuickFixBase
2021
private readonly IMessageBox _messageBox;
2122

2223
public RenameDeclarationQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target, RubberduckParserState state, IMessageBox messageBox)
23-
: base(context, selection, string.Format(RubberduckUI.Rename_DeclarationType, RubberduckUI.ResourceManager.GetString("DeclarationType_" + target.DeclarationType, UI.Settings.Settings.Culture)))
24+
: base(context, selection, string.Format(RubberduckUI.Rename_DeclarationType, RubberduckUI.ResourceManager.GetString("DeclarationType_" + target.DeclarationType, CultureInfo.CurrentUICulture)))
2425
{
2526
_target = target;
2627
_state = state;

RetailCoder.VBE/Inspections/QuickFixes/RenameProjectQuickFix.cs

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using System.Windows.Forms;
1+
using System.Globalization;
2+
using System.Windows.Forms;
23
using Antlr4.Runtime;
34
using Rubberduck.Inspections.Abstract;
45
using Rubberduck.Parsing.Symbols;
@@ -20,7 +21,7 @@ public class RenameProjectQuickFix : QuickFixBase
2021
private readonly RubberduckParserState _state;
2122

2223
public RenameProjectQuickFix(ParserRuleContext context, QualifiedSelection selection, Declaration target, RubberduckParserState state)
23-
: base(context, selection, string.Format(RubberduckUI.Rename_DeclarationType, RubberduckUI.ResourceManager.GetString("DeclarationType_" + DeclarationType.Project, UI.Settings.Settings.Culture)))
24+
: base(context, selection, string.Format(RubberduckUI.Rename_DeclarationType, RubberduckUI.ResourceManager.GetString("DeclarationType_" + DeclarationType.Project, CultureInfo.CurrentUICulture)))
2425
{
2526
_target = target;
2627
_state = state;

RetailCoder.VBE/Inspections/Resources/InspectionsUI.de.resx

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="UTF-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -59,7 +59,7 @@
5959
: using a System.ComponentModel.TypeConverter
6060
: and then encoded with base64 encoding.
6161
-->
62-
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
62+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
6363
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
6464
<xsd:element name="root" msdata:IsDataSet="true">
6565
<xsd:complexType>
@@ -624,9 +624,6 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null'
624624
<data name="ApplicationWorksheetFunctionInspectionMeta">
625625
<value>Das Excel Application-Objekt implementiert das WorksheetFunction interface direkt. Alle Aufrufe an WorksheetFunction-Member werden als laufzeitgebunden behandelt und Fehler im aufgerufenen Member werden in ein Variant des Typs VbVarType.Error gekapselt. Dadurch können Fehler nicht mit Fehleranweisungen behandelt werden und gegenüber skriptzeitgebundenen Aufrufen sinkt die Performanz. Ziehen Sie in Erwägung Application.WorksheetFunction explizit aufzurufen. Bedenken Sie: Falls dieser Aufruf in der Vergangenheit Fehler erzeugt hat, wurden diese ignoriert. Es sollte eine Fehlerbehandlung vorhanden sein, bevor Sie die schnelle Korrektur anwenden.</value>
626626
</data>
627-
<data name="AssignedByValParameterQuickFix">
628-
<value>Eine lokale Kopie des Parameters erstellen und verwenden</value>
629-
</data>
630627
<data name="WhiteListIdentifierQuickFix">
631628
<value>Zur Whitelist hinzufügen</value>
632629
</data>
@@ -645,4 +642,7 @@ Falls der Parameter 'null' sein kann, bitte dieses Auftreten ignorieren. 'null'
645642
<data name="HostSpecificExpressionInspectionMeta">
646643
<value>Geklammerte Ausdrücke werden von der Hostanwendung zur Laufzeit ausgewertet, was bedeutet, dass VBA den Ausdruck nicht zur Kompilierzeit validieren kann. Erwägen sie, das hostspezifische Objektmodell zu verwenden.</value>
647644
</data>
645+
<data name="AssignedByValParameterMakeLocalCopyQuickFix">
646+
<value />
647+
</data>
648648
</root>

RetailCoder.VBE/Inspections/Resources/InspectionsUI.fr.resx

Lines changed: 45 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="utf-8"?>
1+
<?xml version="1.0" encoding="UTF-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -59,7 +59,7 @@
5959
: using a System.ComponentModel.TypeConverter
6060
: and then encoded with base64 encoding.
6161
-->
62-
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
62+
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
6363
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
6464
<xsd:element name="root" msdata:IsDataSet="true">
6565
<xsd:complexType>
@@ -604,4 +604,46 @@ Si le paramètre peut être nul, ignorer ce résultat; passer une valeur nulle
604604
<data name="AggregateInspectionResultFormat" xml:space="preserve">
605605
<value>{0} ({1} résultats)</value>
606606
</data>
607-
</root>
607+
<data name="ApplicationWorksheetFunctionQuickFix">
608+
<value>Utiliser Application.WorksheetFunction explicitement.</value>
609+
</data>
610+
<data name="ApplicationWorksheetFunctionInspectionName">
611+
<value>Appel de fonction WorksheetFunction à liaison tardive.</value>
612+
</data>
613+
<data name="ApplicationWorksheetFunctionInspectionResultFormat">
614+
<value>Utilisation du membre à liaison tardive Application.{0}.</value>
615+
</data>
616+
<data name="HostSpecificExpressionInspectionName">
617+
<value>Les expressions spécifiques à l'application hôte, encadrées de crochets, sont seulement évaluées lors de l'exécution.</value>
618+
</data>
619+
<data name="HungarianNotationInspectionName">
620+
<value>L'identifiant utilise la notation hongroise.</value>
621+
</data>
622+
<data name="MemberNotOnInterfaceInspectionMeta">
623+
<value>Un membre est accédé mais ne semble pas exister dans l'interface de l'objet. Ceci causera probablement une erreur d'exécution #438.</value>
624+
</data>
625+
<data name="HungarianNotationInspectionMeta">
626+
<value>La notation hongroise rend le code plus difficile à lire, et est redondante lorsque les variables ont un type explicite et que des identifiants éloquents sont utilisés.</value>
627+
</data>
628+
<data name="ApplicationWorksheetFunctionInspectionMeta">
629+
<value>L'objet Excel Application n'implémente pas l'interface WorksheetFunction directement; les appels de fonctions WorksheetFunction effectués sur Application, renvoie une valeur VbVarType.Error; ces erreurs ne peuvent être capturées avec la gestion d'erreurs de VBA et encourent une pénalité de performance par rapport à un appel équivalent de WorksheetFunction. Note: assurez-vous de gérer les erreurs d'exécution en appliquant ce correctif.</value>
630+
</data>
631+
<data name="WhiteListIdentifierQuickFix">
632+
<value>Ajouter à la liste blanche</value>
633+
</data>
634+
<data name="HostSpecificExpressionInspectionResultFormat">
635+
<value>L'espression '{0}' ne peut être validée lors de la compilation.</value>
636+
</data>
637+
<data name="MemberNotOnInterfaceInspectionName">
638+
<value>Membre inexistant ou introuvable</value>
639+
</data>
640+
<data name="MemberNotOnInterfaceInspectionResultFormat">
641+
<value>Le membre '{0}' n'est pas exposé par l'interface du type '{1}'.</value>
642+
</data>
643+
<data name="AssignedByValParameterMakeLocalCopyQuickFix">
644+
<value>Créer et utiliser une copie locale du paramètre</value>
645+
</data>
646+
<data name="HostSpecificExpressionInspectionMeta">
647+
<value>L'expression est évaluée par l'application hôte au moment de l'exécution, ce qui implique que VBA ne peut valider l'expression lors de la compilation. Considérez utiliser plutôt le modèle d'objet de l'application hôte.</value>
648+
</data>
649+
</root>

0 commit comments

Comments
 (0)