Skip to content

Commit 333bfa0

Browse files
authored
Merge pull request #5561 from rubberduck-vba/next
2.5.1 release
2 parents 6027378 + a110623 commit 333bfa0

File tree

1,021 files changed

+46378
-17250
lines changed

Some content is hidden

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

1,021 files changed

+46378
-17250
lines changed

.gitignore

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,7 +186,9 @@ CodeGraphData/
186186

187187
# Generated Artifacts
188188
Rubberduck.CodeAnalysis.xml
189+
Rubberduck.Parsing.xml
189190

190191
#Gradle
191192
/.gradle/
192193
/Rubberduck.CodeAnalysis/Rubberduck.CodeAnalysis.xml
194+
/Rubberduck.Parsing/Rubberduck.Parsing.xml

README.md

Lines changed: 10 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,6 @@
11
<img alt="Rubberduck Open-Source VBE Add-In - VBA6 | VBA7 x86/x64 | VB6" src="https://user-images.githubusercontent.com/5751684/48656196-a507af80-e9ef-11e8-9c09-1ce3c619c019.png" />
2-
3-
<!-- campaign is no longer accepting donations
4-
### Donate!
52

6-
If you like this project and would like to thank its contributors, you are welcome to support our GoFundMe campaign to finance Rubberduck swag and international shipping - contributors will be getting t-shirts, mugs, and other cool things.
7-
8-
[![GoFundMe campaign](https://user-images.githubusercontent.com/5751684/29191799-e3d20b72-7dec-11e7-8ec6-0c69da4a3135.png)](https://www.gofundme.com/rubberduckvba)
9-
-->
3+
---
104

115
|Branch | Description | Build Status | Download link |
126
|------------|---|--------------|-|
@@ -20,9 +14,15 @@ If you like this project and would like to thank its contributors, you are welco
2014
[![Chat on stackexchange](https://img.shields.io/badge/chat-on%20stackexchange-blue.svg)](https://chat.stackexchange.com/rooms/14929/vba-rubberducking)
2115
[![License](https://img.shields.io/github/license/rubberduck-vba/Rubberduck.svg)](https://github.com/rubberduck-vba/Rubberduck/blob/next/LICENSE)
2216

23-
> **[rubberduckvba.com](http://rubberduckvba.com)** [Wiki](https://github.com/rubberduck-vba/Rubberduck/wiki) [Rubberduck News](https://rubberduckvba.wordpress.com/)
24-
> devs@rubberduckvba.com
25-
> Follow [@rubberduckvba](https://twitter.com/rubberduckvba) on Twitter
17+
18+
> **[rubberduckvba.com](http://rubberduckvba.com)** | **[Rubberduck News](https://rubberduckvba.wordpress.com/)**
19+
| **[Twitter (@rubberduckvba)](https://twitter.com/rubberduckvba)** | **[Wiki](https://github.com/rubberduck-vba/Rubberduck/wiki)**
20+
21+
Rubberduck is free, but keeping it visible online isn't. Donate to help us pay for hosting and keep the blog free of ads!
22+
23+
|Donate|Note |
24+
|:------:|-|
25+
|<a href="https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=UY5K5X36B7T2S&currency_code=CAD&source=url"><img alt="Donate via PayPal" src="https://www.paypalobjects.com/en_US/i/btn/btn_donateCC_LG.gif"></a><p><sub>via PayPal</sub></p>|Donations in excess of what's needed to cover our fees will be donated to the <a href="https://mssociety.ca/">Multiple Sclerosis Society of Canada</a>.|
2626

2727
---
2828

Rubberduck.CodeAnalysis/CodePathAnalysis/Extensions/NodeExtensions.cs

Lines changed: 20 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -2,13 +2,12 @@
22
using System;
33
using System.Collections.Generic;
44
using System.Linq;
5-
using Rubberduck.Parsing.Symbols;
65

76
namespace Rubberduck.Inspections.CodePathAnalysis.Extensions
87
{
98
public static class NodeExtensions
109
{
11-
public static IEnumerable<INode> GetFlattenedNodes(this INode node, IEnumerable<Type> excludedTypes)
10+
public static IEnumerable<INode> FlattenedNodes(this INode node, IEnumerable<Type> excludedTypes)
1211
{
1312
foreach (var child in node.Children)
1413
{
@@ -18,15 +17,15 @@ public static IEnumerable<INode> GetFlattenedNodes(this INode node, IEnumerable<
1817
}
1918
else
2019
{
21-
foreach (var nextChild in GetFlattenedNodes(child, excludedTypes))
20+
foreach (var nextChild in FlattenedNodes(child, excludedTypes))
2221
{
2322
yield return nextChild;
2423
}
2524
}
2625
}
2726
}
2827

29-
public static IEnumerable<INode> GetNodes(this INode node, IEnumerable<Type> types)
28+
public static IEnumerable<INode> Nodes(this INode node, ICollection<Type> types)
3029
{
3130
if (types.Contains(node.GetType()))
3231
{
@@ -35,50 +34,42 @@ public static IEnumerable<INode> GetNodes(this INode node, IEnumerable<Type> typ
3534

3635
foreach (var child in node.Children)
3736
{
38-
foreach (var childNode in GetNodes(child, types))
37+
foreach (var childNode in Nodes(child, types))
3938
{
4039
yield return childNode;
4140
}
4241
}
4342
}
4443

45-
public static INode GetFirstNode(this INode node, IEnumerable<Type> excludedTypes)
44+
public static INode GetFirstNode(this INode node, ICollection<Type> excludedTypes)
4645
{
4746
if (!excludedTypes.Contains(node.GetType()))
4847
{
4948
return node;
5049
}
5150

51+
if (!node.Children.Any())
52+
{
53+
return null;
54+
}
55+
5256
return GetFirstNode(node.Children[0], excludedTypes);
5357
}
5458

55-
public static List<IdentifierReference> GetIdentifierReferences(this INode node)
59+
public static bool TryGetAncestorNode<T>(this INode node, out T ancestor) where T: INode
5660
{
57-
var nodes = new List<IdentifierReference>();
58-
59-
var blockNodes = node.GetNodes(new[] { typeof(BlockNode) });
60-
foreach (var block in blockNodes)
61+
ancestor = default;
62+
if (node.Parent is null)
6163
{
62-
INode lastNode = default;
63-
foreach (var flattenedNode in block.GetFlattenedNodes(new[] { typeof(GenericNode), typeof(BlockNode) }))
64-
{
65-
if (flattenedNode is AssignmentNode &&
66-
lastNode is AssignmentNode)
67-
{
68-
nodes.Add(lastNode.Reference);
69-
}
70-
71-
lastNode = flattenedNode;
72-
}
73-
74-
if (lastNode is AssignmentNode &&
75-
block.Children[0].GetFirstNode(new[] { typeof(GenericNode) }) is DeclarationNode)
76-
{
77-
nodes.Add(lastNode.Reference);
78-
}
64+
return false;
7965
}
8066

81-
return nodes;
67+
if (node.Parent is T result)
68+
{
69+
ancestor = result;
70+
return true;
71+
}
72+
return TryGetAncestorNode(node.Parent, out ancestor);
8273
}
8374
}
8475
}
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
using Antlr4.Runtime.Tree;
2+
3+
namespace Rubberduck.Inspections.CodePathAnalysis.Nodes
4+
{
5+
public class AssignmentExpressionNode : NodeBase
6+
{
7+
public AssignmentExpressionNode(IParseTree tree) : base(tree) { }
8+
}
9+
}

Rubberduck.CodeAnalysis/CodePathAnalysis/Walker.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,10 @@ public INode GenerateTree(IParseTree tree, Declaration declaration)
3333
case VBAParser.BlockContext _:
3434
node = new BlockNode(tree);
3535
break;
36+
case VBAParser.LetStmtContext _:
37+
case VBAParser.SetStmtContext _:
38+
node = new AssignmentExpressionNode(tree);
39+
break;
3640
}
3741

3842
if (declaration.Context == tree)
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Parsing.Symbols;
4+
using Rubberduck.Parsing.VBA;
5+
using Rubberduck.Parsing.VBA.DeclarationCaching;
6+
7+
namespace Rubberduck.CodeAnalysis.Inspections.Abstract
8+
{
9+
internal abstract class ArgumentReferenceInspectionFromDeclarationsBase : IdentifierReferenceInspectionFromDeclarationsBase
10+
{
11+
protected ArgumentReferenceInspectionFromDeclarationsBase(RubberduckParserState state)
12+
: base(state) { }
13+
14+
protected abstract bool IsUnsuitableArgument(ArgumentReference reference, DeclarationFinder finder);
15+
16+
protected override IEnumerable<IdentifierReference> ObjectionableReferences(DeclarationFinder finder)
17+
{
18+
return ObjectionableDeclarations(finder)
19+
.OfType<ParameterDeclaration>()
20+
.SelectMany(parameter => parameter.ArgumentReferences);
21+
}
22+
23+
protected override bool IsResultReference(IdentifierReference reference, DeclarationFinder finder)
24+
{
25+
if (!(reference is ArgumentReference argumentReference))
26+
{
27+
return false;
28+
}
29+
30+
return IsUnsuitableArgument(argumentReference, finder);
31+
}
32+
}
33+
34+
internal abstract class ArgumentReferenceInspectionFromDeclarationsBase<T> : IdentifierReferenceInspectionFromDeclarationsBase<T>
35+
{
36+
protected ArgumentReferenceInspectionFromDeclarationsBase(IDeclarationFinderProvider declarationFinderProvider)
37+
: base(declarationFinderProvider)
38+
{}
39+
40+
protected abstract (bool isResult, T properties) IsUnsuitableArgumentWithAdditionalProperties(ArgumentReference reference, DeclarationFinder finder);
41+
42+
protected override IEnumerable<IdentifierReference> ObjectionableReferences(DeclarationFinder finder)
43+
{
44+
return ObjectionableDeclarations(finder)
45+
.OfType<ParameterDeclaration>()
46+
.SelectMany(parameter => parameter.ArgumentReferences);
47+
}
48+
49+
protected override (bool isResult, T properties) IsResultReferenceWithAdditionalProperties(IdentifierReference reference, DeclarationFinder finder)
50+
{
51+
if (!(reference is ArgumentReference argumentReference))
52+
{
53+
return (false, default);
54+
}
55+
56+
return IsUnsuitableArgumentWithAdditionalProperties(argumentReference, finder);
57+
}
58+
}
59+
}
Lines changed: 91 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.CodeAnalysis.Inspections.Results;
4+
using Rubberduck.Parsing.Symbols;
5+
using Rubberduck.Parsing.VBA;
6+
using Rubberduck.Parsing.VBA.DeclarationCaching;
7+
using Rubberduck.VBEditor;
8+
9+
namespace Rubberduck.CodeAnalysis.Inspections.Abstract
10+
{
11+
internal abstract class DeclarationInspectionBase : DeclarationInspectionBaseBase
12+
{
13+
protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes)
14+
: base(declarationFinderProvider, relevantDeclarationTypes)
15+
{}
16+
17+
protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes)
18+
: base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes)
19+
{}
20+
21+
protected abstract bool IsResultDeclaration(Declaration declaration, DeclarationFinder finder);
22+
protected abstract string ResultDescription(Declaration declaration);
23+
24+
protected virtual ICollection<string> DisabledQuickFixes(Declaration declaration) => new List<string>();
25+
26+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder)
27+
{
28+
var objectionableDeclarations = RelevantDeclarationsInModule(module, finder)
29+
.Where(declaration => IsResultDeclaration(declaration, finder));
30+
31+
return objectionableDeclarations
32+
.Select(InspectionResult)
33+
.ToList();
34+
}
35+
36+
protected virtual IInspectionResult InspectionResult(Declaration declaration)
37+
{
38+
return new DeclarationInspectionResult(
39+
this,
40+
ResultDescription(declaration),
41+
declaration,
42+
disabledQuickFixes: DisabledQuickFixes(declaration));
43+
}
44+
}
45+
46+
internal abstract class DeclarationInspectionBase<T> : DeclarationInspectionBaseBase
47+
{
48+
protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes)
49+
: base(declarationFinderProvider, relevantDeclarationTypes)
50+
{}
51+
52+
protected DeclarationInspectionBase(IDeclarationFinderProvider declarationFinderProvider , DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes)
53+
: base(declarationFinderProvider, relevantDeclarationTypes, excludeDeclarationTypes)
54+
{}
55+
56+
protected abstract (bool isResult, T properties) IsResultDeclarationWithAdditionalProperties(Declaration declaration, DeclarationFinder finder);
57+
protected abstract string ResultDescription(Declaration declaration, T properties);
58+
59+
protected virtual ICollection<string> DisabledQuickFixes(Declaration declaration, T properties) => new List<string>();
60+
61+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults(QualifiedModuleName module, DeclarationFinder finder)
62+
{
63+
var objectionableDeclarationsWithAdditionalProperties = RelevantDeclarationsInModule(module, finder)
64+
.Select(declaration => DeclarationWithResultProperties(declaration, finder))
65+
.Where(result => result.HasValue)
66+
.Select(result => result.Value);
67+
68+
return objectionableDeclarationsWithAdditionalProperties
69+
.Select(tpl => InspectionResult(tpl.declaration, tpl.properties))
70+
.ToList();
71+
}
72+
73+
private (Declaration declaration, T properties)? DeclarationWithResultProperties(Declaration declaration, DeclarationFinder finder)
74+
{
75+
var (isResult, properties) = IsResultDeclarationWithAdditionalProperties(declaration, finder);
76+
return isResult
77+
? (declaration, properties)
78+
: ((Declaration declaration, T properties)?) null;
79+
}
80+
81+
protected virtual IInspectionResult InspectionResult(Declaration declaration, T properties)
82+
{
83+
return new DeclarationInspectionResult<T>(
84+
this,
85+
ResultDescription(declaration, properties),
86+
declaration,
87+
properties: properties,
88+
disabledQuickFixes: DisabledQuickFixes(declaration, properties));
89+
}
90+
}
91+
}
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
using System.Collections.Generic;
2+
using System.Linq;
3+
using Rubberduck.Parsing.Symbols;
4+
using Rubberduck.Parsing.VBA;
5+
using Rubberduck.Parsing.VBA.DeclarationCaching;
6+
using Rubberduck.VBEditor;
7+
8+
namespace Rubberduck.CodeAnalysis.Inspections.Abstract
9+
{
10+
/// <summary>
11+
/// This is a base class for the other declaration inspection base classes. It should not be implemented directly by concrete inspections.
12+
/// </summary>
13+
internal abstract class DeclarationInspectionBaseBase : InspectionBase
14+
{
15+
private readonly DeclarationType[] _relevantDeclarationTypes;
16+
private readonly DeclarationType[] _excludeDeclarationTypes;
17+
18+
protected DeclarationInspectionBaseBase(IDeclarationFinderProvider declarationFinderProvider, params DeclarationType[] relevantDeclarationTypes)
19+
: base(declarationFinderProvider)
20+
{
21+
_relevantDeclarationTypes = relevantDeclarationTypes;
22+
_excludeDeclarationTypes = new DeclarationType[0];
23+
}
24+
25+
protected DeclarationInspectionBaseBase(IDeclarationFinderProvider declarationFinderProvider, DeclarationType[] relevantDeclarationTypes, DeclarationType[] excludeDeclarationTypes)
26+
: base(declarationFinderProvider)
27+
{
28+
_relevantDeclarationTypes = relevantDeclarationTypes;
29+
_excludeDeclarationTypes = excludeDeclarationTypes;
30+
}
31+
32+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults(DeclarationFinder finder)
33+
{
34+
return finder.UserDeclarations(DeclarationType.Module)
35+
.Concat(finder.UserDeclarations(DeclarationType.Project))
36+
.Where(declaration => declaration != null)
37+
.SelectMany(declaration => DoGetInspectionResults(declaration.QualifiedModuleName, finder))
38+
.ToList();
39+
}
40+
41+
protected virtual IEnumerable<Declaration> RelevantDeclarationsInModule(QualifiedModuleName module, DeclarationFinder finder)
42+
{
43+
var potentiallyRelevantDeclarations = _relevantDeclarationTypes.Length == 0
44+
? finder.Members(module)
45+
: _relevantDeclarationTypes
46+
.SelectMany(declarationType => finder.Members(module, declarationType))
47+
.Distinct();
48+
return potentiallyRelevantDeclarations
49+
.Where(declaration => !_excludeDeclarationTypes.Contains(declaration.DeclarationType));
50+
}
51+
}
52+
}

0 commit comments

Comments
 (0)