diff --git a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs index daffa54ff125356392890f251ae0abf1c40e5b05..b7feb0833d5e14f42ded33b0624c891bf3cc8a04 100644 --- a/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs +++ b/src/Compilers/CSharp/Portable/Operations/CSharpOperationFactory.cs @@ -334,13 +334,14 @@ private ILocalReferenceExpression CreateBoundLocalOperation(BoundLocal boundLoca private IFieldReferenceExpression CreateBoundFieldAccessOperation(BoundFieldAccess boundFieldAccess) { IFieldSymbol field = boundFieldAccess.FieldSymbol; + bool isDeclaration = boundFieldAccess.IsDeclaration; Lazy instance = new Lazy(() => Create(boundFieldAccess.FieldSymbol.IsStatic ? null : boundFieldAccess.ReceiverOpt)); ISymbol member = boundFieldAccess.FieldSymbol; SyntaxNode syntax = boundFieldAccess.Syntax; ITypeSymbol type = boundFieldAccess.Type; Optional constantValue = ConvertToOptional(boundFieldAccess.ConstantValue); bool isImplicit = boundFieldAccess.WasCompilerGenerated; - return new LazyFieldReferenceExpression(field, instance, member, _semanticModel, syntax, type, constantValue, isImplicit); + return new LazyFieldReferenceExpression(field, isDeclaration, instance, member, _semanticModel, syntax, type, constantValue, isImplicit); } private IPropertyReferenceExpression CreateBoundPropertyAccessOperation(BoundPropertyAccess boundPropertyAccess) @@ -550,7 +551,8 @@ private IMemberReferenceExpression CreateBoundObjectInitializerMemberOperation(B { case SymbolKind.Field: var field = (FieldSymbol)boundObjectInitializerMember.MemberSymbol; - return new LazyFieldReferenceExpression(field, instance, field, _semanticModel, syntax, type, constantValue, isImplicit); + bool isDeclaration = false; + return new LazyFieldReferenceExpression(field, isDeclaration, instance, field, _semanticModel, syntax, type, constantValue, isImplicit); case SymbolKind.Event: var eventSymbol = (EventSymbol)boundObjectInitializerMember.MemberSymbol; return new LazyEventReferenceExpression(eventSymbol, instance, eventSymbol, _semanticModel, syntax, type, constantValue, isImplicit); diff --git a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILocalReferenceExpression.cs b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILocalReferenceExpression.cs index c1cf652ac9993069450c0e1d88e5e00af6c45364..f1d40a3f54934efd616c0c2b5ab357ea663719c3 100644 --- a/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILocalReferenceExpression.cs +++ b/src/Compilers/CSharp/Test/Semantic/IOperation/IOperationTests_ILocalReferenceExpression.cs @@ -88,7 +88,5 @@ public virtual void M1() VerifyOperationTreeAndDiagnosticsForTest(source, expectedOperationTree, expectedDiagnostics); } - - } } diff --git a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs index 84cad468a3059f5998418999ce943b4252ce181b..becc71aeb62f83e58e6849f50dc57b1027f48897 100644 --- a/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs +++ b/src/Compilers/Core/Portable/Generated/Operations.xml.Generated.cs @@ -1598,15 +1598,17 @@ internal sealed partial class LazyFieldInitializer : BaseFieldInitializer, IFiel /// internal abstract partial class BaseFieldReferenceExpression : MemberReferenceExpression, IFieldReferenceExpression { - public BaseFieldReferenceExpression(IFieldSymbol field, ISymbol member, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + public BaseFieldReferenceExpression(IFieldSymbol field, bool isDeclaration, ISymbol member, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : base(member, OperationKind.FieldReferenceExpression, semanticModel, syntax, type, constantValue, isImplicit) { Field = field; + IsDeclaration = isDeclaration; } /// /// Referenced field. /// public IFieldSymbol Field { get; } + public bool IsDeclaration { get; } public override IEnumerable Children { get @@ -1630,8 +1632,8 @@ public override void Accept(OperationVisitor visitor) /// internal sealed partial class FieldReferenceExpression : BaseFieldReferenceExpression, IFieldReferenceExpression { - public FieldReferenceExpression(IFieldSymbol field, IOperation instance, ISymbol member, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(field, member, semanticModel, syntax, type, constantValue, isImplicit) + public FieldReferenceExpression(IFieldSymbol field, bool isDeclaration, IOperation instance, ISymbol member, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(field, isDeclaration, member, semanticModel, syntax, type, constantValue, isImplicit) { InstanceImpl = instance; } @@ -1645,8 +1647,8 @@ internal sealed partial class LazyFieldReferenceExpression : BaseFieldReferenceE { private readonly Lazy _lazyInstance; - public LazyFieldReferenceExpression(IFieldSymbol field, Lazy instance, ISymbol member, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : - base(field, member, semanticModel, syntax, type, constantValue, isImplicit) + public LazyFieldReferenceExpression(IFieldSymbol field, bool isDeclaration, Lazy instance, ISymbol member, SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, Optional constantValue, bool isImplicit) : + base(field, isDeclaration, member, semanticModel, syntax, type, constantValue, isImplicit) { _lazyInstance = instance ?? throw new System.ArgumentNullException(nameof(instance)); } diff --git a/src/Compilers/Core/Portable/Operations/IFieldReferenceExpression.cs b/src/Compilers/Core/Portable/Operations/IFieldReferenceExpression.cs index 7626035514dbd1ba70328d963cc282bf176662c7..ae569f19305fd535b3950a1e77c818ce7c417359 100644 --- a/src/Compilers/Core/Portable/Operations/IFieldReferenceExpression.cs +++ b/src/Compilers/Core/Portable/Operations/IFieldReferenceExpression.cs @@ -17,6 +17,14 @@ public interface IFieldReferenceExpression : IMemberReferenceExpression /// Referenced field. /// IFieldSymbol Field { get; } + /// + /// If the field reference is also where the field was declared. + /// + /// + /// This is only ever true in CSharp scripts, where a top-level statement creates a new variable + /// in a reference, such as an out variable declaration or a tuple deconstruction declaration. + /// + bool IsDeclaration { get; } } } diff --git a/src/Compilers/Core/Portable/Operations/OperationCloner.cs b/src/Compilers/Core/Portable/Operations/OperationCloner.cs index d5fe29783cd99739159bf6c368d9b9214349e5b2..1bf2cf6b1f0f883e31abb5da20ddc961c2f94c2f 100644 --- a/src/Compilers/Core/Portable/Operations/OperationCloner.cs +++ b/src/Compilers/Core/Portable/Operations/OperationCloner.cs @@ -216,7 +216,7 @@ public override IOperation VisitInstanceReferenceExpression(IInstanceReferenceEx public override IOperation VisitFieldReferenceExpression(IFieldReferenceExpression operation, object argument) { - return new FieldReferenceExpression(operation.Field, Visit(operation.Instance), operation.Member, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); + return new FieldReferenceExpression(operation.Field, operation.IsDeclaration, Visit(operation.Instance), operation.Member, ((Operation)operation).SemanticModel, operation.Syntax, operation.Type, operation.ConstantValue, operation.IsImplicit); } public override IOperation VisitMethodBindingExpression(IMethodBindingExpression operation, object argument) diff --git a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt index 77d6573c04d8db324c038628cb94fef26bf229f5..e06cc07b574b9987508d716ae747d5fc14182dd1 100644 --- a/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt +++ b/src/Compilers/Core/Portable/PublicAPI.Unshipped.txt @@ -428,6 +428,7 @@ Microsoft.CodeAnalysis.Semantics.IFieldInitializer Microsoft.CodeAnalysis.Semantics.IFieldInitializer.InitializedFields.get -> System.Collections.Immutable.ImmutableArray Microsoft.CodeAnalysis.Semantics.IFieldReferenceExpression Microsoft.CodeAnalysis.Semantics.IFieldReferenceExpression.Field.get -> Microsoft.CodeAnalysis.IFieldSymbol +Microsoft.CodeAnalysis.Semantics.IFieldReferenceExpression.IsDeclaration.get -> bool Microsoft.CodeAnalysis.Semantics.IFixedStatement Microsoft.CodeAnalysis.Semantics.IFixedStatement.Body.get -> Microsoft.CodeAnalysis.IOperation Microsoft.CodeAnalysis.Semantics.IFixedStatement.Variables.get -> Microsoft.CodeAnalysis.Semantics.IVariableDeclarationStatement diff --git a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb index b0f6d041ea082b94131c9e5f19ae846a3e683d87..541af706834dd134d66ed808d2253f4123cf47d2 100644 --- a/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb +++ b/src/Compilers/VisualBasic/Portable/Operations/VisualBasicOperationFactory.vb @@ -695,6 +695,7 @@ Namespace Microsoft.CodeAnalysis.Semantics Private Function CreateBoundFieldAccessOperation(boundFieldAccess As BoundFieldAccess) As IFieldReferenceExpression Dim field As IFieldSymbol = boundFieldAccess.FieldSymbol + Dim isDeclaration As Boolean = False Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)( Function() If boundFieldAccess.FieldSymbol.IsShared Then @@ -709,7 +710,7 @@ Namespace Microsoft.CodeAnalysis.Semantics Dim type As ITypeSymbol = boundFieldAccess.Type Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundFieldAccess.ConstantValueOpt) Dim isImplicit As Boolean = boundFieldAccess.WasCompilerGenerated - Return New LazyFieldReferenceExpression(field, instance, member, _semanticModel, syntax, type, constantValue, isImplicit) + Return New LazyFieldReferenceExpression(field, isDeclaration, instance, member, _semanticModel, syntax, type, constantValue, isImplicit) End Function Private Function CreateBoundConditionalAccessOperation(boundConditionalAccess As BoundConditionalAccess) As IConditionalAccessExpression