Skip to content

Commit fb0f9b7

Browse files
authored
Merge pull request #4488 from comintern/validref
Add new inspection for Excel UDFs hidden by cells.
2 parents 83e94b2 + 3643c7e commit fb0f9b7

14 files changed

+799
-921
lines changed
Lines changed: 49 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text.RegularExpressions;
5+
using Rubberduck.Inspections.Abstract;
6+
using Rubberduck.Inspections.Results;
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+
13+
namespace Rubberduck.Inspections.Inspections.Concrete
14+
{
15+
[RequiredLibrary("Excel")]
16+
public class ExcelUdfNameIsValidCellReferenceInspection : InspectionBase
17+
{
18+
public ExcelUdfNameIsValidCellReferenceInspection(RubberduckParserState state) : base(state) { }
19+
20+
private static readonly Regex ValidCellIdRegex =
21+
new Regex(@"^([a-z]|[a-z]{2}|[a-w][a-z]{2}|x([a-e][a-z]|f[a-d]))(?<Row>\d+)$",
22+
RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.ExplicitCapture);
23+
24+
private static readonly HashSet<Accessibility> VisibleAsUdf = new HashSet<Accessibility> { Accessibility.Public, Accessibility.Implicit };
25+
26+
private const uint MaximumExcelRows = 1048576;
27+
28+
protected override IEnumerable<IInspectionResult> DoGetInspectionResults()
29+
{
30+
var excel = State.DeclarationFinder.Projects.SingleOrDefault(item => !item.IsUserDefined && item.IdentifierName == "Excel");
31+
if (excel == null)
32+
{
33+
return Enumerable.Empty<IInspectionResult>();
34+
}
35+
36+
var candidates = UserDeclarations.OfType<FunctionDeclaration>().Where(decl =>
37+
decl.ParentScopeDeclaration.DeclarationType == DeclarationType.ProceduralModule &&
38+
VisibleAsUdf.Contains(decl.Accessibility));
39+
40+
return (from function in candidates.Where(decl => ValidCellIdRegex.IsMatch(decl.IdentifierName))
41+
let row = Convert.ToUInt32(ValidCellIdRegex.Matches(function.IdentifierName)[0].Groups["Row"].Value)
42+
where row > 0 && row <= MaximumExcelRows && !IsIgnoringInspectionResultFor(function, AnnotationName)
43+
select new DeclarationInspectionResult(this,
44+
string.Format(InspectionResults.ExcelUdfNameIsValidCellReferenceInspection, function.IdentifierName),
45+
function))
46+
.Cast<IInspectionResult>().ToList();
47+
}
48+
}
49+
}

Rubberduck.CodeAnalysis/QuickFixes/RenameDeclarationQuickFix.cs

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using System.Globalization;
22
using Rubberduck.Inspections.Abstract;
33
using Rubberduck.Inspections.Concrete;
4+
using Rubberduck.Inspections.Inspections.Concrete;
45
using Rubberduck.Interaction;
56
using Rubberduck.Parsing.Inspections.Abstract;
67
using Rubberduck.Parsing.Rewriter;
@@ -20,7 +21,11 @@ public sealed class RenameDeclarationQuickFix : QuickFixBase
2021
private readonly IMessageBox _messageBox;
2122

2223
public RenameDeclarationQuickFix(IVBE vbe, RubberduckParserState state, IMessageBox messageBox, IRewritingManager rewritingManager)
23-
: base(typeof(HungarianNotationInspection), typeof(UseMeaningfulNameInspection), typeof(DefaultProjectNameInspection), typeof(UnderscoreInPublicClassModuleMemberInspection))
24+
: base(typeof(HungarianNotationInspection),
25+
typeof(UseMeaningfulNameInspection),
26+
typeof(DefaultProjectNameInspection),
27+
typeof(UnderscoreInPublicClassModuleMemberInspection),
28+
typeof(ExcelUdfNameIsValidCellReferenceInspection))
2429
{
2530
_vbe = vbe;
2631
_state = state;

Rubberduck.Core/Properties/Settings.Designer.cs

Lines changed: 300 additions & 285 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Core/Properties/Settings.settings

Lines changed: 257 additions & 236 deletions
Large diffs are not rendered by default.

Rubberduck.Core/Rubberduck.Core.csproj

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -81,4 +81,17 @@
8181
<Version>2.0.20525</Version>
8282
</PackageReference>
8383
</ItemGroup>
84+
<ItemGroup>
85+
<Compile Update="Properties\Settings.Designer.cs">
86+
<DesignTime>True</DesignTime>
87+
<AutoGen>True</AutoGen>
88+
<DependentUpon>Settings.settings</DependentUpon>
89+
</Compile>
90+
</ItemGroup>
91+
<ItemGroup>
92+
<None Update="Properties\Settings.settings">
93+
<Generator>SettingsSingleFileGenerator</Generator>
94+
<LastGenOutput>Settings.Designer.cs</LastGenOutput>
95+
</None>
96+
</ItemGroup>
8497
</Project>

Rubberduck.Core/app.config

Lines changed: 0 additions & 399 deletions
Large diffs are not rendered by default.

Rubberduck.Resources/Inspections/InspectionInfo.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/Inspections/InspectionInfo.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -355,4 +355,7 @@ If the parameter can be null, ignore this inspection result; passing a null valu
355355
<data name="ExcelMemberMayReturnNothingInspection" xml:space="preserve">
356356
<value>A procedure that returns an object may return 'Nothing'. That will cause a runtime error 91 - "Object variable or With block variable not set" on subsequent member access. Perform an 'Is Nothing' check after the 'Set' assignment to guard against runtime errors.</value>
357357
</data>
358+
<data name="ExcelUdfNameIsValidCellReferenceInspection" xml:space="preserve">
359+
<value>Functions that are visible to Excel as User-Defined Functions will return a '#REF' error when used on a Worksheet if they match the name of a valid cell reference. If the function is intended to be used as a UDF, it must be renamed. If the function is not intended to be used as a UDF, it should be scoped as 'Private' or moved out of a standard Module.</value>
360+
</data>
358361
</root>

Rubberduck.Resources/Inspections/InspectionNames.Designer.cs

Lines changed: 9 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Rubberduck.Resources/Inspections/InspectionNames.resx

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -354,4 +354,7 @@
354354
<data name="ExcelMemberMayReturnNothingInspection" xml:space="preserve">
355355
<value>Member access may return 'Nothing'</value>
356356
</data>
357+
<data name="ExcelUdfNameIsValidCellReferenceInspection" xml:space="preserve">
358+
<value>Function is hidden by Excel cell reference</value>
359+
</data>
357360
</root>

0 commit comments

Comments
 (0)