public void IgnoreOtherDiagnosticsCompilingSynthesizedMethods() { var source = @"class C { static object F = new object(); // generate .cctor static System.Action M() { return () => { }; // generate lambda } }"; var compilation = CreateCompilationWithMscorlib(source, options: TestOptions.ReleaseDll.WithConcurrentBuild(false)); var options = compilation.Options; var diagnostics = DiagnosticBag.GetInstance(); var assembly = (SourceAssemblySymbol)compilation.Assembly; var module = new PEAssemblyBuilder( assembly, EmitOptions.Default, options.OutputKind, GetDefaultModulePropertiesForSerialization(), new ResourceDescription[0]); var methodBodyCompiler = new MethodCompiler( compilation: compilation, moduleBeingBuiltOpt: module, emittingPdb: false, hasDeclarationErrors: false, diagnostics: diagnostics, filterOpt: null, cancellationToken: CancellationToken.None); // Add diagnostic to MethodBodyCompiler bag, as if // code gen for an earlier method had generated an error. diagnostics.Add(new CSDiagnostic(new CSDiagnosticInfo(ErrorCode.ERR_IntDivByZero), NoLocation.Singleton)); // Compile all methods for type including synthesized methods. var type = compilation.GlobalNamespace.GetMember<NamedTypeSymbol>("C"); methodBodyCompiler.Visit(type); Assert.Equal(1, diagnostics.AsEnumerable().Count()); diagnostics.Free(); }
/// <summary> /// Resets numbering in anonymous type names and compiles the /// anonymous type methods. Also seals the collection of templates. /// </summary> public void AssignTemplatesNamesAndCompile(MethodCompiler compiler, PEModuleBuilder moduleBeingBuilt, DiagnosticBag 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); } compiler.Visit(template, null); } } builder.Free(); var synthesizedDelegates = ArrayBuilder <SynthesizedDelegateSymbol> .GetInstance(); GetCreatedSynthesizedDelegates(synthesizedDelegates); foreach (var synthesizedDelegate in synthesizedDelegates) { compiler.Visit(synthesizedDelegate, null); } synthesizedDelegates.Free(); }
/// <summary> /// Resets numbering in anonymous type names and compiles the /// anonymous type methods. Also seals the collection of templates. /// </summary> public void AssignTemplatesNamesAndCompile(MethodCompiler compiler, PEModuleBuilder moduleBeingBuilt, DiagnosticBag 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.Names, f => f); this.AnonymousTypeTemplates.GetOrAdd(templateKey, k => this.CreatePlaceholderTemplate(key)); } // Get all anonymous types owned by this manager var builder = ArrayBuilder <AnonymousTypeTemplateSymbol> .GetInstance(); var anonymousTypes = lazyAnonymousTypeTemplates; if (anonymousTypes != null) { foreach (var template in anonymousTypes.Values) { // NOTE: in interactive scenarios the cache may contain templates // from other compilation, those should be discarded here if (ReferenceEquals(template.Manager, this)) { builder.Add(template); } } } // If the collection is not sealed yet we should assign // new indexes to the created anonymous type templates if (this.anonymousTypeTemplatesIsSealed != ThreeState.True) { // Sort type templates using smallest location builder.Sort(new AnonymousTypeComparer(this.Compilation)); // 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 = moduleId.Replace('.', '_'); } 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.anonymousTypeTemplatesIsSealed = ThreeState.True; } 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); } compiler.Visit(template, null); } } builder.Free(); var delegates = lazySynthesizedDelegates; if (delegates != null) { foreach (var template in delegates.Values) { // NOTE: in interactive scenarios the cache may contain templates // from other compilation, those should be discarded here if (ReferenceEquals(template.Manager, this)) { compiler.Visit(template.Delegate, null); } } } }