Skip to content

Commit 9db8fb8

Browse files
authored
Merge pull request #1 from rubberduck-vba/next
Update local fork with rubberduck changes
2 parents 16d72d6 + d04b41c commit 9db8fb8

File tree

209 files changed

+12953
-3519
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

209 files changed

+12953
-3519
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,8 @@ If you like this project and would like to thank its contributors, you are welco
1515

1616
[nextBuildStatus]:https://ci.appveyor.com/api/projects/status/we3pdnkeebo4nlck/branch/next?svg=true
1717
[masterBuildStatus]:https://ci.appveyor.com/api/projects/status/we3pdnkeebo4nlck/branch/master?svg=true
18-
19-
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/rubberduck-vba/Rubberduck.svg)](http://isitmaintained.com/project/rubberduck-vba/Rubberduck "Average time to resolve an issue") [![Percentage of issues still open](http://isitmaintained.com/badge/open/rubberduck-vba/Rubberduck.svg)](http://isitmaintained.com/project/rubberduck-vba/Rubberduck "Percentage of issues still open")
18+
[![Average time to resolve an issue](http://isitmaintained.com/badge/resolution/Rubberduck-vba/rubberduck.svg)](http://isitmaintained.com/project/Rubberduck-vba/rubberduck "Average time to resolve an issue")
19+
[![Percentage of issues still open](http://isitmaintained.com/badge/open/Rubberduck-vba/rubberduck.svg)](http://isitmaintained.com/project/Rubberduck-vba/rubberduck "Percentage of issues still open")
2020

2121
> **[rubberduckvba.com](http://rubberduckvba.com)** [Wiki](https://github.com/rubberduck-vba/Rubberduck/wiki) [Rubberduck News](https://rubberduckvba.wordpress.com/)
2222
> devs@rubberduckvba.com

Rubberduck.CodeAnalysis/Inspections/Abstract/InspectionBase.cs

Lines changed: 15 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -86,28 +86,22 @@ protected virtual IEnumerable<Declaration> BuiltInDeclarations
8686

8787
protected bool IsIgnoringInspectionResultFor(QualifiedModuleName module, int line)
8888
{
89-
var annotations = State.GetModuleAnnotations(module).ToList();
90-
91-
if (State.GetModuleAnnotations(module) == null)
92-
{
93-
return false;
94-
}
95-
96-
// VBE 1-based indexing
97-
for (var i = line; i >= 1; i--)
89+
var lineScopedAnnotations = State.DeclarationFinder.FindAnnotations(module, line);
90+
foreach (var ignoreAnnotation in lineScopedAnnotations.OfType<IgnoreAnnotation>())
9891
{
99-
var annotation = annotations.SingleOrDefault(a => a.QualifiedSelection.Selection.StartLine == i);
100-
var ignoreAnnotation = annotation as IgnoreAnnotation;
101-
var ignoreModuleAnnotation = annotation as IgnoreModuleAnnotation;
102-
103-
if (ignoreAnnotation?.InspectionNames.Contains(AnnotationName) == true)
92+
if (ignoreAnnotation.InspectionNames.Contains(AnnotationName))
10493
{
10594
return true;
10695
}
96+
}
97+
98+
var moduleDeclaration = State.DeclarationFinder.Members(module)
99+
.First(decl => decl.DeclarationType.HasFlag(DeclarationType.Module));
107100

108-
if (ignoreModuleAnnotation != null
109-
&& (ignoreModuleAnnotation.InspectionNames.Contains(AnnotationName)
110-
|| !ignoreModuleAnnotation.InspectionNames.Any()))
101+
foreach (var ignoreModuleAnnotation in moduleDeclaration.Annotations.OfType<IgnoreModuleAnnotation>())
102+
{
103+
if (ignoreModuleAnnotation.InspectionNames.Contains(AnnotationName)
104+
|| !ignoreModuleAnnotation.InspectionNames.Any())
111105
{
112106
return true;
113107
}
@@ -119,7 +113,10 @@ protected bool IsIgnoringInspectionResultFor(QualifiedModuleName module, int lin
119113
protected bool IsIgnoringInspectionResultFor(Declaration declaration, string inspectionName)
120114
{
121115
var module = Declaration.GetModuleParent(declaration);
122-
if (module == null) { return false; }
116+
if (module == null)
117+
{
118+
return false;
119+
}
123120

124121
var isIgnoredAtModuleLevel = module.Annotations
125122
.Any(annotation => annotation.AnnotationType == AnnotationType.IgnoreModule
Lines changed: 73 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,73 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Inspections.Abstract;
4+
using Rubberduck.Inspections.Results;
5+
using Rubberduck.Parsing;
6+
using Rubberduck.Parsing.Annotations;
7+
using Rubberduck.Parsing.Inspections;
8+
using Rubberduck.Parsing.Inspections.Abstract;
9+
using Rubberduck.Parsing.Symbols;
10+
using Rubberduck.Parsing.VBA;
11+
using Rubberduck.Resources.Inspections;
12+
using Rubberduck.VBEditor.SafeComWrappers;
13+
14+
namespace Rubberduck.Inspections.Concrete
15+
{
16+
[CannotAnnotate]
17+
public sealed class AttributeValueOutOfSyncInspection : InspectionBase
18+
{
19+
public AttributeValueOutOfSyncInspection(RubberduckParserState state)
20+
:base(state)
21+
{
22+
}
23+
24+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
25+
{
26+
var declarationsWithAttributeAnnotations = State.DeclarationFinder.AllUserDeclarations
27+
.Where(declaration => declaration.Annotations.Any(annotation => annotation.AnnotationType.HasFlag(AnnotationType.Attribute)));
28+
var results = new List<DeclarationInspectionResult>();
29+
foreach (var declaration in declarationsWithAttributeAnnotations.Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document))
30+
{
31+
foreach (var annotation in declaration.Annotations.OfType<IAttributeAnnotation>())
32+
{
33+
if (HasDifferingAttributeValues(declaration, annotation, out var attributeValues))
34+
{
35+
var description = string.Format(InspectionResults.AttributeValueOutOfSyncInspection,
36+
annotation.Attribute,
37+
string.Join(", ", attributeValues),
38+
annotation.AnnotationType);
39+
40+
var result = new DeclarationInspectionResult(this, description, declaration,
41+
new QualifiedContext(declaration.QualifiedModuleName, annotation.Context));
42+
result.Properties.Annotation = annotation;
43+
result.Properties.AttributeName = annotation.Attribute;
44+
result.Properties.AttributeValues = attributeValues;
45+
46+
results.Add(result);
47+
}
48+
}
49+
}
50+
51+
return results;
52+
}
53+
54+
private static bool HasDifferingAttributeValues(Declaration declaration, IAttributeAnnotation annotation, out IReadOnlyList<string> attributeValues)
55+
{
56+
var attributeNodes = declaration.DeclarationType.HasFlag(DeclarationType.Module)
57+
? declaration.Attributes.AttributeNodesFor(annotation)
58+
: declaration.Attributes.AttributeNodesFor(annotation, declaration.IdentifierName);
59+
60+
foreach (var attributeNode in attributeNodes)
61+
{
62+
var values = attributeNode.Values;
63+
if (!annotation.AttributeValues.SequenceEqual(values))
64+
{
65+
attributeValues = values;
66+
return true;
67+
}
68+
}
69+
attributeValues = new List<string>();
70+
return false;
71+
}
72+
}
73+
}

Rubberduck.CodeAnalysis/Inspections/Concrete/IllegalAnnotationInspection.cs

Lines changed: 16 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@
88
using Rubberduck.Parsing.Symbols;
99
using Rubberduck.Resources.Inspections;
1010
using Rubberduck.Parsing.VBA;
11+
using Rubberduck.Parsing.VBA.DeclarationCaching;
1112
using Rubberduck.Parsing.VBA.Extensions;
13+
using Rubberduck.VBEditor.SafeComWrappers;
1214

1315
namespace Rubberduck.Inspections.Concrete
1416
{
@@ -24,8 +26,12 @@ protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
2426
var identifierReferences = State.DeclarationFinder.AllIdentifierReferences().ToList();
2527
var annotations = State.AllAnnotations;
2628

27-
var illegalAnnotations = UnboundAnnotations(annotations, userDeclarations, identifierReferences)
28-
.Where(annotation => !annotation.AnnotationType.HasFlag(AnnotationType.GeneralAnnotation));
29+
var unboundAnnotations = UnboundAnnotations(annotations, userDeclarations, identifierReferences)
30+
.Where(annotation => !annotation.AnnotationType.HasFlag(AnnotationType.GeneralAnnotation)
31+
|| annotation.AnnotatedLine == null);
32+
var attributeAnnotationsInDocuments = AttributeAnnotationsInDocuments(userDeclarations);
33+
34+
var illegalAnnotations = unboundAnnotations.Concat(attributeAnnotationsInDocuments).ToHashSet();
2935

3036
return illegalAnnotations.Select(annotation =>
3137
new QualifiedContextInspectionResult(
@@ -34,7 +40,7 @@ protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
3440
new QualifiedContext(annotation.QualifiedSelection.QualifiedName, annotation.Context)));
3541
}
3642

37-
private static ICollection<IAnnotation> UnboundAnnotations(IEnumerable<IAnnotation> annotations, IEnumerable<Declaration> userDeclarations, IEnumerable<IdentifierReference> identifierReferences)
43+
private static IEnumerable<IAnnotation> UnboundAnnotations(IEnumerable<IAnnotation> annotations, IEnumerable<Declaration> userDeclarations, IEnumerable<IdentifierReference> identifierReferences)
3844
{
3945
var boundAnnotationsSelections = userDeclarations
4046
.SelectMany(declaration => declaration.Annotations)
@@ -44,5 +50,12 @@ private static ICollection<IAnnotation> UnboundAnnotations(IEnumerable<IAnnotati
4450

4551
return annotations.Where(annotation => !boundAnnotationsSelections.Contains(annotation.QualifiedSelection)).ToList();
4652
}
53+
54+
private static IEnumerable<IAnnotation> AttributeAnnotationsInDocuments(IEnumerable<Declaration> userDeclarations)
55+
{
56+
var declarationsInDocuments = userDeclarations
57+
.Where(declaration => declaration.QualifiedModuleName.ComponentType == ComponentType.Document);
58+
return declarationsInDocuments.SelectMany(doc => doc.Annotations).OfType<IAttributeAnnotation>();
59+
}
4760
}
4861
}
Lines changed: 29 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,87 +1,60 @@
11
using System.Collections.Generic;
22
using System.Linq;
3-
using Antlr4.Runtime;
43
using Rubberduck.Inspections.Abstract;
54
using Rubberduck.Inspections.Results;
65
using Rubberduck.Parsing;
76
using Rubberduck.Parsing.Annotations;
8-
using Rubberduck.Parsing.Grammar;
97
using Rubberduck.Parsing.Inspections;
108
using Rubberduck.Parsing.Inspections.Abstract;
11-
using Rubberduck.Resources.Inspections;
129
using Rubberduck.Parsing.Symbols;
1310
using Rubberduck.Parsing.VBA;
14-
using Rubberduck.Parsing.VBA.Parsing;
11+
using Rubberduck.Resources.Inspections;
12+
using Rubberduck.VBEditor.SafeComWrappers;
1513

1614
namespace Rubberduck.Inspections.Concrete
1715
{
1816
[CannotAnnotate]
19-
public sealed class MissingAttributeInspection : ParseTreeInspectionBase
17+
public sealed class MissingAttributeInspection : InspectionBase
2018
{
2119
public MissingAttributeInspection(RubberduckParserState state)
2220
: base(state)
23-
{
24-
Listener = new MissingMemberAttributeListener(state);
25-
}
26-
27-
public override CodeKind TargetKindOfCode => CodeKind.AttributesCode;
28-
29-
public override IInspectionListener Listener { get; }
21+
{}
3022

3123
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
3224
{
33-
return Listener.Contexts.Select(context =>
25+
var declarationsWithAttributeAnnotations = State.DeclarationFinder.AllUserDeclarations
26+
.Where(declaration => declaration.Annotations.Any(annotation => annotation.AnnotationType.HasFlag(AnnotationType.Attribute)));
27+
var results = new List<DeclarationInspectionResult>();
28+
foreach (var declaration in declarationsWithAttributeAnnotations.Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document))
3429
{
35-
var name = string.Format(InspectionResults.MissingAttributeInspection, context.MemberName.MemberName,
36-
((VBAParser.AnnotationContext) context.Context).annotationName().GetText());
37-
return new QualifiedContextInspectionResult(this, name, context);
38-
});
39-
}
40-
41-
public class MissingMemberAttributeListener : ParseTreeListeners.AttributeAnnotationListener
42-
{
43-
public MissingMemberAttributeListener(RubberduckParserState state) : base(state) { }
44-
45-
public override void ExitAnnotation(VBAParser.AnnotationContext context)
46-
{
47-
var annotationType = context.AnnotationType;
48-
49-
if (!annotationType.HasFlag(AnnotationType.Attribute))
30+
foreach(var annotation in declaration.Annotations.OfType<IAttributeAnnotation>())
5031
{
51-
return;
52-
}
32+
if (MissesCorrespondingAttribute(declaration, annotation))
33+
{
34+
var description = string.Format(InspectionResults.MissingAttributeInspection, declaration.IdentifierName,
35+
annotation.AnnotationType.ToString());
5336

54-
var isMemberAnnotation = annotationType.HasFlag(AnnotationType.MemberAnnotation);
55-
var isModuleScope = CurrentScopeDeclaration.DeclarationType.HasFlag(DeclarationType.Module);
37+
var result = new DeclarationInspectionResult(this, description, declaration,
38+
new QualifiedContext(declaration.QualifiedModuleName, annotation.Context));
39+
result.Properties.Annotation = annotation;
5640

57-
if (isModuleScope && !isMemberAnnotation)
58-
{
59-
// module-level annotation
60-
var module = State.DeclarationFinder.UserDeclarations(DeclarationType.Module).Single(m => m.QualifiedName.QualifiedModuleName.Equals(CurrentModuleName));
61-
if (!module.Attributes.HasAttributeFor(context.AnnotationType))
62-
{
63-
AddContext(new QualifiedContext<ParserRuleContext>(CurrentModuleName, context));
41+
results.Add(result);
6442
}
6543
}
66-
else if (isMemberAnnotation)
67-
{
68-
// member-level annotation is above the context for the first member in the module..
69-
if (isModuleScope)
70-
{
71-
CurrentScopeDeclaration = FirstMember;
72-
}
44+
}
7345

74-
var member = Members.Value.Single(m => m.Key.Equals(CurrentScopeDeclaration.QualifiedName.MemberName));
75-
if (!member.Value.Attributes.HasAttributeFor(context.AnnotationType, member.Key))
76-
{
77-
AddContext(new QualifiedContext<ParserRuleContext>(CurrentModuleName, context));
78-
}
79-
}
80-
else
81-
{
82-
// annotation is illegal. ignore.
83-
}
46+
return results;
47+
}
48+
49+
private static bool MissesCorrespondingAttribute(Declaration declaration, IAttributeAnnotation annotation)
50+
{
51+
if (string.IsNullOrEmpty(annotation.Attribute))
52+
{
53+
return false;
8454
}
55+
return declaration.DeclarationType.HasFlag(DeclarationType.Module)
56+
? !declaration.Attributes.HasAttributeFor(annotation)
57+
: !declaration.Attributes.HasAttributeFor(annotation, declaration.IdentifierName);
8558
}
8659
}
8760
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Inspections.Abstract;
4+
using Rubberduck.Inspections.Results;
5+
using Rubberduck.Parsing;
6+
using Rubberduck.Parsing.Annotations;
7+
using Rubberduck.Parsing.Inspections.Abstract;
8+
using Rubberduck.Parsing.Symbols;
9+
using Rubberduck.Parsing.VBA;
10+
using Rubberduck.Resources.Inspections;
11+
using Rubberduck.VBEditor.SafeComWrappers;
12+
13+
namespace Rubberduck.Inspections.Concrete
14+
{
15+
public sealed class MissingMemberAnnotationInspection : InspectionBase
16+
{
17+
public MissingMemberAnnotationInspection(RubberduckParserState state)
18+
:base(state)
19+
{}
20+
21+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
22+
{
23+
var memberDeclarationsWithAttributes = State.DeclarationFinder.AllUserDeclarations
24+
.Where(decl => !decl.DeclarationType.HasFlag(DeclarationType.Module)
25+
&& decl.Attributes.Any());
26+
27+
var declarationsToInspect = memberDeclarationsWithAttributes
28+
.Where(decl => decl.QualifiedModuleName.ComponentType != ComponentType.Document
29+
&& !IsIgnoringInspectionResultFor(decl, AnnotationName));
30+
31+
var results = new List<DeclarationInspectionResult>();
32+
foreach (var declaration in declarationsToInspect)
33+
{
34+
foreach (var attribute in declaration.Attributes)
35+
{
36+
if (MissesCorrespondingMemberAnnotation(declaration, attribute))
37+
{
38+
var attributeBaseName = AttributeBaseName(declaration, attribute);
39+
40+
var description = string.Format(InspectionResults.MissingMemberAnnotationInspection,
41+
declaration.IdentifierName,
42+
attributeBaseName,
43+
string.Join(", ", attribute.Values));
44+
45+
var result = new DeclarationInspectionResult(this, description, declaration,
46+
new QualifiedContext(declaration.QualifiedModuleName, declaration.Context));
47+
result.Properties.AttributeName = attributeBaseName;
48+
result.Properties.AttributeValues = attribute.Values;
49+
50+
results.Add(result);
51+
}
52+
}
53+
}
54+
55+
return results;
56+
}
57+
58+
private static bool MissesCorrespondingMemberAnnotation(Declaration declaration, AttributeNode attribute)
59+
{
60+
if (string.IsNullOrEmpty(attribute.Name) || declaration.DeclarationType.HasFlag(DeclarationType.Module))
61+
{
62+
return false;
63+
}
64+
65+
var attributeBaseName = AttributeBaseName(declaration, attribute);
66+
67+
//VB_Ext_Key attributes are special in that identity also depends on the first value, the key.
68+
if (attributeBaseName == "VB_Ext_Key")
69+
{
70+
return !declaration.Annotations.OfType<IAttributeAnnotation>()
71+
.Any(annotation => annotation.Attribute.Equals("VB_Ext_Key") && attribute.Values[0].Equals(annotation.AttributeValues[0]));
72+
}
73+
74+
return !declaration.Annotations.OfType<IAttributeAnnotation>()
75+
.Any(annotation => annotation.Attribute.Equals(attributeBaseName));
76+
}
77+
78+
private static string AttributeBaseName(Declaration declaration, AttributeNode attribute)
79+
{
80+
var attributeName = attribute.Name;
81+
return attributeName.StartsWith($"{declaration.IdentifierName}.")
82+
? attributeName.Substring(declaration.IdentifierName.Length + 1)
83+
: attributeName;
84+
}
85+
}
86+
}

0 commit comments

Comments
 (0)