From 617f16c63bcd524536b2073c7e29ccdb5a7b6abf Mon Sep 17 00:00:00 2001 From: Tom Helm Date: Sat, 27 Jan 2024 09:41:32 +0000 Subject: [PATCH 1/4] Fix for #6187, single line if must have something after the Then --- Rubberduck.Parsing/Grammar/VBAParser.g4 | 2 +- RubberduckTests/Grammar/VBAParserTests.cs | 14 ++++++++++++++ 2 files changed, 15 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Grammar/VBAParser.g4 b/Rubberduck.Parsing/Grammar/VBAParser.g4 index c968dccee9..9311ff9176 100644 --- a/Rubberduck.Parsing/Grammar/VBAParser.g4 +++ b/Rubberduck.Parsing/Grammar/VBAParser.g4 @@ -421,7 +421,7 @@ elseBlock : // 5.4.2.9 Single-line If Statement singleLineIfStmt : ifWithNonEmptyThen | ifWithEmptyThen; ifWithNonEmptyThen : IF whiteSpace? booleanExpression whiteSpace? THEN whiteSpace? listOrLabel (whiteSpace singleLineElseClause)?; -ifWithEmptyThen : IF whiteSpace? booleanExpression whiteSpace? THEN whiteSpace? emptyThenStatement? singleLineElseClause?; +ifWithEmptyThen : IF whiteSpace? booleanExpression whiteSpace? THEN whiteSpace? (emptyThenStatement singleLineElseClause? | singleLineElseClause); singleLineElseClause : ELSE whiteSpace? listOrLabel?; // lineNumberLabel should actually be "statement-label" according to MS VBAL but they only allow lineNumberLabels: diff --git a/RubberduckTests/Grammar/VBAParserTests.cs b/RubberduckTests/Grammar/VBAParserTests.cs index 5fb1c2320b..682734b760 100644 --- a/RubberduckTests/Grammar/VBAParserTests.cs +++ b/RubberduckTests/Grammar/VBAParserTests.cs @@ -4032,6 +4032,20 @@ public void ParserCanDealWithStatementSeparateorsInOneLineIfStatements(string on AssertTree(parseResult.Item1, parseResult.Item2, "//singleLineIfStmt", matches => matches.Count == 1); } + // Adapted from opened issue https://github.com/rubberduck-vba/Rubberduck/issues/6187 + [Test] + public void OneLineIfStatementNotMistakenForIfStatement() + { + string code = @" +Sub Test() + If True Then: A = 1 + If False Then + A = 5 + End If +End Sub"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//singleLineIfStmt", matches => matches.Count == 1); + } // Adapted from opened issue https://github.com/rubberduck-vba/Rubberduck/issues/4875 [Test] From 2d211245bdf81f6ba1120ed27e9b00fc4377054b Mon Sep 17 00:00:00 2001 From: Tom Helm Date: Sat, 27 Jan 2024 09:53:06 +0000 Subject: [PATCH 2/4] Fix for #6194, difference in VBA implementation to specification --- Rubberduck.Parsing/Grammar/VBAParser.g4 | 2 +- RubberduckTests/Grammar/VBAParserTests.cs | 12 ++++++++++++ 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/Grammar/VBAParser.g4 b/Rubberduck.Parsing/Grammar/VBAParser.g4 index 9311ff9176..3525d8f487 100644 --- a/Rubberduck.Parsing/Grammar/VBAParser.g4 +++ b/Rubberduck.Parsing/Grammar/VBAParser.g4 @@ -548,7 +548,7 @@ udtMemberList : (udtMember endOfStatement)+; udtMember : reservedNameMemberDeclaration | untypedNameMemberDeclaration; untypedNameMemberDeclaration : untypedIdentifier whiteSpace? optionalArrayClause; reservedNameMemberDeclaration : unrestrictedIdentifier whiteSpace asTypeClause; -optionalArrayClause : (arrayDim whiteSpace)? asTypeClause; +optionalArrayClause : ((arrayDim whiteSpace)? asTypeClause | arrayDim); // 5.2.3.1.3 Array Dimensions and Bounds arrayDim : LPAREN whiteSpace? boundsList? whiteSpace? RPAREN; diff --git a/RubberduckTests/Grammar/VBAParserTests.cs b/RubberduckTests/Grammar/VBAParserTests.cs index 682734b760..3e12be0ed3 100644 --- a/RubberduckTests/Grammar/VBAParserTests.cs +++ b/RubberduckTests/Grammar/VBAParserTests.cs @@ -4047,6 +4047,18 @@ End If AssertTree(parseResult.Item1, parseResult.Item2, "//singleLineIfStmt", matches => matches.Count == 1); } + // Adapted from opened issue https://github.com/rubberduck-vba/Rubberduck/issues/6194 + [Test] + public void UDTMemberCanHaveArrayWithoutType() + { + string code = @" +Type Test + A(0 To 2) +End Type"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//untypedNameMemberDeclaration", matches => matches.Count == 1); + } + // Adapted from opened issue https://github.com/rubberduck-vba/Rubberduck/issues/4875 [Test] [TestCase("form.Line (0, 0)-(12, 12), RGB(255, 255, 0), B")] From 411d825570e04a4bbe5bc378af875d48eb9761d1 Mon Sep 17 00:00:00 2001 From: Tom Helm Date: Sat, 27 Jan 2024 09:55:19 +0000 Subject: [PATCH 3/4] Add note to grammar about why UDT member rule deviates from VBA specification --- Rubberduck.Parsing/Grammar/VBAParser.g4 | 1 + 1 file changed, 1 insertion(+) diff --git a/Rubberduck.Parsing/Grammar/VBAParser.g4 b/Rubberduck.Parsing/Grammar/VBAParser.g4 index 3525d8f487..01c7efa0bb 100644 --- a/Rubberduck.Parsing/Grammar/VBAParser.g4 +++ b/Rubberduck.Parsing/Grammar/VBAParser.g4 @@ -543,6 +543,7 @@ subroutineName : identifier; // 5.2.3.3 User Defined Type Declarations // member list includes trailing endOfStatement +// To support actual VBA behaviour, had to change optionalArrayClause to allow a standalone arrayDim without the asTypeClause - see issue #6194 udtDeclaration : (visibility whiteSpace)? TYPE whiteSpace untypedIdentifier endOfStatement udtMemberList END_TYPE; udtMemberList : (udtMember endOfStatement)+; udtMember : reservedNameMemberDeclaration | untypedNameMemberDeclaration; From c7b7d38b7db7c20c9fc57112e9abee9450edf67e Mon Sep 17 00:00:00 2001 From: Tom Helm Date: Sat, 27 Jan 2024 21:16:37 +0000 Subject: [PATCH 4/4] Add null check to ifWithEmptyThen path, consistent with ifWithNonEmpthThen path --- .../VBA/ReferenceManagement/IdentifierReferenceResolver.cs | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Rubberduck.Parsing/VBA/ReferenceManagement/IdentifierReferenceResolver.cs b/Rubberduck.Parsing/VBA/ReferenceManagement/IdentifierReferenceResolver.cs index 85c822f548..c625cee9a1 100644 --- a/Rubberduck.Parsing/VBA/ReferenceManagement/IdentifierReferenceResolver.cs +++ b/Rubberduck.Parsing/VBA/ReferenceManagement/IdentifierReferenceResolver.cs @@ -321,7 +321,10 @@ public void Resolve(VBAParser.SingleLineIfStmtContext context) if (context.ifWithEmptyThen() != null) { ResolveDefault(context.ifWithEmptyThen().booleanExpression()); - ResolveListOrLabel(context.ifWithEmptyThen().singleLineElseClause().listOrLabel()); + if (context.ifWithEmptyThen().singleLineElseClause() != null) + { + ResolveListOrLabel(context.ifWithEmptyThen().singleLineElseClause().listOrLabel()); + } } else {