463 lines
18 KiB
C#
463 lines
18 KiB
C#
using System.Collections.Immutable;
|
|
using System.Runtime.CompilerServices;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Syntax;
|
|
using Roslyn.Utilities;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
|
|
internal class SourceLocalSymbol : LocalSymbol
|
|
{
|
|
private sealed class LocalWithInitializer : SourceLocalSymbol
|
|
{
|
|
private readonly EqualsValueClauseSyntax _initializer;
|
|
|
|
private readonly Binder _initializerBinder;
|
|
|
|
private EvaluatedConstant _constantTuple;
|
|
|
|
internal override SyntaxNode ForbiddenZone => (SyntaxNode)(object)_initializer;
|
|
|
|
public LocalWithInitializer(Symbol containingSymbol, Binder scopeBinder, TypeSyntax typeSyntax, SyntaxToken identifierToken, EqualsValueClauseSyntax initializer, Binder initializerBinder, LocalDeclarationKind declarationKind, bool allowScoped)
|
|
: base(containingSymbol, scopeBinder, allowRefKind: true, allowScoped, typeSyntax, identifierToken, declarationKind)
|
|
{
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
_initializer = initializer;
|
|
_initializerBinder = initializerBinder;
|
|
}
|
|
|
|
protected override TypeWithAnnotations InferTypeOfVarVariable(BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_0008: Unknown result type (might be due to invalid IL or missing references)
|
|
return TypeWithAnnotations.Create(_initializerBinder.BindInferredVariableInitializer(diagnostics, RefKind, _initializer, _initializer)?.Type);
|
|
}
|
|
|
|
private void MakeConstantTuple(LocalSymbol inProgress, BoundExpression boundInitValue)
|
|
{
|
|
//IL_0064: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0039: Unknown result type (might be due to invalid IL or missing references)
|
|
if (base.IsConst && _constantTuple == null)
|
|
{
|
|
ConstantValue bad = ConstantValue.Bad;
|
|
BindingDiagnosticBag instance = BindingDiagnosticBag.GetInstance();
|
|
TypeSymbol type = base.Type;
|
|
if (boundInitValue == null)
|
|
{
|
|
boundInitValue = new LocalInProgressBinder(this, _initializerBinder).BindVariableOrAutoPropInitializerValue(_initializer, RefKind, type, instance);
|
|
}
|
|
bad = ConstantValueUtils.GetAndValidateConstantValue(boundInitValue, this, type, (SyntaxNode)(object)_initializer.Value, instance);
|
|
Interlocked.CompareExchange(ref _constantTuple, new EvaluatedConstant(bad, ((BindingDiagnosticBag<AssemblySymbol>)(object)instance).ToReadOnlyAndFree()), null);
|
|
}
|
|
}
|
|
|
|
internal override ConstantValue GetConstantValue(SyntaxNode node, LocalSymbol inProgress, BindingDiagnosticBag diagnostics = null)
|
|
{
|
|
if (base.IsConst && inProgress == this)
|
|
{
|
|
diagnostics?.Add(ErrorCode.ERR_CircConstValue, node.GetLocation(), this);
|
|
return ConstantValue.Bad;
|
|
}
|
|
MakeConstantTuple(inProgress, null);
|
|
if (_constantTuple != null)
|
|
{
|
|
return _constantTuple.Value;
|
|
}
|
|
return null;
|
|
}
|
|
|
|
internal override ImmutableBindingDiagnostic<AssemblySymbol> GetConstantValueDiagnostics(BoundExpression boundInitValue)
|
|
{
|
|
//IL_001c: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0016: Unknown result type (might be due to invalid IL or missing references)
|
|
MakeConstantTuple(null, boundInitValue);
|
|
if (_constantTuple != null)
|
|
{
|
|
return _constantTuple.Diagnostics;
|
|
}
|
|
return ImmutableBindingDiagnostic<AssemblySymbol>.Empty;
|
|
}
|
|
}
|
|
|
|
private sealed class ForEachLocalSymbol : SourceLocalSymbol
|
|
{
|
|
private readonly ExpressionSyntax _collection;
|
|
|
|
private ForEachLoopBinder ForEachLoopBinder => (ForEachLoopBinder)base.ScopeBinder;
|
|
|
|
internal override SyntaxNode ForbiddenZone => null;
|
|
|
|
public ForEachLocalSymbol(Symbol containingSymbol, ForEachLoopBinder scopeBinder, TypeSyntax typeSyntax, SyntaxToken identifierToken, ExpressionSyntax collection, LocalDeclarationKind declarationKind)
|
|
: base(containingSymbol, scopeBinder, allowRefKind: true, allowScoped: true, typeSyntax, identifierToken, declarationKind)
|
|
{
|
|
//IL_0006: Unknown result type (might be due to invalid IL or missing references)
|
|
_collection = collection;
|
|
}
|
|
|
|
protected override TypeWithAnnotations InferTypeOfVarVariable(BindingDiagnosticBag diagnostics)
|
|
{
|
|
return ForEachLoopBinder.InferCollectionElementType(diagnostics, _collection);
|
|
}
|
|
}
|
|
|
|
private sealed class DeconstructionLocalSymbol : SourceLocalSymbol
|
|
{
|
|
private readonly SyntaxNode _deconstruction;
|
|
|
|
private readonly Binder _nodeBinder;
|
|
|
|
internal override SyntaxNode ForbiddenZone => (SyntaxNode)(_deconstruction.Kind() switch
|
|
{
|
|
SyntaxKind.SimpleAssignmentExpression => _deconstruction,
|
|
SyntaxKind.ForEachVariableStatement => ((ForEachVariableStatementSyntax)(object)_deconstruction).Variable,
|
|
_ => null,
|
|
});
|
|
|
|
public DeconstructionLocalSymbol(Symbol containingSymbol, Binder scopeBinder, Binder nodeBinder, TypeSyntax typeSyntax, SyntaxToken identifierToken, LocalDeclarationKind declarationKind, SyntaxNode deconstruction)
|
|
: base(containingSymbol, scopeBinder, allowRefKind: false, allowScoped: true, typeSyntax, identifierToken, declarationKind)
|
|
{
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
_deconstruction = deconstruction;
|
|
_nodeBinder = nodeBinder;
|
|
}
|
|
|
|
protected override TypeWithAnnotations InferTypeOfVarVariable(BindingDiagnosticBag diagnostics)
|
|
{
|
|
switch (_deconstruction.Kind())
|
|
{
|
|
case SyntaxKind.SimpleAssignmentExpression:
|
|
{
|
|
AssignmentExpressionSyntax assignmentExpressionSyntax = (AssignmentExpressionSyntax)(object)_deconstruction;
|
|
DeclarationExpressionSyntax declaration = null;
|
|
ExpressionSyntax expression = null;
|
|
_nodeBinder.BindDeconstruction(assignmentExpressionSyntax, assignmentExpressionSyntax.Left, assignmentExpressionSyntax.Right, diagnostics, ref declaration, ref expression);
|
|
break;
|
|
}
|
|
case SyntaxKind.ForEachVariableStatement:
|
|
_nodeBinder.BindForEachDeconstruction(diagnostics, _nodeBinder);
|
|
break;
|
|
default:
|
|
return TypeWithAnnotations.Create(_nodeBinder.CreateErrorType());
|
|
}
|
|
return _type.Value;
|
|
}
|
|
}
|
|
|
|
private sealed class LocalSymbolWithEnclosingContext : SourceLocalSymbol
|
|
{
|
|
private readonly SyntaxNode _forbiddenZone;
|
|
|
|
private readonly Binder _nodeBinder;
|
|
|
|
private readonly SyntaxNode _nodeToBind;
|
|
|
|
internal override SyntaxNode ForbiddenZone => _forbiddenZone;
|
|
|
|
internal override ErrorCode ForbiddenDiagnostic => ErrorCode.ERR_ImplicitlyTypedOutVariableUsedInTheSameArgumentList;
|
|
|
|
public LocalSymbolWithEnclosingContext(Symbol containingSymbol, Binder scopeBinder, Binder nodeBinder, TypeSyntax typeSyntax, SyntaxToken identifierToken, LocalDeclarationKind declarationKind, SyntaxNode nodeToBind, SyntaxNode forbiddenZone)
|
|
: base(containingSymbol, scopeBinder, allowRefKind: false, allowScoped: true, typeSyntax, identifierToken, declarationKind)
|
|
{
|
|
//IL_0007: Unknown result type (might be due to invalid IL or missing references)
|
|
_nodeBinder = nodeBinder;
|
|
_nodeToBind = nodeToBind;
|
|
_forbiddenZone = forbiddenZone;
|
|
}
|
|
|
|
protected override TypeWithAnnotations InferTypeOfVarVariable(BindingDiagnosticBag diagnostics)
|
|
{
|
|
switch (_nodeToBind.Kind())
|
|
{
|
|
case SyntaxKind.BaseConstructorInitializer:
|
|
case SyntaxKind.ThisConstructorInitializer:
|
|
{
|
|
ConstructorInitializerSyntax initializer3 = (ConstructorInitializerSyntax)(object)_nodeToBind;
|
|
_nodeBinder.BindConstructorInitializer(initializer3, diagnostics);
|
|
break;
|
|
}
|
|
case SyntaxKind.PrimaryConstructorBaseType:
|
|
_nodeBinder.BindConstructorInitializer((PrimaryConstructorBaseTypeSyntax)(object)_nodeToBind, diagnostics);
|
|
break;
|
|
case SyntaxKind.ArgumentList:
|
|
{
|
|
SyntaxNode parent = _nodeToBind.Parent;
|
|
if (!(parent is ConstructorInitializerSyntax initializer))
|
|
{
|
|
if (!(parent is PrimaryConstructorBaseTypeSyntax initializer2))
|
|
{
|
|
throw ExceptionUtilities.UnexpectedValue((object)_nodeToBind.Parent);
|
|
}
|
|
_nodeBinder.BindConstructorInitializer(initializer2, diagnostics);
|
|
}
|
|
else
|
|
{
|
|
_nodeBinder.BindConstructorInitializer(initializer, diagnostics);
|
|
}
|
|
break;
|
|
}
|
|
case SyntaxKind.CasePatternSwitchLabel:
|
|
_nodeBinder.BindPatternSwitchLabelForInference((CasePatternSwitchLabelSyntax)(object)_nodeToBind, diagnostics);
|
|
break;
|
|
case SyntaxKind.VariableDeclarator:
|
|
_nodeBinder.BindDeclaratorArguments((VariableDeclaratorSyntax)(object)_nodeToBind, diagnostics);
|
|
break;
|
|
case SyntaxKind.SwitchExpressionArm:
|
|
{
|
|
SwitchExpressionArmSyntax node = (SwitchExpressionArmSyntax)(object)_nodeToBind;
|
|
((SwitchExpressionArmBinder)_nodeBinder).BindSwitchExpressionArm(node, diagnostics);
|
|
break;
|
|
}
|
|
case SyntaxKind.GotoCaseStatement:
|
|
_nodeBinder.BindStatement((GotoStatementSyntax)(object)_nodeToBind, diagnostics);
|
|
break;
|
|
default:
|
|
_nodeBinder.BindExpression((ExpressionSyntax)(object)_nodeToBind, diagnostics);
|
|
break;
|
|
}
|
|
if (_type == null)
|
|
{
|
|
SetTypeWithAnnotations(TypeWithAnnotations.Create(_nodeBinder.CreateErrorType("var")));
|
|
}
|
|
return _type.Value;
|
|
}
|
|
}
|
|
|
|
private readonly Binder _scopeBinder;
|
|
|
|
private readonly Symbol _containingSymbol;
|
|
|
|
private readonly SyntaxToken _identifierToken;
|
|
|
|
private readonly TypeSyntax _typeSyntax;
|
|
|
|
private readonly RefKind _refKind;
|
|
|
|
private readonly LocalDeclarationKind _declarationKind;
|
|
|
|
private readonly ScopedKind _scope;
|
|
|
|
private TypeWithAnnotations.Boxed _type;
|
|
|
|
internal Binder ScopeBinder => _scopeBinder;
|
|
|
|
internal override SyntaxNode ScopeDesignatorOpt => _scopeBinder.ScopeDesignator;
|
|
|
|
internal sealed override ScopedKind Scope => _scope;
|
|
|
|
internal Binder TypeSyntaxBinder => _scopeBinder;
|
|
|
|
internal override bool IsImportedFromMetadata => false;
|
|
|
|
internal override LocalDeclarationKind DeclarationKind => _declarationKind;
|
|
|
|
internal override SynthesizedLocalKind SynthesizedKind => (SynthesizedLocalKind)0;
|
|
|
|
internal override bool IsPinned => false;
|
|
|
|
internal sealed override bool IsKnownToReferToTempIfReferenceType => false;
|
|
|
|
public override Symbol ContainingSymbol => _containingSymbol;
|
|
|
|
public override string Name => ((SyntaxToken)(ref _identifierToken)).ValueText;
|
|
|
|
internal override SyntaxToken IdentifierToken => _identifierToken;
|
|
|
|
public override TypeWithAnnotations TypeWithAnnotations
|
|
{
|
|
get
|
|
{
|
|
if (_type == null)
|
|
{
|
|
TypeWithAnnotations typeSymbol = GetTypeSymbol();
|
|
SetTypeWithAnnotations(typeSymbol);
|
|
}
|
|
return _type.Value;
|
|
}
|
|
}
|
|
|
|
public bool IsVar
|
|
{
|
|
get
|
|
{
|
|
if (_typeSyntax == null)
|
|
{
|
|
return true;
|
|
}
|
|
bool isScoped;
|
|
TypeSyntax typeSyntax = _typeSyntax.SkipScoped(out isScoped).SkipRef();
|
|
if (typeSyntax.IsVar)
|
|
{
|
|
TypeSyntaxBinder.BindTypeOrVarKeyword(typeSyntax, BindingDiagnosticBag.Discarded, out var isVar);
|
|
return isVar;
|
|
}
|
|
return false;
|
|
}
|
|
}
|
|
|
|
public override ImmutableArray<Location> Locations => ImmutableArray.Create<Location>(GetFirstLocation());
|
|
|
|
internal override bool HasSourceLocation => true;
|
|
|
|
public override ImmutableArray<SyntaxReference> DeclaringSyntaxReferences => ImmutableArray.Create<SyntaxReference>(((SyntaxToken)(ref _identifierToken)).Parent.GetReference());
|
|
|
|
internal override bool IsCompilerGenerated => false;
|
|
|
|
public override RefKind RefKind => _refKind;
|
|
|
|
private SourceLocalSymbol(Symbol containingSymbol, Binder scopeBinder, bool allowRefKind, bool allowScoped, TypeSyntax typeSyntax, SyntaxToken identifierToken, LocalDeclarationKind declarationKind)
|
|
{
|
|
//IL_0015: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0017: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0048: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_005f: Unknown result type (might be due to invalid IL or missing references)
|
|
_scopeBinder = scopeBinder;
|
|
_containingSymbol = containingSymbol;
|
|
_identifierToken = identifierToken;
|
|
_typeSyntax = typeSyntax;
|
|
typeSyntax = typeSyntax.SkipScoped(out var isScoped);
|
|
isScoped = isScoped && allowScoped;
|
|
if (allowRefKind)
|
|
{
|
|
typeSyntax.SkipRefInLocalOrReturn(null, out _refKind);
|
|
}
|
|
_scope = (ScopedKind)(((int)_refKind == 0) ? (isScoped ? 2 : 0) : (isScoped ? 1 : 0));
|
|
_declarationKind = declarationKind;
|
|
}
|
|
|
|
internal override string GetDebuggerDisplay()
|
|
{
|
|
//IL_000e: Unknown result type (might be due to invalid IL or missing references)
|
|
if (_type == null)
|
|
{
|
|
return $"{Kind} <var> ${Name}";
|
|
}
|
|
return base.GetDebuggerDisplay();
|
|
}
|
|
|
|
public static SourceLocalSymbol MakeForeachLocal(MethodSymbol containingMethod, ForEachLoopBinder binder, TypeSyntax typeSyntax, SyntaxToken identifierToken, ExpressionSyntax collection)
|
|
{
|
|
//IL_0003: Unknown result type (might be due to invalid IL or missing references)
|
|
return new ForEachLocalSymbol(containingMethod, binder, typeSyntax, identifierToken, collection, LocalDeclarationKind.ForEachIterationVariable);
|
|
}
|
|
|
|
public static SourceLocalSymbol MakeDeconstructionLocal(Symbol containingSymbol, Binder scopeBinder, Binder nodeBinder, TypeSyntax closestTypeSyntax, SyntaxToken identifierToken, LocalDeclarationKind kind, SyntaxNode deconstruction)
|
|
{
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0019: Unknown result type (might be due to invalid IL or missing references)
|
|
if (!closestTypeSyntax.SkipScoped(out var _).SkipRef().IsVar)
|
|
{
|
|
return new SourceLocalSymbol(containingSymbol, scopeBinder, allowRefKind: false, allowScoped: true, closestTypeSyntax, identifierToken, kind);
|
|
}
|
|
return new DeconstructionLocalSymbol(containingSymbol, scopeBinder, nodeBinder, closestTypeSyntax, identifierToken, kind, deconstruction);
|
|
}
|
|
|
|
internal static LocalSymbol MakeLocalSymbolWithEnclosingContext(Symbol containingSymbol, Binder scopeBinder, Binder nodeBinder, TypeSyntax typeSyntax, SyntaxToken identifierToken, LocalDeclarationKind kind, SyntaxNode nodeToBind, SyntaxNode forbiddenZone)
|
|
{
|
|
//IL_0025: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0033: Unknown result type (might be due to invalid IL or missing references)
|
|
if ((typeSyntax != null && !typeSyntax.SkipScoped(out var _).SkipRef().IsVar) || kind == LocalDeclarationKind.DeclarationExpressionVariable)
|
|
{
|
|
return new SourceLocalSymbol(containingSymbol, scopeBinder, allowRefKind: false, allowScoped: true, typeSyntax, identifierToken, kind);
|
|
}
|
|
return new LocalSymbolWithEnclosingContext(containingSymbol, scopeBinder, nodeBinder, typeSyntax, identifierToken, kind, nodeToBind, forbiddenZone);
|
|
}
|
|
|
|
public static SourceLocalSymbol MakeLocal(Symbol containingSymbol, Binder scopeBinder, bool allowRefKind, bool allowScoped, TypeSyntax typeSyntax, SyntaxToken identifierToken, LocalDeclarationKind declarationKind, EqualsValueClauseSyntax initializer, Binder initializerBinderOpt = null)
|
|
{
|
|
//IL_0018: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_000a: Unknown result type (might be due to invalid IL or missing references)
|
|
if (initializer == null)
|
|
{
|
|
return new SourceLocalSymbol(containingSymbol, scopeBinder, allowRefKind, allowScoped, typeSyntax, identifierToken, declarationKind);
|
|
}
|
|
return new LocalWithInitializer(containingSymbol, scopeBinder, typeSyntax, identifierToken, initializer, initializerBinderOpt ?? scopeBinder, declarationKind, allowScoped);
|
|
}
|
|
|
|
internal override LocalSymbol WithSynthesizedLocalKindAndSyntax(SynthesizedLocalKind kind, SyntaxNode syntax)
|
|
{
|
|
throw ExceptionUtilities.Unreachable("/_/src/Compilers/CSharp/Portable/Symbols/Source/SourceLocalSymbol.cs", 241);
|
|
}
|
|
|
|
private TypeWithAnnotations GetTypeSymbol()
|
|
{
|
|
BindingDiagnosticBag discarded = BindingDiagnosticBag.Discarded;
|
|
Binder typeSyntaxBinder = TypeSyntaxBinder;
|
|
bool isVar;
|
|
TypeWithAnnotations result;
|
|
if (_typeSyntax == null)
|
|
{
|
|
isVar = true;
|
|
result = default(TypeWithAnnotations);
|
|
}
|
|
else
|
|
{
|
|
result = typeSyntaxBinder.BindTypeOrVarKeyword(_typeSyntax.SkipScoped(out var _).SkipRef(), discarded, out isVar);
|
|
}
|
|
if (isVar)
|
|
{
|
|
TypeWithAnnotations typeWithAnnotations = InferTypeOfVarVariable(discarded);
|
|
result = ((!typeWithAnnotations.HasType || typeWithAnnotations.IsVoidType()) ? TypeWithAnnotations.Create(typeSyntaxBinder.CreateErrorType("var")) : typeWithAnnotations);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
protected virtual TypeWithAnnotations InferTypeOfVarVariable(BindingDiagnosticBag diagnostics)
|
|
{
|
|
return _type?.Value ?? default(TypeWithAnnotations);
|
|
}
|
|
|
|
internal void SetTypeWithAnnotations(TypeWithAnnotations newType)
|
|
{
|
|
_ = _type?.Value;
|
|
if (_type == null)
|
|
{
|
|
Interlocked.CompareExchange(ref _type, new TypeWithAnnotations.Boxed(newType), null);
|
|
}
|
|
}
|
|
|
|
public override Location TryGetFirstLocation()
|
|
{
|
|
return ((SyntaxToken)(ref _identifierToken)).GetLocation();
|
|
}
|
|
|
|
internal sealed override SyntaxNode GetDeclaratorSyntax()
|
|
{
|
|
return ((SyntaxToken)(ref _identifierToken)).Parent;
|
|
}
|
|
|
|
internal override ConstantValue GetConstantValue(SyntaxNode node, LocalSymbol inProgress, BindingDiagnosticBag diagnostics)
|
|
{
|
|
return null;
|
|
}
|
|
|
|
internal override ImmutableBindingDiagnostic<AssemblySymbol> GetConstantValueDiagnostics(BoundExpression boundInitValue)
|
|
{
|
|
//IL_0000: Unknown result type (might be due to invalid IL or missing references)
|
|
return ImmutableBindingDiagnostic<AssemblySymbol>.Empty;
|
|
}
|
|
|
|
public sealed override bool Equals(Symbol obj, TypeCompareKind compareKind)
|
|
{
|
|
//IL_0012: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_002a: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0042: Unknown result type (might be due to invalid IL or missing references)
|
|
if ((object)obj == this)
|
|
{
|
|
return true;
|
|
}
|
|
if (obj is UpdatedContainingSymbolAndNullableAnnotationLocal updatedContainingSymbolAndNullableAnnotationLocal)
|
|
{
|
|
return updatedContainingSymbolAndNullableAnnotationLocal.Equals(this, compareKind);
|
|
}
|
|
if (obj is SourceLocalSymbol sourceLocalSymbol && ((SyntaxToken)(ref sourceLocalSymbol._identifierToken)).Equals(_identifierToken))
|
|
{
|
|
return sourceLocalSymbol._containingSymbol.Equals(_containingSymbol, compareKind);
|
|
}
|
|
return false;
|
|
}
|
|
|
|
public sealed override int GetHashCode()
|
|
{
|
|
return Hash.Combine(((object)Unsafe.As<SyntaxToken, SyntaxToken>(ref _identifierToken)/*cast due to constrained. prefix*/).GetHashCode(), _containingSymbol.GetHashCode());
|
|
}
|
|
}
|