diff --git a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs index 08bd5a05b442ea2f3526e82425a8eb1bc7adc0c9..afe1ac351b39fc3f3b5354a79d70008d47a7a432 100644 --- a/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs +++ b/src/Compilers/CSharp/Portable/Compilation/SyntaxTreeSemanticModel.cs @@ -163,9 +163,6 @@ internal override Binder GetEnclosingBinderInternal(int position) internal override IOperation GetOperationWorker(CSharpSyntaxNode node, CancellationToken cancellationToken) { - // in case this is right side of a qualified name or member access (or part of a cref) - node = SyntaxFactory.GetStandaloneNode(node); - var model = this.GetMemberModel(node); if (model != null) { diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs index 31443be10b6a3245cf1b43122c1d0ea1ce705132..85d26d8fc122bfd608a0301221109e9423d2c4e4 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests.cs @@ -159,5 +159,45 @@ public void TestParentOperations() VerifyParentOperations(model); } + + [CompilerTrait(CompilerFeature.IOperation)] + [WorkItem(23001, "https://github.com/dotnet/roslyn/issues/23001")] + [Fact] + public void TestGetOperationForQualifiedName() + { + var text = @"using System; + +public class Test +{ + class A + { + public B b; + } + class B + { + } + + void M(A a) + { + int x2 = /**/a.b/**/; + } +} +"; + var comp = CreateStandardCompilation(text, parseOptions: TestOptions.RegularWithIOperationFeature); + var tree = comp.SyntaxTrees.Single(); + var model = comp.GetSemanticModel(tree); + + // Verify we return non-null operation only for topmost member access expression. + var expr = (MemberAccessExpressionSyntax)GetExprSyntaxForBinding(GetExprSyntaxList(tree)); + Assert.Equal("a.b", expr.ToString()); + var operation = model.GetOperation(expr); + Assert.NotNull(operation); + Assert.Equal(OperationKind.FieldReference, operation.Kind); + var fieldOperation = (IFieldReferenceOperation)operation; + Assert.Equal("b", fieldOperation.Field.Name); + + // Verify we return null operation for child nodes of member access expression. + Assert.Null(model.GetOperation(expr.Name)); + } } } diff --git a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb index 1c9e00336bf3fb57ca9836d337306eb1bc034043..8b91a676b54052eb482e07db1d84b9592541dfcd 100644 --- a/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb +++ b/src/Compilers/VisualBasic/Test/Semantic/IOperation/IOperationTests.vb @@ -834,5 +834,39 @@ IAnonymousFunctionOperation (Symbol: Sub ()) (OperationKind.AnonymousFunction, T VerifyOperationTreeAndDiagnosticsForTest(Of MultiLineLambdaExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics) End Sub + + + + Public Sub TestGetOperationForQualifiedName() + Dim source = .Value + + Dim comp = CreateVisualBasicCompilation(source, parseOptions:=TestOptions.RegularWithIOperationFeature) + Dim tree = comp.SyntaxTrees.Single() + Dim model = comp.GetSemanticModel(tree) + + ' Verify we return non-null operation only for topmost member access expression. + Dim expr = CompilationUtils.FindBindingText(Of MemberAccessExpressionSyntax)(comp, tree.FilePath) + Assert.Equal("a.b", expr.ToString()) + Dim operation = model.GetOperation(expr) + Assert.NotNull(operation) + Assert.Equal(OperationKind.FieldReference, operation.Kind) + Dim fieldOperation = DirectCast(operation, IFieldReferenceOperation) + Assert.Equal("b", fieldOperation.Field.Name) + + ' Verify we return null operation for child nodes of member access expression. + Assert.Null(model.GetOperation(expr.Name)) + End Sub End Class End Namespace