Skip to content

Commit 0a67277

Browse files
committed
Notify user about member attribute recovery failure
1 parent 47a5199 commit 0a67277

File tree

7 files changed

+168
-11
lines changed

7 files changed

+168
-11
lines changed
Lines changed: 61 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,61 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using Rubberduck.Interaction;
4+
using Rubberduck.Parsing.Rewriter;
5+
using Rubberduck.VBEditor;
6+
7+
namespace Rubberduck.UI.Notifiers
8+
{
9+
public class MemberAttributeRecoveryFailureNotifier : IMemberAttributeRecoveryFailureNotifier
10+
{
11+
private readonly IMessageBox _messageBox;
12+
13+
public MemberAttributeRecoveryFailureNotifier(IMessageBox messageBox)
14+
{
15+
_messageBox = messageBox;
16+
}
17+
18+
public void NotifyRewriteFailed(RewriteSessionState sessionState)
19+
{
20+
var message = RewriteFailureMessage(sessionState);
21+
var caption = Resources.RubberduckUI.MemberAttributeRecoveryFailureCaption;
22+
23+
_messageBox.NotifyWarn(message, caption);
24+
}
25+
26+
private static string RewriteFailureMessage(RewriteSessionState sessionState)
27+
{
28+
var baseFailureMessage = Resources.RubberduckUI.MemberAttributeRecoveryRewriteFailedMessage;
29+
var failureReasonMessage = RewriteFailureReasonMessage(sessionState);
30+
var message = string.IsNullOrEmpty(failureReasonMessage)
31+
? baseFailureMessage
32+
: $"{baseFailureMessage}{Environment.NewLine}{Environment.NewLine}{failureReasonMessage}";
33+
return message;
34+
}
35+
36+
private static string RewriteFailureReasonMessage(RewriteSessionState sessionState)
37+
{
38+
switch (sessionState)
39+
{
40+
case RewriteSessionState.StaleParseTree:
41+
return Resources.Inspections.QuickFixes.StaleModuleFailureReason;
42+
default:
43+
return string.Empty;
44+
}
45+
}
46+
47+
public void NotifyMembersForRecoveryNotFound(IEnumerable<QualifiedMemberName> membersNotFound)
48+
{
49+
var message = MembersNotFoundMessage(membersNotFound);
50+
var caption = Resources.RubberduckUI.MemberAttributeRecoveryFailureCaption;
51+
52+
_messageBox.NotifyWarn(message, caption);
53+
}
54+
55+
private string MembersNotFoundMessage(IEnumerable<QualifiedMemberName> membersNotFound)
56+
{
57+
var missingMemberList = $"{Environment.NewLine}{string.Join(Environment.NewLine, membersNotFound)}";
58+
return string.Format(Resources.RubberduckUI.MemberAttributeRecoveryMembersNotFoundMessage, missingMemberList); ;
59+
}
60+
}
61+
}
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
using System.Collections.Generic;
2+
using Rubberduck.VBEditor;
3+
4+
namespace Rubberduck.Parsing.Rewriter
5+
{
6+
public interface IMemberAttributeRecoveryFailureNotifier
7+
{
8+
void NotifyRewriteFailed(RewriteSessionState rewriteSessionState);
9+
void NotifyMembersForRecoveryNotFound(IEnumerable<QualifiedMemberName> membersNotFound);
10+
}
11+
}

Rubberduck.Parsing/Rewriter/MemberAttributeRecoverer.cs

Lines changed: 37 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -17,19 +17,22 @@ public class MemberAttributeRecoverer : IMemberAttributeRecovererWithSettableRew
1717
private readonly IParseManager _parseManager;
1818
private readonly IAttributesUpdater _attributesUpdater;
1919
private IRewritingManager _rewritingManager;
20+
private readonly IMemberAttributeRecoveryFailureNotifier _failureNotifier;
2021

2122
private readonly
2223
IDictionary<QualifiedModuleName, IDictionary<string, HashSet<AttributeNode>>> _attributesToRecover
2324
= new Dictionary<QualifiedModuleName, IDictionary<string, HashSet<AttributeNode>>>();
25+
private readonly HashSet<QualifiedMemberName> _missingMembers = new HashSet<QualifiedMemberName>();
2426

2527
private readonly Logger _logger = LogManager.GetCurrentClassLogger();
2628

2729
public MemberAttributeRecoverer(IDeclarationFinderProvider declarationFinderProvider,
28-
IParseManager parseManager, IAttributesUpdater attributesUpdater)
30+
IParseManager parseManager, IAttributesUpdater attributesUpdater, IMemberAttributeRecoveryFailureNotifier failureNotifier)
2931
{
3032
_declarationFinderProvider = declarationFinderProvider;
3133
_parseManager = parseManager;
3234
_attributesUpdater = attributesUpdater;
35+
_failureNotifier = failureNotifier;
3336
}
3437

3538
//This needs to be property injected because this class will be constructor injected into the RewritingManager that needs to set itself as the dependency here.
@@ -101,6 +104,8 @@ private void ExecuteRecoveryOfAttributes(object sender, ParserStateEventArgs e)
101104
StopRecoveringAttributesOnNextParse();
102105

103106
var rewriteSession = _rewritingManager.CheckOutAttributesSession();
107+
108+
_missingMembers.Clear();
104109
foreach (var module in _attributesToRecover.Keys)
105110
{
106111
RecoverAttributes(rewriteSession, module, _attributesToRecover[module]);
@@ -112,13 +117,33 @@ private void ExecuteRecoveryOfAttributes(object sender, ParserStateEventArgs e)
112117
return;
113118
}
114119

120+
if (rewriteSession.Status != RewriteSessionState.Valid)
121+
{
122+
_failureNotifier.NotifyRewriteFailed(rewriteSession.Status);
123+
return;
124+
}
125+
115126
CancelTheCurrentParse();
116127

117-
Task.Run(() => rewriteSession.TryRewrite());
128+
Task.Run(() => Apply(rewriteSession));
118129

119130
EndTheCurrentParse(e.Token);
120131
}
121132

133+
private void Apply(IRewriteSession rewriteSession)
134+
{
135+
136+
var rewriteSucceeded = rewriteSession.TryRewrite();
137+
if (!rewriteSucceeded)
138+
{
139+
_failureNotifier.NotifyRewriteFailed(rewriteSession.Status);
140+
}
141+
else if (_missingMembers.Any())
142+
{
143+
_failureNotifier.NotifyMembersForRecoveryNotFound(_missingMembers);
144+
}
145+
}
146+
122147
private void StopRecoveringAttributesOnNextParse()
123148
{
124149
_parseManager.StateChanged -= ExecuteRecoveryOfAttributes;
@@ -140,7 +165,9 @@ private void RecoverAttributes(IRewriteSession rewriteSession, QualifiedModuleNa
140165

141166
if (membersWithAttributesToRecover.Count != declarationsWithAttributesToRecover.Count)
142167
{
143-
LogFailureToRecoverAllAttributes(module, membersWithAttributesToRecover, declarationsWithAttributesToRecover);
168+
var membersWithoutDeclarations = MembersWithoutDeclarations(membersWithAttributesToRecover, declarationsWithAttributesToRecover);
169+
LogFailureToRecoverAllAttributes(module, membersWithoutDeclarations);
170+
_missingMembers.UnionWith(membersWithoutDeclarations.Select(memberName => new QualifiedMemberName(module, memberName)));
144171
}
145172

146173
foreach (var declaration in declarationsWithAttributesToRecover)
@@ -149,12 +176,16 @@ private void RecoverAttributes(IRewriteSession rewriteSession, QualifiedModuleNa
149176
}
150177
}
151178

152-
private void LogFailureToRecoverAllAttributes(QualifiedModuleName module, IEnumerable<string> membersWithAttributesToRecover, List<Declaration> declarationsWithAttributesToRecover)
179+
private static ICollection<string> MembersWithoutDeclarations(HashSet<string> membersWithAttributesToRecover, IEnumerable<Declaration> declarationsWithAttributesToRecover)
153180
{
154-
_logger.Warn("Could not recover the attributes for all members because one or more members could no longer be found.");
155-
156181
var membersWithoutDeclarations = membersWithAttributesToRecover.ToHashSet();
157182
membersWithoutDeclarations.ExceptWith(declarationsWithAttributesToRecover.Select(decl => decl.IdentifierName));
183+
return membersWithoutDeclarations;
184+
}
185+
186+
private void LogFailureToRecoverAllAttributes(QualifiedModuleName module, IEnumerable<string> membersWithoutDeclarations)
187+
{
188+
_logger.Warn("Could not recover the attributes for all members because one or more members could no longer be found.");
158189
foreach (var member in membersWithoutDeclarations)
159190
{
160191
_logger.Trace($"Could not recover the attributes for member {member} in module {module} because a member of that name exists no longer.");

Rubberduck.Resources/RubberduckUI.Designer.cs

Lines changed: 31 additions & 1 deletion
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: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1347,4 +1347,13 @@ ACHTUNG: Ein Neustart ist nötig, damit die Änderungen wirksam werden.</value>
13471347
<data name="References_MoveUpToolTip" xml:space="preserve">
13481348
<value>Abwärts bewegen</value>
13491349
</data>
1350+
<data name="MemberAttributeRecoveryRewriteFailedMessage" xml:space="preserve">
1351+
<value>Das Wiederherstellen der Elementattribute ist fehlgeschlagen.</value>
1352+
</data>
1353+
<data name="MemberAttributeRecoveryFailureCaption" xml:space="preserve">
1354+
<value>Wiederherstellen der Elementattribute fehlgeschlagen</value>
1355+
</data>
1356+
<data name="MemberAttributeRecoveryMembersNotFoundMessage" xml:space="preserve">
1357+
<value>Die Elementattribute für die folgenden Elemente konnten nicht wiederhergestellt werden, da sie nicht mehr aufgefunden wurden: {0} </value>
1358+
</data>
13501359
</root>

Rubberduck.Resources/RubberduckUI.resx

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1481,4 +1481,14 @@ NOTE: Restart is required for the setting to take effect.</value>
14811481
<data name="References_RemoveToolTip" xml:space="preserve">
14821482
<value>Remove from project</value>
14831483
</data>
1484+
<data name="MemberAttributeRecoveryRewriteFailedMessage" xml:space="preserve">
1485+
<value>Failed to recover member attributes.</value>
1486+
</data>
1487+
<data name="MemberAttributeRecoveryFailureCaption" xml:space="preserve">
1488+
<value>Member Attribute Recovery Failure </value>
1489+
</data>
1490+
<data name="MemberAttributeRecoveryMembersNotFoundMessage" xml:space="preserve">
1491+
<value>Member attributes for the following modules could not be recovered because they could no longer be found. {0}</value>
1492+
<comment>{0} = Missing member list</comment>
1493+
</data>
14841494
</root>

RubberduckTests/Rewriter/MemberAttributeRecovererTests.cs

Lines changed: 9 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
using System.Collections.Generic;
33
using System.Linq;
44
using System.Threading;
5+
using Moq;
56
using NUnit.Framework;
67
using Rubberduck.Parsing;
78
using Rubberduck.Parsing.Grammar;
@@ -45,7 +46,8 @@ Public Function Bar() As Variant
4546
using (state)
4647
{
4748
var attributesUpdater = new AttributesUpdater(state);
48-
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater);
49+
var mockFailureNotifier = new Mock<IMemberAttributeRecoveryFailureNotifier>();
50+
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater, mockFailureNotifier.Object);
4951
memberAttributeRecoverer.RewritingManager = rewritingManager;
5052

5153
var fooDeclaration = state.DeclarationFinder.UserDeclarations(DeclarationType.Function)
@@ -90,7 +92,8 @@ Public Function Bar() As Variant
9092
using (state)
9193
{
9294
var attributesUpdater = new AttributesUpdater(state);
93-
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater);
95+
var mockFailureNotifier = new Mock<IMemberAttributeRecoveryFailureNotifier>();
96+
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater, mockFailureNotifier.Object);
9497
memberAttributeRecoverer.RewritingManager = rewritingManager;
9598

9699
var modulesToRecoverMemberAttributesIn = new List<QualifiedModuleName> { component.QualifiedModuleName };
@@ -131,7 +134,8 @@ Public Function Bar() As Variant
131134
using (state)
132135
{
133136
var attributesUpdater = new AttributesUpdater(state);
134-
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater);
137+
var mockFailureNotifier = new Mock<IMemberAttributeRecoveryFailureNotifier>();
138+
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater, mockFailureNotifier.Object);
135139
memberAttributeRecoverer.RewritingManager = rewritingManager;
136140

137141
var fooDeclaration = state.DeclarationFinder.UserDeclarations(DeclarationType.Function)
@@ -232,7 +236,8 @@ Public Function Bar() As Variant
232236
using (state)
233237
{
234238
var attributesUpdater = new AttributesUpdater(state);
235-
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater);
239+
var mockFailureNotifier = new Mock<IMemberAttributeRecoveryFailureNotifier>();
240+
var memberAttributeRecoverer = new MemberAttributeRecoverer(state, state, attributesUpdater, mockFailureNotifier.Object);
236241
memberAttributeRecoverer.RewritingManager = rewritingManager;
237242

238243
var recoveryModule = state.DeclarationFinder.UserDeclarations(DeclarationType.Module)

0 commit comments

Comments
 (0)