Skip to content

Commit

Permalink
Merge pull request #4642 from MDoerner/AttributeValueOutOfSyncInspection
Browse files Browse the repository at this point in the history
Attribute value out of sync inspection
  • Loading branch information
retailcoder committed Dec 18, 2018
2 parents 4a6976f + 59c2a33 commit c5be87b
Show file tree
Hide file tree
Showing 22 changed files with 631 additions and 140 deletions.
@@ -0,0 +1,71 @@
using System.Collections.Generic;
using System.Linq;
using Rubberduck.Inspections.Abstract;
using Rubberduck.Inspections.Results;
using Rubberduck.Parsing;
using Rubberduck.Parsing.Annotations;
using Rubberduck.Parsing.Inspections;
using Rubberduck.Parsing.Inspections.Abstract;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.Resources.Inspections;

namespace Rubberduck.Inspections.Concrete
{
[CannotAnnotate]
public sealed class AttributeValueOutOfSyncInspection : InspectionBase
{
public AttributeValueOutOfSyncInspection(RubberduckParserState state)
:base(state)
{
}

protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
{
var declarationsWithAttributeAnnotations = State.DeclarationFinder.AllUserDeclarations
.Where(declaration => declaration.Annotations.Any(annotation => annotation.AnnotationType.HasFlag(AnnotationType.Attribute)));
var results = new List<DeclarationInspectionResult>();
foreach (var declaration in declarationsWithAttributeAnnotations)
{
foreach (var annotation in declaration.Annotations.OfType<IAttributeAnnotation>())
{
if (HasDifferingAttributeValues(declaration, annotation, out var attributeValues))
{
var description = string.Format(InspectionResults.AttributeValueOutOfSyncInspection,
annotation.Attribute,
string.Join(", ", attributeValues),
annotation.AnnotationType);

var result = new DeclarationInspectionResult(this, description, declaration,
new QualifiedContext(declaration.QualifiedModuleName, annotation.Context));
result.Properties.Annotation = annotation;
result.Properties.AttributeValues = attributeValues;

results.Add(result);
}
}
}

return results;
}

private static bool HasDifferingAttributeValues(Declaration declaration, IAttributeAnnotation annotation, out IReadOnlyList<string> attributeValues)
{
var attributeNodes = declaration.DeclarationType.HasFlag(DeclarationType.Module)
? declaration.Attributes.AttributeNodesFor(annotation)
: declaration.Attributes.AttributeNodesFor(annotation, declaration.IdentifierName);

foreach (var attributeNode in attributeNodes)
{
var values = attributeNode.Values;
if (!annotation.AttributeValues.SequenceEqual(values))
{
attributeValues = values;
return true;
}
}
attributeValues = new List<string>();
return false;
}
}
}
@@ -0,0 +1,45 @@
using System;
using System.Collections.Generic;
using Rubberduck.Inspections.Abstract;
using Rubberduck.Inspections.Concrete;
using Rubberduck.Parsing.Annotations;
using Rubberduck.Parsing.Inspections.Abstract;
using Rubberduck.Parsing.Rewriter;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Parsing.VBA;
using Rubberduck.Parsing.VBA.Parsing;

namespace Rubberduck.Inspections.QuickFixes
{
public class AdjustAttributeValuesQuickFix : QuickFixBase
{
private readonly IAttributesUpdater _attributesUpdater;

public AdjustAttributeValuesQuickFix(IAttributesUpdater attributesUpdater)
: base(typeof(AttributeValueOutOfSyncInspection))
{
_attributesUpdater = attributesUpdater;
}

public override void Fix(IInspectionResult result, IRewriteSession rewriteSession)
{
var declaration = result.Target;
IAttributeAnnotation annotation = result.Properties.Annotation;
IReadOnlyList<string> attributeValues = result.Properties.AttributeValues;

var attributeName = declaration.DeclarationType.HasFlag(DeclarationType.Module)
? annotation.Attribute
: $"{declaration.IdentifierName}.{annotation.Attribute}";

_attributesUpdater.UpdateAttribute(rewriteSession, declaration, attributeName, annotation.AttributeValues, attributeValues);
}

public override string Description(IInspectionResult result) => Resources.Inspections.QuickFixes.AdjustAttributeValuesQuickFix;

public override CodeKind TargetCodeKind => CodeKind.AttributesCode;

public override bool CanFixInProcedure => true;
public override bool CanFixInModule => true;
public override bool CanFixInProject => true;
}
}

0 comments on commit c5be87b

Please sign in to comment.