Skip to content

Commit

Permalink
Merge pull request #4693 from MDoerner/StopRewritingDirtyModules
Browse files Browse the repository at this point in the history
Stop rewriting dirty modules
  • Loading branch information
Hosch250 committed Jan 7, 2019
2 parents 99c2d75 + 39ce242 commit e543769
Show file tree
Hide file tree
Showing 15 changed files with 406 additions and 81 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
using Rubberduck.Parsing.Rewriter;

namespace Rubberduck.Inspections.QuickFixes
{
public interface IQuickFixFailureNotifier
{
void NotifyQuickFixExecutionFailure(RewriteSessionState sessionState);
}
}
45 changes: 45 additions & 0 deletions Rubberduck.CodeAnalysis/QuickFixes/QuickFixFailureNotifier.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
using System;
using Rubberduck.Interaction;
using Rubberduck.Parsing.Rewriter;

namespace Rubberduck.Inspections.QuickFixes
{
public class QuickFixFailureNotifier : IQuickFixFailureNotifier
{
private readonly IMessageBox _messageBox;

public QuickFixFailureNotifier(IMessageBox messageBox)
{
_messageBox = messageBox;
}

public void NotifyQuickFixExecutionFailure(RewriteSessionState sessionState)
{
var message = FailureMessage(sessionState);
var caption = Resources.Inspections.QuickFixes.ApplyQuickFixFailedCaption;

_messageBox.NotifyWarn(message, caption);
}

private static string FailureMessage(RewriteSessionState sessionState)
{
var baseFailureMessage = Resources.Inspections.QuickFixes.ApplyQuickFixesFailedMessage;
var failureReasonMessage = FailureReasonMessage(sessionState);
var message = string.IsNullOrEmpty(failureReasonMessage)
? baseFailureMessage
: $"{baseFailureMessage}{Environment.NewLine}{Environment.NewLine}{failureReasonMessage}";
return message;
}

private static string FailureReasonMessage(RewriteSessionState sessionState)
{
switch (sessionState)
{
case RewriteSessionState.StaleParseTree:
return Resources.Inspections.QuickFixes.StaleModuleFailureReason;
default:
return string.Empty;
}
}
}
}
23 changes: 16 additions & 7 deletions Rubberduck.CodeAnalysis/QuickFixes/QuickFixProvider.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@
using Microsoft.CSharp.RuntimeBinder;
using Rubberduck.Parsing.Inspections.Abstract;
using Rubberduck.Parsing.Rewriter;
using Rubberduck.Parsing.VBA;
using Rubberduck.Parsing.VBA.Parsing;
using Rubberduck.VBEditor;

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

public QuickFixProvider(IRewritingManager rewritingManager, IEnumerable<IQuickFix> quickFixes)
public QuickFixProvider(IRewritingManager rewritingManager, IQuickFixFailureNotifier failureNotifier, IEnumerable<IQuickFix> quickFixes)
{
_rewritingManager = rewritingManager;
_failureNotifier = failureNotifier;
foreach (var quickFix in quickFixes)
{
foreach (var supportedInspection in quickFix.SupportedInspections)
Expand Down Expand Up @@ -78,7 +79,15 @@ public void Fix(IQuickFix fix, IInspectionResult result)

var rewriteSession = RewriteSession(fix.TargetCodeKind);
fix.Fix(result, rewriteSession);
rewriteSession.TryRewrite();
Apply(rewriteSession);
}

private void Apply(IRewriteSession rewriteSession)
{
if (!rewriteSession.TryRewrite())
{
_failureNotifier.NotifyQuickFixExecutionFailure(rewriteSession.Status);
}
}

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

fix.Fix(result, rewriteSession);
}
rewriteSession.TryRewrite();
Apply(rewriteSession);
}

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

fix.Fix(result, rewriteSession);
}
rewriteSession.TryRewrite();
Apply(rewriteSession);
}

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

fix.Fix(result, rewriteSession);
}
rewriteSession.TryRewrite();
Apply(rewriteSession);
}

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

fix.Fix(result, rewriteSession);
}
rewriteSession.TryRewrite();
Apply(rewriteSession);
}

public bool HasQuickFixes(IInspectionResult inspectionResult)
Expand Down
3 changes: 1 addition & 2 deletions Rubberduck.Interaction/Input/IMessageBox.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,4 @@
using System;
using Forms = System.Windows.Forms;
using Forms = System.Windows.Forms;

namespace Rubberduck.Interaction
{
Expand Down
11 changes: 9 additions & 2 deletions Rubberduck.Parsing/Rewriter/IRewriteSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,15 @@ public interface IRewriteSession
{
IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName module);
bool TryRewrite();
bool IsInvalidated { get; }
void Invalidate();
RewriteSessionState Status { get; set; }
CodeKind TargetCodeKind { get; }
}

public enum RewriteSessionState
{
Valid,
RewriteApplied,
OtherSessionsRewriteApplied,
StaleParseTree
}
}
54 changes: 31 additions & 23 deletions Rubberduck.Parsing/Rewriter/RewriteSessionBase.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ public abstract class RewriteSessionBase : IRewriteSession
private readonly Func<IRewriteSession, bool> _rewritingAllowed;

protected readonly Logger Logger = LogManager.GetCurrentClassLogger();
private readonly object _invalidationLockObject = new object();
private readonly object _statusLockObject = new object();

public abstract CodeKind TargetCodeKind { get; }

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

private RewriteSessionState _status = RewriteSessionState.Valid;
public RewriteSessionState Status
{
get
{
lock (_statusLockObject)
{
return _status;
}
}
set
{
lock (_statusLockObject)
{
if (_status == RewriteSessionState.Valid)
{
_status = value;
}
}
}
}

public IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName module)
{
Expand All @@ -35,6 +56,13 @@ public IModuleRewriter CheckOutModuleRewriter(QualifiedModuleName module)

rewriter = ModuleRewriter(module);
CheckedOutModuleRewriters.Add(module, rewriter);

if (rewriter.IsDirty)
{
//The parse tree is stale.
Status = RewriteSessionState.StaleParseTree;
}

return rewriter;
}

Expand All @@ -48,9 +76,9 @@ public bool TryRewrite()
}

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

Expand All @@ -64,25 +92,5 @@ public bool TryRewrite()
}

protected abstract bool TryRewriteInternal();

private bool _isInvalidated = false;
public bool IsInvalidated
{
get
{
lock (_invalidationLockObject)
{
return _isInvalidated;
}
}
}

public void Invalidate()
{
lock(_invalidationLockObject)
{
_isInvalidated = true;
}
}
}
}
6 changes: 4 additions & 2 deletions Rubberduck.Parsing/Rewriter/RewritingManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,8 @@ private bool TryAllowExclusiveRewrite(IRewriteSession rewriteSession)
return false;
}

rewriteSession.Status = RewriteSessionState.RewriteApplied;

InvalidateAllSessionsInternal();
return true;
}
Expand Down Expand Up @@ -80,13 +82,13 @@ private void InvalidateAllSessionsInternal()
{
foreach (var rewriteSession in _activeCodePaneSessions)
{
rewriteSession.Invalidate();
rewriteSession.Status = RewriteSessionState.OtherSessionsRewriteApplied;
}
_activeCodePaneSessions.Clear();

foreach (var rewriteSession in _activeAttributesSessions)
{
rewriteSession.Invalidate();
rewriteSession.Status = RewriteSessionState.OtherSessionsRewriteApplied;
}
_activeAttributesSessions.Clear();
}
Expand Down
32 changes: 31 additions & 1 deletion Rubberduck.Resources/Inspections/QuickFixes.Designer.cs

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 9 additions & 0 deletions Rubberduck.Resources/Inspections/QuickFixes.de.resx
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,13 @@
<data name="AddAttributeAnnotationQuickFix" xml:space="preserve">
<value>Attributannotation hinzufügen</value>
</data>
<data name="ApplyQuickFixesFailedMessage" xml:space="preserve">
<value>Die Ausführen des Quickfixes ist fehlgeschlagen. </value>
</data>
<data name="StaleModuleFailureReason" xml:space="preserve">
<value>Ein betroffenes Module wurde seit dem letzten Parse modifiziert.</value>
</data>
<data name="ApplyQuickFixFailedCaption" xml:space="preserve">
<value>Quickfixausführung fehlgeschlagen</value>
</data>
</root>
9 changes: 9 additions & 0 deletions Rubberduck.Resources/Inspections/QuickFixes.resx
Original file line number Diff line number Diff line change
Expand Up @@ -279,4 +279,13 @@
<data name="AddAttributeAnnotationQuickFix" xml:space="preserve">
<value>Add attribute annotation</value>
</data>
<data name="ApplyQuickFixesFailedMessage" xml:space="preserve">
<value>Failed to apply the quick fix.</value>
</data>
<data name="StaleModuleFailureReason" xml:space="preserve">
<value>An affected module has been modified since the last parse.</value>
</data>
<data name="ApplyQuickFixFailedCaption" xml:space="preserve">
<value>Quick Fix Application Failure</value>
</data>
</root>
Loading

0 comments on commit e543769

Please sign in to comment.