Skip to content

Commit 8a0da07

Browse files
committed
Make Rename dialog use the TextBoxErrorStyle
This adds error tooltips. In addistion, renaming to the same name is allowed now.
1 parent 55d0f99 commit 8a0da07

File tree

8 files changed

+115
-20
lines changed

8 files changed

+115
-20
lines changed

Rubberduck.Core/UI/Refactorings/Rename/RenameView.xaml

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -32,19 +32,13 @@
3232
VerticalAlignment="Top"
3333
Margin="0,0,5,0" />
3434
<TextBox Name="RenameTextBox"
35+
Style="{StaticResource TextBoxErrorStyle}"
3536
Grid.Column="1"
3637
Text="{Binding NewName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
3738
Height="22"
3839
VerticalAlignment="Top"
3940
VerticalContentAlignment="Center"
4041
HorizontalAlignment="Stretch" />
41-
<Image Grid.Column="1"
42-
Source="{StaticResource InvalidTextImage}"
43-
Height="16"
44-
Margin="0,-8,-8,0"
45-
HorizontalAlignment="Right"
46-
VerticalAlignment="Top"
47-
Visibility="{Binding IsValidName, Converter={StaticResource BoolToHiddenVisibility}}"/>
4842
</Grid>
4943
<Grid Grid.Row="2" Background="{x:Static SystemColors.ControlDarkBrush}" Grid.IsSharedSizeScope="True">
5044
<Grid HorizontalAlignment="Right"

Rubberduck.Core/UI/Refactorings/Rename/RenameViewModel.cs

Lines changed: 22 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,11 @@
11
using System;
2-
using System.Collections.Generic;
32
using System.Globalization;
43
using System.Linq;
54
using Rubberduck.Interaction;
6-
using Rubberduck.Parsing.Grammar;
75
using Rubberduck.Parsing.Symbols;
86
using Rubberduck.Parsing.VBA;
97
using Rubberduck.Refactorings.Rename;
108
using Rubberduck.Resources;
11-
using Rubberduck.Common;
129
using Rubberduck.Refactorings.Common;
1310

1411
namespace Rubberduck.UI.Refactorings.Rename
@@ -50,26 +47,40 @@ public string NewName
5047
set
5148
{
5249
Model.NewName = value;
50+
ValidateName();
5351
OnPropertyChanged();
5452
OnPropertyChanged(nameof(IsValidName));
5553
}
5654
}
5755

58-
public bool IsValidName
56+
private void ValidateName()
5957
{
60-
get
58+
if (Target == null)
6159
{
62-
if (Target == null) { return false; }
60+
return;
61+
}
6362

64-
if (VBAIdentifierValidator.IsValidIdentifier(NewName, Target.DeclarationType))
65-
{
66-
return !NewName.Equals(Target.IdentifierName, StringComparison.InvariantCultureIgnoreCase);
67-
}
63+
var errors = VBAIdentifierValidator.SatisfiedInvalidIdentifierCriteria(NewName, Target.DeclarationType).ToList();
64+
65+
var originalName = Model.Target.IdentifierName;
66+
if (!originalName.Equals(NewName)
67+
&& originalName.Equals(NewName, StringComparison.InvariantCultureIgnoreCase))
68+
{
69+
errors.Add(RubberduckUI.RenameDialog_OnlyCasingDifferent);
70+
}
6871

69-
return false;
72+
if (errors.Any())
73+
{
74+
SetErrors(nameof(NewName), errors);
75+
}
76+
else
77+
{
78+
ClearErrors();
7079
}
7180
}
7281

82+
public bool IsValidName => !HasErrors;
83+
7384
protected override void DialogOk()
7485
{
7586
if (Target == null

Rubberduck.Core/UI/ViewModelBase.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ protected static BitmapImage GetImageSource(Bitmap image)
4646
protected virtual void OnErrorsChanged(string propertyName = null)
4747
{
4848
ErrorsChanged?.Invoke(this, new DataErrorsChangedEventArgs(propertyName));
49-
OnPropertyChanged("HasErrors");
49+
OnPropertyChanged(nameof(HasErrors));
5050
}
5151

5252
public IEnumerable GetErrors(string propertyName)

Rubberduck.Refactorings/Common/VBAIdentifierValidator.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -143,5 +143,73 @@ public static bool TryMatchInvalidIdentifierCriteria(string name, DeclarationTyp
143143
}
144144
return false;
145145
}
146+
147+
/// <summary>
148+
/// Evaluates an identifier string's conformance with MS-VBAL naming requirements.
149+
/// </summary>
150+
/// <returns>Messages for all matching invalid identifier criteria</returns>
151+
public static IReadOnlyList<string> SatisfiedInvalidIdentifierCriteria(string name, DeclarationType declarationType, bool isArrayDeclaration = false)
152+
{
153+
var criteriaMatchMessages = new List<string>();
154+
155+
var maxNameLength = declarationType.HasFlag(DeclarationType.Module)
156+
? Declaration.MaxModuleNameLength
157+
: Declaration.MaxMemberNameLength;
158+
159+
if (string.IsNullOrEmpty(name))
160+
{
161+
criteriaMatchMessages.Add(RubberduckUI.InvalidNameCriteria_IsNullOrEmpty);
162+
}
163+
164+
//Does not start with a letter
165+
if (!char.IsLetter(name.First()))
166+
{
167+
criteriaMatchMessages.Add(string.Format(RubberduckUI.InvalidNameCriteria_DoesNotStartWithLetterFormat, name));
168+
}
169+
170+
//Has special characters
171+
if (name.Any(c => !char.IsLetterOrDigit(c) && c != '_'))
172+
{
173+
criteriaMatchMessages.Add(string.Format(RubberduckUI.InvalidNameCriteria_InvalidCharactersFormat, name));
174+
}
175+
176+
//Is a reserved identifier
177+
if (!declarationType.HasFlag(DeclarationType.UserDefinedTypeMember))
178+
{
179+
if (ReservedIdentifiers.Contains(name, StringComparer.InvariantCultureIgnoreCase))
180+
{
181+
criteriaMatchMessages.Add(string.Format(RubberduckUI.InvalidNameCriteria_IsReservedKeywordFormat, name));
182+
}
183+
}
184+
else if (isArrayDeclaration) //is a DeclarationType.UserDefinedTypeMember
185+
{
186+
//DeclarationType.UserDefinedTypeMember can have reserved identifier keywords
187+
//...unless the declaration is an array. Adding the parentheses causes errors.
188+
189+
//Name is not a reserved identifier, but when used as a UDTMember array declaration
190+
//it collides with the 'Name' Statement (Renames a disk file, directory, or folder)
191+
var invalidUDTArrayIdentifiers = ReservedIdentifiers.Concat(new List<string>() { "Name" });
192+
193+
if (invalidUDTArrayIdentifiers.Contains(name, StringComparer.InvariantCultureIgnoreCase))
194+
{
195+
criteriaMatchMessages.Add(string.Format(RubberduckUI.InvalidNameCriteria_IsReservedKeywordFormat, name));
196+
}
197+
}
198+
199+
//"VBA" identifier not allowed for projects
200+
if (declarationType.HasFlag(DeclarationType.Project)
201+
&& name.Equals("VBA", StringComparison.InvariantCultureIgnoreCase))
202+
{
203+
criteriaMatchMessages.Add(string.Format(RubberduckUI.InvalidNameCriteria_IsReservedKeywordFormat, name));
204+
}
205+
206+
//Exceeds max length
207+
if (name.Length > maxNameLength)
208+
{
209+
criteriaMatchMessages.Add(string.Format(RubberduckUI.InvalidNameCriteria_ExceedsMaximumLengthFormat, name));
210+
}
211+
212+
return criteriaMatchMessages;
213+
}
146214
}
147215
}

Rubberduck.Refactorings/Rename/RenameRefactoringAction.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
using Rubberduck.Parsing.Symbols;
1+
using System;
2+
using Rubberduck.Parsing.Symbols;
23

34
namespace Rubberduck.Refactorings.Rename
45
{
@@ -17,6 +18,12 @@ public RenameRefactoringAction(
1718

1819
public void Refactor(RenameModel model)
1920
{
21+
if (model?.Target == null
22+
|| model.Target.IdentifierName.Equals(model.NewName, StringComparison.InvariantCultureIgnoreCase))
23+
{
24+
return;
25+
}
26+
2027
if (IsComponentOrProjectTarget(model))
2128
{
2229
_renameComponentOrProjectRefactoringAction.Refactor(model);

Rubberduck.Resources/RubberduckUI.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/RubberduckUI.de.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1682,4 +1682,7 @@ Import abgebrochen.</value>
16821682
<data name="RefactoringFailure_AnnotateDeclaration_InvalidType" xml:space="preserve">
16831683
<value>Das Refactoring kann Annotationen nur zu Komponenten, Methoden und Variablen hinzufügen. Die Zieldeklaration hatte allerdings den Typ '{0}'.</value>
16841684
</data>
1685+
<data name="RenameDialog_OnlyCasingDifferent" xml:space="preserve">
1686+
<value>Es ist in VBA nicht möglich nur die Groß- und Kleinschreibung eines Namens zu ändern.</value>
1687+
</data>
16851688
</root>

Rubberduck.Resources/RubberduckUI.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1896,4 +1896,7 @@ Import aborted.</value>
18961896
<value>The refactoring can only annotate components, members and variables, but the target had type '{0}'.</value>
18971897
<comment>{0} declaration type</comment>
18981898
</data>
1899+
<data name="RenameDialog_OnlyCasingDifferent" xml:space="preserve">
1900+
<value>It is not possible to change only the case of an identifier in VBA.</value>
1901+
</data>
18991902
</root>

0 commit comments

Comments
 (0)