diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs index 7a2aa9e0bb..2dbddde0e2 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/MemberNotOnInterfaceInspection.cs @@ -2,6 +2,7 @@ using System.Linq; using Rubberduck.Inspections.Abstract; using Rubberduck.Inspections.Results; +using Rubberduck.Parsing.Grammar; using Rubberduck.Parsing.Inspections.Abstract; using Rubberduck.Resources.Inspections; using Rubberduck.Parsing.Symbols; @@ -23,12 +24,19 @@ protected override IEnumerable DoGetInspectionResults() decl.AsTypeDeclaration.DeclarationType.HasFlag(DeclarationType.ClassModule) && ((ClassModuleDeclaration)decl.AsTypeDeclaration).IsExtensible) .SelectMany(decl => decl.References).ToList(); - return from access in unresolved - let callingContext = targets.FirstOrDefault(usage => usage.Context.Equals(access.CallingContext)) - where callingContext != null - select new DeclarationInspectionResult(this, - string.Format(InspectionResults.MemberNotOnInterfaceInspection, access.IdentifierName, callingContext.Declaration.AsTypeDeclaration.IdentifierName), - access); + return unresolved + .Select(access => new + { + access, + callingContext = targets.FirstOrDefault(usage => usage.Context.Equals(access.CallingContext) + || (access.CallingContext is VBAParser.NewExprContext && + usage.Context.Parent.Parent.Equals(access.CallingContext)) + ) + }) + .Where(memberAccess => memberAccess.callingContext != null) + .Select(memberAccess => new DeclarationInspectionResult(this, + string.Format(InspectionResults.MemberNotOnInterfaceInspection, memberAccess.access.IdentifierName, + memberAccess.callingContext.Declaration.AsTypeDeclaration.IdentifierName), memberAccess.access)); } } } diff --git a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs index befdc8b149..5d53b51a07 100644 --- a/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs +++ b/Rubberduck.CodeAnalysis/Inspections/Concrete/ParameterCanBeByValInspection.cs @@ -1,4 +1,5 @@ using System.Collections.Generic; +using System.Diagnostics; using System.Linq; using Rubberduck.Common; using Rubberduck.Inspections.Abstract; @@ -91,6 +92,9 @@ private IEnumerable GetResults(Declaration[] declarations, De for (var i = 0; i < parameters.Count; i++) { + //If you hit this assert, congratulations! you've found a test case for https://github.com/rubberduck-vba/Rubberduck/issues/3906 + //Please examine the code, and if possible, either fix the indexing on this or upload your failing code to the GitHub issue. + Debug.Assert(parametersAreByRef.Count == parameters.Count); parametersAreByRef[i] = parametersAreByRef[i] && !IsUsedAsByRefParam(declarations, parameters[i]) && ((VBAParser.ArgContext) parameters[i].Context).BYVAL() == null && diff --git a/Rubberduck.Parsing/Grammar/VBALexer.g4 b/Rubberduck.Parsing/Grammar/VBALexer.g4 index 6bb3d31455..d99f6d5e55 100644 --- a/Rubberduck.Parsing/Grammar/VBALexer.g4 +++ b/Rubberduck.Parsing/Grammar/VBALexer.g4 @@ -301,9 +301,14 @@ UNDERSCORE : '_'; WS : [ \t]; GUIDLITERAL : '{' [0-9A-F]+ '-' [0-9A-F]+ '-' [0-9A-F]+ '-' [0-9A-F]+ '-' [0-9A-F]+ '}'; IDENTIFIER : ~[[\](){}\r\n\t.,'"|!@#$%^&*\-+:=; 0-9-/\\-] ~[[\](){}\r\n\t.,'"|!@#$%^&*\-+:=; -]*; -LINE_CONTINUATION : [ \t]* UNDERSCORE [ \t]* '\r'? '\n'; +LINE_CONTINUATION : [ \t]+ UNDERSCORE [ \t]* '\r'? '\n' WS_NOT_FOLLOWED_BY_LINE_CONTINUATION*; // The following rule is needed in order to capture hex literals without format prefixes which start with a digit. Needed for VBForm resources. -BARE_HEX_LITERAL : [0-9] [0-9a-fA-F]*; +BARE_HEX_LITERAL : [0-9] [0-9a-fA-F]*; +fragment WS_NOT_FOLLOWED_BY_LINE_CONTINUATION : [ \t] {(char)_input.La(1) != '_' + || ((char)_input.La(2) != '\r' + && (char)_input.La(2) != '\n' + && (char)_input.La(2) != '\t' + && (char)_input.La(2) != ' ')}?; fragment LETTER : [a-zA-Z_äöüÄÖÜ]; fragment DIGIT : [0-9]; fragment LETTERORDIGIT : [a-zA-Z0-9_äöüÄÖÜ]; diff --git a/Rubberduck.Parsing/Grammar/VBAParser.g4 b/Rubberduck.Parsing/Grammar/VBAParser.g4 index 81f2820a22..76f86533de 100644 --- a/Rubberduck.Parsing/Grammar/VBAParser.g4 +++ b/Rubberduck.Parsing/Grammar/VBAParser.g4 @@ -601,7 +601,7 @@ complexType : fieldLength : MULT whiteSpace? (numberLiteral | identifierValue); //Statement labels can only appear at the start of a line. -statementLabelDefinition : {_input.La(-1) == NEWLINE}? (combinedLabels | identifierStatementLabel | standaloneLineNumberLabel); +statementLabelDefinition : {_input.La(-1) == NEWLINE || _input.La(-1) == LINE_CONTINUATION}? (combinedLabels | identifierStatementLabel | standaloneLineNumberLabel); identifierStatementLabel : legalLabelIdentifier whiteSpace? COLON; standaloneLineNumberLabel : lineNumberLabel whiteSpace? COLON diff --git a/Rubberduck.sln b/Rubberduck.sln index 5024818f98..6fa3b0b7c6 100644 --- a/Rubberduck.sln +++ b/Rubberduck.sln @@ -55,6 +55,9 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.RegexAssistant", EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.CodeAnalysis", "Rubberduck.CodeAnalysis\Rubberduck.CodeAnalysis.csproj", "{DEF2FB9D-6E62-49D6-8E26-9983AC025768}" + ProjectSection(ProjectDependencies) = postProject + {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} = {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.Main", "Rubberduck.Main\Rubberduck.Main.csproj", "{E8AB5D93-2D0F-423D-BC15-5EE118673E48}" ProjectSection(ProjectDependencies) = postProject @@ -96,10 +99,19 @@ EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "RubberduckTestsCodeAnalysis", "RubberduckTestsCodeAnalysis\RubberduckTestsCodeAnalysis.csproj", "{E9FC6518-F9E8-4E57-BD28-583A9EA69297}" EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.Resources", "Rubberduck.Resources\Rubberduck.Resources.csproj", "{1B84B387-F7C4-4876-9BDF-C644C365359A}" + ProjectSection(ProjectDependencies) = postProject + {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} = {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.Refactorings", "Rubberduck.Refactorings\Rubberduck.Refactorings.csproj", "{D4B6A510-14E1-420A-A8D5-6A09890FD7D8}" + ProjectSection(ProjectDependencies) = postProject + {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} = {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} + EndProjectSection EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Rubberduck.Interaction", "Rubberduck.Interaction\Rubberduck.Interaction.csproj", "{AC54B7FB-170D-4DA6-A30B-8CAD182F0E6B}" + ProjectSection(ProjectDependencies) = postProject + {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} = {F83B6746-49A6-4CFD-9A29-3D7BBD4F0323} + EndProjectSection EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution diff --git a/RubberduckTests/Grammar/VBAParserTests.cs b/RubberduckTests/Grammar/VBAParserTests.cs index 75938d879a..6a32823fdb 100644 --- a/RubberduckTests/Grammar/VBAParserTests.cs +++ b/RubberduckTests/Grammar/VBAParserTests.cs @@ -550,7 +550,7 @@ public void TestTrivialCase() public void TestEmptyModule() { string code = @" -_ + _ _ @@ -1748,7 +1748,7 @@ Sub Test() a = m + n + c + d For k = 0 To 100 t = a + k - Next k, d, m,_ + Next k, d, m, _ c, _ n End Sub"; @@ -2813,6 +2813,290 @@ End Sub AssertTree(parseResult.Item1, parseResult.Item2, "//argumentList", matches => matches.Count == 2); } + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnUnderscoreComment() + { + const string code = @" +Sub Test() + '_ + If True Then + End If +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//ifStmt", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnUnderscoreAfterNonBreakingSpaceInComment() + { + const string code = @" +Sub Test() + '" + "\u00A0" + @"_ + If True Then + End If +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//ifStmt", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnStartOfLineUnderscoreInLineContinuedComment() + { + const string code = @" +Sub Test() + ' _ +_ + If True Then + End If +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//ifStmt", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedMemberAccessExpressionInType1() + { + const string code = @" +Sub Test() +Dim dic2 As _ +Scripting _ +. _ +Dictionary +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedMemberAccessExpressionInType2() + { + const string code = @" +Sub Test() + Dim dic3 As Scripting _ + . _ + Dictionary +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedMemberAccessExpressionOnObject1() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + + Debug.Print dict. _ + Item(""a"") +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedMemberAccessExpressionOnObject2() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + +Debug.Print dict _ +. _ +Item(""a"") +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedMemberAccessExpressionOnObject3() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + +Debug.Print dict _ + . _ +Item(""a"") +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedBangOperator1() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + +Dim x +x = dict _ +! _ +a +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedBangOperator2() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + +Dim x +x = dict _ + ! _ + a + +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedBangOperator3() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + +Dim x +x = dict _ +!a +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineContinuedTypeDeclaration() + { + const string code = @" +Sub Test() +Dim dic1 As _ +Dictionary +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnIdentifierEndingInUnderscore() + { + const string code = @" +Sub Test() +Dim dict As Scripting.Dictionary + +Dim x_ +End Sub +"; + var parseResult = Parse(code); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineNumberNotOnStartOfLineAfterALineContinuation() + { + const string code = @" +Sub foo() + _ + 10 + _ +Beep +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//standaloneLineNumberLabel", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineLAbelNotOnStartOfLineAfterALineContinuation() + { + const string code = @" +Sub foo() + _ + foo: Beep +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//identifierStatementLabel", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLinecontinuedLabel() + { + const string code = @" +Sub foo() +foo _ +: Beep +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//identifierStatementLabel", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineNumberAndLineContinuedLabelNotOnStartOfLineAfterALineContinuation() + { + const string code = @" +Sub foo() + _ + 10 + _ + foo _ + : Beeb +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//standaloneLineNumberLabel", matches => matches.Count == 1); + AssertTree(parseResult.Item1, parseResult.Item2, "//identifierStatementLabel", matches => matches.Count == 1); + } + + [Category("Parser")] + [Test] + public void ParserDoesNotFailOnLineNumberAndLineContinuedLabelNotOnStartOfLineAfterMultipleLineContinuation() + { + const string code = @" +Sub foo() + _ + _ + _ + 10 + _ + _ + _ + foo _ + : Beeb +End Sub +"; + var parseResult = Parse(code); + AssertTree(parseResult.Item1, parseResult.Item2, "//standaloneLineNumberLabel", matches => matches.Count == 1); + AssertTree(parseResult.Item1, parseResult.Item2, "//identifierStatementLabel", matches => matches.Count == 1); + } + [Category("Parser")] [Test] public void LeftOutOptionalArgumentsAreCountedAsMissingArguments() diff --git a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs index fefcb79958..65e4885c54 100644 --- a/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs +++ b/RubberduckTests/Inspections/MemberNotOnInterfaceInspectionTests.cs @@ -255,6 +255,66 @@ public void MemberNotOnInterface_Ignored_DoesNotReturnResult() } } + [Test] + [Category("Inspections")] + public void MemberNotOnInterface_WithNewReturnsResult() + { + const string inputCode = + @"Sub Foo() + With New Dictionary + Debug.Print .FooBar + End With +End Sub"; + + using (var state = ArrangeParserAndParse(inputCode)) + { + var inspection = new MemberNotOnInterfaceInspection(state); + var inspectionResults = inspection.GetInspectionResults(CancellationToken.None); + + Assert.AreEqual(1, inspectionResults.Count()); + } + } + + [Test] + [Category("Inspections")] + public void MemberNotOnInterface_DoesNotReturnResult_WithNewBlockBangNotation() + { + const string inputCode = + @"Sub Foo() + With New Dictionary + !FooBar = 42 + End With +End Sub"; + + using (var state = ArrangeParserAndParse(inputCode)) + { + var inspection = new MemberNotOnInterfaceInspection(state); + var inspectionResults = inspection.GetInspectionResults(CancellationToken.None); + + Assert.IsFalse(inspectionResults.Any()); + } + } + + [Test] + [Category("Inspections")] + public void MemberNotOnInterface_DoesNotReturnResult_WithNewBlockOnInterface() + { + const string inputCode = + @"Sub Foo() + With New Dictionary + .Add 42, 42 + End With +End Sub"; + + using (var state = ArrangeParserAndParse(inputCode)) + { + var inspection = new MemberNotOnInterfaceInspection(state); + var inspectionResults = inspection.GetInspectionResults(CancellationToken.None); + + Assert.IsFalse(inspectionResults.Any()); + } + } + [Test] [Category("Inspections")] public void MemberNotOnInterface_CatchesInvalidUseOfMember() diff --git a/RubberduckTests/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFixTests.cs b/RubberduckTests/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFixTests.cs index 88fc587cc5..1c298ee576 100644 --- a/RubberduckTests/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/AssignedByValParameterMakeLocalCopyQuickFixTests.cs @@ -145,7 +145,7 @@ End Property public void AssignedByValParameter_LocalVariableAssignment_ComplexFormat() { var inputCode = - @"Sub DoSomething(_ + @"Sub DoSomething( _ ByVal foo As Long, _ ByRef _ bar, _ @@ -157,7 +157,7 @@ ByRef _ End Sub "; var expectedCode = - @"Sub DoSomething(_ + @"Sub DoSomething( _ ByVal foo As Long, _ ByRef _ bar, _ diff --git a/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs b/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs index 4f6290a8ea..bc014e453d 100644 --- a/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs +++ b/RubberduckTests/QuickFixes/PassParameterByReferenceQuickFixTests.cs @@ -1,12 +1,9 @@ -using System.Collections.Generic; using System.Linq; using System.Threading; using NUnit.Framework; using Moq; using Rubberduck.Inspections.Concrete; using Rubberduck.Inspections.QuickFixes; -using Rubberduck.Parsing.Inspections.Abstract; -using Rubberduck.Parsing.VBA; using Rubberduck.VBEditor.SafeComWrappers.Abstract; using RubberduckTests.Mocks; @@ -21,32 +18,41 @@ public void AssignedByValParameter_PassByReferenceQuickFixWorks() { string inputCode = -@"Public Sub Foo(Optional ByVal barByVal As String = ""XYZ"") + @"Public Sub Foo(Optional ByVal barByVal As String = ""XYZ"") Let barByVal = ""test"" End Sub"; string expectedCode = -@"Public Sub Foo(Optional ByRef barByVal As String = ""XYZ"") + @"Public Sub Foo(Optional ByRef barByVal As String = ""XYZ"") Let barByVal = ""test"" End Sub"; var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); + } - //check when ByVal argument is one of several parameters - inputCode = -@"Public Sub Foo(ByRef firstArg As Long, Optional ByVal barByVal As String = """", secondArg as Double) + [Test] + [Category("QuickFixes")] + public void AssignedByValParameter_PassByReferenceQuickFixWorks_ByValParameterIsOneOfSeveral() + { + var inputCode = + @"Public Sub Foo(ByRef firstArg As Long, Optional ByVal barByVal As String = """", secondArg as Double) Let barByVal = ""test"" End Sub"; - expectedCode = -@"Public Sub Foo(ByRef firstArg As Long, Optional ByRef barByVal As String = """", secondArg as Double) + var expectedCode = + @"Public Sub Foo(ByRef firstArg As Long, Optional ByRef barByVal As String = """", secondArg as Double) Let barByVal = ""test"" End Sub"; - quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); + var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); - //AppleWatch IDE test - inputCode = -@" + } + + [Test] + [Category("QuickFixes")] + public void AssignedByValParameter_PassByReferenceQuickFixWorks_LineContinued1() + { + var inputCode = + @" Private Sub Foo(Optional ByVal _ bar _ As _ @@ -58,9 +64,9 @@ As _ bar = 42 End Sub " -; - expectedCode = -@" + ; + var expectedCode = + @" Private Sub Foo(Optional ByRef _ bar _ As _ @@ -72,20 +78,25 @@ As _ bar = 42 End Sub " -; - quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); + ; + var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); + } - inputCode = -@"Private Sub Foo(ByVal barByVal As Long, ByVal _xByValbar As Long, ByVal _ + [Test] + [Category("QuickFixes")] + public void AssignedByValParameter_PassByReferenceQuickFixWorks_LineContinued2() + { + var inputCode = + @"Private Sub Foo(ByVal barByVal As Long, ByVal _xByValbar As Long, ByVal _ barTwo _ As _ Long) barTwo = 42 End Sub "; - expectedCode = -@"Private Sub Foo(ByVal barByVal As Long, ByVal _xByValbar As Long, ByRef _ + var expectedCode = + @"Private Sub Foo(ByVal barByVal As Long, ByVal _xByValbar As Long, ByRef _ barTwo _ As _ Long) @@ -93,19 +104,24 @@ As _ End Sub "; - quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); + var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); + } - inputCode = -@"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByVal _ + [Test] + [Category("QuickFixes")] + public void AssignedByValParameter_PassByReferenceQuickFixWorks_LineContinued3() + { + var inputCode = + @"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByVal _ barTwo _ As _ Long) barTwo = 42 End Sub "; - expectedCode = -@"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByRef _ + var expectedCode = + @"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByRef _ barTwo _ As _ Long) @@ -113,29 +129,41 @@ As _ End Sub "; - quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); + var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); + } - inputCode = -@"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByVal barTwo _ + [Test] + [Category("QuickFixes")] + public void AssignedByValParameter_PassByReferenceQuickFixWorks_LineContinued4() + { + var inputCode = + @"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByVal barTwo _ As _ Long) barTwo = 42 End Sub "; - expectedCode = -@"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByRef barTwo _ + var expectedCode = + @"Private Sub Foo(ByVal barByVal As Long, ByVal barTwoon As Long, ByRef barTwo _ As _ Long) barTwo = 42 End Sub "; - quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); + + var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); + } + + [Test] + [Category("QuickFixes")] + public void AssignedByValParameter_PassByReferenceQuickFixWorks_LineContinued5() + { //weaponized code test - inputCode = -@"Sub DoSomething(_ + var inputCode = +@"Sub DoSomething( _ ByVal foo As Long, _ ByRef _ bar, _ @@ -147,8 +175,8 @@ ByRef _ End Sub "; - expectedCode = -@"Sub DoSomething(_ + var expectedCode = +@"Sub DoSomething( _ ByRef foo As Long, _ ByRef _ bar, _ @@ -159,7 +187,7 @@ ByRef _ bar + foo / barbecue End Sub "; - quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); + var quickFixResult = ApplyPassParameterByReferenceQuickFixToVBAFragment(inputCode); Assert.AreEqual(expectedCode, quickFixResult); }