From dad935e1113adba7978a3dc49062f73fbd26ce72 Mon Sep 17 00:00:00 2001 From: Fredric Silberberg Date: Fri, 25 Aug 2017 15:19:48 -0700 Subject: [PATCH] Added deconstruction support, tests for IFieldReferenceExpression in out var and deconstruction script scenarios. --- .../Portable/Binder/Binder_Deconstruct.cs | 1 + .../Portable/Binder/Binder_Expressions.cs | 8 +- .../CSharp/Portable/BoundTree/Constructors.cs | 18 ++- .../BoundTree/VariablePendingInference.cs | 9 +- ...perationTests_IFieldReferenceExpression.cs | 110 +++++++++++++++++- 5 files changed, 137 insertions(+), 9 deletions(-) diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs index 88b47b52f8f..2a670529818 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Deconstruct.cs @@ -830,6 +830,7 @@ private static string ExtractDeconstructResultElementName(BoundExpression expres field, constantValueOpt: null, resultKind: LookupResultKind.Viable, + isDeclaration: true, type: fieldType); } diff --git a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs index 166d1b01245..7af75b1e08b 100644 --- a/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs +++ b/src/Compilers/CSharp/Portable/Binder/Binder_Expressions.cs @@ -2361,7 +2361,7 @@ private BoundExpression BindOutDeclarationArgument(DeclarationExpressionSyntax d CheckRestrictedTypeInAsync(this.ContainingMemberOrLambda, declType, diagnostics, typeSyntax); - return new BoundLocal(declarationExpression, localSymbol, isDeclaration:true, constantValueOpt: null, type: declType); + return new BoundLocal(declarationExpression, localSymbol, isDeclaration: true, constantValueOpt: null, type: declType); } // Is this a field? @@ -2390,7 +2390,11 @@ private BoundExpression BindOutDeclarationArgument(DeclarationExpressionSyntax d TypeSymbol fieldType = expressionVariableField.GetFieldType(this.FieldsBeingBound); return new BoundFieldAccess(declarationExpression, receiver, - expressionVariableField, null, LookupResultKind.Viable, fieldType, isDeclaration: true); + expressionVariableField, + null, + LookupResultKind.Viable, + isDeclaration: true, + type: fieldType); } /// diff --git a/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs b/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs index 55901e9ab04..fd05b72b556 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/Constructors.cs @@ -25,9 +25,21 @@ internal sealed partial class BoundFieldAccess ConstantValue constantValueOpt, LookupResultKind resultKind, TypeSymbol type, - bool hasErrors = false, - bool isDeclaration = false) - : this(syntax, receiver, fieldSymbol, constantValueOpt, resultKind, NeedsByValueFieldAccess(receiver, fieldSymbol), isDeclaration, type, hasErrors) + bool hasErrors = false) + : this(syntax, receiver, fieldSymbol, constantValueOpt, resultKind, NeedsByValueFieldAccess(receiver, fieldSymbol), isDeclaration: false, type: type, hasErrors: hasErrors) + { + } + + public BoundFieldAccess( + SyntaxNode syntax, + BoundExpression receiver, + FieldSymbol fieldSymbol, + ConstantValue constantValueOpt, + LookupResultKind resultKind, + bool isDeclaration, + TypeSymbol type, + bool hasErrors = false) + : this(syntax, receiver, fieldSymbol, constantValueOpt, resultKind, NeedsByValueFieldAccess(receiver, fieldSymbol), isDeclaration: isDeclaration, type: type, hasErrors: hasErrors) { } diff --git a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs index 6a2700c92d9..528ae707e4e 100644 --- a/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs +++ b/src/Compilers/CSharp/Portable/BoundTree/VariablePendingInference.cs @@ -79,9 +79,12 @@ internal BoundExpression SetInferredType(TypeSymbol type, Binder binderOpt, Diag return new BoundFieldAccess(this.Syntax, this.ReceiverOpt, - fieldSymbol, null, LookupResultKind.Viable, type, - this.HasErrors || inferenceFailed, - isDeclaration: true); + fieldSymbol, + null, + LookupResultKind.Viable, + isDeclaration: true, + type: type, + hasErrors: this.HasErrors || inferenceFailed); default: throw ExceptionUtilities.UnexpectedValue(this.VariableSymbol.Kind); diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.cs index e58060335f5..851168f032a 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_IFieldReferenceExpression.cs @@ -1,6 +1,7 @@ -// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. +// Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information. using Microsoft.CodeAnalysis.CSharp.Syntax; +using Microsoft.CodeAnalysis.CSharp.Test.Utilities; using Microsoft.CodeAnalysis.Test.Utilities; using Roslyn.Test.Utilities; using Xunit; @@ -36,5 +37,112 @@ void M() VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IFieldReferenceExpression_OutVar_Script() + { + string source = @" +public void M2(out int i ) +{ + i = 0; +} + +M2(out /**/int i/**/); +"; + string expectedOperationTree = @" +IFieldReferenceExpression: System.Int32 Script.i (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'int i') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, + parseOptions: TestOptions.Script); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IFieldReferenceExpression_DeconstructionDeclaration_Script() + { + string source = @" +/**/(int i1, int i2)/**/ = (1, 2); +"; + string expectedOperationTree = @" +ITupleExpression (OperationKind.TupleExpression, Type: (System.Int32 i1, System.Int32 i2)) (Syntax: '(int i1, int i2)') + Elements(2): + IFieldReferenceExpression: System.Int32 Script.i1 (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'int i1') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i1') + IFieldReferenceExpression: System.Int32 Script.i2 (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'int i2') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i2') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, + parseOptions: TestOptions.Script); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IFieldReferenceExpression_InferenceOutVar_Script() + { + string source = @" +public void M2(out int i ) +{ + i = 0; +} + +M2(out /**/var i/**/); +"; + string expectedOperationTree = @" +IFieldReferenceExpression: System.Int32 Script.i (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'var i') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, + parseOptions: TestOptions.Script); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IFieldReferenceExpression_InferenceDeconstructionDeclaration_Script() + { + string source = @" +/**/(var i1, var i2)/**/ = (1, 2); +"; + string expectedOperationTree = @" +ITupleExpression (OperationKind.TupleExpression, Type: (System.Int32 i1, System.Int32 i2)) (Syntax: '(var i1, var i2)') + Elements(2): + IFieldReferenceExpression: System.Int32 Script.i1 (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'var i1') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i1') + IFieldReferenceExpression: System.Int32 Script.i2 (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'var i2') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i2') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, + parseOptions: TestOptions.Script); + } + + [CompilerTrait(CompilerFeature.IOperation)] + [Fact] + public void IFieldReferenceExpression_InferenceDeconstructionDeclaration_AlternateSyntax_Script() + { + string source = @" +/**/var (i1, i2)/**/ = (1, 2); +"; + string expectedOperationTree = @" +ITupleExpression (OperationKind.TupleExpression, Type: (System.Int32 i1, System.Int32 i2)) (Syntax: 'var (i1, i2)') + Elements(2): + IFieldReferenceExpression: System.Int32 Script.i1 (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'i1') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i1') + IFieldReferenceExpression: System.Int32 Script.i2 (IsDeclaration: True) (OperationKind.FieldReferenceExpression, Type: System.Int32) (Syntax: 'i2') + Instance Receiver: IInstanceReferenceExpression (InstanceReferenceKind.Implicit) (OperationKind.InstanceReferenceExpression, Type: Script) (Syntax: 'i2') +"; + var expectedDiagnostics = DiagnosticDescription.None; + + VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics, + parseOptions: TestOptions.Script); + } } } -- GitLab