140 lines
4.7 KiB
C#
140 lines
4.7 KiB
C#
using System;
|
|
using System.Collections.Immutable;
|
|
using System.Threading;
|
|
using Microsoft.CodeAnalysis.CSharp.Symbols;
|
|
|
|
namespace Microsoft.CodeAnalysis.CSharp;
|
|
|
|
internal sealed class ExecutableCodeBinder : Binder
|
|
{
|
|
private readonly Symbol _memberSymbol;
|
|
|
|
private readonly SyntaxNode _root;
|
|
|
|
private readonly Action<Binder, SyntaxNode> _binderUpdatedHandler;
|
|
|
|
private SmallDictionary<SyntaxNode, Binder> _lazyBinderMap;
|
|
|
|
internal override Symbol ContainingMemberOrLambda => _memberSymbol ?? base.Next.ContainingMemberOrLambda;
|
|
|
|
protected override bool InExecutableBinder => true;
|
|
|
|
internal Symbol MemberSymbol => _memberSymbol;
|
|
|
|
private SmallDictionary<SyntaxNode, Binder> BinderMap
|
|
{
|
|
get
|
|
{
|
|
if (_lazyBinderMap == null)
|
|
{
|
|
ComputeBinderMap();
|
|
}
|
|
return _lazyBinderMap;
|
|
}
|
|
}
|
|
|
|
internal ExecutableCodeBinder(SyntaxNode root, Symbol memberSymbol, Binder next, Action<Binder, SyntaxNode> binderUpdatedHandler = null)
|
|
: this(root, memberSymbol, next, next.Flags)
|
|
{
|
|
_binderUpdatedHandler = binderUpdatedHandler;
|
|
}
|
|
|
|
internal ExecutableCodeBinder(SyntaxNode root, Symbol memberSymbol, Binder next, BinderFlags additionalFlags)
|
|
: base(next, (BinderFlags)((uint)(next.Flags | additionalFlags) & 0xFFC0FFFFu))
|
|
{
|
|
_memberSymbol = memberSymbol;
|
|
_root = root;
|
|
}
|
|
|
|
internal override Binder GetBinder(SyntaxNode node)
|
|
{
|
|
Binder result = default(Binder);
|
|
if (!BinderMap.TryGetValue(node, ref result))
|
|
{
|
|
return base.Next.GetBinder(node);
|
|
}
|
|
return result;
|
|
}
|
|
|
|
private void ComputeBinderMap()
|
|
{
|
|
SmallDictionary<SyntaxNode, Binder> val;
|
|
if (!(_memberSymbol is SynthesizedSimpleProgramEntryPointSymbol synthesizedSimpleProgramEntryPointSymbol) || (object)_root != synthesizedSimpleProgramEntryPointSymbol.SyntaxNode)
|
|
{
|
|
val = (((object)_memberSymbol == null || _root == null) ? SmallDictionary<SyntaxNode, Binder>.Empty : LocalBinderFactory.BuildMap(_memberSymbol, _root, this, _binderUpdatedHandler));
|
|
}
|
|
else
|
|
{
|
|
SimpleProgramBinder simpleProgramBinder = new SimpleProgramBinder(this, synthesizedSimpleProgramEntryPointSymbol);
|
|
val = LocalBinderFactory.BuildMap(_memberSymbol, _root, simpleProgramBinder, _binderUpdatedHandler);
|
|
val.Add(_root, (Binder)simpleProgramBinder);
|
|
}
|
|
Interlocked.CompareExchange(ref _lazyBinderMap, val, null);
|
|
}
|
|
|
|
public static void ValidateIteratorMethod(CSharpCompilation compilation, MethodSymbol iterator, BindingDiagnosticBag diagnostics)
|
|
{
|
|
//IL_0027: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00ee: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f3: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_00f5: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0146: Unknown result type (might be due to invalid IL or missing references)
|
|
//IL_0108: Unknown result type (might be due to invalid IL or missing references)
|
|
if (!iterator.IsIterator)
|
|
{
|
|
return;
|
|
}
|
|
ImmutableArray<ParameterSymbol>.Enumerator enumerator = iterator.Parameters.GetEnumerator();
|
|
while (enumerator.MoveNext())
|
|
{
|
|
ParameterSymbol current = enumerator.Current;
|
|
if ((int)current.RefKind != 0)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_BadIteratorArgType, current.GetFirstLocation());
|
|
}
|
|
else if (current.Type.IsPointerOrFunctionPointer())
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_UnsafeIteratorArgType, current.GetFirstLocation());
|
|
}
|
|
}
|
|
SynthesizedSimpleProgramEntryPointSymbol obj = iterator as SynthesizedSimpleProgramEntryPointSymbol;
|
|
Location val = (((object)obj != null) ? obj.ReturnTypeSyntax.GetLocation() : null) ?? iterator.GetFirstLocation();
|
|
if (iterator.IsVararg)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_VarargsIterator, val);
|
|
}
|
|
SourceMemberMethodSymbol obj2 = iterator as SourceMemberMethodSymbol;
|
|
if ((object)obj2 == null || !obj2.IsUnsafe)
|
|
{
|
|
LocalFunctionSymbol obj3 = iterator as LocalFunctionSymbol;
|
|
if ((object)obj3 == null || !obj3.IsUnsafe)
|
|
{
|
|
goto IL_00e6;
|
|
}
|
|
}
|
|
if (compilation.Options.AllowUnsafe)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_IllegalInnerUnsafe, val);
|
|
}
|
|
goto IL_00e6;
|
|
IL_00e6:
|
|
TypeSymbol returnType = iterator.ReturnType;
|
|
RefKind refKind = iterator.RefKind;
|
|
if (InMethodBinder.GetIteratorElementTypeFromReturnType(compilation, refKind, returnType, val, diagnostics).IsDefault)
|
|
{
|
|
if ((int)refKind != 0)
|
|
{
|
|
Binder.Error(diagnostics, ErrorCode.ERR_BadIteratorReturnRef, val, iterator);
|
|
}
|
|
else if (!returnType.IsErrorType())
|
|
{
|
|
Binder.Error(diagnostics, ErrorCode.ERR_BadIteratorReturn, val, iterator, returnType);
|
|
}
|
|
}
|
|
if (InMethodBinder.IsAsyncStreamInterface(compilation, refKind, returnType) && !iterator.IsAsync)
|
|
{
|
|
diagnostics.Add(ErrorCode.ERR_IteratorMustBeAsync, val, iterator, returnType);
|
|
}
|
|
}
|
|
}
|