Remove the OperationConstantValue wrapper type and push the WeakReference...

Remove the OperationConstantValue wrapper type and push the WeakReference logic into string specialized ConstantValue implemention. Optimized internal calls to `ConstantValue.HasValue` to get the underlying instance to avoid realizing strings for these cases.
上级 022b6e65
......@@ -1968,9 +1968,9 @@ public override CommonConversion ClassifyCommonConversion(ITypeSymbol source, IT
return ClassifyConversion(source, destination).ToCommonConversion();
}
internal override IConvertibleConversion ClassifyConvertibleConversion(IOperation source, ITypeSymbol? destination, out OperationConstantValue constantValue)
internal override IConvertibleConversion ClassifyConvertibleConversion(IOperation source, ITypeSymbol? destination, out ConstantValue? constantValue)
{
constantValue = OperationConstantValue.None;
constantValue = null;
if (destination is null)
{
......@@ -1979,11 +1979,12 @@ internal override IConvertibleConversion ClassifyConvertibleConversion(IOperatio
ITypeSymbol sourceType = source.Type;
ConstantValue? sourceConstantValue = source.GetConstantValue();
if (sourceType is null)
{
if (source.ConstantValue.HasValue && source.ConstantValue.Value is null && destination.IsReferenceType)
if (sourceConstantValue is { IsNull: true } && destination.IsReferenceType)
{
constantValue = source.GetConstantValue();
constantValue = sourceConstantValue;
return Conversion.NullLiteral;
}
......@@ -1992,9 +1993,11 @@ internal override IConvertibleConversion ClassifyConvertibleConversion(IOperatio
Conversion result = ClassifyConversion(sourceType, destination);
if (result.IsReference && source.ConstantValue.HasValue && source.ConstantValue.Value is null)
{
constantValue = source.GetConstantValue();
if (result.IsReference && sourceConstantValue is { IsNull: true } cv)
{
constantValue = sourceConstantValue;
}
}
return result;
......
......@@ -16,11 +16,6 @@ internal sealed partial class CSharpOperationFactory
{
private static readonly IConvertibleConversion s_boxedIdentityConversion = Conversion.Identity;
internal static OperationConstantValue ConvertToConstantValue(ConstantValue value)
{
return OperationConstantValue.Create(value);
}
internal ImmutableArray<BoundStatement> ToStatements(BoundStatement statement)
{
if (statement == null)
......@@ -37,7 +32,7 @@ internal ImmutableArray<BoundStatement> ToStatements(BoundStatement statement)
}
private IInstanceReferenceOperation CreateImplicitReceiver(SyntaxNode syntax, TypeSymbol type) =>
new InstanceReferenceOperation(InstanceReferenceKind.ImplicitReceiver, _semanticModel, syntax, type.GetPublicSymbol(), constantValue: OperationConstantValue.None, isImplicit: true);
new InstanceReferenceOperation(InstanceReferenceKind.ImplicitReceiver, _semanticModel, syntax, type.GetPublicSymbol(), constantValue: null, isImplicit: true);
internal IArgumentOperation CreateArgumentOperation(ArgumentKind kind, IParameterSymbol parameter, BoundExpression expression)
{
......@@ -95,7 +90,7 @@ internal IVariableInitializerOperation CreateVariableDeclaratorInitializer(Bound
initializerIsImplicit = true;
}
return new CSharpLazyVariableInitializerOperation(this, boundLocalDeclaration.InitializerOpt, _semanticModel, initializerSyntax, type: null, constantValue: OperationConstantValue.None, initializerIsImplicit);
return new CSharpLazyVariableInitializerOperation(this, boundLocalDeclaration.InitializerOpt, _semanticModel, initializerSyntax, type: null, constantValue: null, initializerIsImplicit);
}
return null;
......@@ -106,7 +101,7 @@ private IVariableDeclaratorOperation CreateVariableDeclaratorInternal(BoundLocal
ILocalSymbol symbol = boundLocalDeclaration.LocalSymbol.GetPublicSymbol();
SyntaxNode syntaxNode = boundLocalDeclaration.Syntax;
ITypeSymbol type = null;
var constantValue = OperationConstantValue.None;
ConstantValue constantValue = null;
bool isImplicit = false;
return new CSharpLazyVariableDeclaratorOperation(this, boundLocalDeclaration, symbol, _semanticModel, syntax, type, constantValue, isImplicit);
......@@ -114,7 +109,7 @@ private IVariableDeclaratorOperation CreateVariableDeclaratorInternal(BoundLocal
internal IVariableDeclaratorOperation CreateVariableDeclarator(BoundLocal boundLocal)
{
return boundLocal == null ? null : new VariableDeclaratorOperation(boundLocal.LocalSymbol.GetPublicSymbol(), initializer: null, ignoredArguments: ImmutableArray<IOperation>.Empty, semanticModel: _semanticModel, syntax: boundLocal.Syntax, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
return boundLocal == null ? null : new VariableDeclaratorOperation(boundLocal.LocalSymbol.GetPublicSymbol(), initializer: null, ignoredArguments: ImmutableArray<IOperation>.Empty, semanticModel: _semanticModel, syntax: boundLocal.Syntax, type: null, constantValue: null, isImplicit: false);
}
internal IOperation CreateReceiverOperation(BoundNode instance, Symbol symbol)
......@@ -156,7 +151,7 @@ internal IEventReferenceOperation CreateBoundEventAccessOperation(BoundEventAssi
SyntaxNode eventAccessSyntax = ((AssignmentExpressionSyntax)syntax).Left;
bool isImplicit = boundEventAssignmentOperator.WasCompilerGenerated;
return new CSharpLazyEventReferenceOperation(this, instance, @event, _semanticModel, eventAccessSyntax, @event.Type, ConvertToConstantValue(null), isImplicit);
return new CSharpLazyEventReferenceOperation(this, instance, @event, _semanticModel, eventAccessSyntax, @event.Type, constantValue: null, isImplicit);
}
internal IOperation CreateDelegateTargetOperation(BoundNode delegateNode)
......@@ -393,7 +388,7 @@ internal static ImmutableArray<BoundNode> CreateInvalidChildrenFromArgumentsExpr
semanticModel: _semanticModel,
syntax: syntax,
type: type,
constantValue: OperationConstantValue.None,
constantValue: null,
isImplicit: true);
// Find matching declaration for the current argument.
......@@ -409,7 +404,7 @@ internal static ImmutableArray<BoundNode> CreateInvalidChildrenFromArgumentsExpr
semanticModel: _semanticModel,
syntax: value.Syntax,
type: property.Type.GetPublicSymbol(),
constantValue: OperationConstantValue.None,
constantValue: null,
isImplicit: true);
isImplicitAssignment = true;
}
......@@ -421,7 +416,7 @@ internal static ImmutableArray<BoundNode> CreateInvalidChildrenFromArgumentsExpr
_semanticModel,
anonymousProperty.Syntax,
anonymousProperty.Type.GetPublicSymbol(),
ConvertToConstantValue(anonymousProperty.ConstantValue),
anonymousProperty.ConstantValue,
anonymousProperty.WasCompilerGenerated);
isImplicitAssignment = isImplicit;
}
......
......@@ -75,7 +75,7 @@ public void IDynamicInvocationExpression_PublicExtensionMethodTests()
Assert.Throws<ArgumentNullException>(() => nullDynamicExpression.GetArgumentRefKind(0));
Func<ImmutableArray<IOperation>, ImmutableArray<string>, ImmutableArray<RefKind>, HasDynamicArgumentsExpression> createDynamicExpression =
(arguments, argumentNames, argumentRefKinds) => new DynamicInvocationOperation(null, arguments, argumentNames, argumentRefKinds, null, null, null, OperationConstantValue.None, false);
(arguments, argumentNames, argumentRefKinds) => new DynamicInvocationOperation(operation: null, arguments, argumentNames, argumentRefKinds, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: false);
TestCore(createDynamicExpression);
}
......@@ -90,7 +90,7 @@ public void IDynamicIndexerAccessExpression_PublicExtensionMethodTests()
Assert.Throws<ArgumentNullException>(() => nullDynamicExpression.GetArgumentRefKind(0));
Func<ImmutableArray<IOperation>, ImmutableArray<string>, ImmutableArray<RefKind>, HasDynamicArgumentsExpression> createDynamicExpression =
(arguments, argumentNames, argumentRefKinds) => new DynamicIndexerAccessOperation(null, arguments, argumentNames, argumentRefKinds, null, null, null, OperationConstantValue.None, false);
(arguments, argumentNames, argumentRefKinds) => new DynamicIndexerAccessOperation(operation: null, arguments, argumentNames, argumentRefKinds, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: false);
TestCore(createDynamicExpression);
}
......@@ -105,7 +105,7 @@ public void IDynamicObjectCreationExpression_PublicExtensionMethodTests()
Assert.Throws<ArgumentNullException>(() => nullDynamicExpression.GetArgumentRefKind(0));
Func<ImmutableArray<IOperation>, ImmutableArray<string>, ImmutableArray<RefKind>, HasDynamicArgumentsExpression> createDynamicExpression =
(arguments, argumentNames, argumentRefKinds) => new DynamicObjectCreationOperation(arguments, argumentNames, argumentRefKinds, null, null, null, null, OperationConstantValue.None, false);
(arguments, argumentNames, argumentRefKinds) => new DynamicObjectCreationOperation(arguments, argumentNames, argumentRefKinds, initializer: null, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: false);
TestCore(createDynamicExpression);
}
......@@ -127,7 +127,7 @@ public void TestGetFlowGraphNullArgument()
public void TestGetFlowGraphInvalidArgumentWithNonNullParent()
{
IOperation parent = new BlockOperation(ImmutableArray<IOperation>.Empty, ImmutableArray<ILocalSymbol>.Empty,
semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: false);
TestGetFlowGraphInvalidArgumentCore(argumentExceptionMessage: CodeAnalysisResources.NotARootOperation, parent);
}
......@@ -146,7 +146,7 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage
{
IBlockOperation block = new BlockOperation(
ImmutableArray<IOperation>.Empty, ImmutableArray<ILocalSymbol>.Empty,
semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: false);
block = Operation.SetParentOperation(block, parent);
_ = ControlFlowGraph.Create(block);
}
......@@ -164,7 +164,7 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage
IFieldInitializerOperation initializer = new FieldInitializerOperation(
ImmutableArray<IFieldSymbol>.Empty, ImmutableArray<ILocalSymbol>.Empty,
value: null, semanticModel: null,
syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
syntax: null, type: null, constantValue: null, isImplicit: false);
initializer = Operation.SetParentOperation(initializer, parent);
_ = ControlFlowGraph.Create(initializer);
}
......@@ -182,7 +182,7 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage
IPropertyInitializerOperation initializer = new PropertyInitializerOperation(
ImmutableArray<IPropertySymbol>.Empty, ImmutableArray<ILocalSymbol>.Empty,
value: null, semanticModel: null,
syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
syntax: null, type: null, constantValue: null, isImplicit: false);
initializer = Operation.SetParentOperation(initializer, parent);
_ = ControlFlowGraph.Create(initializer);
}
......@@ -200,7 +200,7 @@ private void TestGetFlowGraphInvalidArgumentCore(string argumentExceptionMessage
IParameterInitializerOperation initializer = new ParameterInitializerOperation(
parameter: null, locals: ImmutableArray<ILocalSymbol>.Empty,
value: null, semanticModel: null,
syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
syntax: null, type: null, constantValue: null, isImplicit: false);
initializer = Operation.SetParentOperation(initializer, parent);
_ = ControlFlowGraph.Create(initializer);
}
......
......@@ -1428,7 +1428,7 @@ bool isContainingAssemblyInReferences(ISymbol s)
ISymbol within,
ITypeSymbol? throughType);
internal abstract IConvertibleConversion ClassifyConvertibleConversion(IOperation source, ITypeSymbol destination, out OperationConstantValue constantValue);
internal abstract IConvertibleConversion ClassifyConvertibleConversion(IOperation source, ITypeSymbol destination, out ConstantValue? constantValue);
#endregion
......
......@@ -5,6 +5,7 @@
#nullable enable
using System;
using System.Diagnostics;
using Microsoft.CodeAnalysis.Text;
using Roslyn.Utilities;
......@@ -125,6 +126,13 @@ internal override string GetValueToDisplay()
private sealed class ConstantValueString : ConstantValue
{
private readonly Rope _value;
/// <summary>
/// Some string constant values can have large costs to realize. To compensate, we realize
/// constant values lazily, and hold onto a weak reference. If the next time we're asked for the constant
/// value the previous one still exists, we can avoid rerealizing it. But we don't want to root the constant
/// value if it's not being used.
/// </summary>
private WeakReference<string>? _constantValueReference;
public ConstantValueString(string value)
{
......@@ -157,7 +165,19 @@ public override string StringValue
{
get
{
return _value.ToString();
string? constantValue = null;
if (_constantValueReference?.TryGetTarget(out constantValue) != true)
{
// Note: we could end up realizing the constant value multiple times if there's
// a race here. Currently, this isn't believed to be an issue, as the assignment
// to _constantValueReference is atomic so the worst that will happen is we return
// different instances of a string constant.
constantValue = _value.ToString();
_constantValueReference = new WeakReference<string>(constantValue);
}
Debug.Assert(constantValue != null);
return constantValue;
}
}
......
因为 它太大了无法显示 source diff 。你可以改为 查看blob
......@@ -20,33 +20,31 @@ namespace Microsoft.CodeAnalysis
internal abstract class Operation : IOperation
{
protected static readonly IOperation s_unset = new EmptyOperation(
semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IBlockOperation s_unsetBlock = new BlockOperation(
operations: ImmutableArray<IOperation>.Empty, locals: default, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
operations: ImmutableArray<IOperation>.Empty, locals: default, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IArrayInitializerOperation s_unsetArrayInitializer = new ArrayInitializerOperation(
elementValues: ImmutableArray<IOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
elementValues: ImmutableArray<IOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IEventReferenceOperation s_unsetEventReference = new EventReferenceOperation(
@event: null, instance: null, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
@event: null, instance: null, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IObjectOrCollectionInitializerOperation s_unsetObjectOrCollectionInitializer = new ObjectOrCollectionInitializerOperation(
initializers: ImmutableArray<IOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
initializers: ImmutableArray<IOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IPatternOperation s_unsetPattern = new ConstantPatternOperation(
value: null, inputType: null, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
value: null, inputType: null, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IVariableDeclarationGroupOperation s_unsetVariableDeclarationGroup = new VariableDeclarationGroupOperation(
declarations: ImmutableArray<IVariableDeclarationOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: true);
declarations: ImmutableArray<IVariableDeclarationOperation>.Empty, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: true);
protected static readonly IVariableInitializerOperation s_unsetVariableInitializer = new VariableInitializerOperation(
locals: ImmutableArray<ILocalSymbol>.Empty, value: null, semanticModel: null, syntax: null, type: null, constantValue: OperationConstantValue.None, isImplicit: false);
locals: ImmutableArray<ILocalSymbol>.Empty, value: null, semanticModel: null, syntax: null, type: null, constantValue: null, isImplicit: false);
private readonly SemanticModel? _owningSemanticModelOpt;
// this will be lazily initialized. this will be initialized only once
// but once initialized, will never change
private IOperation? _parentDoNotAccessDirectly;
protected Operation(OperationKind kind, SemanticModel? semanticModel, SyntaxNode syntax, ITypeSymbol type, OperationConstantValue constantValue, bool isImplicit)
protected Operation(OperationKind kind, SemanticModel? semanticModel, SyntaxNode syntax, ITypeSymbol type, ConstantValue constantValue, bool isImplicit)
{
// Constant value must at least be ConstantValue.None.
Debug.Assert(constantValue is object);
// Constant value cannot be "null" for non-nullable value type operations.
Debug.Assert(type?.IsValueType != true || ITypeSymbolHelpers.IsNullableType(type) || !constantValue.Value.HasValue || constantValue.Value.Value != null);
Debug.Assert(type?.IsValueType != true || ITypeSymbolHelpers.IsNullableType(type) || constantValue == null || constantValue == CodeAnalysis.ConstantValue.Unset || !constantValue.IsNull);
#if DEBUG
if (semanticModel != null)
......@@ -122,11 +120,23 @@ public string Language
get => Syntax.Language;
}
internal OperationConstantValue OperationConstantValue { get; }
internal CodeAnalysis.ConstantValue? OperationConstantValue { get; }
/// <summary>
/// If the operation is an expression that evaluates to a constant value, <see cref="Optional{Object}.HasValue"/> is true and <see cref="Optional{Object}.Value"/> is the value of the expression. Otherwise, <see cref="Optional{Object}.HasValue"/> is false.
/// </summary>
public Optional<object?> ConstantValue => OperationConstantValue.Value;
public Optional<object?> ConstantValue
{
get
{
if (OperationConstantValue == null || OperationConstantValue.IsBad)
{
return default(Optional<object?>);
}
return new Optional<object?>(OperationConstantValue.Value);
}
}
public abstract IEnumerable<IOperation> Children { get; }
......
// Licensed to the .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// See the LICENSE file in the project root for more information.
#nullable enable
using System;
using System.Diagnostics;
namespace Microsoft.CodeAnalysis
{
/// <summary>
/// Root type for operation constant values.
/// </summary>
internal abstract class OperationConstantValue
{
internal static OperationConstantValue None => NoConstantValue.Instance;
internal static OperationConstantValue Create(ConstantValue? originalConstant)
=> originalConstant switch
{
null => NoConstantValue.Instance,
{ IsBad: true } => NoConstantValue.Instance,
{ IsString: true } => new StringConstantValue(originalConstant),
{ IsBoolean: true } => originalConstant.BooleanValue ? NonStringConstantValue.True : NonStringConstantValue.False,
{ IsNull: true } => NonStringConstantValue.Null,
_ => new NonStringConstantValue(originalConstant.Value)
};
internal static OperationConstantValue FromBoolean(bool value)
=> Create(value ? ConstantValue.True : ConstantValue.False);
protected OperationConstantValue() { }
internal abstract Optional<object?> Value { get; }
private sealed class NoConstantValue : OperationConstantValue
{
internal static readonly NoConstantValue Instance = new NoConstantValue();
private NoConstantValue() { }
internal override Optional<object?> Value => default;
}
private sealed class NonStringConstantValue : OperationConstantValue
{
internal static readonly NonStringConstantValue True = new NonStringConstantValue(true);
internal static readonly NonStringConstantValue False = new NonStringConstantValue(false);
internal static readonly NonStringConstantValue Null = new NonStringConstantValue(null);
internal NonStringConstantValue(object? constantValue)
{
Debug.Assert(!(constantValue is string));
Value = new Optional<object?>(constantValue);
}
internal override Optional<object?> Value { get; }
}
private sealed class StringConstantValue : OperationConstantValue
{
/// <summary>
/// Some string constant values can have large costs to realize. To compensate, we realize
/// constant values lazily, and hold onto a weak reference. If the next time a user asks for the contant
/// value the previous one still exists, we can avoid rerealizing it. But we don't want to root the constant
/// value if no users are still using it.
/// </summary>
private WeakReference<string>? _constantValueReference;
private readonly ConstantValue _originalConstantValue;
internal StringConstantValue(ConstantValue originalConstantValue)
{
Debug.Assert(originalConstantValue.IsString);
_originalConstantValue = originalConstantValue;
}
internal override Optional<object?> Value
{
get
{
string? constantValue = null;
if (_constantValueReference?.TryGetTarget(out constantValue) != true)
{
// Note: we could end up realizing the constant value multiple times if there's
// a race here. Currently, this isn't believed to be an issue, as the assignment
// to _constantValueReference is atomic so the worst that will happen is we return
// different instances of a string constant to users.
constantValue = _originalConstantValue.StringValue;
Debug.Assert(constantValue != null);
_constantValueReference = new WeakReference<string>(constantValue);
}
return new Optional<object?>(constantValue);
}
}
}
}
}
......@@ -377,9 +377,11 @@ public static IOperation GetCorrespondingOperation(this IBranchOperation operati
return null;
}
internal static OperationConstantValue GetConstantValue(this IOperation operation)
#nullable enable
internal static ConstantValue? GetConstantValue(this IOperation operation)
{
return ((Operation)operation).OperationConstantValue;
}
#nullable restore
}
}
......@@ -11,7 +11,7 @@ internal static class OperationFactory
{
public static IInvalidOperation CreateInvalidOperation(SemanticModel semanticModel, SyntaxNode syntax, ImmutableArray<IOperation> children, bool isImplicit)
{
return new InvalidOperation(children, semanticModel, syntax, type: null, constantValue: OperationConstantValue.None, isImplicit: isImplicit);
return new InvalidOperation(children, semanticModel, syntax, type: null, constantValue: null, isImplicit: isImplicit);
}
}
}
......@@ -1807,8 +1807,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Return ClassifyConversion(source, destination).ToCommonConversion()
End Function
Friend Overrides Function ClassifyConvertibleConversion(source As IOperation, destination As ITypeSymbol, ByRef constantValue As OperationConstantValue) As IConvertibleConversion
constantValue = OperationConstantValue.None
Friend Overrides Function ClassifyConvertibleConversion(source As IOperation, destination As ITypeSymbol, ByRef constantValue As ConstantValue) As IConvertibleConversion
constantValue = Nothing
If destination Is Nothing Then
Return New Conversion(Nothing) ' No conversion
......@@ -1816,9 +1816,10 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim sourceType As ITypeSymbol = source.Type
Dim sourceConstantValue as ConstantValue = source.GetConstantValue()
If sourceType Is Nothing Then
If source.ConstantValue.HasValue AndAlso source.ConstantValue.Value Is Nothing AndAlso destination.IsReferenceType Then
constantValue = source.GetConstantValue()
If sourceConstantValue?.IsNothing = True AndAlso destination.IsReferenceType Then
constantValue = sourceConstantValue
Return New Conversion(New KeyValuePair(Of ConversionKind, MethodSymbol)(ConversionKind.WideningNothingLiteral, Nothing))
End If
......@@ -1827,8 +1828,8 @@ Namespace Microsoft.CodeAnalysis.VisualBasic
Dim result As Conversion = ClassifyConversion(sourceType, destination)
If result.IsReference AndAlso source.ConstantValue.HasValue AndAlso source.ConstantValue.Value Is Nothing Then
constantValue = source.GetConstantValue()
If result.IsReference AndAlso sourceConstantValue?.IsNothing = True Then
constantValue = sourceConstantValue
End If
Return result
......
......@@ -11,10 +11,6 @@ Imports Microsoft.CodeAnalysis.VisualBasic.Syntax
Namespace Microsoft.CodeAnalysis.Operations
Partial Friend NotInheritable Class VisualBasicOperationFactory
Private Shared Function ConvertToOptional(value As ConstantValue) As OperationConstantValue
Return OperationConstantValue.Create(value)
End Function
Private Shared Function IsMidStatement(node As BoundNode) As Boolean
If node.Kind = BoundKind.Conversion Then
node = DirectCast(node, BoundConversion).Operand
......@@ -92,7 +88,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Dim leftOperand As Lazy(Of IOperation) = New Lazy(Of IOperation)(Function() Create(boundAssignment.Left))
Dim syntax As SyntaxNode = boundAssignment.Syntax
Dim type As ITypeSymbol = boundAssignment.Type
Dim constantValue As OperationConstantValue = ConvertToOptional(boundAssignment.ConstantValueOpt)
Dim constantValue As ConstantValue = boundAssignment.ConstantValueOpt
Dim isImplicit As Boolean = boundAssignment.WasCompilerGenerated
Return New VisualBasicLazyCompoundAssignmentOperation(Me, boundAssignment, inConversion, outConversion, operatorInfo.OperatorKind,
......@@ -358,7 +354,7 @@ Namespace Microsoft.CodeAnalysis.Operations
_semanticModel,
value.Syntax,
[property].Type,
constantValue:=OperationConstantValue.None,
constantValue:=Nothing,
isImplicit:=True)
isImplicitAssignment = True
Else
......@@ -371,7 +367,7 @@ Namespace Microsoft.CodeAnalysis.Operations
Dim isRef As Boolean = False
Dim syntax As SyntaxNode = If(value.Syntax?.Parent, expression.Syntax)
Dim type As ITypeSymbol = target.Type
Dim constantValue As OperationConstantValue = value.GetConstantValue()
Dim constantValue As ConstantValue = value.GetConstantValue()
Dim assignment = New SimpleAssignmentOperation(isRef, target, value, _semanticModel, syntax, type, constantValue, isImplicitAssignment)
builder.Add(assignment)
Next i
......@@ -451,14 +447,14 @@ Namespace Microsoft.CodeAnalysis.Operations
initializerSyntax = last.InitializerOpt.Syntax
isImplicit = True
End If
initializer = New VisualBasicLazyVariableInitializerOperation(Me, last.InitializerOpt, _semanticModel, initializerSyntax, type:=Nothing, constantValue:=OperationConstantValue.None, isImplicit)
initializer = New VisualBasicLazyVariableInitializerOperation(Me, last.InitializerOpt, _semanticModel, initializerSyntax, type:=Nothing, constantValue:=Nothing, isImplicit)
End If
Else
Dim asNewDeclarations = DirectCast(first, BoundAsNewLocalDeclarations)
declarators = asNewDeclarations.LocalDeclarations.SelectAsArray(AddressOf GetVariableDeclarator)
Dim initializerSyntax As AsClauseSyntax = DirectCast(asNewDeclarations.Syntax, VariableDeclaratorSyntax).AsClause
Dim initializerValue As IOperation = Create(asNewDeclarations.Initializer)
initializer = New VisualBasicLazyVariableInitializerOperation(Me, asNewDeclarations.Initializer, _semanticModel, initializerSyntax, type:=Nothing, constantValue:=OperationConstantValue.None, isImplicit:=False)
initializer = New VisualBasicLazyVariableInitializerOperation(Me, asNewDeclarations.Initializer, _semanticModel, initializerSyntax, type:=Nothing, constantValue:=Nothing, isImplicit:=False)
End If
builder.Add(New VariableDeclarationOperation(declarators,
......@@ -467,7 +463,7 @@ Namespace Microsoft.CodeAnalysis.Operations
_semanticModel,
declarationGroup.Key,
type:=Nothing,
constantValue:=OperationConstantValue.None,
constantValue:=Nothing,
isImplicit:=False))
Next
......@@ -479,12 +475,12 @@ Namespace Microsoft.CodeAnalysis.Operations
If boundLocalDeclaration.IdentifierInitializerOpt IsNot Nothing Then
Dim syntax = boundLocalDeclaration.Syntax
Dim initializerValue As BoundNode = boundLocalDeclaration.IdentifierInitializerOpt
initializer = New VisualBasicLazyVariableInitializerOperation(Me, initializerValue, _semanticModel, syntax, type:=Nothing, constantValue:=OperationConstantValue.None, isImplicit:=True)
initializer = New VisualBasicLazyVariableInitializerOperation(Me, initializerValue, _semanticModel, syntax, type:=Nothing, constantValue:=Nothing, isImplicit:=True)
End If
Dim ignoredArguments = ImmutableArray(Of IOperation).Empty
Return New VariableDeclaratorOperation(boundLocalDeclaration.LocalSymbol, initializer, ignoredArguments, _semanticModel, boundLocalDeclaration.Syntax, type:=Nothing, constantValue:=OperationConstantValue.None, isImplicit:=boundLocalDeclaration.WasCompilerGenerated)
Return New VariableDeclaratorOperation(boundLocalDeclaration.LocalSymbol, initializer, ignoredArguments, _semanticModel, boundLocalDeclaration.Syntax, type:=Nothing, constantValue:=Nothing, isImplicit:=boundLocalDeclaration.WasCompilerGenerated)
End Function
Private Function GetUsingStatementDeclaration(resourceList As ImmutableArray(Of BoundLocalDeclarationBase), syntax As SyntaxNode) As IVariableDeclarationGroupOperation
......@@ -493,14 +489,14 @@ Namespace Microsoft.CodeAnalysis.Operations
_semanticModel,
syntax,
type:=Nothing,
constantValue:=OperationConstantValue.None,
constantValue:=Nothing,
isImplicit:=False) ' Declaration is always explicit
End Function
Friend Function GetAddRemoveHandlerStatementExpression(statement As BoundAddRemoveHandlerStatement) As IOperation
Dim adds = statement.Kind = BoundKind.AddHandlerStatement
Return New VisualBasicLazyEventAssignmentOperation(
Me, statement, adds:=adds, semanticModel:=_semanticModel, syntax:=statement.Syntax, type:=Nothing, constantValue:=OperationConstantValue.None, isImplicit:=True)
Me, statement, adds:=adds, semanticModel:=_semanticModel, syntax:=statement.Syntax, type:=Nothing, constantValue:=Nothing, isImplicit:=True)
End Function
#Region "Conversions"
......@@ -542,7 +538,7 @@ Namespace Microsoft.CodeAnalysis.Operations
_semanticModel,
boundOperand.Syntax,
adjustedInfo.Operation.Type,
ConvertToOptional(boundOperand.ConstantValueOpt),
boundOperand.ConstantValueOpt,
boundOperand.WasCompilerGenerated),
adjustedInfo.Conversion,
adjustedInfo.IsDelegateCreation)
......
......@@ -63,7 +63,7 @@ public sealed override void Initialize(AnalysisContext context)
{
SyntaxNode syntax = increment.Syntax;
ITypeSymbol type = increment.Type;
var constantValue = OperationConstantValue.Create(ConstantValue.Create(1));
var constantValue = ConstantValue.Create(1);
bool isImplicit = increment.IsImplicit;
var value = new LiteralOperation(increment.SemanticModel, syntax, type, constantValue, isImplicit);
......
......@@ -589,7 +589,7 @@ void writeConstructor(string accessibility, string @class, IEnumerable<Property>
{
Write("OperationKind kind, ");
}
Write("SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, OperationConstantValue constantValue, bool isImplicit");
Write("SemanticModel semanticModel, SyntaxNode syntax, ITypeSymbol type, ConstantValue constantValue, bool isImplicit");
WriteLine(")");
Indent();
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册