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); }
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; }
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); }
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)); }
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]; } }
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); }
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; } } }
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; }
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); } } }); }
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); } } }); }
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); }