Skip to content

Commit 5e8a911

Browse files
committed
Enhance AnnotateDeclarationRefactoringAction to allow adjusting corresponding attributes
The adjustment/addition of an attribute only happens if the corresponding flag is set on the model and the annotation is an IAttributeAnnotation.
1 parent ebe40b9 commit 5e8a911

12 files changed

+682
-74
lines changed

Rubberduck.Refactorings/Abstract/CodeOnlyRefactoringActionBase.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ protected CodeOnlyRefactoringActionBase(IRewritingManager rewritingManager)
1818

1919
public virtual void Refactor(TModel model)
2020
{
21-
var rewriteSession = RewriteSession(RewriteSessionCodeKind);
21+
var rewriteSession = RewriteSession(RewriteSessionCodeKind(model));
2222

2323
Refactor(model, rewriteSession);
2424

@@ -35,6 +35,6 @@ private IExecutableRewriteSession RewriteSession(CodeKind codeKind)
3535
: _rewritingManager.CheckOutCodePaneSession();
3636
}
3737

38-
protected virtual CodeKind RewriteSessionCodeKind => CodeKind.CodePaneCode;
38+
protected virtual CodeKind RewriteSessionCodeKind(TModel model) => CodeKind.CodePaneCode;
3939
}
4040
}

Rubberduck.Refactorings/AnnotateDeclaration/AnnotateDeclarationModel.cs

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,15 +22,18 @@ public class AnnotateDeclarationModel : IRefactoringModel
2222
public Declaration Target { get; }
2323
public IAnnotation Annotation { get; set; }
2424
public IList<TypedAnnotationArgument> Arguments { get; set; }
25+
public bool AdjustAttribute { get; set; }
2526

2627
public AnnotateDeclarationModel(
2728
Declaration target,
2829
IAnnotation annotation = null,
29-
IList<TypedAnnotationArgument> arguments = null)
30+
IList<TypedAnnotationArgument> arguments = null,
31+
bool adjustAttribute = false)
3032
{
3133
Target = target;
3234
Annotation = annotation;
3335
Arguments = arguments ?? new List<TypedAnnotationArgument>();
36+
AdjustAttribute = adjustAttribute;
3437
}
3538
}
3639
}
Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System.Linq;
2+
using Rubberduck.Common;
3+
using Rubberduck.Parsing.Annotations;
4+
using Rubberduck.Parsing.Grammar;
5+
using Rubberduck.Parsing.Rewriter;
6+
using Rubberduck.Parsing.Symbols;
7+
using Rubberduck.Parsing.VBA;
8+
using Rubberduck.Parsing.VBA.Parsing;
9+
using Rubberduck.Refactorings.Exceptions;
10+
11+
namespace Rubberduck.Refactorings.AnnotateDeclaration
12+
{
13+
public class AnnotateDeclarationRefactoringAction : CodeOnlyRefactoringActionBase<AnnotateDeclarationModel>
14+
{
15+
private readonly IAnnotationUpdater _annotationUpdater;
16+
private readonly IAttributesUpdater _attributesUpdater;
17+
18+
public AnnotateDeclarationRefactoringAction(
19+
IRewritingManager rewritingManager,
20+
IAnnotationUpdater annotationUpdater,
21+
IAttributesUpdater attributesUpdater)
22+
: base(rewritingManager)
23+
{
24+
_annotationUpdater = annotationUpdater;
25+
_attributesUpdater = attributesUpdater;
26+
}
27+
28+
protected override CodeKind RewriteSessionCodeKind(AnnotateDeclarationModel model)
29+
{
30+
return model.AdjustAttribute
31+
&& model.Annotation is IAttributeAnnotation
32+
? CodeKind.AttributesCode
33+
: CodeKind.CodePaneCode;
34+
}
35+
36+
public override void Refactor(AnnotateDeclarationModel model, IRewriteSession rewriteSession)
37+
{
38+
if (model.AdjustAttribute
39+
&& rewriteSession.TargetCodeKind != CodeKind.AttributesCode
40+
&& model.Annotation is IAttributeAnnotation)
41+
{
42+
throw new AttributeRewriteSessionRequiredException();
43+
}
44+
45+
var targetDeclaration = model.Target;
46+
47+
if (rewriteSession.TargetCodeKind == CodeKind.AttributesCode
48+
&& targetDeclaration.AttributesPassContext == null
49+
&& !targetDeclaration.DeclarationType.HasFlag(DeclarationType.Module))
50+
{
51+
throw new AttributeRewriteSessionNotSupportedException();
52+
}
53+
54+
var arguments = model.Arguments.Select(ToCode).ToList();
55+
56+
if (model.AdjustAttribute
57+
&& model.Annotation is IAttributeAnnotation attributeAnnotation)
58+
{
59+
var baseAttribute = attributeAnnotation.Attribute(arguments);
60+
var attribute = targetDeclaration.DeclarationType.HasFlag(DeclarationType.Module)
61+
? baseAttribute
62+
: Attributes.MemberAttributeName(baseAttribute, targetDeclaration.IdentifierName);
63+
var attributeValues = attributeAnnotation.AnnotationToAttributeValues(arguments);
64+
_attributesUpdater.AddOrUpdateAttribute(rewriteSession, targetDeclaration, attribute, attributeValues);
65+
}
66+
67+
_annotationUpdater.AddAnnotation(rewriteSession, targetDeclaration, model.Annotation, arguments);
68+
}
69+
70+
private string ToCode(TypedAnnotationArgument annotationArgument)
71+
{
72+
switch (annotationArgument.ArgumentType)
73+
{
74+
case AnnotationArgumentType.Text:
75+
return annotationArgument.Argument.ToVbaStringLiteral();
76+
case AnnotationArgumentType.Boolean:
77+
return ToBooleanLiteral(annotationArgument.Argument);
78+
default:
79+
return annotationArgument.Argument;
80+
}
81+
}
82+
83+
private const string NotABoolean = "NOT_A_BOOLEAN";
84+
private string ToBooleanLiteral(string booleanText)
85+
{
86+
if (!bool.TryParse(booleanText, out var booleanValue))
87+
{
88+
return NotABoolean;
89+
}
90+
91+
return booleanValue
92+
? Tokens.True
93+
: Tokens.False;
94+
}
95+
}
96+
}

Rubberduck.Refactorings/AnnotateDeclaration/AnnotateFolderRefactoringAction.cs

Lines changed: 0 additions & 55 deletions
This file was deleted.
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace Rubberduck.Refactorings.Exceptions
2+
{
3+
public class AttributeRewriteSessionNotSupportedException : RefactoringException
4+
{ }
5+
}
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
namespace Rubberduck.Refactorings.Exceptions
2+
{
3+
public class AttributeRewriteSessionRequiredException : RefactoringException
4+
{ }
5+
}

RubberduckTests/Commands/RefactorCommands/AnnotateSelectedDeclarationCommandTests.cs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,8 @@ public void AnnotateDeclaration_CanExecute_InvalidTargetType()
3131
}
3232

3333
protected override CommandBase TestCommand(
34-
IVBE vbe, RubberduckParserState state,
34+
IVBE vbe,
35+
RubberduckParserState state,
3536
IRewritingManager rewritingManager,
3637
ISelectionService selectionService)
3738
{
@@ -45,7 +46,8 @@ protected override CommandBase TestCommand(
4546
var userInteraction = new RefactoringUserInteraction<IAnnotateDeclarationPresenter, AnnotateDeclarationModel>(factory, uiDispatcherMock.Object);
4647

4748
var annotationUpdater = new AnnotationUpdater(state);
48-
var annotateDeclarationAction = new AnnotateDeclarationRefactoringAction(rewritingManager, annotationUpdater);
49+
var attributesUpdater = new AttributesUpdater(state);
50+
var annotateDeclarationAction = new AnnotateDeclarationRefactoringAction(rewritingManager, annotationUpdater, attributesUpdater);
4951

5052
var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state);
5153

RubberduckTests/Commands/RefactorCommands/AnnotateSelectedMemberCommandTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ protected override CommandBase TestCommand(
4545
var userInteraction = new RefactoringUserInteraction<IAnnotateDeclarationPresenter, AnnotateDeclarationModel>(factory, uiDispatcherMock.Object);
4646

4747
var annotationUpdater = new AnnotationUpdater(state);
48-
var annotateDeclarationAction = new AnnotateDeclarationRefactoringAction(rewritingManager, annotationUpdater);
48+
var attributesUpdater = new AttributesUpdater(state);
49+
var annotateDeclarationAction = new AnnotateDeclarationRefactoringAction(rewritingManager, annotationUpdater, attributesUpdater);
4950

5051
var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state);
5152

RubberduckTests/Commands/RefactorCommands/AnnotateSelectedModuleCommandTests.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,8 @@ protected override CommandBase TestCommand(
4545
var userInteraction = new RefactoringUserInteraction<IAnnotateDeclarationPresenter, AnnotateDeclarationModel>(factory, uiDispatcherMock.Object);
4646

4747
var annotationUpdater = new AnnotationUpdater(state);
48-
var annotateDeclarationAction = new AnnotateDeclarationRefactoringAction(rewritingManager, annotationUpdater);
48+
var attributesUpdater = new AttributesUpdater(state);
49+
var annotateDeclarationAction = new AnnotateDeclarationRefactoringAction(rewritingManager, annotationUpdater, attributesUpdater);
4950

5051
var selectedDeclarationProvider = new SelectedDeclarationProvider(selectionService, state);
5152

0 commit comments

Comments
 (0)