Пример #1
0
        internal static PEMethodSymbol GetSourceMethod(this CSharpCompilation compilation, Guid moduleVersionId, MethodDefinitionHandle methodHandle)
        {
            var method          = GetMethod(compilation, moduleVersionId, methodHandle);
            var metadataDecoder = new MetadataDecoder((PEModuleSymbol)method.ContainingModule);
            var containingType  = method.ContainingType;

            if (GeneratedNameParser.TryParseSourceMethodNameFromGeneratedName(containingType.Name, GeneratedNameKind.StateMachineType, out var sourceMethodName))
            {
                foreach (var member in containingType.ContainingType.GetMembers(sourceMethodName))
                {
                    if (member is PEMethodSymbol candidateMethod)
                    {
                        var module = metadataDecoder.Module;
                        methodHandle = candidateMethod.Handle;
                        string stateMachineTypeName;
                        if (module.HasStringValuedAttribute(methodHandle, AttributeDescription.AsyncStateMachineAttribute, out stateMachineTypeName) ||
                            module.HasStringValuedAttribute(methodHandle, AttributeDescription.IteratorStateMachineAttribute, out stateMachineTypeName))
                        {
                            if (metadataDecoder.GetTypeSymbolForSerializedType(stateMachineTypeName).OriginalDefinition.Equals(containingType))
                            {
                                return(candidateMethod);
                            }
                        }
                    }
                }
            }
            return(method);
        }
Пример #2
0
 private static FieldSymbol SubstituteField(FieldSymbol field, TypeMap typeMap)
 {
     Debug.Assert(!field.IsStatic);
     Debug.Assert(!field.IsReadOnly || GeneratedNameParser.GetKind(field.Name) == GeneratedNameKind.AnonymousTypeField);
     // CONSIDER: Instead of digging fields out of the unsubstituted type and then performing substitution
     // on each one individually, we could dig fields out of the substituted type.
     return(new EEDisplayClassFieldSymbol(typeMap.SubstituteNamedType(field.ContainingType), field.Name, typeMap.SubstituteType(field.TypeWithAnnotations)));
 }
 internal DisplayClassInstanceFromParameter(ParameterSymbol parameter)
 {
     Debug.Assert((object)parameter != null);
     Debug.Assert(parameter.Name.EndsWith("this", StringComparison.Ordinal) ||
                  parameter.Name.Length == 0 ||                               // unnamed
                  parameter.Name.Equals("value", StringComparison.Ordinal) || // display class instance passed to local function as parameter
                  GeneratedNameParser.GetKind(parameter.Name) == GeneratedNameKind.TransparentIdentifier);
     this.Parameter = parameter;
 }
Пример #4
0
        internal override string GetOriginalFieldName(string name)
        {
            if (!GeneratedNameParser.TryParseGeneratedName(name, out _, out var openBracketOffset, out var closeBracketOffset))
            {
                return(name);
            }

            var result = name.Substring(openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1);

            return(result);
        }
Пример #5
0
        public override string FormatTypeName(Type type, CommonTypeNameFormatterOptions options)
        {
            string stateMachineName;

            if (GeneratedNameParser.TryParseSourceMethodNameFromGeneratedName(type.Name, GeneratedNameKind.StateMachineType, out stateMachineName))
            {
                return(stateMachineName);
            }

            return(base.FormatTypeName(type, options));
        }
Пример #6
0
        internal override void LookupSymbolsInSingleBinder(LookupResult result, string name, int arity, ConsList <TypeSymbol> basesBeingResolved, LookupOptions options, Binder originalBinder, bool diagnose, ref CompoundUseSiteInfo <AssemblySymbol> useSiteInfo)
        {
            _sourceBinder.LookupSymbolsInSingleBinder(result, name, arity, basesBeingResolved, options, this, diagnose, ref useSiteInfo);

            var symbols = result.Symbols;

            for (int i = 0; i < symbols.Count; i++)
            {
                // Type parameters requiring mapping to the target type and
                // should be found by WithMethodTypeParametersBinder instead.
                var parameter = (ParameterSymbol)symbols[i];
                Debug.Assert(parameter.ContainingSymbol == _sourceBinder.ContainingMemberOrLambda);
                Debug.Assert(GeneratedNameParser.GetKind(parameter.Name) == GeneratedNameKind.None);
                symbols[i] = _targetParameters[parameter.Ordinal + _parameterOffset];
            }
        }
Пример #7
0
        private static bool TryGetAnonymousTypeKey(
            MetadataReader reader,
            TypeDefinition def,
            ArrayBuilder <AnonymousTypeKeyField> builder)
        {
            foreach (var typeParameterHandle in def.GetGenericParameters())
            {
                var typeParameter = reader.GetGenericParameter(typeParameterHandle);
                if (!GeneratedNameParser.TryParseAnonymousTypeParameterName(reader.GetString(typeParameter.Name), out var fieldName))
                {
                    return(false);
                }

                builder.Add(new AnonymousTypeKeyField(fieldName, isKey: false, ignoreCase: false));
            }
            return(true);
        }
Пример #8
0
        private BoundExpression GenerateThisReference(SyntaxNode syntax)
        {
            var thisProxy = CompilationContext.GetThisProxy(_displayClassVariables);

            if (thisProxy != null)
            {
                return(thisProxy.ToBoundExpression(syntax));
            }
            if ((object)_thisParameter != null)
            {
                var typeNameKind = GeneratedNameParser.GetKind(_thisParameter.TypeWithAnnotations.Type.Name);
                if (typeNameKind != GeneratedNameKind.None && typeNameKind != GeneratedNameKind.AnonymousType)
                {
                    Debug.Assert(typeNameKind == GeneratedNameKind.LambdaDisplayClass ||
                                 typeNameKind == GeneratedNameKind.StateMachineType,
                                 $"Unexpected typeNameKind '{typeNameKind}'");
                    return(null);
                }
                return(new BoundParameter(syntax, _thisParameter));
            }
            return(null);
        }
        /// <summary>
        /// Adds a <see cref="RouteEndpoint"/> to the <see cref="IEndpointRouteBuilder"/> that matches HTTP requests
        /// for the specified pattern.
        /// </summary>
        /// <param name="endpoints">The <see cref="IEndpointRouteBuilder"/> to add the route to.</param>
        /// <param name="pattern">The route pattern.</param>
        /// <param name="handler">The delegate executed when the endpoint is matched.</param>
        /// <returns>A <see cref="IEndpointConventionBuilder"/> that can be used to further customize the endpoint.</returns>
        public static DelegateEndpointConventionBuilder Map(
            this IEndpointRouteBuilder endpoints,
            RoutePattern pattern,
            Delegate handler)
        {
            if (endpoints is null)
            {
                throw new ArgumentNullException(nameof(endpoints));
            }

            if (pattern is null)
            {
                throw new ArgumentNullException(nameof(pattern));
            }

            if (handler is null)
            {
                throw new ArgumentNullException(nameof(handler));
            }

            const int defaultOrder = 0;

            var routeParams = new List <string>(pattern.Parameters.Count);

            foreach (var part in pattern.Parameters)
            {
                routeParams.Add(part.Name);
            }

            var routeHandlerOptions = endpoints.ServiceProvider?.GetService <IOptions <RouteHandlerOptions> >();

            var options = new RequestDelegateFactoryOptions
            {
                ServiceProvider     = endpoints.ServiceProvider,
                RouteParameterNames = routeParams,
                ThrowOnBadRequest   = routeHandlerOptions?.Value.ThrowOnBadRequest ?? false,
            };

            var requestDelegateResult = RequestDelegateFactory.Create(handler, options);

            var builder = new RouteEndpointBuilder(
                requestDelegateResult.RequestDelegate,
                pattern,
                defaultOrder)
            {
                DisplayName = pattern.RawText ?? pattern.DebuggerToString(),
            };

            // REVIEW: Should we add an IActionMethodMetadata with just MethodInfo on it so we are
            // explicit about the MethodInfo representing the "handler" and not the RequestDelegate?

            // Add MethodInfo as metadata to assist with OpenAPI generation for the endpoint.
            builder.Metadata.Add(handler.Method);

            // Methods defined in a top-level program are generated as statics so the delegate
            // target will be null. Inline lambdas are compiler generated method so they can
            // be filtered that way.
            if (GeneratedNameParser.TryParseLocalFunctionName(handler.Method.Name, out var endpointName) ||
                !TypeHelper.IsCompilerGeneratedMethod(handler.Method))
            {
                endpointName ??= handler.Method.Name;

                builder.Metadata.Add(new EndpointNameMetadata(endpointName));
                builder.Metadata.Add(new RouteNameMetadata(endpointName));
                builder.DisplayName = $"{builder.DisplayName} => {endpointName}";
            }

            // Add delegate attributes as metadata
            var attributes = handler.Method.GetCustomAttributes();

            // Add add request delegate metadata
            foreach (var metadata in requestDelegateResult.EndpointMetadata)
            {
                builder.Metadata.Add(metadata);
            }

            // This can be null if the delegate is a dynamic method or compiled from an expression tree
            if (attributes is not null)
            {
                foreach (var attribute in attributes)
                {
                    builder.Metadata.Add(attribute);
                }
            }

            var dataSource = endpoints.DataSources.OfType <ModelEndpointDataSource>().FirstOrDefault();

            if (dataSource is null)
            {
                dataSource = new ModelEndpointDataSource();
                endpoints.DataSources.Add(dataSource);
            }

            return(new DelegateEndpointConventionBuilder(dataSource.AddEndpointBuilder(builder)));
        }
        internal override void AppendFullName(StringBuilder builder, MethodSymbol method)
        {
            var displayFormat = (method.MethodKind == MethodKind.PropertyGet || method.MethodKind == MethodKind.PropertySet) ?
                                s_propertyDisplayFormat :
                                DisplayFormat;

            var parts    = method.ToDisplayParts(displayFormat);
            var numParts = parts.Length;

            for (int i = 0; i < numParts; i++)
            {
                var part          = parts[i];
                var displayString = part.ToString();

                switch (part.Kind)
                {
                case SymbolDisplayPartKind.ClassName:
                    if (GeneratedNameParser.GetKind(displayString) != GeneratedNameKind.LambdaDisplayClass)
                    {
                        builder.Append(displayString);
                    }
                    else
                    {
                        // Drop any remaining display class name parts and the subsequent dot...
                        do
                        {
                            i++;
                        }while (i < numParts && parts[i].Kind != SymbolDisplayPartKind.MethodName);
                        i--;
                    }
                    break;

                case SymbolDisplayPartKind.MethodName:
                    GeneratedNameKind kind;
                    int openBracketOffset, closeBracketOffset;
                    if (GeneratedNameParser.TryParseGeneratedName(displayString, out kind, out openBracketOffset, out closeBracketOffset) &&
                        (kind == GeneratedNameKind.LambdaMethod || kind == GeneratedNameKind.LocalFunction))
                    {
                        builder.Append(displayString, openBracketOffset + 1, closeBracketOffset - openBracketOffset - 1);     // source method name
                        builder.Append('.');
                        if (kind == GeneratedNameKind.LambdaMethod)
                        {
                            builder.Append(AnonymousMethodName);
                        }
                        // NOTE: Local functions include the local function name inside the suffix ("<Main>__Local1_1")
                        // NOTE: The old implementation only appended the first ordinal number.  Since this is not useful
                        // in uniquely identifying the lambda, we'll append the entire ordinal suffix (which may contain
                        // multiple numbers, as well as '-' or '_').
                        builder.Append(displayString.Substring(closeBracketOffset + 2));     // ordinal suffix (e.g. "__1")
                    }
                    else
                    {
                        builder.Append(displayString);
                    }
                    break;

                default:
                    builder.Append(displayString);
                    break;
                }
            }
        }
Пример #11
0
        protected override void GetStateMachineFieldMapFromMetadata(
            ITypeSymbolInternal stateMachineType,
            ImmutableArray <LocalSlotDebugInfo> localSlotDebugInfo,
            out IReadOnlyDictionary <EncHoistedLocalInfo, int> hoistedLocalMap,
            out IReadOnlyDictionary <Cci.ITypeReference, int> awaiterMap,
            out int awaiterSlotCount)
        {
            // we are working with PE symbols
            Debug.Assert(stateMachineType.ContainingAssembly is PEAssemblySymbol);

            var hoistedLocals       = new Dictionary <EncHoistedLocalInfo, int>();
            var awaiters            = new Dictionary <Cci.ITypeReference, int>(Cci.SymbolEquivalentEqualityComparer.Instance);
            int maxAwaiterSlotIndex = -1;

            foreach (var member in ((TypeSymbol)stateMachineType).GetMembers())
            {
                if (member.Kind == SymbolKind.Field)
                {
                    string name = member.Name;
                    int    slotIndex;

                    switch (GeneratedNameParser.GetKind(name))
                    {
                    case GeneratedNameKind.AwaiterField:
                        if (GeneratedNameParser.TryParseSlotIndex(name, out slotIndex))
                        {
                            var field = (FieldSymbol)member;

                            // correct metadata won't contain duplicates, but malformed might, ignore the duplicate:
                            awaiters[(Cci.ITypeReference)field.Type.GetCciAdapter()] = slotIndex;

                            if (slotIndex > maxAwaiterSlotIndex)
                            {
                                maxAwaiterSlotIndex = slotIndex;
                            }
                        }

                        break;

                    case GeneratedNameKind.HoistedLocalField:
                    case GeneratedNameKind.HoistedSynthesizedLocalField:
                        if (GeneratedNameParser.TryParseSlotIndex(name, out slotIndex))
                        {
                            var field = (FieldSymbol)member;
                            if (slotIndex >= localSlotDebugInfo.Length)
                            {
                                // invalid or missing metadata
                                continue;
                            }

                            var key = new EncHoistedLocalInfo(localSlotDebugInfo[slotIndex], (Cci.ITypeReference)field.Type.GetCciAdapter());

                            // correct metadata won't contain duplicate ids, but malformed might, ignore the duplicate:
                            hoistedLocals[key] = slotIndex;
                        }

                        break;
                    }
                }
            }

            hoistedLocalMap  = hoistedLocals;
            awaiterMap       = awaiters;
            awaiterSlotCount = maxAwaiterSlotIndex + 1;
        }
Пример #12
0
        public void LambdaLocations_Static()
        {
            var source = @"
using System;

class C
{
    static int f = ((Func<int, int>)(x => ((Func<int>)(() => x + 2))() + x))(1);

    static C()
    {
        int l = ((Func<int, int>)(x => ((Func<int>)(() => x + 4))() + x))(1);
    }

    static int P
    {
        get
        {
            return ((Func<int, int>)(x => ((Func<int>)(() => x + 7))() + x))(1);
        }
        set
        {
            value = ((Func<int, int>)(x => ((Func<int>)(() => x + 8))() + x))(1);
        }
    }

    static event Action E
    {
        add
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => x + 11))() + x))(1);
        }
        remove
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => x + 12))() + x))(1);
        }
    }
}
";

            var comp = CreateCompilation(source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName());

            WithRuntimeInstance(comp, runtime =>
            {
                var dummyComp         = CreateCompilation("", new[] { comp.EmitToImageReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
                var typeC             = dummyComp.GlobalNamespace.GetMember <NamedTypeSymbol>("C");
                var displayClassTypes = typeC.GetMembers().OfType <NamedTypeSymbol>();
                Assert.True(displayClassTypes.Any());
                foreach (var displayClassType in displayClassTypes)
                {
                    var displayClassName = displayClassType.Name;
                    Assert.Equal(GeneratedNameKind.LambdaDisplayClass, GeneratedNameParser.GetKind(displayClassName));
                    foreach (var displayClassMethod in displayClassType.GetMembers().OfType <MethodSymbol>().Where(m => GeneratedNameParser.GetKind(m.Name) == GeneratedNameKind.LambdaMethod))
                    {
                        var lambdaMethodName = string.Format("C.{0}.{1}", displayClassName, displayClassMethod.Name);
                        var context          = CreateMethodContext(runtime, lambdaMethodName);
                        VerifyNoThis(context);
                    }
                }
            });
        }
Пример #13
0
        public void LambdaLocations_Instance()
        {
            var source = @"
using System;

class C
{
    int _toBeCaptured;

    C()
    {
        int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 4))() + x))(1);
    }

    ~C()
    {
        int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 6))() + x))(1);
    }

    int P
    {
        get
        {
            return ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 7))() + x))(1);
        }
        set
        {
            value = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 8))() + x))(1);
        }
    }

    int this[int p]
    {
        get
        {
            return ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 9))() + x))(1);
        }
        set
        {
            value = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 10))() + x))(1);
        }
    }

    event Action E
    {
        add
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 11))() + x))(1);
        }
        remove
        {
            int l = ((Func<int, int>)(x => ((Func<int>)(() => _toBeCaptured + x + 12))() + x))(1);
        }
    }
}
";

            var expectedILTemplate = @"
{{
  // Code size        7 (0x7)
  .maxstack  1
  IL_0000:  ldarg.0
  IL_0001:  ldfld      ""C C.{0}.<>4__this""
  IL_0006:  ret
}}";

            var comp = CreateCompilation(source, options: TestOptions.DebugDll, assemblyName: ExpressionCompilerUtilities.GenerateUniqueName());

            WithRuntimeInstance(comp, runtime =>
            {
                var dummyComp         = CreateCompilation("", new[] { comp.EmitToImageReference() }, options: TestOptions.DebugDll.WithMetadataImportOptions(MetadataImportOptions.All));
                var typeC             = dummyComp.GlobalNamespace.GetMember <NamedTypeSymbol>("C");
                var displayClassTypes = typeC.GetMembers().OfType <NamedTypeSymbol>();
                Assert.True(displayClassTypes.Any());
                foreach (var displayClassType in displayClassTypes)
                {
                    var displayClassName = displayClassType.Name;
                    Assert.Equal(GeneratedNameKind.LambdaDisplayClass, GeneratedNameParser.GetKind(displayClassName));
                    foreach (var displayClassMethod in displayClassType.GetMembers().OfType <MethodSymbol>().Where(m => GeneratedNameParser.GetKind(m.Name) == GeneratedNameKind.LambdaMethod))
                    {
                        var lambdaMethodName = string.Format("C.{0}.{1}", displayClassName, displayClassMethod.Name);
                        var context          = CreateMethodContext(runtime, lambdaMethodName);
                        var expectedIL       = string.Format(expectedILTemplate, displayClassName);
                        VerifyHasThis(context, "C", expectedIL);
                    }
                }
            });
        }
Пример #14
0
        private static void CheckIteratorOverloading(string source, Func <MethodSymbol, bool> isDesiredOverload)
        {
            var comp1 = CreateCompilation(source, options: TestOptions.DebugDll);
            var ref1  = comp1.EmitToImageReference();
            var comp2 = CreateCompilation("", new[] { ref1 }, options: TestOptions.DebugDll);

            var originalType   = comp2.GlobalNamespace.GetMember <NamedTypeSymbol>("C");
            var iteratorMethod = originalType.GetMembers("M").OfType <MethodSymbol>().Single(isDesiredOverload);

            var stateMachineType = originalType.GetMembers().OfType <NamedTypeSymbol>().Single(t => GeneratedNameParser.GetKind(t.Name) == GeneratedNameKind.StateMachineType);
            var moveNextMethod   = stateMachineType.GetMember <MethodSymbol>("MoveNext");

            var guessedIterator = CompilationContext.GetSubstitutedSourceMethod(moveNextMethod, sourceMethodMustBeInstance: true);

            Assert.Equal(iteratorMethod, guessedIterator.OriginalDefinition);
        }