未验证 提交 4dbe940a 编写于 作者: F Fred Silberberg 提交者: GitHub

Merge pull request #22972 from 333fred/static-instance

Update static instance handling
......@@ -18,9 +18,6 @@ internal sealed partial class CSharpOperationFactory
private readonly ConcurrentDictionary<BoundNode, IOperation> _cache =
new ConcurrentDictionary<BoundNode, IOperation>(concurrencyLevel: 2, capacity: 10);
private readonly Lazy<IOperation> _lazyNullOperation =
new Lazy<IOperation>(() => null);
private readonly SemanticModel _semanticModel;
public CSharpOperationFactory(SemanticModel semanticModel)
......@@ -320,7 +317,7 @@ private IOperation CreateBoundCallOperation(BoundCall boundCall)
return CreateInvalidExpressionForHasArgumentsExpression(boundCall.ReceiverOpt, boundCall.Arguments, null, syntax, type, constantValue, isImplicit);
}
Lazy<IOperation> instance = new Lazy<IOperation>(() => CreateBoundCallInstanceOperation(boundCall));
Lazy<IOperation> instance = CreateReceiverOperation(boundCall.ReceiverOpt, targetMethod);
bool isVirtual = (object)targetMethod != null &&
boundCall.ReceiverOpt != null &&
(targetMethod.IsVirtual || targetMethod.IsAbstract || targetMethod.IsOverride) &&
......@@ -366,7 +363,7 @@ private IOperation CreateBoundFieldAccessOperation(BoundFieldAccess boundFieldAc
{
IFieldSymbol field = boundFieldAccess.FieldSymbol;
bool isDeclaration = boundFieldAccess.IsDeclaration;
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(boundFieldAccess.FieldSymbol.IsStatic ? null : boundFieldAccess.ReceiverOpt));
Lazy<IOperation> instance = CreateReceiverOperation(boundFieldAccess.ReceiverOpt, field);
SyntaxNode syntax = boundFieldAccess.Syntax;
ITypeSymbol type = boundFieldAccess.Type;
Optional<object> constantValue = ConvertToOptional(boundFieldAccess.ConstantValue);
......@@ -384,7 +381,7 @@ private IOperation CreateBoundFieldAccessOperation(BoundFieldAccess boundFieldAc
private IPropertyReferenceOperation CreateBoundPropertyAccessOperation(BoundPropertyAccess boundPropertyAccess)
{
IPropertySymbol property = boundPropertyAccess.PropertySymbol;
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(boundPropertyAccess.PropertySymbol.IsStatic ? null : boundPropertyAccess.ReceiverOpt));
Lazy<IOperation> instance = CreateReceiverOperation(boundPropertyAccess.ReceiverOpt, property);
Lazy<ImmutableArray<IArgumentOperation>> arguments = new Lazy<ImmutableArray<IArgumentOperation>>(() => ImmutableArray<IArgumentOperation>.Empty);
SyntaxNode syntax = boundPropertyAccess.Syntax;
ITypeSymbol type = boundPropertyAccess.Type;
......@@ -410,7 +407,7 @@ private IOperation CreateBoundIndexerAccessOperation(BoundIndexerAccess boundInd
return CreateInvalidExpressionForHasArgumentsExpression(boundIndexerAccess.ReceiverOpt, boundIndexerAccess.Arguments, null, syntax, type, constantValue, isImplicit);
}
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(property.IsStatic ? null : boundIndexerAccess.ReceiverOpt));
Lazy<IOperation> instance = CreateReceiverOperation(boundIndexerAccess.ReceiverOpt, property);
Lazy<ImmutableArray<IArgumentOperation>> arguments = new Lazy<ImmutableArray<IArgumentOperation>>(() =>
DeriveArguments(
boundIndexerAccess,
......@@ -430,7 +427,7 @@ private IOperation CreateBoundIndexerAccessOperation(BoundIndexerAccess boundInd
private IEventReferenceOperation CreateBoundEventAccessOperation(BoundEventAccess boundEventAccess)
{
IEventSymbol @event = boundEventAccess.EventSymbol;
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(boundEventAccess.EventSymbol.IsStatic ? null : boundEventAccess.ReceiverOpt));
Lazy<IOperation> instance = CreateReceiverOperation(boundEventAccess.ReceiverOpt, @event);
SyntaxNode syntax = boundEventAccess.Syntax;
ITypeSymbol type = boundEventAccess.Type;
Optional<object> constantValue = ConvertToOptional(boundEventAccess.ConstantValue);
......@@ -482,7 +479,7 @@ private IAnonymousObjectCreationOperation CreateBoundAnonymousObjectCreationExpr
private IPropertyReferenceOperation CreateBoundAnonymousPropertyDeclarationOperation(BoundAnonymousPropertyDeclaration boundAnonymousPropertyDeclaration)
{
PropertySymbol property = boundAnonymousPropertyDeclaration.Property;
Lazy<IOperation> instance = _lazyNullOperation;
Lazy<IOperation> instance = OperationFactory.NullOperation;
Lazy<ImmutableArray<IArgumentOperation>> arguments = new Lazy<ImmutableArray<IArgumentOperation>>(() => ImmutableArray<IArgumentOperation>.Empty);
SyntaxNode syntax = boundAnonymousPropertyDeclaration.Syntax;
ITypeSymbol type = boundAnonymousPropertyDeclaration.Type;
......@@ -594,12 +591,15 @@ private IObjectOrCollectionInitializerOperation CreateBoundCollectionInitializer
private IOperation CreateBoundObjectInitializerMemberOperation(BoundObjectInitializerMember boundObjectInitializerMember)
{
Lazy<IOperation> instance = new Lazy<IOperation>(() => new InstanceReferenceExpression(
semanticModel: _semanticModel,
syntax: boundObjectInitializerMember.Syntax,
type: boundObjectInitializerMember.ReceiverType,
constantValue: default(Optional<object>),
isImplicit: true));
Lazy<IOperation> instance = boundObjectInitializerMember.MemberSymbol.IsStatic ?
OperationFactory.NullOperation :
new Lazy<IOperation>(() =>
new InstanceReferenceExpression(
semanticModel: _semanticModel,
syntax: boundObjectInitializerMember.Syntax,
type: boundObjectInitializerMember.ReceiverType,
constantValue: default(Optional<object>),
isImplicit: true));
SyntaxNode syntax = boundObjectInitializerMember.Syntax;
ITypeSymbol type = boundObjectInitializerMember.Type;
......@@ -844,15 +844,7 @@ private IDelegateCreationOperation CreateBoundDelegateCreationExpressionOperatio
private IMethodReferenceOperation CreateBoundMethodGroupSingleMethodOperation(BoundMethodGroup boundMethodGroup, IMethodSymbol methodSymbol, bool suppressVirtualCalls)
{
bool isVirtual = (methodSymbol.IsAbstract || methodSymbol.IsOverride || methodSymbol.IsVirtual) && !suppressVirtualCalls;
BoundExpression receiverOpt = boundMethodGroup.InstanceOpt;
if (methodSymbol.IsStatic && receiverOpt != null &&
receiverOpt.WasCompilerGenerated && receiverOpt.Kind == BoundKind.ThisReference)
{
receiverOpt = null;
}
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(receiverOpt));
Lazy<IOperation> instance = CreateReceiverOperation(boundMethodGroup.ReceiverOpt, methodSymbol);
SyntaxNode bindingSyntax = boundMethodGroup.Syntax;
ITypeSymbol bindingType = null;
Optional<object> bindingConstantValue = ConvertToOptional(boundMethodGroup.ConstantValue);
......@@ -1316,7 +1308,7 @@ private IWhileLoopOperation CreateBoundWhileStatementOperation(BoundWhileStateme
{
Lazy<IOperation> condition = new Lazy<IOperation>(() => Create(boundWhileStatement.Condition));
Lazy<IOperation> body = new Lazy<IOperation>(() => Create(boundWhileStatement.Body));
Lazy<IOperation> ignoredCondition = _lazyNullOperation;
Lazy<IOperation> ignoredCondition = OperationFactory.NullOperation;
ImmutableArray<ILocalSymbol> locals = boundWhileStatement.Locals.As<ILocalSymbol>();
bool conditionIsTop = true;
bool conditionIsUntil = false;
......@@ -1331,7 +1323,7 @@ private IWhileLoopOperation CreateBoundDoStatementOperation(BoundDoStatement bou
{
Lazy<IOperation> condition = new Lazy<IOperation>(() => Create(boundDoStatement.Condition));
Lazy<IOperation> body = new Lazy<IOperation>(() => Create(boundDoStatement.Body));
Lazy<IOperation> ignoredCondition = _lazyNullOperation;
Lazy<IOperation> ignoredCondition = OperationFactory.NullOperation;
bool conditionIsTop = false;
bool conditionIsUntil = false;
ImmutableArray<ILocalSymbol> locals = boundDoStatement.Locals.As<ILocalSymbol>();
......@@ -1373,7 +1365,7 @@ private IForEachLoopOperation CreateBoundForEachStatementOperation(BoundForEachS
}
else
{
loopControlVariable = _lazyNullOperation;
loopControlVariable = OperationFactory.NullOperation;
}
Lazy<IOperation> collection = new Lazy<IOperation>(() => Create(boundForEachStatement.Expression));
......@@ -1567,7 +1559,7 @@ private IOperation CreateBoundLocalDeclarationOperation(BoundLocalDeclaration bo
Lazy<ImmutableArray<IVariableDeclaratorOperation>> declarations = new Lazy<ImmutableArray<IVariableDeclaratorOperation>>(() => ImmutableArray.Create(CreateVariableDeclaratorInternal(boundLocalDeclaration, varDeclarator)));
bool multiVariableImplicit = boundLocalDeclaration.WasCompilerGenerated;
// In C#, the MultiVariable initializer will always be null, but we can't pass null as the actual lazy. We assume that all lazy elements always exist
Lazy<IVariableInitializerOperation> initializer = OperationFactory.EmptyInitializer;
Lazy<IVariableInitializerOperation> initializer = OperationFactory.NullInitializer;
IVariableDeclarationOperation multiVariableDeclaration = new LazyVariableDeclaration(declarations, initializer, _semanticModel, varDeclaration, null, default, multiVariableImplicit);
ITypeSymbol type = null;
Optional<object> constantValue = default(Optional<object>);
......@@ -1582,7 +1574,7 @@ private IVariableDeclarationGroupOperation CreateBoundMultipleLocalDeclarationsO
Lazy<ImmutableArray<IVariableDeclaratorOperation>> declarators = new Lazy<ImmutableArray<IVariableDeclaratorOperation>>(() =>
boundMultipleLocalDeclarations.LocalDeclarations.SelectAsArray(declaration => CreateVariableDeclarator(declaration)));
// In C#, the MultiVariable initializer will always be null, but we can't pass null as the actual lazy. We assume that all lazy elements always exist
Lazy<IVariableInitializerOperation> initializer = OperationFactory.EmptyInitializer;
Lazy<IVariableInitializerOperation> initializer = OperationFactory.NullInitializer;
// The syntax for the boundMultipleLocalDeclarations can either be a LocalDeclarationStatement or a VariableDeclaration, depending on the context
// (using/fixed statements vs variable declaration)
......
......@@ -91,14 +91,20 @@ private IVariableDeclaratorOperation CreateVariableDeclarator(BoundLocal boundLo
return new VariableDeclarator(boundLocal.LocalSymbol, initializer: null, semanticModel: _semanticModel, syntax: boundLocal.Syntax, type: null, constantValue: default, isImplicit: false);
}
private IOperation CreateBoundCallInstanceOperation(BoundCall boundCall)
private Lazy<IOperation> CreateReceiverOperation(BoundNode instance, ISymbol symbol)
{
if (boundCall.Method == null || boundCall.Method.IsStatic)
if (instance == null || instance.Kind == BoundKind.TypeExpression)
{
return null;
return OperationFactory.NullOperation;
}
return Create(boundCall.ReceiverOpt);
// Static members cannot have an implicit this receiver
if (symbol != null && symbol.IsStatic && instance.WasCompilerGenerated && instance.Kind == BoundKind.ThisReference)
{
return OperationFactory.NullOperation;
}
return new Lazy<IOperation>(() => Create(instance));
}
private IEventReferenceOperation CreateBoundEventAccessOperation(BoundEventAssignmentOperator boundEventAssignmentOperator)
......@@ -110,7 +116,7 @@ private IEventReferenceOperation CreateBoundEventAccessOperation(BoundEventAssig
// 2. the constant value of BoundEventAccess is always null.
// 3. the syntax of the boundEventAssignmentOperator is always AssignmentExpressionSyntax, so the syntax for the event reference would be the LHS of the assignment.
IEventSymbol @event = boundEventAssignmentOperator.Event;
Lazy<IOperation> instance = new Lazy<IOperation>(() => Create(boundEventAssignmentOperator.Event.IsStatic ? null : boundEventAssignmentOperator.ReceiverOpt));
Lazy<IOperation> instance = CreateReceiverOperation(boundEventAssignmentOperator.ReceiverOpt, @event);
SyntaxNode eventAccessSyntax = ((AssignmentExpressionSyntax)syntax).Left;
bool isImplicit = boundEventAssignmentOperator.WasCompilerGenerated;
......@@ -158,10 +164,10 @@ private IInvalidOperation CreateInvalidExpressionForHasArgumentsExpression(Bound
{
ArrayBuilder<IOperation> builder = ArrayBuilder<IOperation>.GetInstance();
if (receiverOpt != null
&& (!receiverOpt.WasCompilerGenerated
|| (receiverOpt.Kind != BoundKind.ThisReference
&& receiverOpt.Kind != BoundKind.BaseReference
if (receiverOpt != null
&& (!receiverOpt.WasCompilerGenerated
|| (receiverOpt.Kind != BoundKind.ThisReference
&& receiverOpt.Kind != BoundKind.BaseReference
&& receiverOpt.Kind != BoundKind.ImplicitReceiver)))
{
builder.Add(Create(receiverOpt));
......
......@@ -309,7 +309,7 @@ void M()
Event Reference:
IEventReferenceOperation: event System.EventHandler Test.MyEvent (Static) (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 't.MyEvent')
Instance Receiver:
null
ILocalReferenceOperation: t (OperationKind.LocalReference, Type: Test, IsInvalid) (Syntax: 't')
Handler:
IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.EventHandler, IsImplicit) (Syntax: 'Handler')
Target:
......@@ -359,7 +359,7 @@ void M()
Event Reference:
IEventReferenceOperation: event System.EventHandler Test.MyEvent (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 'Test.MyEvent')
Instance Receiver:
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'Test')
null
Handler:
IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.EventHandler, IsImplicit) (Syntax: 'Handler')
Target:
......
// 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.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IEventReference_AddEvent_StaticEventAccessOnClass()
{
string source = @"
using System;
using System.Collections.Generic;
class C
{
static event EventHandler Event;
public static void M()
{
/*<bind>*/C.Event/*</bind>*/ += (sender, args) => { };
}
}
";
string expectedOperationTree = @"
IEventReferenceOperation: event System.EventHandler C.Event (Static) (OperationKind.EventReference, Type: System.EventHandler) (Syntax: 'C.Event')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0067: The event 'C.Event' is never used
// static event EventHandler Event;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("C.Event").WithLocation(7, 31)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IEventReference_AddEvent_InstanceEventAccessOnClass()
{
string source = @"
using System;
using System.Collections.Generic;
class C
{
event EventHandler Event;
public static void M()
{
/*<bind>*/C.Event/*</bind>*/ += (sender, args) => { };
}
}
";
string expectedOperationTree = @"
IEventReferenceOperation: event System.EventHandler C.Event (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 'C.Event')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0120: An object reference is required for the non-static field, method, or property 'C.Event'
// /*<bind>*/C.Event/*</bind>*/ += (sender, args) => { };
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.Event").WithArguments("C.Event").WithLocation(11, 19),
// CS0067: The event 'C.Event' is never used
// event EventHandler Event;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("C.Event").WithLocation(7, 24)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IEventReference_AddEvent_StaticEventWithInstanceReceiver()
{
string source = @"
using System;
using System.Collections.Generic;
class C
{
static event EventHandler Event;
public static void M()
{
var c = new C();
/*<bind>*/c.Event/*</bind>*/ += (sender, args) => { };
}
}
";
string expectedOperationTree = @"
IEventReferenceOperation: event System.EventHandler C.Event (Static) (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 'c.Event')
Instance Receiver:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0176: Member 'C.Event' cannot be accessed with an instance reference; qualify it with a type name instead
// /*<bind>*/c.Event/*</bind>*/ += (sender, args) => { };
Diagnostic(ErrorCode.ERR_ObjectProhibited, "c.Event").WithArguments("C.Event").WithLocation(12, 19),
// CS0067: The event 'C.Event' is never used
// static event EventHandler Event;
Diagnostic(ErrorCode.WRN_UnreferencedEvent, "Event").WithArguments("C.Event").WithLocation(7, 31)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IEventReference_AccessEvent_StaticEventAccessOnClass()
{
string source = @"
using System;
class C
{
static event EventHandler Event;
public static void M()
{
/*<bind>*/C.Event/*</bind>*/(null, null);
}
}
";
string expectedOperationTree = @"
IEventReferenceOperation: event System.EventHandler C.Event (Static) (OperationKind.EventReference, Type: System.EventHandler) (Syntax: 'C.Event')
Instance Receiver:
null
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IEventReference_AccessEvent_InstanceEventAccessOnClass()
{
string source = @"
using System;
class C
{
event EventHandler Event;
public static void M()
{
/*<bind>*/C.Event/*</bind>*/(null, null);
}
}
";
string expectedOperationTree = @"
IEventReferenceOperation: event System.EventHandler C.Event (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 'C.Event')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0120: An object reference is required for the non-static field, method, or property 'C.Event'
// /*<bind>*/C.Event/*</bind>*/(null, null);
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.Event").WithArguments("C.Event").WithLocation(10, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IEventReference_AccessEvent_StaticEventWithInstanceReceiver()
{
string source = @"
using System;
class C
{
static event EventHandler Event;
public static void M()
{
var c = new C();
/*<bind>*/c.Event/*</bind>*/(null, null);
}
}
";
string expectedOperationTree = @"
IEventReferenceOperation: event System.EventHandler C.Event (Static) (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 'c.Event')
Instance Receiver:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0176: Member 'C.Event' cannot be accessed with an instance reference; qualify it with a type name instead
// /*<bind>*/c.Event/*</bind>*/(null, null);
Diagnostic(ErrorCode.ERR_ObjectProhibited, "c.Event").WithArguments("C.Event").WithLocation(11, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
......@@ -241,5 +241,132 @@ void M()
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IFieldReference_StaticFieldWithInstanceReceiver()
{
string source = @"
class C
{
static int i;
public static void M()
{
var c = new C();
var i1 = /*<bind>*/c.i/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IFieldReferenceOperation: System.Int32 C.i (Static) (OperationKind.FieldReference, Type: System.Int32, IsInvalid) (Syntax: 'c.i')
Instance Receiver:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0176: Member 'C.i' cannot be accessed with an instance reference; qualify it with a type name instead
// var i1 = /*<bind>*/c.i/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectProhibited, "c.i").WithArguments("C.i").WithLocation(9, 28),
// CS0649: Field 'C.i' is never assigned to, and will always have its default value 0
// static int i;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "i").WithArguments("C.i", "0").WithLocation(4, 16)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IFieldReference_StaticFieldInObjectInitializer_NoInstance()
{
string source = @"
class C
{
static int i1;
public static void Main()
{
var c = new C { /*<bind>*/i1/*</bind>*/ = 1 };
}
}
";
string expectedOperationTree = @"
IFieldReferenceOperation: System.Int32 C.i1 (Static) (OperationKind.FieldReference, Type: System.Int32, IsInvalid) (Syntax: 'i1')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1914: Static field or property 'C.i1' cannot be assigned in an object initializer
// var c = new C { /*<bind>*/i1/*</bind>*/ = 1 };
Diagnostic(ErrorCode.ERR_StaticMemberInObjectInitializer, "i1").WithArguments("C.i1").WithLocation(7, 35),
// CS0414: The field 'C.i1' is assigned but its value is never used
// static int i1;
Diagnostic(ErrorCode.WRN_UnreferencedFieldAssg, "i1").WithArguments("C.i1").WithLocation(4, 16)
};
VerifyOperationTreeAndDiagnosticsForTest<IdentifierNameSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IFieldReference_StaticField()
{
string source = @"
class C
{
static int i;
public static void M()
{
var i1 = /*<bind>*/C.i/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IFieldReferenceOperation: System.Int32 C.i (Static) (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'C.i')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0649: Field 'C.i' is never assigned to, and will always have its default value 0
// static int i;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "i").WithArguments("C.i", "0").WithLocation(4, 16)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IFieldReference_InstanceField_InvalidAccessOffOfClass()
{
string source = @"
class C
{
int i;
public static void M()
{
var i1 = /*<bind>*/C.i/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IFieldReferenceOperation: System.Int32 C.i (OperationKind.FieldReference, Type: System.Int32, IsInvalid) (Syntax: 'C.i')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0120: An object reference is required for the non-static field, method, or property 'C.i'
// var i1 = /*<bind>*/C.i/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.i").WithArguments("C.i").WithLocation(8, 28),
// CS0649: Field 'C.i' is never assigned to, and will always have its default value 0
// int i;
Diagnostic(ErrorCode.WRN_UnassignedInternalField, "i").WithArguments("C.i", "0").WithLocation(4, 9)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
// 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.Test.Utilities;
using Xunit;
namespace Microsoft.CodeAnalysis.CSharp.UnitTests
{
public partial class IOperationTests : SemanticModelTestBase
{
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IInvocation_StaticMethodWithInstanceReceiver()
{
string source = @"
class C
{
static void M1() { }
public static void M2()
{
var c = new C();
/*<bind>*/c.M1()/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IInvocationOperation ( void C.M1()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'c.M1()')
Instance Receiver:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Arguments(0)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0176: Member 'C.M1()' cannot be accessed with an instance reference; qualify it with a type name instead
// /*<bind>*/c.M1()/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectProhibited, "c.M1").WithArguments("C.M1()").WithLocation(9, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IInvocation_StaticMethodAccessOnType()
{
string source = @"
class C
{
static void M1() { }
public static void M2()
{
/*<bind>*/C.M1()/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IInvocationOperation (void C.M1()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'C.M1()')
Instance Receiver:
null
Arguments(0)
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IInvocation_InstanceMethodAccessOnType()
{
string source = @"
class C
{
void M1() { }
public static void M2()
{
/*<bind>*/C.M1()/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IInvocationOperation (void C.M1()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'C.M1()')
Instance Receiver:
null
Arguments(0)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0120: An object reference is required for the non-static field, method, or property 'C.M1()'
// /*<bind>*/C.M1()/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.M1").WithArguments("C.M1()").WithLocation(8, 19)
};
VerifyOperationTreeAndDiagnosticsForTest<InvocationExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
// 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.Test.Utilities;
......@@ -45,5 +45,310 @@ class C2 : C1
VerifyOperationTreeAndDiagnosticsForTest<AssignmentExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_StaticPropertyWithInstanceReceiver()
{
string source = @"
class C
{
static int I { get; }
public static void M()
{
var c = new C();
var i1 = /*<bind>*/c.I/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 C.I { get; } (Static) (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'c.I')
Instance Receiver:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0176: Member 'C.I' cannot be accessed with an instance reference; qualify it with a type name instead
// var i1 = /*<bind>*/c.I/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectProhibited, "c.I").WithArguments("C.I").WithLocation(9, 28)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_StaticPropertyAccessOnClass()
{
string source = @"
class C
{
static int I { get; }
public static void M()
{
var i1 = /*<bind>*/C.I/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 C.I { get; } (Static) (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'C.I')
Instance Receiver:
null
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_InstancePropertyAccessOnClass()
{
string source = @"
class C
{
int I { get; }
public static void M()
{
var i1 = /*<bind>*/C.I/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 C.I { get; } (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'C.I')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0120: An object reference is required for the non-static field, method, or property 'C.I'
// var i1 = /*<bind>*/C.I/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.I").WithArguments("C.I").WithLocation(8, 28)
};
VerifyOperationTreeAndDiagnosticsForTest<MemberAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_StaticPropertyWithInstanceReceiver_Indexer()
{
string source = @"
using System.Collections.Generic;
class C
{
static List<int> list = new List<int>();
public static void M()
{
var c = new C();
var i1 = /*<bind>*/c.list[1]/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 System.Collections.Generic.List<System.Int32>.this[System.Int32 index] { get; set; } (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'c.list[1]')
Instance Receiver:
IFieldReferenceOperation: System.Collections.Generic.List<System.Int32> C.list (Static) (OperationKind.FieldReference, Type: System.Collections.Generic.List<System.Int32>, IsInvalid) (Syntax: 'c.list')
Instance Receiver:
ILocalReferenceOperation: c (OperationKind.LocalReference, Type: C, IsInvalid) (Syntax: 'c')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: index) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0176: Member 'C.list' cannot be accessed with an instance reference; qualify it with a type name instead
// var i1 = /*<bind>*/c.list[1]/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectProhibited, "c.list").WithArguments("C.list").WithLocation(11, 28)
};
VerifyOperationTreeAndDiagnosticsForTest<ElementAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_StaticPropertyAccessOnClass_IndexerOnProperty()
{
string source = @"
using System.Collections.Generic;
class C
{
static List<int> list = new List<int>();
public static void M()
{
var i1 = /*<bind>*/C.list[1]/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 System.Collections.Generic.List<System.Int32>.this[System.Int32 index] { get; set; } (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'C.list[1]')
Instance Receiver:
IFieldReferenceOperation: System.Collections.Generic.List<System.Int32> C.list (Static) (OperationKind.FieldReference, Type: System.Collections.Generic.List<System.Int32>) (Syntax: 'C.list')
Instance Receiver:
null
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: index) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
";
var expectedDiagnostics = DiagnosticDescription.None;
VerifyOperationTreeAndDiagnosticsForTest<ElementAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_InstancePropertyAccessOnClass_IndexerOnProperty()
{
string source = @"
using System.Collections.Generic;
class C
{
List<int> list = new List<int>();
public static void M()
{
var i1 = /*<bind>*/C.list[1]/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 System.Collections.Generic.List<System.Int32>.this[System.Int32 index] { get; set; } (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'C.list[1]')
Instance Receiver:
IFieldReferenceOperation: System.Collections.Generic.List<System.Int32> C.list (OperationKind.FieldReference, Type: System.Collections.Generic.List<System.Int32>, IsInvalid) (Syntax: 'C.list')
Instance Receiver:
null
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: index) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0120: An object reference is required for the non-static field, method, or property 'C.list'
// var i1 = /*<bind>*/C.list[1]/*</bind>*/;
Diagnostic(ErrorCode.ERR_ObjectRequired, "C.list").WithArguments("C.list").WithLocation(10, 28)
};
VerifyOperationTreeAndDiagnosticsForTest<ElementAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_InstancePropertyAccessOnClass_IndexerAccessOnType()
{
string source = @"
class C
{
public C this[int i]
{
get => null;
set { }
}
public static void M()
{
var c1 = /*<bind>*/C[1]/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: C C.this[System.Int32 i] { get; set; } (OperationKind.PropertyReference, Type: C, IsInvalid) (Syntax: 'C[1]')
Instance Receiver:
IInvalidOperation (OperationKind.Invalid, Type: C, IsInvalid, IsImplicit) (Syntax: 'C')
Children(1):
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'C')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0119: 'C' is a type, which is not valid in the given context
// var c1 = /*<bind>*/C[1]/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadSKunknown, "C").WithArguments("C", "type").WithLocation(12, 28)
};
VerifyOperationTreeAndDiagnosticsForTest<ElementAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_InstancePropertyAccessOnClass_StaticIndexerAccessOnType()
{
string source = @"
class C
{
public static C this[int i]
{
get => null;
set { }
}
public static void M()
{
var c1 = /*<bind>*/C[1]/*</bind>*/;
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: C C.this[System.Int32 i] { get; set; } (OperationKind.PropertyReference, Type: C, IsInvalid) (Syntax: 'C[1]')
Instance Receiver:
IInvalidOperation (OperationKind.Invalid, Type: C, IsInvalid, IsImplicit) (Syntax: 'C')
Children(1):
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'C')
Arguments(1):
IArgumentOperation (ArgumentKind.Explicit, Matching Parameter: i) (OperationKind.Argument, Type: null) (Syntax: '1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
InConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
OutConversion: CommonConversion (Exists: True, IsIdentity: True, IsNumeric: False, IsReference: False, IsUserDefined: False) (MethodSymbol: null)
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS0106: The modifier 'static' is not valid for this item
// public static C this[int i]
Diagnostic(ErrorCode.ERR_BadMemberFlag, "this").WithArguments("static").WithLocation(4, 21),
// CS0119: 'C' is a type, which is not valid in the given context
// var c1 = /*<bind>*/C[1]/*</bind>*/;
Diagnostic(ErrorCode.ERR_BadSKunknown, "C").WithArguments("C", "type").WithLocation(12, 28)
};
VerifyOperationTreeAndDiagnosticsForTest<ElementAccessExpressionSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
[CompilerTrait(CompilerFeature.IOperation)]
[Fact]
public void IPropertyReference_StaticPropertyInObjectInitializer_NoInstance()
{
string source = @"
class C
{
static int I1 { get; set; }
public static void Main()
{
var c = new C { /*<bind>*/I1/*</bind>*/ = 1 };
}
}
";
string expectedOperationTree = @"
IPropertyReferenceOperation: System.Int32 C.I1 { get; set; } (Static) (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'I1')
Instance Receiver:
null
";
var expectedDiagnostics = new DiagnosticDescription[] {
// CS1914: Static field or property 'C.I1' cannot be assigned in an object initializer
// var c = new C { /*<bind>*/I1/*</bind>*/ = 1 };
Diagnostic(ErrorCode.ERR_StaticMemberInObjectInitializer, "I1").WithArguments("C.I1").WithLocation(7, 35)
};
VerifyOperationTreeAndDiagnosticsForTest<IdentifierNameSyntax>(source, expectedOperationTree, expectedDiagnostics);
}
}
}
......@@ -1725,7 +1725,7 @@ public static void Main()
Left:
IFieldReferenceOperation: X.x (Static) (OperationKind.FieldReference, Type: X, IsInvalid) (Syntax: 'x')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: X, IsInvalid, IsImplicit) (Syntax: 'x')
null
Right:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 0) (Syntax: '0')
";
......@@ -1764,14 +1764,14 @@ public static void Main()
Left:
IFieldReferenceOperation: System.Int32 MemberInitializerTest.x (Static) (OperationKind.FieldReference, Type: System.Int32, IsInvalid) (Syntax: 'x')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: MemberInitializerTest, IsInvalid, IsImplicit) (Syntax: 'x')
null
Right:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Int32, IsInvalid) (Syntax: 'Prop = 1')
Left:
IPropertyReferenceOperation: System.Int32 MemberInitializerTest.Prop { get; set; } (Static) (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'Prop')
Instance Receiver:
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: MemberInitializerTest, IsInvalid, IsImplicit) (Syntax: 'Prop')
null
Right:
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
";
......
......@@ -81,6 +81,7 @@ public static IInvalidOperation CreateInvalidExpression(SemanticModel semanticMo
return new InvalidOperation(children, semanticModel, syntax, type: null, constantValue: default(Optional<object>), isImplicit: isImplicit);
}
public static Lazy<IVariableInitializerOperation> EmptyInitializer { get; } = new Lazy<IVariableInitializerOperation>(() => null);
public static Lazy<IOperation> NullOperation { get; } = new Lazy<IOperation>(() => null);
public static Lazy<IVariableInitializerOperation> NullInitializer { get; } = new Lazy<IVariableInitializerOperation>(() => null);
}
}
......@@ -13,9 +13,6 @@ Namespace Microsoft.CodeAnalysis.Operations
Private ReadOnly _cache As ConcurrentDictionary(Of BoundNode, IOperation) =
New ConcurrentDictionary(Of BoundNode, IOperation)(concurrencyLevel:=2, capacity:=10)
Private ReadOnly _lazyNothingOperation As Lazy(Of IOperation) =
New Lazy(Of IOperation)(Function() Nothing)
Private ReadOnly _semanticModel As SemanticModel
Public Sub New(semanticModel As SemanticModel)
......@@ -369,15 +366,14 @@ Namespace Microsoft.CodeAnalysis.Operations
Private Function CreateBoundCallOperation(boundCall As BoundCall) As IInvocationOperation
Dim targetMethod As IMethodSymbol = boundCall.Method
Dim receiver As IOperation = Create(boundCall.ReceiverOpt)
Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() If(targetMethod.IsShared, Nothing, receiver))
Dim instance As Lazy(Of IOperation) = CreateReceiverOperation(If(boundCall.ReceiverOpt, boundCall.MethodGroupOpt?.ReceiverOpt), targetMethod)
Dim isVirtual As Boolean =
targetMethod IsNot Nothing AndAlso
instance IsNot Nothing AndAlso
(targetMethod.IsVirtual OrElse targetMethod.IsAbstract OrElse targetMethod.IsOverride) AndAlso
receiver.Kind <> BoundKind.MyBaseReference AndAlso
receiver.Kind <> BoundKind.MyClassReference
If(boundCall.ReceiverOpt?.Kind <> BoundKind.MyBaseReference, False) AndAlso
If(boundCall.ReceiverOpt?.Kind <> BoundKind.MyClassReference, False)
Dim arguments As Lazy(Of ImmutableArray(Of IArgumentOperation)) = New Lazy(Of ImmutableArray(Of IArgumentOperation))(
Function()
......@@ -620,12 +616,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Dim receiverOpt As BoundExpression = If(boundDelegateCreationExpression.ReceiverOpt, boundDelegateCreationExpression.MethodGroupOpt?.ReceiverOpt)
If receiverOpt IsNot Nothing AndAlso method IsNot Nothing AndAlso method.IsShared AndAlso
receiverOpt.WasCompilerGenerated AndAlso receiverOpt.Kind = BoundKind.MeReference Then
receiverOpt = Nothing
End If
Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(receiverOpt))
Dim instance As Lazy(Of IOperation) = CreateReceiverOperation(receiverOpt, method)
' The compiler creates a BoundDelegateCreationExpression node for the AddressOf expression, and that's the node we want to use for the operand
' of the IDelegateCreationExpression parent
......@@ -769,16 +760,10 @@ Namespace Microsoft.CodeAnalysis.Operations
End Function
Private Function CreateBoundPropertyAccessOperation(boundPropertyAccess As BoundPropertyAccess) As IPropertyReferenceOperation
Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)(
Function()
If boundPropertyAccess.PropertySymbol.IsShared Then
Return Nothing
Else
Return Create(boundPropertyAccess.ReceiverOpt)
End If
End Function)
Dim [property] As IPropertySymbol = boundPropertyAccess.PropertySymbol
Dim instance As Lazy(Of IOperation) =
CreateReceiverOperation(If(boundPropertyAccess.ReceiverOpt, boundPropertyAccess.PropertyGroupOpt?.ReceiverOpt), [property])
Dim arguments As Lazy(Of ImmutableArray(Of IArgumentOperation)) = New Lazy(Of ImmutableArray(Of IArgumentOperation))(
Function()
Return If(boundPropertyAccess.Arguments.Length = 0,
......@@ -809,16 +794,9 @@ Namespace Microsoft.CodeAnalysis.Operations
End Function
Private Function CreateBoundEventAccessOperation(boundEventAccess As BoundEventAccess) As IEventReferenceOperation
Dim instance As Lazy(Of IOperation) = New Lazy(Of IOperation)(
Function()
If boundEventAccess.EventSymbol.IsShared Then
Return Nothing
Else
Return Create(boundEventAccess.ReceiverOpt)
End If
End Function)
Dim [event] As IEventSymbol = boundEventAccess.EventSymbol
Dim instance As Lazy(Of IOperation) = CreateReceiverOperation(boundEventAccess.ReceiverOpt, [event])
Dim syntax As SyntaxNode = boundEventAccess.Syntax
Dim type As ITypeSymbol = boundEventAccess.Type
Dim constantValue As [Optional](Of Object) = ConvertToOptional(boundEventAccess.ConstantValueOpt)
......@@ -829,14 +807,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Private Function CreateBoundFieldAccessOperation(boundFieldAccess As BoundFieldAccess) As IFieldReferenceOperation
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
Return Nothing
Else
Return Create(boundFieldAccess.ReceiverOpt)
End If
End Function)
Dim instance As Lazy(Of IOperation) = CreateReceiverOperation(boundFieldAccess.ReceiverOpt, field)
Dim syntax As SyntaxNode = boundFieldAccess.Syntax
Dim type As ITypeSymbol = boundFieldAccess.Type
......@@ -1238,7 +1209,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Private Function CreateBoundWhileStatementOperation(boundWhileStatement As BoundWhileStatement) As IWhileLoopOperation
Dim condition As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundWhileStatement.Condition))
Dim body As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundWhileStatement.Body))
Dim ignoredCondition As Lazy(Of IOperation) = _lazyNothingOperation
Dim ignoredCondition As Lazy(Of IOperation) = OperationFactory.NullOperation
Dim locals As ImmutableArray(Of ILocalSymbol) = ImmutableArray(Of ILocalSymbol).Empty
Dim conditionIsTop As Boolean = True
Dim conditionIsUntil As Boolean = False
......@@ -1270,7 +1241,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Private Function CreateBoundLabelStatementOperation(boundLabelStatement As BoundLabelStatement) As ILabeledOperation
Dim label As ILabelSymbol = boundLabelStatement.Label
Dim statement As Lazy(Of IOperation) = _lazyNothingOperation
Dim statement As Lazy(Of IOperation) = OperationFactory.NullOperation
Dim syntax As SyntaxNode = boundLabelStatement.Syntax
Dim type As ITypeSymbol = Nothing
Dim constantValue As [Optional](Of Object) = New [Optional](Of Object)()
......@@ -1415,7 +1386,7 @@ Namespace Microsoft.CodeAnalysis.Operations
boundInstance = receiver
End If
Dim eventReferenceInstance As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() If(eventSymbol.IsShared, Nothing, Create(boundInstance)))
Dim eventReferenceInstance As Lazy(Of IOperation) = CreateReceiverOperation(boundInstance, eventSymbol)
Dim eventReference As Lazy(Of IEventReferenceOperation) = New Lazy(Of IEventReferenceOperation)(Function() As IEventReferenceOperation
Return New LazyEventReferenceExpression(eventSymbol,
......@@ -1517,7 +1488,7 @@ Namespace Microsoft.CodeAnalysis.Operations
End Function
Private Function CreateBoundAnonymousTypePropertyAccessOperation(boundAnonymousTypePropertyAccess As BoundAnonymousTypePropertyAccess) As IPropertyReferenceOperation
Dim instance As Lazy(Of IOperation) = _lazyNothingOperation
Dim instance As Lazy(Of IOperation) = OperationFactory.NullOperation
Dim [property] As IPropertySymbol = DirectCast(boundAnonymousTypePropertyAccess.ExpressionSymbol, IPropertySymbol)
Dim arguments As Lazy(Of ImmutableArray(Of IArgumentOperation)) = New Lazy(Of ImmutableArray(Of IArgumentOperation))(Function() ImmutableArray(Of IArgumentOperation).Empty)
Dim syntax As SyntaxNode = boundAnonymousTypePropertyAccess.Syntax
......
......@@ -162,6 +162,23 @@ Namespace Microsoft.CodeAnalysis.Operations
isImplicit:=isImplicit OrElse argument Is Nothing)
End Function
Private Function CreateReceiverOperation(node As BoundNode, symbol As ISymbol) As Lazy(Of IOperation)
If node Is Nothing OrElse node.Kind = BoundKind.TypeExpression Then
Return OperationFactory.NullOperation
End If
If symbol IsNot Nothing AndAlso
node.WasCompilerGenerated AndAlso
symbol.IsStatic AndAlso
(node.Kind = BoundKind.MeReference OrElse
node.Kind = BoundKind.WithLValueExpressionPlaceholder OrElse
node.Kind = BoundKind.WithRValueExpressionPlaceholder) Then
Return OperationFactory.NullOperation
End If
Return New Lazy(Of IOperation)(Function() Create(node))
End Function
Private Shared Function ParameterIsParamArray(parameter As VisualBasic.Symbols.ParameterSymbol) As Boolean
Return If(parameter.IsParamArray AndAlso parameter.Type.Kind = SymbolKind.ArrayType, DirectCast(parameter.Type, VisualBasic.Symbols.ArrayTypeSymbol).IsSZArray, False)
End Function
......
......@@ -499,6 +499,47 @@ BC30991: Member 'Field1' cannot be initialized in an object initializer expressi
VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub ObjectInitializerInitializeSharedPropertyOnNewInstance()
Dim source = <![CDATA[
Option Strict On
Imports System
Class C1
Public Shared Property Property1 As String
Public Shared Sub Main()
Dim c1 As New C1() With {.Property1 = "Hello World!"}'BIND:"New C1() With {.Property1 = "Hello World!"}"
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IObjectCreationOperation (Constructor: Sub C1..ctor()) (OperationKind.ObjectCreation, Type: C1, IsInvalid) (Syntax: 'New C1() Wi ... lo World!"}')
Arguments(0)
Initializer:
IObjectOrCollectionInitializerOperation (OperationKind.ObjectOrCollectionInitializer, Type: C1, IsInvalid) (Syntax: 'With {.Prop ... lo World!"}')
Initializers(1):
ISimpleAssignmentOperation (OperationKind.SimpleAssignment, Type: System.Void, IsInvalid) (Syntax: '.Property1 ... llo World!"')
Left:
IPropertyReferenceOperation: Property C1.Property1 As System.String (Static) (OperationKind.PropertyReference, Type: System.String, IsInvalid) (Syntax: 'Property1')
Instance Receiver:
null
Right:
ILiteralOperation (OperationKind.Literal, Type: System.String, Constant: "Hello World!") (Syntax: '"Hello World!"')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30991: Member 'Property1' cannot be initialized in an object initializer expression because it is shared.
Dim c1 As New C1() With {.Property1 = "Hello World!"}'BIND:"New C1() With {.Property1 = "Hello World!"}"
~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub ObjectInitializerInitializeNonExistentField()
......
......@@ -3406,6 +3406,102 @@ BC30002: Type 'NonExistant' is not defined.
VerifyOperationTreeAndDiagnosticsForTest(Of ObjectCreationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IDelegateCreation_SharedAddressOfWithInstanceReceiver()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Sub S1()
End Sub
Shared Sub S2()
Dim c1Instance As New C1
Dim a As Action = AddressOf c1Instance.S1'BIND:"AddressOf c1Instance.S1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IMethodReferenceOperation: Sub M1.C1.S1() (Static) (OperationKind.MethodReference, Type: null) (Syntax: 'AddressOf c1Instance.S1')
Instance Receiver:
ILocalReferenceOperation: c1Instance (OperationKind.LocalReference, Type: M1.C1) (Syntax: 'c1Instance')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
Dim a As Action = AddressOf c1Instance.S1'BIND:"AddressOf c1Instance.S1"
~~~~~~~~~~~~~~~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of UnaryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IDelegateCreation_SharedAddressOfAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Sub S1()
End Sub
Shared Sub S2()
Dim a As Action = AddressOf C1.S1'BIND:"AddressOf C1.S1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IMethodReferenceOperation: Sub M1.C1.S1() (Static) (OperationKind.MethodReference, Type: null) (Syntax: 'AddressOf C1.S1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of UnaryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IDelegateCreation_InstanceAddressOfAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Sub S1()
End Sub
Shared Sub S2()
Dim a As Action = AddressOf C1.S1'BIND:"AddressOf C1.S1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'AddressOf C1.S1')
Children(1):
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'C1.S1')
Children(1):
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'C1')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30469: Reference to a non-shared member requires an object reference.
Dim a As Action = AddressOf C1.S1'BIND:"AddressOf C1.S1"
~~~~~~~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of UnaryExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
#End Region
#Region "Anonymous Delegates"
......
......@@ -233,7 +233,7 @@ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null) (S
Event Reference:
IEventReferenceOperation: Event TestClass.TestEvent As System.Action (Static) (OperationKind.EventReference, Type: System.Action) (Syntax: 'Me.TestEvent')
Instance Receiver:
null
IInstanceReferenceOperation (OperationKind.InstanceReference, Type: TestClass) (Syntax: 'Me')
Handler:
IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Action, IsImplicit) (Syntax: 'AddressOf M')
Target:
......@@ -275,7 +275,7 @@ IExpressionStatementOperation (OperationKind.ExpressionStatement, Type: null, Is
Event Reference:
IEventReferenceOperation: Event TestClass.TestEvent As System.Action (OperationKind.EventReference, Type: System.Action, IsInvalid) (Syntax: 'TestClass.TestEvent')
Instance Receiver:
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'TestClass')
null
Handler:
IDelegateCreationOperation (OperationKind.DelegateCreation, Type: System.Action, IsImplicit) (Syntax: 'AddressOf M')
Target:
......
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
Inherits SemanticModelTestBase
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IEventReference_AddHandlerSharedEvent()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Event E1 As EventHandler
Shared Sub S2()
AddHandler E1, Sub(sender, args)'BIND:"E1"
End Sub
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IEventReferenceOperation: Event M1.C1.E1 As System.EventHandler (Static) (OperationKind.EventReference, Type: System.EventHandler) (Syntax: 'E1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of IdentifierNameSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IEventReference_AddHandlerSharedEventWithInstanceReference()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Event E1 As EventHandler
Shared Sub S2()
Dim c1Instance As New C1
AddHandler c1Instance.E1, Sub(sender, arg) Console.WriteLine()'BIND:"c1Instance.E1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IEventReferenceOperation: Event M1.C1.E1 As System.EventHandler (Static) (OperationKind.EventReference, Type: System.EventHandler) (Syntax: 'c1Instance.E1')
Instance Receiver:
ILocalReferenceOperation: c1Instance (OperationKind.LocalReference, Type: M1.C1) (Syntax: 'c1Instance')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
AddHandler c1Instance.E1, Sub(sender, arg) Console.WriteLine()'BIND:"c1Instance.E1"
~~~~~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IEventReference_AddHandlerSharedEventAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Event E1 As EventHandler
Shared Sub S2()
Dim c1Instance As New C1
AddHandler C1.E1, Sub(sender, arg) Console.WriteLine()'BIND:"C1.E1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IEventReferenceOperation: Event M1.C1.E1 As System.EventHandler (Static) (OperationKind.EventReference, Type: System.EventHandler) (Syntax: 'C1.E1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IEventReference_AddHandlerInstanceEventAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Event E1 As EventHandler
Shared Sub S2()
Dim c1Instance As New C1
AddHandler C1.E1, Sub(sender, arg) Console.WriteLine()'BIND:"C1.E1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IEventReferenceOperation: Event M1.C1.E1 As System.EventHandler (OperationKind.EventReference, Type: System.EventHandler, IsInvalid) (Syntax: 'C1.E1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30469: Reference to a non-shared member requires an object reference.
AddHandler C1.E1, Sub(sender, arg) Console.WriteLine()'BIND:"C1.E1"
~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
......@@ -130,5 +130,152 @@ IFieldReferenceOperation: C.i As System.Int32 (OperationKind.FieldReference, Typ
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IFieldReference_SharedField()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared i1 As Integer
Shared Sub S2()
Dim i2 = i1'BIND:"i1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IFieldReferenceOperation: M1.C1.i1 As System.Int32 (Static) (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'i1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of IdentifierNameSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IFieldReference_SharedFieldWithInstanceReceiver()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared i1 As Integer = 1
Shared Sub S2()
Dim c1Instance As New C1
Dim i1 = c1Instance.i1'BIND:"c1Instance.i1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IFieldReferenceOperation: M1.C1.i1 As System.Int32 (Static) (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'c1Instance.i1')
Instance Receiver:
ILocalReferenceOperation: c1Instance (OperationKind.LocalReference, Type: M1.C1) (Syntax: 'c1Instance')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
Dim i1 = c1Instance.i1'BIND:"c1Instance.i1"
~~~~~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IFieldReference_SharedFieldAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared i1 As Integer = 1
Shared Sub S2()
Dim i1 = C1.i1'BIND:"C1.i1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IFieldReferenceOperation: M1.C1.i1 As System.Int32 (Static) (OperationKind.FieldReference, Type: System.Int32) (Syntax: 'C1.i1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IFieldReference_InstanceFieldAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Dim i1 As Integer = 1
Shared Sub S2()
Dim i1 = C1.i1'BIND:"C1.i1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IFieldReferenceOperation: M1.C1.i1 As System.Int32 (OperationKind.FieldReference, Type: System.Int32, IsInvalid) (Syntax: 'C1.i1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30469: Reference to a non-shared member requires an object reference.
Dim i1 = C1.i1'BIND:"C1.i1"
~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IFieldReference_StaticFieldReferenceInInitializer_RightHandSide()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Public Shared i1 As Integer
Public i2 As Integer
End Class
Sub S1()
Dim a = New C1 With {.i2 = .i1}'BIND:".i1"
End Sub
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IFieldReferenceOperation: M1.C1.i1 As System.Int32 (Static) (OperationKind.FieldReference, Type: System.Int32) (Syntax: '.i1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
' Copyright (c) Microsoft. All Rights Reserved. Licensed under the Apache License, Version 2.0. See License.txt in the project root for license information.
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.VisualBasic.UnitTests.Semantics
Partial Public Class IOperationTests
Inherits SemanticModelTestBase
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IInvocation_SharedMethodWithInstanceReceiver()
Dim source = <![CDATA[
Option Strict On
Module M1
Class C1
Shared Sub S1()
End Sub
Shared Sub S2()
Dim c1Instance As New C1
c1Instance.S1()'BIND:"c1Instance.S1()"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationOperation ( Sub M1.C1.S1()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'c1Instance.S1()')
Instance Receiver:
ILocalReferenceOperation: c1Instance (OperationKind.LocalReference, Type: M1.C1) (Syntax: 'c1Instance')
Arguments(0)
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
c1Instance.S1()'BIND:"c1Instance.S1()"
~~~~~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IInvocation_SharedMethodAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Module M1
Class C1
Shared Sub S1()
End Sub
Shared Sub S2()
C1.S1()'BIND:"C1.S1()"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationOperation (Sub M1.C1.S1()) (OperationKind.Invocation, Type: System.Void) (Syntax: 'C1.S1()')
Instance Receiver:
null
Arguments(0)
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IInvocation_InstanceMethodAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Module M1
Class C1
Sub S1()
End Sub
Shared Sub S2()
C1.S1()'BIND:"C1.S1()"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvocationOperation (Sub M1.C1.S1()) (OperationKind.Invocation, Type: System.Void, IsInvalid) (Syntax: 'C1.S1()')
Instance Receiver:
null
Arguments(0)
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30469: Reference to a non-shared member requires an object reference.
C1.S1()'BIND:"C1.S1()"
~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
' 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.
Imports Microsoft.CodeAnalysis.Test.Utilities
Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
......@@ -70,5 +70,122 @@ IPropertyReferenceOperation: Property M1.C1.P1 As System.Object (OperationKind.P
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IPropertyReference_SharedPropertyWithInstanceReceiver()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Property P1 As Integer
Shared Sub S2()
Dim c1Instance As New C1
Dim i1 As Integer = c1Instance.P1'BIND:"c1Instance.P1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IPropertyReferenceOperation: Property M1.C1.P1 As System.Int32 (Static) (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'c1Instance.P1')
Instance Receiver:
ILocalReferenceOperation: c1Instance (OperationKind.LocalReference, Type: M1.C1) (Syntax: 'c1Instance')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
Dim i1 As Integer = c1Instance.P1'BIND:"c1Instance.P1"
~~~~~~~~~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IPropertyReference_SharedPropertyAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Property P1 As Integer
Shared Sub S2()
Dim i1 As Integer = C1.P1'BIND:"C1.P1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IPropertyReferenceOperation: Property M1.C1.P1 As System.Int32 (Static) (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'C1.P1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IPropertyReference_InstancePropertyAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Property P1 As Integer
Shared Sub S2()
Dim i1 As Integer = C1.P1'BIND:"C1.P1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IPropertyReferenceOperation: Property M1.C1.P1 As System.Int32 (OperationKind.PropertyReference, Type: System.Int32, IsInvalid) (Syntax: 'C1.P1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30469: Reference to a non-shared member requires an object reference.
Dim i1 As Integer = C1.P1'BIND:"C1.P1"
~~~~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IPropertyReference_SharedProperty()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Shared Property P1 As Integer
Shared Sub S2()
Dim i1 = P1'BIND:"P1"
End Sub
End Class
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IPropertyReferenceOperation: Property M1.C1.P1 As System.Int32 (Static) (OperationKind.PropertyReference, Type: System.Int32) (Syntax: 'P1')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = String.Empty
VerifyOperationTreeAndDiagnosticsForTest(Of IdentifierNameSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
......@@ -112,5 +112,41 @@ IBlockOperation (3 statements) (OperationKind.Block, Type: null) (Syntax: 'Priva
VerifyOperationTreeAndDiagnosticsForTest(Of MethodBlockSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IWithStatement_StaticFieldReferenceAsRValue_NoInstanceReceiver()
Dim source = <![CDATA[
Imports System
Structure SSS
Public Shared A As String
Public Sub New(_a As String)
End Sub
End Structure
Class Clazz
Sub TEST(i As Integer)
With New SSS(Me.ToString())
.A = ""'BIND:".A"
End With
End Sub
End Class]]>.Value
Dim expectedOperationTree = <![CDATA[
IFieldReferenceOperation: SSS.A As System.String (Static) (OperationKind.FieldReference, Type: System.String) (Syntax: '.A')
Instance Receiver:
null
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC42025: Access of shared member, constant member, enum member or nested type through an instance; qualifying expression will not be evaluated.
.A = ""'BIND:".A"
~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of MemberAccessExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
' 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.
Imports Microsoft.CodeAnalysis.Operations
Imports Microsoft.CodeAnalysis.Test.Utilities
......@@ -463,5 +463,43 @@ BC30059: Constant expression is required.
VerifyOperationTreeAndDiagnosticsForTest(Of EqualsValueSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
<CompilerTrait(CompilerFeature.IOperation)>
<Fact()>
Public Sub IInvalid_InstanceIndexerAccessOnClass()
Dim source = <![CDATA[
Option Strict On
Imports System
Module M1
Class C1
Default Public ReadOnly Property Item(i As Integer) As C1
'indexer
Get
Return Nothing
End Get
End Property
End Class
Sub S1()
Dim a = C1(1)'BIND:"C1(1)"
End Sub
End Module]]>.Value
Dim expectedOperationTree = <![CDATA[
IInvalidOperation (OperationKind.Invalid, Type: ?, IsInvalid) (Syntax: 'C1(1)')
Children(2):
IOperation: (OperationKind.None, Type: null, IsInvalid) (Syntax: 'C1')
ILiteralOperation (OperationKind.Literal, Type: System.Int32, Constant: 1) (Syntax: '1')
]]>.Value
Dim expectedDiagnostics = <![CDATA[
BC30109: 'M1.C1' is a class type and cannot be used as an expression.
Dim a = C1(1)'BIND:"C1(1)"
~~
]]>.Value
VerifyOperationTreeAndDiagnosticsForTest(Of InvocationExpressionSyntax)(source, expectedOperationTree, expectedDiagnostics)
End Sub
End Class
End Namespace
......@@ -309,6 +309,21 @@ public static void ValidateIOperations(Func<Compilation> createCompilation)
Assert.True(argument.Descendants().All(n => n.IsImplicit), $"Explicit node in default argument value ({argument.Syntax.RawKind}): {argument.Syntax.ToString()}");
}
}
// Make sure that all static member references or invocations of static methods do not have implicit IInstanceReferenceOperations
// as their receivers
if (operation is IMemberReferenceOperation memberReference &&
memberReference.Member.IsStatic &&
memberReference.Instance is IInstanceReferenceOperation)
{
Assert.False(memberReference.Instance.IsImplicit, $"Implicit IInstanceReceiver on {operation.Syntax}");
}
else if (operation is IInvocationOperation invocation &&
invocation.TargetMethod.IsStatic &&
invocation.Instance is IInstanceReferenceOperation)
{
Assert.False(invocation.IsImplicit, $"Implicit IInstanceReceiver on {operation.Syntax}");
}
}
}
......
......@@ -785,6 +785,18 @@ public override void VisitInstanceReference(IInstanceReferenceOperation operatio
{
LogString(nameof(IInstanceReferenceOperation));
LogCommonPropertiesAndNewLine(operation);
if (operation.IsImplicit)
{
if (operation.Parent is IMemberReferenceOperation memberReference && memberReference.Instance == operation)
{
Assert.False(memberReference.Member.IsStatic);
}
else if (operation.Parent is IInvocationOperation invocation && invocation.Instance == operation)
{
Assert.False(invocation.TargetMethod.IsStatic);
}
}
}
private void VisitMemberReferenceExpressionCommon(IMemberReferenceOperation operation)
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册