Skip to content

Commit 17a6d16

Browse files
authored
Merge pull request #2014 from Hosch250/Issues2012And2013
Prevent ctor throwing/create inspection for malformed annotations
2 parents b9febb8 + ea806a4 commit 17a6d16

File tree

12 files changed

+330
-32
lines changed

12 files changed

+330
-32
lines changed

RetailCoder.VBE/Inspections/IParseTreeInspection.cs

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
using Rubberduck.Parsing;
22
using System.Collections.Generic;
33
using System.Linq;
4+
using Rubberduck.Parsing.Grammar;
45

56
namespace Rubberduck.Inspections
67
{
@@ -17,11 +18,13 @@ public ParseTreeResults()
1718
ObsoleteLetContexts = Enumerable.Empty<QualifiedContext>();
1819
ArgListsWithOneByRefParam = Enumerable.Empty<QualifiedContext>();
1920
EmptyStringLiterals = Enumerable.Empty<QualifiedContext>();
21+
MalformedAnnotations = Enumerable.Empty<QualifiedContext<VBAParser.AnnotationContext>>();
2022
}
2123

2224
public IEnumerable<QualifiedContext> ObsoleteCallContexts;
2325
public IEnumerable<QualifiedContext> ObsoleteLetContexts;
2426
public IEnumerable<QualifiedContext> ArgListsWithOneByRefParam;
2527
public IEnumerable<QualifiedContext> EmptyStringLiterals;
28+
public IEnumerable<QualifiedContext<VBAParser.AnnotationContext>> MalformedAnnotations;
2629
}
2730
}

RetailCoder.VBE/Inspections/InspectionsUI.Designer.cs

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

RetailCoder.VBE/Inspections/InspectionsUI.resx

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
<?xml version="1.0" encoding="UTF-8"?>
1+
<?xml version="1.0" encoding="utf-8"?>
22
<root>
33
<!--
44
Microsoft ResX Schema
@@ -59,7 +59,7 @@
5959
: using a System.ComponentModel.TypeConverter
6060
: and then encoded with base64 encoding.
6161
-->
62-
<xsd:schema xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata" id="root">
62+
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
6363
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
6464
<xsd:element name="root" msdata:IsDataSet="true">
6565
<xsd:complexType>
@@ -555,4 +555,13 @@
555555
<data name="VariableTypeNotDeclaredInspectionResultFormat" xml:space="preserve">
556556
<value>{0} '{1}' is implicitly 'Variant'</value>
557557
</data>
558-
</root>
558+
<data name="MalformedAnnotationInspectionMeta" xml:space="preserve">
559+
<value>An annotation comment is malformed.</value>
560+
</data>
561+
<data name="MalformedAnnotationInspectionName" xml:space="preserve">
562+
<value>Malformed annotation.</value>
563+
</data>
564+
<data name="MalformedAnnotationInspectionResultFormat" xml:space="preserve">
565+
<value>The annotation '{0}' is malformed</value>
566+
</data>
567+
</root>

RetailCoder.VBE/Inspections/Inspector.cs

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
using Rubberduck.UI;
1010
using Antlr4.Runtime.Tree;
1111
using Rubberduck.Parsing;
12+
using Rubberduck.Parsing.Grammar;
1213

1314
namespace Rubberduck.Inspections
1415
{
@@ -78,7 +79,7 @@ public async Task<IEnumerable<ICodeInspectionResult>> FindIssuesAsync(Rubberduck
7879
{
7980
allIssues.Add(inspectionResult);
8081
}
81-
})).ToList();
82+
}, token)).ToList();
8283

8384
await Task.WhenAll(inspections);
8485
state.OnStatusMessageUpdate(RubberduckUI.ResourceManager.GetString("ParserState_" + state.Status, UI.Settings.Settings.Culture)); // should be "Ready"
@@ -99,12 +100,14 @@ before moving them into the ParseTreeResults after qualifying them
99100
var obsoleteLetStatementListener = new ObsoleteLetStatementInspection.ObsoleteLetStatementListener();
100101
var emptyStringLiteralListener = new EmptyStringLiteralInspection.EmptyStringLiteralListener();
101102
var argListWithOneByRefParamListener = new ProcedureCanBeWrittenAsFunctionInspection.ArgListWithOneByRefParamListener();
103+
var malformedAnnotationListenter = new MalformedAnnotationInspection.MalformedAnnotationStatementListener();
102104

103105
var combinedListener = new CombinedParseTreeListener(new IParseTreeListener[]{
104106
obsoleteCallStatementListener,
105107
obsoleteLetStatementListener,
106108
emptyStringLiteralListener,
107109
argListWithOneByRefParamListener,
110+
malformedAnnotationListenter
108111
});
109112

110113
ParseTreeWalker.Default.Walk(combinedListener, componentTreePair.Value);
@@ -113,6 +116,7 @@ before moving them into the ParseTreeResults after qualifying them
113116
result.EmptyStringLiterals = result.EmptyStringLiterals.Concat(emptyStringLiteralListener.Contexts.Select(context => new QualifiedContext(componentTreePair.Key, context)));
114117
result.ObsoleteLetContexts = result.ObsoleteLetContexts.Concat(obsoleteLetStatementListener.Contexts.Select(context => new QualifiedContext(componentTreePair.Key, context)));
115118
result.ObsoleteCallContexts = result.ObsoleteCallContexts.Concat(obsoleteCallStatementListener.Contexts.Select(context => new QualifiedContext(componentTreePair.Key, context)));
119+
result.MalformedAnnotations = result.MalformedAnnotations.Concat(malformedAnnotationListenter.Contexts.Select(context => new QualifiedContext<VBAParser.AnnotationContext>(componentTreePair.Key, context)));
116120
}
117121
return result;
118122
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
using System.Collections.Generic;
2+
using Rubberduck.Parsing;
3+
using Rubberduck.Parsing.Annotations;
4+
using Rubberduck.Parsing.VBA;
5+
using Rubberduck.Parsing.Grammar;
6+
7+
namespace Rubberduck.Inspections
8+
{
9+
public sealed class MalformedAnnotationInspection : InspectionBase, IParseTreeInspection
10+
{
11+
public MalformedAnnotationInspection(RubberduckParserState state)
12+
: base(state, CodeInspectionSeverity.Error)
13+
{
14+
}
15+
16+
public override string Meta { get { return InspectionsUI.MalformedAnnotationInspectionMeta; } }
17+
public override string Description { get { return InspectionsUI.MalformedAnnotationInspectionResultFormat; } }
18+
public override CodeInspectionType InspectionType { get { return CodeInspectionType.CodeQualityIssues; } }
19+
public ParseTreeResults ParseTreeResults { get; set; }
20+
21+
public override IEnumerable<InspectionResultBase> GetInspectionResults()
22+
{
23+
if (ParseTreeResults == null)
24+
{
25+
return new InspectionResultBase[] { };
26+
}
27+
28+
var results = new List<MalformedAnnotationInspectionResult>();
29+
30+
foreach (var context in ParseTreeResults.MalformedAnnotations)
31+
{
32+
if (context.Context.annotationName().GetText() == AnnotationType.Ignore.ToString() ||
33+
context.Context.annotationName().GetText() == AnnotationType.Folder.ToString())
34+
{
35+
if (context.Context.annotationArgList() == null)
36+
{
37+
results.Add(new MalformedAnnotationInspectionResult(this,
38+
new QualifiedContext<VBAParser.AnnotationContext>(context.ModuleName,
39+
context.Context)));
40+
}
41+
}
42+
}
43+
44+
return results;
45+
}
46+
47+
public class MalformedAnnotationStatementListener : VBAParserBaseListener
48+
{
49+
private readonly IList<VBAParser.AnnotationContext> _contexts = new List<VBAParser.AnnotationContext>();
50+
public IEnumerable<VBAParser.AnnotationContext> Contexts { get { return _contexts; } }
51+
52+
public override void ExitAnnotation(VBAParser.AnnotationContext context)
53+
{
54+
if (context.annotationName() != null)
55+
{
56+
_contexts.Add(context);
57+
}
58+
}
59+
}
60+
}
61+
62+
public class MalformedAnnotationInspectionResult : InspectionResultBase
63+
{
64+
public MalformedAnnotationInspectionResult(IInspection inspection, QualifiedContext<VBAParser.AnnotationContext> qualifiedContext)
65+
: base(inspection, qualifiedContext.ModuleName, qualifiedContext.Context)
66+
{
67+
}
68+
69+
public override string Description
70+
{
71+
get { return string.Format(Inspection.Description, ((VBAParser.AnnotationContext)Context).annotationName()); }
72+
}
73+
}
74+
}

RetailCoder.VBE/Properties/AssemblyInfo.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -31,5 +31,5 @@
3131
// You can specify all the values or you can default the Build and Revision Numbers
3232
// by using the '*' as shown below:
3333
// [assembly: AssemblyVersion("1.0.*")]
34-
[assembly: AssemblyVersion("2.0.4.*")]
35-
[assembly: AssemblyFileVersion("2.0.4.0")]
34+
[assembly: AssemblyVersion("2.0.5.*")]
35+
[assembly: AssemblyFileVersion("2.0.5.0")]

RetailCoder.VBE/Rubberduck.csproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -376,6 +376,7 @@
376376
</Compile>
377377
<Compile Include="Inspections\IParseTreeInspection.cs" />
378378
<Compile Include="Inspections\MakeSingleLineParameterQuickFix.cs" />
379+
<Compile Include="Inspections\MalformedAnnotationInspection.cs" />
379380
<Compile Include="Inspections\ObjectVariableNotSetInspection.cs" />
380381
<Compile Include="Inspections\RemoveExplicitCallStatmentQuickFix.cs" />
381382
<Compile Include="Navigation\CodeExplorer\ICodeExplorerDeclarationViewModel.cs" />

Rubberduck.Parsing/Annotations/FolderAnnotation.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ public FolderAnnotation(
1313
IEnumerable<string> parameters)
1414
: base(AnnotationType.Folder, qualifiedSelection)
1515
{
16-
if (parameters.Count() != 1)
17-
{
18-
throw new InvalidAnnotationArgumentException(string.Format("{0} expects exactly one argument, the folder, but none or more than one were passed.", this.GetType().Name));
19-
}
20-
_folderName = parameters.First();
16+
_folderName = parameters.FirstOrDefault() ?? string.Empty;
2117
}
2218

2319
public string FolderName

Rubberduck.Parsing/Annotations/IgnoreAnnotation.cs

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -13,11 +13,7 @@ public IgnoreAnnotation(
1313
IEnumerable<string> parameters)
1414
: base(AnnotationType.Ignore, qualifiedSelection)
1515
{
16-
if (!parameters.Any())
17-
{
18-
throw new InvalidAnnotationArgumentException(string.Format("{0} expects at least one argument but none were given.", this.GetType().Name));
19-
}
20-
_inspectionNames = parameters.ToList();
16+
_inspectionNames = parameters;
2117
}
2218

2319
public IEnumerable<string> InspectionNames

RubberduckTests/Grammar/AnnotationTests.cs

Lines changed: 1 addition & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
1-
using System.Collections.Generic;
2-
using Microsoft.VisualStudio.TestTools.UnitTesting;
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
32
using Rubberduck.Parsing.Annotations;
43
using Rubberduck.VBEditor;
54

@@ -57,20 +56,6 @@ public void IgnoreTestAnnotation_TypeIsIgnoreTest()
5756
Assert.AreEqual(AnnotationType.IgnoreTest, annotation.AnnotationType);
5857
}
5958

60-
[TestMethod, ExpectedException(typeof(InvalidAnnotationArgumentException))]
61-
public void IgnoreAnnotation_TypeIsIgnore_NoParam()
62-
{
63-
var annotation = new IgnoreAnnotation(new QualifiedSelection(), new List<string>());
64-
Assert.AreEqual(AnnotationType.Ignore, annotation.AnnotationType);
65-
}
66-
67-
[TestMethod, ExpectedException(typeof(InvalidAnnotationArgumentException))]
68-
public void FolderAnnotation_TypeIsFolder_NoParam()
69-
{
70-
var annotation = new FolderAnnotation(new QualifiedSelection(), new List<string>());
71-
Assert.AreEqual(AnnotationType.Folder, annotation.AnnotationType);
72-
}
73-
7459
[TestMethod]
7560
public void IgnoreAnnotation_TypeIsIgnore()
7661
{

0 commit comments

Comments
 (0)