Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -97,10 +97,22 @@ internal BoundExpression RewriteConditionalAccess(BoundConditionalAccess node, b
throw ExceptionUtilities.UnexpectedValue(loweringKind);
}

BoundExpression loweredAccessExpression = used ?
this.VisitExpression(node.AccessExpression) :
this.VisitUnusedExpression(node.AccessExpression);
BoundExpression loweredAccessExpression;

if (used)
{
loweredAccessExpression = this.VisitExpression(node.AccessExpression);
}
else
{
loweredAccessExpression = this.VisitUnusedExpression(node.AccessExpression);
if (loweredAccessExpression == null)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why can this return null but not VisitExpression?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah I think I understand now why this works this way.

{
return null;
}
}

Debug.Assert(loweredAccessExpression != null);
_currentConditionalAccessTarget = previousConditionalAccessTarget;

TypeSymbol type = this.VisitType(node.Type);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1400,5 +1400,69 @@ static void Main()

Assert.Null(model.GetSymbolInfo(access).Symbol);
}

[Fact(), WorkItem(4615, "https://github.com/dotnet/roslyn/issues/4615")]
public void ConditionalAndConditionalMethods()
{
string source = @"
class Program
{
static void Main(string[] args)
{
TestClass.Create().Test();
TestClass.Create().Self().Test();
System.Console.WriteLine(""---"");
TestClass.Create()?.Test();
TestClass.Create()?.Self().Test();
TestClass.Create()?.Self()?.Test();
}
}

class TestClass
{
[System.Diagnostics.Conditional(""DEBUG"")]
public void Test()
{
System.Console.WriteLine(""Test"");
}

public static TestClass Create()
{
System.Console.WriteLine(""Create"");
return new TestClass();
}

public TestClass Self()
{
System.Console.WriteLine(""Self"");
return this;
}
}
";

var compilation = CreateCompilationWithMscorlib(source, options: TestOptions.DebugExe,
parseOptions: CSharpParseOptions.Default.WithPreprocessorSymbols("DEBUG"));

CompileAndVerify(compilation, expectedOutput:
@"Create
Test
Create
Self
Test
---
Create
Test
Create
Self
Test
Create
Self
Test
");

compilation = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseExe);

CompileAndVerify(compilation, expectedOutput:"---");
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -26,9 +26,17 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
End Function

Private Function IsOmittedBoundCall(expression As BoundExpression) As Boolean
Return (Me._flags And RewritingFlags.AllowOmissionOfConditionalCalls) = RewritingFlags.AllowOmissionOfConditionalCalls AndAlso
expression.Kind = BoundKind.Call AndAlso
DirectCast(expression, BoundCall).Method.CallsAreOmitted(expression.Syntax, expression.SyntaxTree)
If (Me._flags And RewritingFlags.AllowOmissionOfConditionalCalls) = RewritingFlags.AllowOmissionOfConditionalCalls Then
Select Case expression.Kind
Case BoundKind.ConditionalAccess
Return IsOmittedBoundCall(DirectCast(expression, BoundConditionalAccess).AccessExpression)

Case BoundKind.Call
Return DirectCast(expression, BoundCall).Method.CallsAreOmitted(expression.Syntax, expression.SyntaxTree)
End Select
End If

Return False
End Function
End Class
End Namespace
Original file line number Diff line number Diff line change
Expand Up @@ -9432,5 +9432,70 @@ BC32022: 'Public Event TestEvent As Action' is an event, and cannot be called di
Assert.False(info.CandidateSymbols.Any())
End Sub

<Fact(), WorkItem(4615, "https://github.com/dotnet/roslyn/issues/4615")>
Public Sub ConditionalAndConditionalMethods()

Dim compilationDef =
<compilation>
<file name="a.vb"><![CDATA[
Class Program
Shared Sub Main()
TestClass.Create().Test()
TestClass.Create().Self().Test()
System.Console.WriteLine("---")
TestClass.Create()?.Test()
TestClass.Create()?.Self().Test()
TestClass.Create()?.Self()?.Test()
End Sub
End Class

Class TestClass
<System.Diagnostics.Conditional("DEBUG")>
Public Sub Test()
System.Console.WriteLine("Test")
End Sub

Shared Function Create() As TestClass
System.Console.WriteLine("Create")
return new TestClass()
End Function

Function Self() As TestClass
System.Console.WriteLine("Self")
return Me
End Function
End Class
]]></file>
</compilation>

Dim compilation = CompilationUtils.CreateCompilationWithMscorlib(compilationDef, TestOptions.DebugExe,
parseOptions:=VisualBasicParseOptions.Default.WithPreprocessorSymbols({New KeyValuePair(Of String, Object)("DEBUG", True)}))

Dim verifier = CompileAndVerify(compilation, expectedOutput:=
<![CDATA[
Create
Test
Create
Self
Test
---
Create
Test
Create
Self
Test
Create
Self
Test
]]>)

compilation = CompilationUtils.CreateCompilationWithMscorlib(compilationDef, TestOptions.ReleaseExe)

verifier = CompileAndVerify(compilation, expectedOutput:=
<![CDATA[
---
]]>)
End Sub

End Class
End Namespace