/
IllegalAnnotationInspection.cs
86 lines (78 loc) · 3.62 KB
/
IllegalAnnotationInspection.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
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.Abstract;
using Rubberduck.Parsing.Symbols;
using Rubberduck.Resources.Inspections;
using Rubberduck.Parsing.VBA;
using Rubberduck.Parsing.VBA.Extensions;
using Rubberduck.VBEditor.SafeComWrappers;
namespace Rubberduck.Inspections.Concrete
{
/// <summary>
/// Flags invalid Rubberduck annotation comments.
/// </summary>
/// <why>
/// Rubberduck is correctly parsing an annotation, but that annotation is illegal in that context.
/// </why>
/// <example hasResults="true">
/// <![CDATA[
/// Option Explicit
///
/// Public Sub DoSomething()
/// '@Folder("Module1.DoSomething")
/// Dim foo As Long
/// End Sub
/// ]]>
/// </example>
/// <example hasResults="false">
/// <![CDATA[
/// '@Folder("Module1.DoSomething")
/// Option Explicit
///
/// Public Sub DoSomething()
/// Dim foo As Long
/// End Sub
/// ]]>
/// </example>
public sealed class IllegalAnnotationInspection : InspectionBase
{
public IllegalAnnotationInspection(RubberduckParserState state)
: base(state)
{}
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
{
var userDeclarations = State.DeclarationFinder.AllUserDeclarations.ToList();
var identifierReferences = State.DeclarationFinder.AllIdentifierReferences().ToList();
var annotations = State.AllAnnotations;
var unboundAnnotations = UnboundAnnotations(annotations, userDeclarations, identifierReferences)
.Where(annotation => !annotation.MetaInformation.Target.HasFlag(AnnotationTarget.General)
|| annotation.AnnotatedLine == null);
var attributeAnnotationsInDocuments = AttributeAnnotationsInDocuments(userDeclarations);
var illegalAnnotations = unboundAnnotations.Concat(attributeAnnotationsInDocuments).ToHashSet();
return illegalAnnotations.Select(annotation =>
new QualifiedContextInspectionResult(
this,
string.Format(InspectionResults.IllegalAnnotationInspection, annotation.Context.annotationName().GetText()),
new QualifiedContext(annotation.QualifiedSelection.QualifiedName, annotation.Context)));
}
private static IEnumerable<IAnnotation> UnboundAnnotations(IEnumerable<IAnnotation> annotations, IEnumerable<Declaration> userDeclarations, IEnumerable<IdentifierReference> identifierReferences)
{
var boundAnnotationsSelections = userDeclarations
.SelectMany(declaration => declaration.Annotations)
.Concat(identifierReferences.SelectMany(reference => reference.Annotations))
.Select(annotation => annotation.QualifiedSelection)
.ToHashSet();
return annotations.Where(annotation => !boundAnnotationsSelections.Contains(annotation.QualifiedSelection)).ToList();
}
private static IEnumerable<IAnnotation> AttributeAnnotationsInDocuments(IEnumerable<Declaration> userDeclarations)
{
var declarationsInDocuments = userDeclarations
.Where(declaration => declaration.QualifiedModuleName.ComponentType == ComponentType.Document);
return declarationsInDocuments.SelectMany(doc => doc.Annotations).OfType<IAttributeAnnotation>();
}
}
}