// internal for testing internal static IReadOnlyDictionary <SynthesizedDelegateKey, SynthesizedDelegateValue> GetAnonymousDelegateMapFromMetadata(MetadataReader reader, MetadataDecoder metadataDecoder) { var result = new Dictionary <SynthesizedDelegateKey, SynthesizedDelegateValue>(); foreach (var handle in reader.TypeDefinitions) { var def = reader.GetTypeDefinition(handle); if (!def.Namespace.IsNil) { continue; } if (!reader.StringComparer.StartsWith(def.Name, GeneratedNames.ActionDelegateNamePrefix) && !reader.StringComparer.StartsWith(def.Name, GeneratedNames.FuncDelegateNamePrefix)) { continue; } // The name of a synthesized delegate neatly encodes everything we need to identify it, either // in the prefix (return void or not) or the name (ref kinds and arity) so we don't need anything // fancy for a key. var metadataName = reader.GetString(def.Name); var key = new SynthesizedDelegateKey(metadataName); var type = (NamedTypeSymbol)metadataDecoder.GetTypeOfToken(handle); var value = new SynthesizedDelegateValue(type.GetCciAdapter()); result.Add(key, value); } return(result); }
internal SynthesizedDelegateSymbol SynthesizeDelegate(int parameterCount, BitVector byRefParameters, bool returnsVoid) { // parameterCount doesn't include return type Debug.Assert(byRefParameters.IsNull || parameterCount == byRefParameters.Capacity); var key = new SynthesizedDelegateKey(parameterCount, byRefParameters, returnsVoid); SynthesizedDelegateValue result; if (this.SynthesizedDelegates.TryGetValue(key, out result)) { return(result.Delegate); } // NOTE: the newly created template may be thrown away if another thread wins return(this.SynthesizedDelegates.GetOrAdd(key, new SynthesizedDelegateValue( this, new SynthesizedDelegateSymbol( this.Compilation.Assembly.GlobalNamespace, key.MakeTypeName(), this.System_Object, Compilation.GetSpecialType(SpecialType.System_IntPtr), returnsVoid ? Compilation.GetSpecialType(SpecialType.System_Void) : null, parameterCount, byRefParameters))).Delegate); }
public void AssignTemplatesNamesAndCompile(MethodCompiler compiler, PEModuleBuilder moduleBeingBuilt, BindingDiagnosticBag diagnostics) { // Ensure all previous anonymous type templates are included so the // types are available for subsequent edit and continue generations. foreach (var key in moduleBeingBuilt.GetPreviousAnonymousTypes()) { var templateKey = AnonymousTypeDescriptor.ComputeKey(key.Fields, f => f.Name); this.AnonymousTypeTemplates.GetOrAdd(templateKey, k => this.CreatePlaceholderTemplate(key)); } // Get all anonymous types owned by this manager var builder = ArrayBuilder <AnonymousTypeTemplateSymbol> .GetInstance(); GetCreatedAnonymousTypeTemplates(builder); // If the collection is not sealed yet we should assign // new indexes to the created anonymous type templates if (!this.AreTemplatesSealed) { // If we are emitting .NET module, include module's name into type's name to ensure // uniqueness across added modules. string moduleId; if (moduleBeingBuilt.OutputKind == OutputKind.NetModule) { moduleId = moduleBeingBuilt.Name; string extension = OutputKind.NetModule.GetDefaultExtension(); if (moduleId.EndsWith(extension, StringComparison.OrdinalIgnoreCase)) { moduleId = moduleId.Substring(0, moduleId.Length - extension.Length); } moduleId = MetadataHelpers.MangleForTypeNameIfNeeded(moduleId); } else { moduleId = string.Empty; } int nextIndex = moduleBeingBuilt.GetNextAnonymousTypeIndex(); foreach (var template in builder) { string name; int index; if (!moduleBeingBuilt.TryGetAnonymousTypeName(template, out name, out index)) { index = nextIndex++; name = GeneratedNames.MakeAnonymousTypeTemplateName(index, this.Compilation.GetSubmissionSlotIndex(), moduleId); } // normally it should only happen once, but in case there is a race // NameAndIndex.set has an assert which guarantees that the // template name provided is the same as the one already assigned template.NameAndIndex = new NameAndIndex(name, index); } this.SealTemplates(); } if (builder.Count > 0 && !ReportMissingOrErroneousSymbols(diagnostics)) { // Process all the templates foreach (var template in builder) { foreach (var method in template.SpecialMembers) { moduleBeingBuilt.AddSynthesizedDefinition(template, method.GetCciAdapter()); } compiler.Visit(template, null); } } builder.Free(); // Ensure all previous synthesized delegates are included so the // types are available for subsequent edit and continue generations. foreach (var key in moduleBeingBuilt.GetPreviousSynthesizedDelegates()) { if (GeneratedNames.TryParseSynthesizedDelegateName(key.Name, out var refKinds, out var returnsVoid, out var generation, out var parameterCount)) { var delegateKey = new SynthesizedDelegateKey(parameterCount, refKinds, returnsVoid, generation); this.SynthesizedDelegates.GetOrAdd(delegateKey, (k, args) => CreatePlaceholderSynthesizedDelegateValue(key.Name, args.refKinds, args.returnsVoid, args.parameterCount), (refKinds, returnsVoid, parameterCount)); } } var synthesizedDelegates = ArrayBuilder <SynthesizedDelegateSymbol> .GetInstance(); GetCreatedSynthesizedDelegates(synthesizedDelegates); foreach (var synthesizedDelegate in synthesizedDelegates) { compiler.Visit(synthesizedDelegate, null); } synthesizedDelegates.Free(); }