Skip to content

Commit 4c4a4d8

Browse files
committed
Mark Line Input, Input, and Get references as assignments
1 parent bbf7eed commit 4c4a4d8

File tree

3 files changed

+146
-5
lines changed

3 files changed

+146
-5
lines changed

Rubberduck.Parsing/Symbols/IdentifierReferenceResolver.cs

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -163,7 +163,7 @@ private void ResolveDefault(
163163
"Default Context: Failed to resolve {0}. Binding as much as we can.",
164164
expression.GetText()));
165165
}
166-
_boundExpressionVisitor.AddIdentifierReferences(boundExpression, _qualifiedModuleName, _currentScope, _currentParent, isAssignmentTarget, false);
166+
_boundExpressionVisitor.AddIdentifierReferences(boundExpression, _qualifiedModuleName, _currentScope, _currentParent, isAssignmentTarget, hasExplicitLetStatement);
167167
}
168168

169169
private void ResolveType(ParserRuleContext expression)
@@ -444,7 +444,7 @@ private void ResolveRecordRange(VBAParser.RecordRangeContext recordRange)
444444
public void Resolve(VBAParser.LineInputStmtContext context)
445445
{
446446
ResolveDefault(context.markedFileNumber().expression());
447-
ResolveDefault(context.variableName().expression());
447+
ResolveDefault(context.variableName().expression(), isAssignmentTarget: true);
448448
}
449449

450450
public void Resolve(VBAParser.WidthStmtContext context)
@@ -496,7 +496,7 @@ public void Resolve(VBAParser.InputStmtContext context)
496496
ResolveDefault(context.markedFileNumber().expression());
497497
foreach (var inputVariable in context.inputList().inputVariable())
498498
{
499-
ResolveDefault(inputVariable.expression());
499+
ResolveDefault(inputVariable.expression(), isAssignmentTarget: true);
500500
}
501501
}
502502

@@ -522,7 +522,7 @@ public void Resolve(VBAParser.GetStmtContext context)
522522
}
523523
if (context.variable() != null)
524524
{
525-
ResolveDefault(context.variable().expression());
525+
ResolveDefault(context.variable().expression(), isAssignmentTarget: true);
526526
}
527527
}
528528

RubberduckTests/Grammar/ResolverTests.cs

Lines changed: 74 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1848,6 +1848,26 @@ End Sub
18481848
Assert.AreEqual(2, declaration.References.Count());
18491849
}
18501850

1851+
[TestMethod]
1852+
public void LineInputStmt_ReferenceIsAssignment()
1853+
{
1854+
// arrange
1855+
var code = @"
1856+
Public Sub Test()
1857+
Dim file As Integer, content
1858+
Line Input #file, content
1859+
End Sub
1860+
";
1861+
// act
1862+
var state = Resolve(code);
1863+
1864+
// assert
1865+
var declaration = state.AllUserDeclarations.Single(item =>
1866+
item.DeclarationType == DeclarationType.Variable && item.IdentifierName == "content");
1867+
1868+
Assert.IsTrue(declaration.References.Single().IsAssignment);
1869+
}
1870+
18511871
[TestMethod]
18521872
public void WidthStmt_IsReferenceToLocalVariable()
18531873
{
@@ -1928,6 +1948,39 @@ End Sub
19281948
Assert.AreEqual(2, declaration.References.Count());
19291949
}
19301950

1951+
[TestMethod]
1952+
public void InputStmt_ReferenceIsAssignment()
1953+
{
1954+
// arrange
1955+
var code = @"
1956+
Public Sub Test()
1957+
Dim str As String
1958+
Dim xCoord, yCoord, zCoord As Double
1959+
Input #1, str, xCoord, yCoord, zCoord
1960+
End Sub
1961+
";
1962+
// act
1963+
var state = Resolve(code);
1964+
1965+
// assert
1966+
var strDeclaration = state.AllUserDeclarations.Single(item =>
1967+
item.DeclarationType == DeclarationType.Variable && item.IdentifierName == "str");
1968+
1969+
var xCoordDeclaration = state.AllUserDeclarations.Single(item =>
1970+
item.DeclarationType == DeclarationType.Variable && item.IdentifierName == "xCoord");
1971+
1972+
var yCoordDeclaration = state.AllUserDeclarations.Single(item =>
1973+
item.DeclarationType == DeclarationType.Variable && item.IdentifierName == "yCoord");
1974+
1975+
var zCoordDeclaration = state.AllUserDeclarations.Single(item =>
1976+
item.DeclarationType == DeclarationType.Variable && item.IdentifierName == "zCoord");
1977+
1978+
Assert.IsTrue(strDeclaration.References.Single().IsAssignment);
1979+
Assert.IsTrue(xCoordDeclaration.References.Single().IsAssignment);
1980+
Assert.IsTrue(yCoordDeclaration.References.Single().IsAssignment);
1981+
Assert.IsTrue(zCoordDeclaration.References.Single().IsAssignment);
1982+
}
1983+
19311984
[TestMethod]
19321985
public void PutStmt_IsReferenceToLocalVariable()
19331986
{
@@ -1955,7 +2008,7 @@ public void GetStmt_IsReferenceToLocalVariable()
19552008
var code = @"
19562009
Public Sub Test()
19572010
Dim referenced As Integer
1958-
Get referenced,referenced,referenced
2011+
Get #referenced,referenced,referenced
19592012
End Sub
19602013
";
19612014
// act
@@ -1968,6 +2021,26 @@ End Sub
19682021
Assert.AreEqual(3, declaration.References.Count());
19692022
}
19702023

2024+
[TestMethod]
2025+
public void GetStmt_ReferenceIsAssignment()
2026+
{
2027+
// arrange
2028+
var code = @"
2029+
Public Sub Test()
2030+
Dim fileNumber As Integer, recordNumber, variable
2031+
Get #fileNumber, recordNumber, variable
2032+
End Sub
2033+
";
2034+
// act
2035+
var state = Resolve(code);
2036+
2037+
// assert
2038+
var variableDeclaration = state.AllUserDeclarations.Single(item =>
2039+
item.DeclarationType == DeclarationType.Variable && item.IdentifierName == "variable");
2040+
2041+
Assert.IsTrue(variableDeclaration.References.Single().IsAssignment);
2042+
}
2043+
19712044
[TestMethod]
19722045
public void LineSpecialForm_IsReferenceToLocalVariable()
19732046
{

RubberduckTests/Inspections/ParameterCanBeByValInspectionTests.cs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -333,6 +333,74 @@ Sub Foo(arg1 As String)
333333
Assert.IsFalse(inspectionResults.Any());
334334
}
335335

336+
[TestMethod]
337+
public void ParameterCanBeByVal_InterfaceMember()
338+
{
339+
//Input
340+
const string inputCode1 =
341+
@"Public Sub DoSomething(ByRef a As Integer)
342+
End Sub";
343+
const string inputCode2 =
344+
@"Implements IClass1
345+
346+
Private Sub IClass1_DoSomething(ByRef a As Integer)
347+
End Sub";
348+
349+
//Arrange
350+
var builder = new MockVbeBuilder();
351+
var project = builder.ProjectBuilder("TestProject1", vbext_ProjectProtection.vbext_pp_none)
352+
.AddComponent("IClass1", vbext_ComponentType.vbext_ct_ClassModule, inputCode1)
353+
.AddComponent("Class1", vbext_ComponentType.vbext_ct_ClassModule, inputCode2)
354+
.Build();
355+
var vbe = builder.AddProject(project).Build();
356+
357+
var mockHost = new Mock<IHostApplication>();
358+
mockHost.SetupAllProperties();
359+
var parser = MockParser.Create(vbe.Object, new RubberduckParserState(vbe.Object, new Mock<ISinks>().Object));
360+
361+
parser.Parse(new CancellationTokenSource());
362+
if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
363+
364+
var inspection = new ParameterCanBeByValInspection(parser.State);
365+
var inspectionResults = inspection.GetInspectionResults();
366+
367+
Assert.IsFalse(inspectionResults.Any());
368+
}
369+
370+
[TestMethod]
371+
public void ParameterCanBeByVal_Event()
372+
{
373+
//Input
374+
const string inputCode1 =
375+
@"Public Event Foo(ByVal arg1 As Integer, ByVal arg2 As String)";
376+
377+
const string inputCode2 =
378+
@"Private WithEvents abc As Class1
379+
380+
Private Sub abc_Foo(ByVal arg1 As Integer, ByVal arg2 As String)
381+
End Sub";
382+
383+
//Arrange
384+
var builder = new MockVbeBuilder();
385+
var project = builder.ProjectBuilder("TestProject1", vbext_ProjectProtection.vbext_pp_none)
386+
.AddComponent("Class1", vbext_ComponentType.vbext_ct_ClassModule, inputCode1)
387+
.AddComponent("Class2", vbext_ComponentType.vbext_ct_ClassModule, inputCode2)
388+
.Build();
389+
var vbe = builder.AddProject(project).Build();
390+
391+
var mockHost = new Mock<IHostApplication>();
392+
mockHost.SetupAllProperties();
393+
var parser = MockParser.Create(vbe.Object, new RubberduckParserState(vbe.Object, new Mock<ISinks>().Object));
394+
395+
parser.Parse(new CancellationTokenSource());
396+
if (parser.State.Status >= ParserState.Error) { Assert.Inconclusive("Parser Error"); }
397+
398+
var inspection = new ParameterCanBeByValInspection(parser.State);
399+
var inspectionResults = inspection.GetInspectionResults();
400+
401+
Assert.IsFalse(inspectionResults.Any());
402+
}
403+
336404
[TestMethod]
337405
[TestCategory("Inspections")]
338406
public void ParameterCanBeByVal_QuickFixWorks_SubNameStartsWithParamName()

0 commit comments

Comments
 (0)