Skip to content

Commit b1ff795

Browse files
committed
Guarantee a reparse after an AttributeRewriteSession gets applied
Previously, this would not happen if no rewriter is dirty. This can leave us in a bad state because other functionality might expect it to happen. The exception is when no rewriter has been checked out at all.
1 parent 2128bbc commit b1ff795

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

Rubberduck.Parsing/Rewriter/AttributesRewriteSession.cs

Lines changed: 18 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,8 +24,9 @@ protected override IExecutableModuleRewriter ModuleRewriter(QualifiedModuleName
2424
}
2525

2626
protected override bool TryRewriteInternal()
27-
{
27+
{
2828
//The suspension ensures that only one parse gets executed instead of two for each rewritten module.
29+
GuaranteeReparseAfterRewrite();
2930
var result = _parseManager.OnSuspendParser(this, new[] {ParserState.Ready, ParserState.ResolvedDeclarations}, ExecuteAllRewriters);
3031
if(result != SuspensionResult.Completed)
3132
{
@@ -36,6 +37,22 @@ protected override bool TryRewriteInternal()
3637
return true;
3738
}
3839

40+
private void GuaranteeReparseAfterRewrite()
41+
{
42+
_parseManager.StateChanged += ReparseOnSuspension;
43+
}
44+
45+
private void ReparseOnSuspension(object requestor, ParserStateEventArgs e)
46+
{
47+
if (e.State != ParserState.Busy)
48+
{
49+
return;
50+
}
51+
52+
_parseManager.StateChanged -= ReparseOnSuspension;
53+
_parseManager.OnParseRequested(this);
54+
}
55+
3956
private void ExecuteAllRewriters()
4057
{
4158
foreach (var module in CheckedOutModuleRewriters.Keys)

RubberduckTests/Rewriter/MemberAttributeRecovererTests.cs

Lines changed: 2 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -144,9 +144,7 @@ Public Function Bar() As Variant
144144
var declarationsForWhichToRemoveAttributes = state.DeclarationFinder.UserDeclarations(DeclarationType.Function);
145145
RemoveAttributes(declarationsForWhichToRemoveAttributes, rewriteSession);
146146

147-
//We need the extra parse request because in the mocked setup attribute rewrites do not cause a reparse due to the lack of invoked component added handlers.
148-
ExecuteAndWaitForParserState(state, () => rewriteSession.TryRewrite(), ParserState.Busy);
149-
ExecuteAndWaitForParserState(state, () => state.OnParseRequested(this), ParserState.Ready);
147+
ExecuteAndWaitForParserState(state, () => rewriteSession.TryRewrite(), ParserState.Ready);
150148
}
151149
var actualCode = component.CodeModule.Content();
152150
Assert.AreEqual(expectedCode, actualCode);
@@ -250,9 +248,7 @@ Public Function Bar() As Variant
250248
var declarationsForWhichToRemoveAttributes = state.DeclarationFinder.UserDeclarations(DeclarationType.Function);
251249
RemoveAttributes(declarationsForWhichToRemoveAttributes, rewriteSession);
252250

253-
//We need the extra parse request because in the mocked setup attribute rewrites do not cause a reparse due to the lack of invoked component added handlers.
254-
ExecuteAndWaitForParserState(state, () => rewriteSession.TryRewrite(), ParserState.Busy);
255-
ExecuteAndWaitForParserState(state, () => state.OnParseRequested(this), ParserState.Ready);
251+
ExecuteAndWaitForParserState(state, () => rewriteSession.TryRewrite(), ParserState.Ready);
256252

257253
var actualCodeWithRecovery = state.ProjectsProvider.Component(recoveryModule).CodeModule.Content();
258254
var actualCodeWithoutRecovery = state.ProjectsProvider.Component(noRecoveryModule).CodeModule.Content();

0 commit comments

Comments
 (0)