// 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 System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using Roslyn.Utilities;
namespace Microsoft.CodeAnalysis.CSharp.Symbols
{
///
/// Dynamic call-site delegate, for call-sites that do not
/// match System.Action or System.Func signatures.
///
internal sealed class SynthesizedDelegateSymbol : SynthesizedContainer
{
private readonly NamespaceOrTypeSymbol _containingSymbol;
private readonly MethodSymbol _constructor;
private readonly MethodSymbol _invoke;
public SynthesizedDelegateSymbol(
NamespaceOrTypeSymbol containingSymbol,
string name,
TypeSymbol objectType,
TypeSymbol intPtrType,
TypeSymbol voidReturnTypeOpt,
int parameterCount,
BitVector byRefParameters)
: base(name, parameterCount, returnsVoid: (object)voidReturnTypeOpt != null)
{
_containingSymbol = containingSymbol;
_constructor = new DelegateConstructor(this, objectType, intPtrType);
_invoke = new InvokeMethod(this, byRefParameters, voidReturnTypeOpt);
}
public override Symbol ContainingSymbol
{
get { return _containingSymbol; }
}
public override TypeKind TypeKind
{
get { return TypeKind.Delegate; }
}
internal override MethodSymbol Constructor
{
get { return _constructor; }
}
public override IEnumerable MemberNames
{
get { return new[] { _constructor.Name, _invoke.Name }; }
}
public override ImmutableArray GetMembers()
{
return ImmutableArray.Create(_constructor, _invoke);
}
public override ImmutableArray GetMembers(string name)
{
return
(name == _constructor.Name) ? ImmutableArray.Create(_constructor) :
(name == _invoke.Name) ? ImmutableArray.Create(_invoke) :
ImmutableArray.Empty;
}
public override Accessibility DeclaredAccessibility
{
get { return Accessibility.Internal; }
}
public override bool IsSealed
{
get { return true; }
}
internal override NamedTypeSymbol GetBaseTypeNoUseSiteDiagnostics(bool ignoreNonNullTypesAttribute)
{
return ContainingAssembly.GetSpecialType(SpecialType.System_MulticastDelegate);
}
private sealed class DelegateConstructor : SynthesizedInstanceConstructor
{
private readonly ImmutableArray _parameters;
public DelegateConstructor(NamedTypeSymbol containingType, TypeSymbol objectType, TypeSymbol intPtrType)
: base(containingType)
{
_parameters = ImmutableArray.Create(
SynthesizedParameterSymbol.Create(this, TypeSymbolWithAnnotations.Create(objectType), 0, RefKind.None, "object"),
SynthesizedParameterSymbol.Create(this, TypeSymbolWithAnnotations.Create(intPtrType), 1, RefKind.None, "method"));
}
public override ImmutableArray Parameters
{
get { return _parameters; }
}
}
private sealed class InvokeMethod : SynthesizedInstanceMethodSymbol
{
private readonly ImmutableArray _parameters;
private readonly TypeSymbol _containingType;
private readonly TypeSymbol _returnType;
internal InvokeMethod(SynthesizedDelegateSymbol containingType, BitVector byRefParameters, TypeSymbol voidReturnTypeOpt)
{
var typeParams = containingType.TypeParameters;
_containingType = containingType;
// if we are given Void type the method returns Void, otherwise its return type is the last type parameter of the delegate:
_returnType = voidReturnTypeOpt ?? typeParams.Last();
var parameters = new ParameterSymbol[typeParams.Length - ((object)voidReturnTypeOpt != null ? 0 : 1)];
for (int i = 0; i < parameters.Length; i++)
{
// we don't need to distinguish between out and ref since this is an internal synthesized symbol:
var refKind = !byRefParameters.IsNull && byRefParameters[i] ? RefKind.Ref : RefKind.None;
parameters[i] = SynthesizedParameterSymbol.Create(this, TypeSymbolWithAnnotations.Create(typeParams[i]), i, refKind);
}
_parameters = parameters.AsImmutableOrNull();
}
public override string Name
{
get { return WellKnownMemberNames.DelegateInvokeName; }
}
internal override bool IsMetadataNewSlot(bool ignoreInterfaceImplementationChanges = false)
{
return true;
}
internal override bool IsMetadataVirtual(bool ignoreInterfaceImplementationChanges = false)
{
return true;
}
internal override bool IsMetadataFinal
{
get
{
return false;
}
}
public override MethodKind MethodKind
{
get { return MethodKind.DelegateInvoke; }
}
public override int Arity
{
get { return 0; }
}
public override bool IsExtensionMethod
{
get { return false; }
}
internal override bool HasSpecialName
{
get { return false; }
}
internal override System.Reflection.MethodImplAttributes ImplementationAttributes
{
get { return System.Reflection.MethodImplAttributes.Runtime; }
}
internal override bool HasDeclarativeSecurity
{
get { return false; }
}
public override DllImportData GetDllImportData()
{
return null;
}
internal override IEnumerable GetSecurityInformation()
{
throw ExceptionUtilities.Unreachable;
}
internal override MarshalPseudoCustomAttributeData ReturnValueMarshallingInformation
{
get { return null; }
}
internal override bool RequiresSecurityObject
{
get { return false; }
}
public override bool HidesBaseMethodsByName
{
get { return false; }
}
public override bool IsVararg
{
get { return false; }
}
public override bool ReturnsVoid
{
get { return _returnType.SpecialType == SpecialType.System_Void; }
}
public override bool IsAsync
{
get { return false; }
}
public override RefKind RefKind
{
get { return RefKind.None; }
}
public override TypeSymbolWithAnnotations ReturnType
{
get { return TypeSymbolWithAnnotations.Create(_returnType); }
}
public override ImmutableArray TypeArguments
{
get { return ImmutableArray.Empty; }
}
public override ImmutableArray TypeParameters
{
get { return ImmutableArray.Empty; }
}
public override ImmutableArray Parameters
{
get { return _parameters; }
}
public override ImmutableArray ExplicitInterfaceImplementations
{
get { return ImmutableArray.Empty; }
}
public override ImmutableArray RefCustomModifiers
{
get { return ImmutableArray.Empty; }
}
public override Symbol AssociatedSymbol
{
get { return null; }
}
internal override ImmutableArray GetAppliedConditionalSymbols()
{
return ImmutableArray.Empty;
}
internal override Microsoft.Cci.CallingConvention CallingConvention
{
get { return Microsoft.Cci.CallingConvention.HasThis; }
}
internal override bool GenerateDebugInfo
{
get { return false; }
}
public override Symbol ContainingSymbol
{
get { return _containingType; }
}
public override ImmutableArray Locations
{
get { return ImmutableArray.Empty; }
}
public override Accessibility DeclaredAccessibility
{
get
{
// Invoke method of a delegate used in a dynamic call-site must be public
// since the DLR looks only for public Invoke methods:
return Accessibility.Public;
}
}
public override bool IsStatic
{
get { return false; }
}
public override bool IsVirtual
{
get { return true; }
}
public override bool IsOverride
{
get { return false; }
}
public override bool IsAbstract
{
get { return false; }
}
public override bool IsSealed
{
get { return false; }
}
public override bool IsExtern
{
get { return false; }
}
}
}
}