Skip to content

Commit e543769

Browse files
authored
Merge pull request #4693 from MDoerner/StopRewritingDirtyModules
Stop rewriting dirty modules
2 parents 99c2d75 + 39ce242 commit e543769

File tree

15 files changed

+406
-81
lines changed

15 files changed

+406
-81
lines changed
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Rubberduck.Parsing.Rewriter;
2+
3+
namespace Rubberduck.Inspections.QuickFixes
4+
{
5+
public interface IQuickFixFailureNotifier
6+
{
7+
void NotifyQuickFixExecutionFailure(RewriteSessionState sessionState);
8+
}
9+
}
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
using System;
2+
using Rubberduck.Interaction;
3+
using Rubberduck.Parsing.Rewriter;
4+
5+
namespace Rubberduck.Inspections.QuickFixes
6+
{
7+
public class QuickFixFailureNotifier : IQuickFixFailureNotifier
8+
{
9+
private readonly IMessageBox _messageBox;
10+
11+
public QuickFixFailureNotifier(IMessageBox messageBox)
12+
{
13+
_messageBox = messageBox;
14+
}
15+
16+
public void NotifyQuickFixExecutionFailure(RewriteSessionState sessionState)
17+
{
18+
var message = FailureMessage(sessionState);
19+
var caption = Resources.Inspections.QuickFixes.ApplyQuickFixFailedCaption;
20+
21+
_messageBox.NotifyWarn(message, caption);
22+
}
23+
24+
private static string FailureMessage(RewriteSessionState sessionState)
25+
{
26+
var baseFailureMessage = Resources.Inspections.QuickFixes.ApplyQuickFixesFailedMessage;
27+
var failureReasonMessage = FailureReasonMessage(sessionState);
28+
var message = string.IsNullOrEmpty(failureReasonMessage)
29+
? baseFailureMessage
30+
: $"{baseFailureMessage}{Environment.NewLine}{Environment.NewLine}{failureReasonMessage}";
31+
return message;
32+
}
33+
34+
private static string FailureReasonMessage(RewriteSessionState sessionState)
35+
{
36+
switch (sessionState)
37+
{
38+
case RewriteSessionState.StaleParseTree:
39+
return Resources.Inspections.QuickFixes.StaleModuleFailureReason;
40+
default:
41+
return string.Empty;
42+
}
43+
}
44+
}
45+
}

Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs

Lines changed: 16 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@
55
using Microsoft.CSharp.RuntimeBinder;
66
using Rubberduck.Parsing.Inspections.Abstract;
77
using Rubberduck.Parsing.Rewriter;
8-
using Rubberduck.Parsing.VBA;
98
using Rubberduck.Parsing.VBA.Parsing;
109
using Rubberduck.VBEditor;
1110

@@ -14,11 +13,13 @@ namespace Rubberduck.Inspections.QuickFixes
1413
public class QuickFixProvider : IQuickFixProvider
1514
{
1615
private readonly IRewritingManager _rewritingManager;
16+
private readonly IQuickFixFailureNotifier _failureNotifier;
1717
private readonly Dictionary<Type, HashSet<IQuickFix>> _quickFixes = new Dictionary<Type, HashSet<IQuickFix>>();
1818

19-
public QuickFixProvider(IRewritingManager rewritingManager, IEnumerable<IQuickFix> quickFixes)
19+
public QuickFixProvider(IRewritingManager rewritingManager, IQuickFixFailureNotifier failureNotifier, IEnumerable<IQuickFix> quickFixes)
2020
{
2121
_rewritingManager = rewritingManager;
22+
_failureNotifier = failureNotifier;
2223
foreach (var quickFix in quickFixes)
2324
{
2425
foreach (var supportedInspection in quickFix.SupportedInspections)
@@ -78,7 +79,15 @@ public void Fix(IQuickFix fix, IInspectionResult result)
7879

7980
var rewriteSession = RewriteSession(fix.TargetCodeKind);
8081
fix.Fix(result, rewriteSession);
81-
rewriteSession.TryRewrite();
82+
Apply(rewriteSession);
83+
}
84+
85+
private void Apply(IRewriteSession rewriteSession)
86+
{
87+
if (!rewriteSession.TryRewrite())
88+
{
89+
_failureNotifier.NotifyQuickFixExecutionFailure(rewriteSession.Status);
90+
}
8291
}
8392

8493
private IRewriteSession RewriteSession(CodeKind targetCodeKind)
@@ -115,7 +124,7 @@ public void FixInProcedure(IQuickFix fix, QualifiedMemberName? qualifiedMember,
115124

116125
fix.Fix(result, rewriteSession);
117126
}
118-
rewriteSession.TryRewrite();
127+
Apply(rewriteSession);
119128
}
120129

121130
public void FixInModule(IQuickFix fix, QualifiedSelection selection, Type inspectionType, IEnumerable<IInspectionResult> results)
@@ -137,7 +146,7 @@ public void FixInModule(IQuickFix fix, QualifiedSelection selection, Type inspec
137146

138147
fix.Fix(result, rewriteSession);
139148
}
140-
rewriteSession.TryRewrite();
149+
Apply(rewriteSession);
141150
}
142151

143152
public void FixInProject(IQuickFix fix, QualifiedSelection selection, Type inspectionType, IEnumerable<IInspectionResult> results)
@@ -159,7 +168,7 @@ public void FixInProject(IQuickFix fix, QualifiedSelection selection, Type inspe
159168

160169
fix.Fix(result, rewriteSession);
161170
}
162-
rewriteSession.TryRewrite();
171+
Apply(rewriteSession);
163172
}
164173

165174
public void FixAll(IQuickFix fix, Type inspectionType, IEnumerable<IInspectionResult> results)
@@ -181,7 +190,7 @@ public void FixAll(IQuickFix fix, Type inspectionType, IEnumerable<IInspectionRe
181190

182191
fix.Fix(result, rewriteSession);
183192
}
184-
rewriteSession.TryRewrite();
193+
Apply(rewriteSession);
185194
}
186195

187196
public bool HasQuickFixes(IInspectionResult inspectionResult)

Rubberduck.Interaction/Input/IMessageBox.cs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System;
2-
using Forms = System.Windows.Forms;
1+
using Forms = System.Windows.Forms;
32

43
namespace Rubberduck.Interaction
54
{

Rubberduck.Parsing/Rewriter/IRewriteSession.cs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,8 +7,15 @@ public interface IRewriteSession
77
{
88
IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName module);
99
bool TryRewrite();
10-
bool IsInvalidated { get; }
11-
void Invalidate();
10+
RewriteSessionState Status { get; set; }
1211
CodeKind TargetCodeKind { get; }
1312
}
13+
14+
public enum RewriteSessionState
15+
{
16+
Valid,
17+
RewriteApplied,
18+
OtherSessionsRewriteApplied,
19+
StaleParseTree
20+
}
1421
}

Rubberduck.Parsing/Rewriter/RewriteSessionBase.cs

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public abstract class RewriteSessionBase : IRewriteSession
1515
private readonly Func<IRewriteSession, bool> _rewritingAllowed;
1616

1717
protected readonly Logger Logger = LogManager.GetCurrentClassLogger();
18-
private readonly object _invalidationLockObject = new object();
18+
private readonly object _statusLockObject = new object();
1919

2020
public abstract CodeKind TargetCodeKind { get; }
2121

@@ -25,6 +25,27 @@ protected RewriteSessionBase(IRewriterProvider rewriterProvider, Func<IRewriteSe
2525
_rewritingAllowed = rewritingAllowed;
2626
}
2727

28+
private RewriteSessionState _status = RewriteSessionState.Valid;
29+
public RewriteSessionState Status
30+
{
31+
get
32+
{
33+
lock (_statusLockObject)
34+
{
35+
return _status;
36+
}
37+
}
38+
set
39+
{
40+
lock (_statusLockObject)
41+
{
42+
if (_status == RewriteSessionState.Valid)
43+
{
44+
_status = value;
45+
}
46+
}
47+
}
48+
}
2849

2950
public IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName module)
3051
{
@@ -35,6 +56,13 @@ public IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName module)
3556

3657
rewriter = ModuleRewriter(module);
3758
CheckedOutModuleRewriters.Add(module, rewriter);
59+
60+
if (rewriter.IsDirty)
61+
{
62+
//The parse tree is stale.
63+
Status = RewriteSessionState.StaleParseTree;
64+
}
65+
3866
return rewriter;
3967
}
4068

@@ -48,9 +76,9 @@ public bool TryRewrite()
4876
}
4977

5078
//This is thread-safe because, once invalidated, there is no way back.
51-
if (IsInvalidated)
79+
if (Status != RewriteSessionState.Valid)
5280
{
53-
Logger.Warn("Tried to execute Rewrite on a RewriteSession that was already invalidated.");
81+
Logger.Warn($"Tried to execute Rewrite on a RewriteSession that was in the invalid status {Status}.");
5482
return false;
5583
}
5684

@@ -64,25 +92,5 @@ public bool TryRewrite()
6492
}
6593

6694
protected abstract bool TryRewriteInternal();
67-
68-
private bool _isInvalidated = false;
69-
public bool IsInvalidated
70-
{
71-
get
72-
{
73-
lock (_invalidationLockObject)
74-
{
75-
return _isInvalidated;
76-
}
77-
}
78-
}
79-
80-
public void Invalidate()
81-
{
82-
lock(_invalidationLockObject)
83-
{
84-
_isInvalidated = true;
85-
}
86-
}
8795
}
8896
}

Rubberduck.Parsing/Rewriter/RewritingManager.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,8 @@ private bool TryAllowExclusiveRewrite(IRewriteSession rewriteSession)
5050
return false;
5151
}
5252

53+
rewriteSession.Status = RewriteSessionState.RewriteApplied;
54+
5355
InvalidateAllSessionsInternal();
5456
return true;
5557
}
@@ -80,13 +82,13 @@ private void InvalidateAllSessionsInternal()
8082
{
8183
foreach (var rewriteSession in _activeCodePaneSessions)
8284
{
83-
rewriteSession.Invalidate();
85+
rewriteSession.Status = RewriteSessionState.OtherSessionsRewriteApplied;
8486
}
8587
_activeCodePaneSessions.Clear();
8688

8789
foreach (var rewriteSession in _activeAttributesSessions)
8890
{
89-
rewriteSession.Invalidate();
91+
rewriteSession.Status = RewriteSessionState.OtherSessionsRewriteApplied;
9092
}
9193
_activeAttributesSessions.Clear();
9294
}

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

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,13 @@
279279
<data name="AddAttributeAnnotationQuickFix" xml:space="preserve">
280280
<value>Attributannotation hinzufügen</value>
281281
</data>
282+
<data name="ApplyQuickFixesFailedMessage" xml:space="preserve">
283+
<value>Die Ausführen des Quickfixes ist fehlgeschlagen. </value>
284+
</data>
285+
<data name="StaleModuleFailureReason" xml:space="preserve">
286+
<value>Ein betroffenes Module wurde seit dem letzten Parse modifiziert.</value>
287+
</data>
288+
<data name="ApplyQuickFixFailedCaption" xml:space="preserve">
289+
<value>Quickfixausführung fehlgeschlagen</value>
290+
</data>
282291
</root>

Rubberduck.Resources/Inspections/QuickFixes.resx

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,13 @@
279279
<data name="AddAttributeAnnotationQuickFix" xml:space="preserve">
280280
<value>Add attribute annotation</value>
281281
</data>
282+
<data name="ApplyQuickFixesFailedMessage" xml:space="preserve">
283+
<value>Failed to apply the quick fix.</value>
284+
</data>
285+
<data name="StaleModuleFailureReason" xml:space="preserve">
286+
<value>An affected module has been modified since the last parse.</value>
287+
</data>
288+
<data name="ApplyQuickFixFailedCaption" xml:space="preserve">
289+
<value>Quick Fix Application Failure</value>
290+
</data>
282291
</root>

0 commit comments

Comments
 (0)